Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.cc @ 11854

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

scriptablecontroller testlevel fixed

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