Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/scriptablecontroller/scriptable_controller_api.cc

Last change on this file was 12006, checked in by adamc, 7 years ago

first final draft

File size: 19.9 KB
Line 
1
2#include "scriptable_controller_api.h"
3#include "luatb.h"
4#include "scriptable_controller.h"
5#include "tools/Timer.h"
6#include "worldentities/pawns/Pawn.h"
7#include "infos/Bot.h"
8#include "worldentities/pawns/ModularSpaceShip.h"
9//#include "../modules/objects/collisionshapes/SphereCollisionShape.h"
10#include "graphics/Model.h"
11#include "worldentities/pawns/ScriptableControllerDrone.h"
12
13
14namespace orxonox
15{
16
17    const double ScriptableControllerAPI::periodic_interval = 0.5;
18
19    ScriptableControllerAPI::ScriptableControllerAPI(lua_State *lua, ScriptableController *controller)
20    {
21        this->lua_ = lua;
22        this->controller_ = controller;
23
24        // Haven't found a shorter way yet to write that... We need C++17!
25        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::orxPrint)>::registerFunction<&ScriptableControllerAPI::orxPrint>(this, lua, "orxPrint");
26
27        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAfterTimeout)>::registerFunction<&ScriptableControllerAPI::registerAfterTimeout>(this, lua, "registerAfterTimeout");
28        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtNearObject)>::registerFunction<&ScriptableControllerAPI::registerAtNearObject>(this, lua, "registerAtNearObject");
29        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtNearPoint)>::registerFunction<&ScriptableControllerAPI::registerAtNearPoint>(this, lua, "registerAtNearPoint");
30        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtAreaEnter)>::registerFunction<&ScriptableControllerAPI::registerAtAreaEnter>(this, lua, "registerAtAreaEnter");
31        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtAreaLeave)>::registerFunction<&ScriptableControllerAPI::registerAtAreaLeave>(this, lua, "registerAtAreaLeave");
32        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtPawnKilled)>::registerFunction<&ScriptableControllerAPI::registerAtPawnKilled>(this, lua, "registerAtPawnKilled");
33        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtPawnHit)>::registerFunction<&ScriptableControllerAPI::registerAtPawnHit>(this, lua, "registerAtPawnHit");
34
35        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::setPosition)>::registerFunction<&ScriptableControllerAPI::setPosition>(this, lua, "setPosition");
36        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::setOrientation)>::registerFunction<&ScriptableControllerAPI::setOrientation>(this, lua, "setOrientation");
37        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::setVelocity)>::registerFunction<&ScriptableControllerAPI::setVelocity>(this, lua, "setVelocity");
38        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::setAngularVelocity)>::registerFunction<&ScriptableControllerAPI::setAngularVelocity>(this, lua, "setAngularVelocity");
39
40        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::killPawn)>::registerFunction<&ScriptableControllerAPI::killPawn>(this, lua, "killPawn");
41        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::spawn)>::registerFunction<&ScriptableControllerAPI::spawn>(this, lua, "spawn");
42
43        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::spawnTest)>::registerFunction<&ScriptableControllerAPI::spawnTest>(this, lua, "spawnTest");
44
45
46
47        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::myTestFunction)>::registerFunction<&ScriptableControllerAPI::myTestFunction>(this, lua, "mytestfunction");
48        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::moveControllableEntity)>::registerFunction<&ScriptableControllerAPI::moveControllableEntity>(this, lua, "moveControllableEntity");
49
50
51
52        this->periodicTimer.setTimer(ScriptableControllerAPI::periodic_interval, true, createExecutor(createFunctor(&ScriptableControllerAPI::periodic, this)), false);
53    }
54
55    ScriptableControllerAPI::~ScriptableControllerAPI()
56    {
57        lua_close(this->lua_);
58    }
59
60    void ScriptableControllerAPI::orxPrint(std::string msg)
61    {
62        orxout(user_info) << msg << std::endl;
63    }
64
65    void ScriptableControllerAPI::registerAfterTimeout(std::function<void (void)> callback, double timeout)
66    {
67        // Kills itself when the timer fires
68        new Timer(timeout, false, callback, true);
69    }
70
71    //void ScriptableControllerAPI::registerPeriodically(std::function<void (void)> callback, double timeout)
72    //{
73    //    // Kills itself when the timer fires
74    //    new Timer(timeout, false, callback, true);
75    //}
76
77
78
79
80
81
82
83
84    void ScriptableControllerAPI::registerAtNearObject(std::function<void (std::string, std::string)> callback, std::string id1, std::string id2, double distance)
85    {
86        WorldEntity *entity1 = this->controller_->getWorldEntityByID(id1);
87        WorldEntity *entity2 = this->controller_->getWorldEntityByID(id2);
88
89        if(entity1 != nullptr && entity2 != nullptr)
90            this->nearObjectHandlers_.push_front(NearObjectHandler(entity1, entity2, id1, id2, distance, callback));
91    }
92
93    void ScriptableControllerAPI::registerAtNearPoint(std::function<void (std::string)> callback, std::string id, double x, double y, double z, double distance)
94    {
95        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
96
97        if(entity != nullptr)
98            this->nearPointHandlers_.push_front(NearPointHandler(entity, id, x, y, z, distance, callback));
99    }
100
101    void ScriptableControllerAPI::registerAtAreaEnter(std::function<void (std::string)> callback, std::string id, int x, int y, int z, int dx, int dy, int dz)
102    {
103        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
104
105        if(entity != nullptr)
106            this->areaHandlers_.push_front(AreaHandler(entity, id, x, y, z, dx, dy, dz, true, callback));
107    }
108
109    void ScriptableControllerAPI::registerAtAreaLeave(std::function<void (std::string)> callback, std::string id, int x, int y, int z, int dx, int dy, int dz)
110    {
111        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
112
113        if(entity != nullptr)
114            this->areaHandlers_.push_front(AreaHandler(entity, id, x, y, z, dx, dy, dz, false, callback));
115    }
116
117    void ScriptableControllerAPI::registerAtPawnKilled(std::function<void (std::string)> callback, std::string id)
118    {
119        this->pawnDestroyedHandlers_[id].push_back(callback);
120    }
121
122    void ScriptableControllerAPI::registerAtPawnHit(std::function<void (std::string, std::string, double, double)> callback, std::string id)
123    {
124        this->pawnHitHandlers_[id].push_back(callback);
125    }
126
127    void ScriptableControllerAPI::killPawn(std::string id)
128    {
129        Pawn *pawn = this->controller_->getPawnByID(id);
130        if(pawn == nullptr)
131            orxout(user_warning) << "Trying to kill an unknown pawn" << std::endl;
132        else
133            pawn->kill();
134    }
135
136    void ScriptableControllerAPI::spawn(std::string type, std::string id)
137    {
138        if(this->controller_->getWorldEntityByID(id) != nullptr)
139        {
140            orxout(user_warning) << "Script tried to spawn an object, but an object with the given ID exists already" << std::endl;
141            return;
142        }
143
144        Identifier *identifier = ClassByString(type);
145        if(!identifier)
146        {
147            orxout(user_error) << "Script tried to spawn unknown object" << std::endl;
148            return;
149        }
150
151        if(!identifier->isLoadable())
152        {
153            orxout(user_error) << "Script tried to spawn unloadable object" << std::endl;
154            return;
155        }
156
157        WorldEntity *entity;
158        Identifiable *obj = identifier->fabricate(this->controller_->getWorldEntityByID("Player")->getContext());
159
160        orxout(user_error) << "First hit!" << std::endl;
161
162        if(obj->isA(ClassIdentifier<WorldEntity>::getIdentifier()))
163        {
164            entity = orxonox_cast<WorldEntity*>(obj);
165        }
166        else if(obj->isA(ClassIdentifier<PlayerInfo>::getIdentifier()))
167        {
168            // TODO This does not work yet because somehow the controllable entity is not set
169            // yet at this stage.
170    //        entity = orxonox_cast<PlayerInfo*>(obj)->getControllableEntity();
171
172
173            //use TEMPLATES in the map to define objects that are not present on the map yet
174            return;
175        }
176        else
177        {
178            orxout(user_warning) << "Script tried to spawn an object that is neither a WorldEntity, nor a PlayerInfo" << std::endl;
179           
180            return;
181        }
182
183        orxout(user_error) << "Second hit!" << std::endl;
184
185        if(entity->isA(ClassIdentifier<MobileEntity>::getIdentifier()))
186            this->controller_->registerMobileEntity(id, orxonox_cast<MobileEntity*>(entity));
187
188        if(entity->isA(ClassIdentifier<Pawn>::getIdentifier()))
189            this->controller_->registerPawn(id, orxonox_cast<Pawn*>(entity));
190
191        this->controller_->registerWorldEntity(id, orxonox_cast<WorldEntity*>(entity));
192
193
194        orxout(user_error) << "Third and final hit!" << std::endl;
195
196    }
197
198
199
200
201
202    void ScriptableControllerAPI::spawnTest(std::string id)
203    {
204       
205        if(this->controller_->getWorldEntityByID(id) != nullptr)
206        {
207            orxout(user_warning) << "Script tried to spawn an object, but an object with the given ID exists already" << std::endl;
208            return;
209        }
210       
211
212        Identifier *identifier = ClassByString("ScriptableControllerDrone");
213       
214       
215        if(!identifier)
216        {
217            orxout(user_error) << "Script tried to spawn unknown object" << std::endl;
218            return;
219        }
220
221        if(!identifier->isLoadable())
222        {
223            orxout(user_error) << "Script tried to spawn unloadable object" << std::endl;
224            return;
225        }
226
227       
228
229        WorldEntity *entity;
230        Identifiable *obj = identifier->fabricate(this->controller_->getWorldEntityByID("Player")->getContext());
231
232        orxout(user_status) << "First hit!" << std::endl;
233
234        if(obj->isA(ClassIdentifier<WorldEntity>::getIdentifier()))
235        {
236            orxout(user_status) << "Is WorldEntity!" << std::endl;
237            entity = orxonox_cast<WorldEntity*>(obj);
238        }
239        else if(obj->isA(ClassIdentifier<PlayerInfo>::getIdentifier()))
240        {
241            // TODO This does not work yet because somehow the controllable entity is not set
242            // yet at this stage.
243    //        entity = orxonox_cast<PlayerInfo*>(obj)->getControllableEntity();
244
245            orxout(user_status) << "Is PlayerInfo!" << std::endl;
246
247            //use TEMPLATES in the map to define objects that are not present on the map yet
248            return;
249        }
250        else
251        {
252            orxout(user_warning) << "Script tried to spawn an object that is neither a WorldEntity, nor a PlayerInfo" << std::endl;
253           
254            return;
255        }
256
257
258        if(entity->isA(ClassIdentifier<MobileEntity>::getIdentifier())) {
259            orxout(user_status) << "Is MobileEntity!" << std::endl;
260            this->controller_->registerMobileEntity(id, orxonox_cast<MobileEntity*>(entity));
261        }
262
263        if(entity->isA(ClassIdentifier<Pawn>::getIdentifier())) {
264            orxout(user_status) << "Is Pawn!" << std::endl;
265            this->controller_->registerPawn(id, orxonox_cast<Pawn*>(entity));
266        }
267
268        this->controller_->registerWorldEntity(id, orxonox_cast<WorldEntity*>(entity));
269
270        if(this->controller_->getPawnByID(id) != nullptr) {
271            orxout(user_status) << "Pawn is indeed available!" << std::endl;
272        }
273
274
275
276        ///////////////GOLD!!!!!!!!!!!!!!!////////////////////////
277        Pawn* pawn = this->controller_->getPawnByID(id);
278        //Attach to pawn
279        ScriptableControllerDrone* drone = new ScriptableControllerDrone(pawn->getContext()); // this is neccessary because the projectiles fired need a valid creator for the particlespawner (when colliding against something)
280       
281        drone->addTemplate("ScriptableControllerDroneTemplate"); //ScriptableControllerDroneTemplate spaceshipescort
282
283        Vector3 spawnPosition = pawn->getWorldPosition() + Vector3(30,0,-30);
284        drone->setPosition(spawnPosition);
285        //drone->moveFrontBack(1.0);
286
287
288        orxout(user_status) << "Final hit!" << std::endl;
289    }
290
291
292
293
294
295
296    void ScriptableControllerAPI::setPosition(std::string id, double x, double y, double z)
297    {
298        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
299        if(entity == nullptr)
300        {
301            orxout(user_warning) << "Trying to set position of an unknown object" << std::endl;
302            return;
303        }
304
305        const Vector3 &old = entity->getPosition();
306
307        // If one of the values is NaN, don't change that value
308        x = std::isnan(x) ? old.x : x;
309        y = std::isnan(y) ? old.y : y;
310        z = std::isnan(z) ? old.z : z;
311
312        entity->setPosition(x, y, z);
313    }
314
315    void ScriptableControllerAPI::setOrientation(std::string id, double x, double y, double z, double angle)
316    {
317        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
318        if(entity == nullptr)
319        {
320            orxout(user_warning) << "Trying to set orientation of an unknown object" << std::endl;
321            return;
322        }
323
324        Vector3 old_axis;
325        Degree old_angle;
326
327        entity->getOrientation().ToAngleAxis(old_angle, old_axis);
328
329        // If one of the values is NaN, don't change that value
330        x = std::isnan(x) ? old_axis.x : x;
331        y = std::isnan(y) ? old_axis.y : y;
332        z = std::isnan(z) ? old_axis.z : z;
333        angle = std::isnan(x) ? old_angle.valueDegrees() : angle;
334
335
336        entity->setOrientation(Vector3(x, y, z), Degree(angle));
337    }
338
339    void ScriptableControllerAPI::setVelocity(std::string id, double x, double y, double z)
340    {
341        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
342        if(entity == nullptr)
343        {
344            orxout(user_warning) << "Trying to set velocity of an unknown object" << std::endl;
345            return;
346        }
347
348        const Vector3 &old = entity->getVelocity();
349
350        // If one of the values is NaN, don't change that value
351        x = std::isnan(x) ? old.x : x;
352        y = std::isnan(y) ? old.y : y;
353        z = std::isnan(z) ? old.z : z;
354
355        entity->setVelocity(x, y, z);
356    }
357
358    void ScriptableControllerAPI::setAngularVelocity(std::string id, double x, double y, double z)
359    {
360        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
361        if(entity == nullptr)
362        {
363            orxout(user_warning) << "Trying to set angular velocity of an unknown object" << std::endl;
364            return;
365        }
366
367        const Vector3 &old = entity->getAngularVelocity();
368
369        // If one of the values is NaN, don't change that value
370        x = std::isnan(x) ? old.x : x;
371        y = std::isnan(y) ? old.y : y;
372        z = std::isnan(z) ? old.z : z;
373
374        entity->setAngularVelocity(x, y, z);
375    }
376
377    void ScriptableControllerAPI::pawnKilled(std::string id, Pawn *pawn)
378    {
379        for(auto callback : this->pawnDestroyedHandlers_[id])
380            callback(id);
381
382        this->pawnDestroyedHandlers_.erase(id);
383
384        // We need to delete those handlers as well, they're no longer valid
385        auto near_obj_handler = this->nearObjectHandlers_.begin();
386        while(near_obj_handler != this->nearObjectHandlers_.end())
387        {
388            if(near_obj_handler->entity1_ == pawn || near_obj_handler->entity2_ == pawn)
389                near_obj_handler = this->nearObjectHandlers_.erase(near_obj_handler);
390            else
391                near_obj_handler++;
392        }
393
394        auto near_point_handler = this->nearPointHandlers_.begin();
395        while(near_point_handler != this->nearPointHandlers_.end())
396        {
397            if(near_point_handler->entity_ == pawn)
398                near_point_handler = this->nearPointHandlers_.erase(near_point_handler);
399            else
400                near_point_handler++;
401        }
402
403        auto area_handler = this->areaHandlers_.begin();
404        while(area_handler != this->areaHandlers_.end())
405        {
406            if(area_handler->entity_ == pawn)
407                area_handler = this->areaHandlers_.erase(area_handler);
408            else
409                area_handler++;
410        }
411    }
412
413    void ScriptableControllerAPI::pawnHit(std::string target_id, std::string source_id, double new_health, double new_shield)
414    {
415        for(auto callback : this->pawnHitHandlers_[target_id])
416            callback(target_id, source_id, new_health, new_shield);
417    }
418
419    void ScriptableControllerAPI::periodic()
420    {
421        // Near object
422        auto near_obj_handler = this->nearObjectHandlers_.begin();
423        while(near_obj_handler != this->nearObjectHandlers_.end())
424        {
425            if((near_obj_handler->entity1_->getPosition() - near_obj_handler->entity2_->getPosition()).length() < near_obj_handler->distance_)
426            {
427                near_obj_handler->callback_(near_obj_handler->id1_, near_obj_handler->id2_);
428                near_obj_handler = this->nearObjectHandlers_.erase(near_obj_handler);
429            }
430            else
431            {
432                near_obj_handler++;
433            }
434        }
435
436        // Near point
437        auto near_point_handler = this->nearPointHandlers_.begin();
438        while(near_point_handler != this->nearPointHandlers_.end())
439        {
440            if((near_point_handler->entity_->getPosition() - near_point_handler->point_).length() < near_point_handler->distance_)
441            {
442                near_point_handler->callback_(near_point_handler->id_);
443                near_point_handler = this->nearPointHandlers_.erase(near_point_handler);
444            }
445            else
446            {
447                near_point_handler++;
448            }
449        }
450
451        // Areas
452        auto area_handler = this->areaHandlers_.begin();
453        while(area_handler != this->areaHandlers_.end())
454        {
455            if(area_handler->entity_->getPosition() > area_handler->start_point_ &&
456               area_handler->entity_->getPosition() < area_handler->end_point_)
457            {
458                if(area_handler->atEnter_)
459                {
460                    area_handler->callback_(area_handler->id_);
461                    area_handler = this->areaHandlers_.erase(area_handler);
462                }
463                else
464                {
465                    area_handler++;
466                }
467            }
468            else
469            {
470                if(!area_handler->atEnter_)
471                {
472                    area_handler->callback_(area_handler->id_);
473                    area_handler = this->areaHandlers_.erase(area_handler);
474                }
475                else
476                {
477                    area_handler++;
478                }
479            }
480        }
481
482    }
483
484
485    //// TESTTESTTESTTESTTESTTEST
486    double ScriptableControllerAPI::myTestFunction(double x, double y)
487    {
488        double z = x + y;
489        orxout(user_info) << "Result = " << z << endl;
490        return z;
491    }
492
493
494
495
496
497    void ScriptableControllerAPI::moveControllableEntity(std::string id, double x, double y, double z)
498    {
499        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
500       
501        if(entity == nullptr)
502        {
503            orxout(user_warning) << "Trying to move an unknown object" << std::endl;
504            return;
505        }
506
507        Identifier *identifier = ClassByString("ControllableEntity");
508       
509        ControllableEntity *controllable_entity;
510       
511        if(identifier->isA(ClassIdentifier<ControllableEntity>::getIdentifier()))
512        {
513            orxout(user_info) << "Before final cast..."<< endl;
514            controllable_entity = orxonox_cast<ControllableEntity*>(entity);
515            orxout(user_info) << "After final cast..."<< endl;
516            //ATTACHED COLLISION SHAPE is MANDATORY in order to move the entity
517            controllable_entity->moveFrontBack(x);
518            controllable_entity->moveRightLeft(y);
519            controllable_entity->moveUpDown(z);
520            orxout(user_info) << "After move..."<< endl;
521        }
522
523        return;
524       
525    }
526}
Note: See TracBrowser for help on using the repository browser.