Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Trying to spawn entity (2nd attempt)

File size: 16.2 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
40
41        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::myTestFunction)>::registerFunction<&ScriptableControllerAPI::myTestFunction>(this, lua, "mytestfunction");
42        LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::moveControllableEntity)>::registerFunction<&ScriptableControllerAPI::moveControllableEntity>(this, lua, "moveControllableEntity");
43
44
45
46        this->periodicTimer.setTimer(ScriptableControllerAPI::periodic_interval, true, createExecutor(createFunctor(&ScriptableControllerAPI::periodic, this)), false);
47    }
48
49    ScriptableControllerAPI::~ScriptableControllerAPI()
50    {
51        lua_close(this->lua_);
52    }
53
54    void ScriptableControllerAPI::orxPrint(std::string msg)
55    {
56        orxout(user_info) << msg << std::endl;
57    }
58
59    void ScriptableControllerAPI::registerAfterTimeout(std::function<void (void)> callback, double timeout)
60    {
61        // Kills itself when the timer fires
62        new Timer(timeout, false, callback, true);
63    }
64
65    //void ScriptableControllerAPI::registerPeriodically(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
72
73
74
75
76
77
78    void ScriptableControllerAPI::registerAtNearObject(std::function<void (std::string, std::string)> callback, std::string id1, std::string id2, double distance)
79    {
80        WorldEntity *entity1 = this->controller_->getWorldEntityByID(id1);
81        WorldEntity *entity2 = this->controller_->getWorldEntityByID(id2);
82
83        if(entity1 != nullptr && entity2 != nullptr)
84            this->nearObjectHandlers_.push_front(NearObjectHandler(entity1, entity2, id1, id2, distance, callback));
85    }
86
87    void ScriptableControllerAPI::registerAtNearPoint(std::function<void (std::string)> callback, std::string id, double x, double y, double z, double distance)
88    {
89        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
90
91        if(entity != nullptr)
92            this->nearPointHandlers_.push_front(NearPointHandler(entity, id, x, y, z, distance, callback));
93    }
94
95    void ScriptableControllerAPI::registerAtAreaEnter(std::function<void (std::string)> callback, std::string id, int x, int y, int z, int dx, int dy, int dz)
96    {
97        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
98
99        if(entity != nullptr)
100            this->areaHandlers_.push_front(AreaHandler(entity, id, x, y, z, dx, dy, dz, true, callback));
101    }
102
103    void ScriptableControllerAPI::registerAtAreaLeave(std::function<void (std::string)> callback, std::string id, int x, int y, int z, int dx, int dy, int dz)
104    {
105        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
106
107        if(entity != nullptr)
108            this->areaHandlers_.push_front(AreaHandler(entity, id, x, y, z, dx, dy, dz, false, callback));
109    }
110
111    void ScriptableControllerAPI::registerAtPawnKilled(std::function<void (std::string)> callback, std::string id)
112    {
113        this->pawnDestroyedHandlers_[id].push_back(callback);
114    }
115
116    void ScriptableControllerAPI::registerAtPawnHit(std::function<void (std::string, std::string, double, double)> callback, std::string id)
117    {
118        this->pawnHitHandlers_[id].push_back(callback);
119    }
120
121    void ScriptableControllerAPI::killPawn(std::string id)
122    {
123        Pawn *pawn = this->controller_->getPawnByID(id);
124        if(pawn == nullptr)
125            orxout(user_warning) << "Trying to kill an unknown pawn" << std::endl;
126        else
127            pawn->kill();
128    }
129
130    void ScriptableControllerAPI::spawn(std::string type, std::string id)
131    {
132        if(this->controller_->getWorldEntityByID(id) != nullptr)
133        {
134            orxout(user_warning) << "Script tried to spawn an object, but an object with the given ID exists already" << std::endl;
135            return;
136        }
137
138        Identifier *identifier = ClassByString(type);
139        if(!identifier)
140        {
141            orxout(user_error) << "Script tried to spawn unknown object" << std::endl;
142            return;
143        }
144
145        if(!identifier->isLoadable())
146        {
147            orxout(user_error) << "Script tried to spawn unloadable object" << std::endl;
148            return;
149        }
150
151        WorldEntity *entity;
152        Identifiable *obj = identifier->fabricate(this->controller_->getWorldEntityByID("Player")->getContext());
153
154        orxout(user_error) << "First hit!" << std::endl;
155
156        if(obj->isA(ClassIdentifier<WorldEntity>::getIdentifier()))
157        {
158            entity = orxonox_cast<WorldEntity*>(obj);
159        }
160        else if(obj->isA(ClassIdentifier<PlayerInfo>::getIdentifier()))
161        {
162            // TODO This does not work yet because somehow the controllable entity is not set
163            // yet at this stage.
164    //        entity = orxonox_cast<PlayerInfo*>(obj)->getControllableEntity();
165
166
167            //use TEMPLATES in the map to define objects that are not present on the map yet
168            return;
169        }
170        else
171        {
172            orxout(user_warning) << "Script tried to spawn an object that is neither a WorldEntity, nor a PlayerInfo" << std::endl;
173           
174            return;
175        }
176
177        orxout(user_error) << "Second hit!" << std::endl;
178
179        if(entity->isA(ClassIdentifier<MobileEntity>::getIdentifier()))
180            this->controller_->registerMobileEntity(id, orxonox_cast<MobileEntity*>(entity));
181
182        if(entity->isA(ClassIdentifier<Pawn>::getIdentifier()))
183            this->controller_->registerPawn(id, orxonox_cast<Pawn*>(entity));
184
185        this->controller_->registerWorldEntity(id, orxonox_cast<WorldEntity*>(entity));
186
187        orxout(user_error) << "Third and final hit!" << std::endl;
188    }
189
190    void ScriptableControllerAPI::setPosition(std::string id, double x, double y, double z)
191    {
192        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
193        if(entity == nullptr)
194        {
195            orxout(user_warning) << "Trying to set position of an unknown object" << std::endl;
196            return;
197        }
198
199        const Vector3 &old = entity->getPosition();
200
201        // If one of the values is NaN, don't change that value
202        x = std::isnan(x) ? old.x : x;
203        y = std::isnan(y) ? old.y : y;
204        z = std::isnan(z) ? old.z : z;
205
206        entity->setPosition(x, y, z);
207    }
208
209    void ScriptableControllerAPI::setOrientation(std::string id, double x, double y, double z, double angle)
210    {
211        WorldEntity *entity = this->controller_->getWorldEntityByID(id);
212        if(entity == nullptr)
213        {
214            orxout(user_warning) << "Trying to set orientation of an unknown object" << std::endl;
215            return;
216        }
217
218        Vector3 old_axis;
219        Degree old_angle;
220
221        entity->getOrientation().ToAngleAxis(old_angle, old_axis);
222
223        // If one of the values is NaN, don't change that value
224        x = std::isnan(x) ? old_axis.x : x;
225        y = std::isnan(y) ? old_axis.y : y;
226        z = std::isnan(z) ? old_axis.z : z;
227        angle = std::isnan(x) ? old_angle.valueDegrees() : angle;
228
229
230        entity->setOrientation(Vector3(x, y, z), Degree(angle));
231    }
232
233    void ScriptableControllerAPI::setVelocity(std::string id, double x, double y, double z)
234    {
235        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
236        if(entity == nullptr)
237        {
238            orxout(user_warning) << "Trying to set velocity of an unknown object" << std::endl;
239            return;
240        }
241
242        const Vector3 &old = entity->getVelocity();
243
244        // If one of the values is NaN, don't change that value
245        x = std::isnan(x) ? old.x : x;
246        y = std::isnan(y) ? old.y : y;
247        z = std::isnan(z) ? old.z : z;
248
249        entity->setVelocity(x, y, z);
250    }
251
252    void ScriptableControllerAPI::setAngularVelocity(std::string id, double x, double y, double z)
253    {
254        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
255        if(entity == nullptr)
256        {
257            orxout(user_warning) << "Trying to set angular velocity of an unknown object" << std::endl;
258            return;
259        }
260
261        const Vector3 &old = entity->getAngularVelocity();
262
263        // If one of the values is NaN, don't change that value
264        x = std::isnan(x) ? old.x : x;
265        y = std::isnan(y) ? old.y : y;
266        z = std::isnan(z) ? old.z : z;
267
268        entity->setAngularVelocity(x, y, z);
269    }
270
271    void ScriptableControllerAPI::pawnKilled(std::string id, Pawn *pawn)
272    {
273        for(auto callback : this->pawnDestroyedHandlers_[id])
274            callback(id);
275
276        this->pawnDestroyedHandlers_.erase(id);
277
278        // We need to delete those handlers as well, they're no longer valid
279        auto near_obj_handler = this->nearObjectHandlers_.begin();
280        while(near_obj_handler != this->nearObjectHandlers_.end())
281        {
282            if(near_obj_handler->entity1_ == pawn || near_obj_handler->entity2_ == pawn)
283                near_obj_handler = this->nearObjectHandlers_.erase(near_obj_handler);
284            else
285                near_obj_handler++;
286        }
287
288        auto near_point_handler = this->nearPointHandlers_.begin();
289        while(near_point_handler != this->nearPointHandlers_.end())
290        {
291            if(near_point_handler->entity_ == pawn)
292                near_point_handler = this->nearPointHandlers_.erase(near_point_handler);
293            else
294                near_point_handler++;
295        }
296
297        auto area_handler = this->areaHandlers_.begin();
298        while(area_handler != this->areaHandlers_.end())
299        {
300            if(area_handler->entity_ == pawn)
301                area_handler = this->areaHandlers_.erase(area_handler);
302            else
303                area_handler++;
304        }
305    }
306
307    void ScriptableControllerAPI::pawnHit(std::string target_id, std::string source_id, double new_health, double new_shield)
308    {
309        for(auto callback : this->pawnHitHandlers_[target_id])
310            callback(target_id, source_id, new_health, new_shield);
311    }
312
313    void ScriptableControllerAPI::periodic()
314    {
315        // Near object
316        auto near_obj_handler = this->nearObjectHandlers_.begin();
317        while(near_obj_handler != this->nearObjectHandlers_.end())
318        {
319            if((near_obj_handler->entity1_->getPosition() - near_obj_handler->entity2_->getPosition()).length() < near_obj_handler->distance_)
320            {
321                near_obj_handler->callback_(near_obj_handler->id1_, near_obj_handler->id2_);
322                near_obj_handler = this->nearObjectHandlers_.erase(near_obj_handler);
323            }
324            else
325            {
326                near_obj_handler++;
327            }
328        }
329
330        // Near point
331        auto near_point_handler = this->nearPointHandlers_.begin();
332        while(near_point_handler != this->nearPointHandlers_.end())
333        {
334            if((near_point_handler->entity_->getPosition() - near_point_handler->point_).length() < near_point_handler->distance_)
335            {
336                near_point_handler->callback_(near_point_handler->id_);
337                near_point_handler = this->nearPointHandlers_.erase(near_point_handler);
338            }
339            else
340            {
341                near_point_handler++;
342            }
343        }
344
345        // Areas
346        auto area_handler = this->areaHandlers_.begin();
347        while(area_handler != this->areaHandlers_.end())
348        {
349            if(area_handler->entity_->getPosition() > area_handler->start_point_ &&
350               area_handler->entity_->getPosition() < area_handler->end_point_)
351            {
352                if(area_handler->atEnter_)
353                {
354                    area_handler->callback_(area_handler->id_);
355                    area_handler = this->areaHandlers_.erase(area_handler);
356                }
357                else
358                {
359                    area_handler++;
360                }
361            }
362            else
363            {
364                if(!area_handler->atEnter_)
365                {
366                    area_handler->callback_(area_handler->id_);
367                    area_handler = this->areaHandlers_.erase(area_handler);
368                }
369                else
370                {
371                    area_handler++;
372                }
373            }
374        }
375
376    }
377
378
379    //// TESTTESTTESTTESTTESTTEST
380    double ScriptableControllerAPI::myTestFunction(double x, double y)
381    {
382        double z = x + y;
383        orxout(user_info) << "Result = " << z << endl;
384        return z;
385    }
386
387
388
389
390
391    void ScriptableControllerAPI::moveControllableEntity(std::string id, double x, double y, double z)
392    {
393        MobileEntity *entity = this->controller_->getMobileEntityByID(id);
394        if(entity == nullptr)
395        {
396            orxout(user_warning) << "Trying to move an unknown object" << std::endl;
397            return;
398        }
399
400
401        Identifier *identifier = ClassByString("ControllableEntity");
402       
403        ControllableEntity *controllable_entity;
404       
405
406        if(identifier->isA(ClassIdentifier<ControllableEntity>::getIdentifier()))
407        {
408            controllable_entity = orxonox_cast<ControllableEntity*>(entity);
409            //ATTACHED COLLISION SHAPE is MANDATORY in order to move the entity
410            controllable_entity->moveFrontBack(x);
411            controllable_entity->moveRightLeft(y);
412            controllable_entity->moveUpDown(z);
413        }
414
415        return;
416       
417    }
418}
Note: See TracBrowser for help on using the repository browser.