Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ScriptableController_FS18/src/orxonox/scriptablecontroller/scriptable_controller_api.cc @ 11974

Last change on this file since 11974 was 11974, checked in by adamc, 6 years ago

can

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