1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2014-2015  SuperTuxKart Team
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #include "script_track.hpp"
20 
21 #include "animations/three_d_animation.hpp"
22 #include "font/digit_face.hpp"
23 #include "font/font_manager.hpp"
24 #include "graphics/central_settings.hpp"
25 #include "graphics/irr_driver.hpp"
26 #include "graphics/stk_text_billboard.hpp"
27 #include "guiengine/scalable_font.hpp"
28 #include "input/device_manager.hpp"
29 #include "input/input_device.hpp"
30 #include "input/input_manager.hpp"
31 #include "items/item_manager.hpp"
32 #include "modes/world.hpp"
33 #include "scriptengine/property_animator.hpp"
34 #include "scriptengine/aswrappedcall.hpp"
35 #include "scriptengine/scriptarray.hpp"
36 #include "states_screens/dialogs/tutorial_message_dialog.hpp"
37 #include "states_screens/dialogs/race_paused_dialog.hpp"
38 #include "tracks/track.hpp"
39 #include "tracks/track_object.hpp"
40 #include "tracks/track_object_manager.hpp"
41 #include "utils/string_utils.hpp"
42 
43 #include <IBillboardTextSceneNode.h>
44 #include <angelscript.h>
45 #include <assert.h>
46 #include <ISceneManager.h>
47 
48 /** \cond DOXYGEN_IGNORE */
49 namespace Scripting
50 {
51     /** \endcond */
52     namespace Track
53     {
54         /** \addtogroup Scripting
55         * @{
56         */
57         /** \addtogroup Scripting_Track Track
58         * @{
59         */
60 
61         /*
62         void disableAnimation(std::string *name, void *memory)
63         {
64         std::string *str = name;
65         std::string type = "mesh";
66         World::getWorld()->getTrack()->getTrackObjectManager()->disable(*str, type);
67         }*/
68 
69         /**
70           * Get a track object by ID.
71           * @return An object of type @ref Scripting_TrackObject
72           */
getTrackObject(std::string * libraryInstance,std::string * objID)73         ::TrackObject* getTrackObject(std::string* libraryInstance, std::string* objID)
74         {
75             return ::Track::getCurrentTrack()->getTrackObjectManager()
76                           ->getTrackObject(*libraryInstance, *objID);
77         }
78 
getTrackObjectList()79         CScriptArray* getTrackObjectList()
80         {
81             std::vector<TrackObject*>& tl = ::Track::getCurrentTrack()
82                 ->getTrackObjectManager()->getObjects().m_contents_vector;
83             asIScriptContext* ctx = asGetActiveContext();
84             asIScriptEngine* engine = ctx->GetEngine();
85             asITypeInfo* t = engine->GetTypeInfoByDecl("array<Track::TrackObject@>");
86             CScriptArray* script_array = CScriptArray::Create(t, tl.size());
87             for (unsigned int i = 0; i < tl.size(); ++i)
88                 script_array->SetValue(i, &tl[i]);
89 
90             return script_array;
91         }
92 
93         /** Creates a trigger at the specified location */
createTrigger(std::string * triggerID,SimpleVec3 * creation_loc,float distance)94         void createTrigger(std::string* triggerID, SimpleVec3* creation_loc, float distance)
95         {
96             float x = creation_loc->getX();
97             float y = creation_loc->getY();
98             float z = creation_loc->getZ();
99             core::vector3df posi(x, y, z);
100             core::vector3df hpr(0, 0, 0);
101             core::vector3df scale(1.0f, 1.0f, 1.0f);
102             TrackObjectPresentationActionTrigger* newtrigger =
103                 new TrackObjectPresentationActionTrigger(posi, *triggerID, distance);
104             ::TrackObject* tobj = new ::TrackObject(posi, hpr, scale,
105                 "none", newtrigger, false /* isDynamic */, NULL /* physics settings */);
106             tobj->setID(*triggerID);
107             ::Track::getCurrentTrack()->getTrackObjectManager()->insertObject(tobj);
108         }
109 
createTextBillboard(std::string * text,SimpleVec3 * location)110         void createTextBillboard(std::string* text, SimpleVec3* location)
111         {
112             core::stringw wtext = StringUtils::utf8ToWide(*text);
113             DigitFace* digit_face = font_manager->getFont<DigitFace>();
114             core::vector3df xyz(location->getX(), location->getY(), location->getZ());
115 #ifndef SERVER_ONLY
116             STKTextBillboard* tb = new STKTextBillboard(
117                 GUIEngine::getSkin()->getColor("font::bottom"),
118                 GUIEngine::getSkin()->getColor("font::top"),
119                 irr_driver->getSceneManager()->getRootSceneNode(),
120                 irr_driver->getSceneManager(), -1, xyz,
121                 core::vector3df(1.5f, 1.5f, 1.5f));
122             if (CVS->isGLSL())
123                 tb->init(wtext.c_str(), digit_face);
124             else
125                 tb->initLegacy(wtext.c_str(), digit_face);
126             ::Track::getCurrentTrack()->addNode(tb);
127             tb->drop();
128 #endif
129         }
130 
131         /** Function for re-enable a trigger after a specific timeout*/
setTriggerReenableTimeout(std::string * triggerID,std::string * lib_id,float reenable_time)132         void setTriggerReenableTimeout(std::string* triggerID, std::string* lib_id,
133                                        float reenable_time)
134         {
135             ::TrackObject* tobj = ::Track::getCurrentTrack()->getTrackObjectManager()
136                 ->getTrackObject(*lib_id, *triggerID);
137             if (tobj != NULL)
138             {
139                 TrackObjectPresentationActionTrigger* topat =
140                     tobj->getPresentation<TrackObjectPresentationActionTrigger>();
141                 if (topat != NULL)
142                 {
143                     topat->setReenableTimeout(reenable_time);
144                 }
145             }
146         }
147 
148         /** Exits the race to the main menu */
exitRace()149         void exitRace()
150         {
151             World::getWorld()->scheduleExitRace();
152         }
153 
pauseRace()154         void pauseRace()
155         {
156             new RacePausedDialog(0.8f, 0.6f);
157         }
158 
getNumberOfKarts()159         int getNumberOfKarts()
160         {
161             return RaceManager::get()->getNumberOfKarts();
162         }
163 
getNumLocalPlayers()164         int getNumLocalPlayers()
165         {
166             return RaceManager::get()->getNumLocalPlayers();
167         }
168 
169         /**
170           * Gets the kart type, such as local player, networked player, AI, etc.
171           * @return A KartType enum as defined in race_manager.hpp, implicitly casted to an int
172           */
getKartType(int kartId)173         int getKartType(int kartId)
174         {
175             return RaceManager::get()->getKartType(kartId);
176         }
177 
isTrackReverse()178         bool isTrackReverse()
179         {
180             return RaceManager::get()->getReverseTrack();
181         }
182 
183         /**
184           * Gets the difficulty setting for this race.
185           * @return A Difficulty enum as defined in race_manager.hpp, implicitly casted to an int
186           */
getDifficulty()187         int getDifficulty()
188         {
189             return RaceManager::get()->getDifficulty();
190         }
191 
getMajorRaceMode()192         int getMajorRaceMode()
193         {
194             return RaceManager::get()->getMajorMode();
195         }
196 
getMinorRaceMode()197         int getMinorRaceMode()
198         {
199             return RaceManager::get()->getMinorMode();
200         }
201 
isDuringDay()202         bool isDuringDay()
203         {
204             return ::Track::getCurrentTrack()->getIsDuringDay();
205         }
206 
getItemManagerRandomSeed()207         uint32_t getItemManagerRandomSeed()
208         {
209             return ItemManager::getRandomSeed();
210         }
211 
setFog(float maxDensity,float start,float end,int r,int g,int b,float duration)212         void setFog(float maxDensity, float start, float end, int r, int g, int b, float duration)
213         {
214             PropertyAnimator* animator = PropertyAnimator::get();
215             ::Track* track = ::Track::getCurrentTrack();
216             animator->add(
217                 new AnimatedProperty(FOG_MAX, 1,
218                     new double[1] { track->getFogMax() },
219                     new double[1] { maxDensity }, duration, track)
220             );
221             animator->add(
222                 new AnimatedProperty(FOG_RANGE, 2,
223                     new double[2] { track->getFogStart(), track->getFogEnd() },
224                     new double[2] { start, end }, duration, track)
225             );
226 
227             video::SColor color = track->getFogColor();
228             animator->add(
229                 new AnimatedProperty(FOG_COLOR, 3,
230                     new double[3] {
231                         (double)color.getRed(),
232                         (double)color.getGreen(),
233                         (double)color.getBlue()
234                     },
235                     new double[3] {
236                         (double)r,
237                         (double)g,
238                         (double)b
239                     },
240                     duration, track)
241             );
242         }
243     }
244 
245     /** \cond DOXYGEN_IGNORE */
246     namespace Track
247     {
248     /** \endcond */
249 
250         namespace TrackObject
251         {
getCenterPosition(::TrackObject * obj)252             SimpleVec3 getCenterPosition(::TrackObject* obj)
253             {
254                 core::vector3df pos = obj->getAbsoluteCenterPosition();
255                 return SimpleVec3(pos.X, pos.Y, pos.Z);
256             }
257 
getOrigin(::TrackObject * obj)258             SimpleVec3 getOrigin(::TrackObject* obj)
259             {
260                 core::vector3df pos = obj->getAbsolutePosition();
261                 return SimpleVec3(pos.X, pos.Y, pos.Z);
262             }
263         }
264 
265         // ----------- TrackObjectPresentationMesh methods -----------
266         // TODO: this method is WRONG, we should in most cases move not the presentation but the entire object
267         //void movePresentation(Vec3 *new_pos, void *memory)
268         //{
269         //    core::vector3df xyz = new_pos->toIrrVector();
270         //    core::vector3df hpr = core::vector3df(0, 0, 0);
271         //    core::vector3df scale = core::vector3df(1, 1, 1);
272         //    ((TrackObjectPresentation*)(memory))->move(xyz, hpr, scale, false);
273         //}
274 
275         namespace Mesh
276         {
277             /**
278             * \addtogroup Scripting_Mesh Mesh (script binding)
279             * Type returned by trackObject.getMesh()
280             * @{
281             */
282 
283             /** Sets a loop for a skeletal animation */
284             // TODO: can we use a type and avoid void* ?
setFrameLoop(int start,int end,void * memory)285             void setFrameLoop(int start, int end /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
286             {
287                 if (memory)
288                 {
289                     ((scene::IAnimatedMeshSceneNode*)(memory))->setFrameLoop(start, end);
290                 }
291             }
292 
293             /** Sets a loop once for a skeletal animation */
setFrameLoopOnce(int start,int end,void * memory)294             void setFrameLoopOnce(int start, int end /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
295             {
296                 if (memory)
297                 {
298                     ((scene::IAnimatedMeshSceneNode*)(memory))->setFrameLoopOnce(start, end);
299                 }
300             }
301 
302             /** Get current frame in a skeletal animation */
getFrameNr(void * memory)303             int getFrameNr(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
304             {
305                 if (memory)
306                 {
307                     return (int)((scene::IAnimatedMeshSceneNode*)(memory))->getFrameNr();
308                 }
309                 return -1;
310             }
311 
312             /** Gets the animation set id for a skeletal animation */
getAnimationSet(void * memory)313             int getAnimationSet(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
314             {
315                 if (memory)
316                 {
317                     return ((scene::IAnimatedMeshSceneNode*)(memory))->getAnimationSet();
318                 }
319                 return -1;
320             }
321 
322             /** Gets the animation set frames for a skeletal animation */
getAnimationSetFrames(void * memory)323             CScriptArray* getAnimationSetFrames(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
324             {
325                 asIScriptContext* ctx = asGetActiveContext();
326                 asIScriptEngine* engine = ctx->GetEngine();
327                 asITypeInfo* t = engine->GetTypeInfoByDecl("array<uint>");
328                 if (memory)
329                 {
330                     scene::IAnimatedMeshSceneNode* node =
331                         ((scene::IAnimatedMeshSceneNode*)(memory));
332                     core::array<u32>& f = node->getAnimationSetFrames();
333                     CScriptArray* script_array = CScriptArray::Create(t, f.size());
334                     for (unsigned int i = 0; i < f.size(); ++i)
335                         script_array->SetValue(i, &f[i]);
336 
337                     return script_array;
338                 }
339                 return CScriptArray::Create(t, (unsigned)0);
340             }
341             /** Gets the animation set count for a skeletal animation */
getAnimationSetNum(void * memory)342             int getAnimationSetNum(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
343             {
344                 if (memory)
345                 {
346                     return ((scene::IAnimatedMeshSceneNode*)(memory))->getAnimationSetNum();
347                 }
348                 return -1;
349             }
350 
351             /** Remove all animation set for a skeletal animation */
removeAllAnimationSet(void * memory)352             void removeAllAnimationSet(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
353             {
354                 if (memory)
355                 {
356                     ((scene::IAnimatedMeshSceneNode*)(memory))->removeAllAnimationSet();
357                 }
358             }
359 
360             /** Add an animation set for a skeletal animation */
addAnimationSet(int start,int end,void * memory)361             void addAnimationSet(int start/** \cond DOXYGEN_IGNORE */, int end/** \cond DOXYGEN_IGNORE */, /** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
362             {
363                 if (memory)
364                 {
365                     ((scene::IAnimatedMeshSceneNode*)(memory))->addAnimationSet(start, end);
366                 }
367             }
368 
369             /** use an current frame for a skeletal animation */
useAnimationSet(int set_num,void * memory)370             void useAnimationSet(int set_num /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
371             {
372                 if (memory)
373                 {
374                     ((scene::IAnimatedMeshSceneNode*)(memory))->useAnimationSet(set_num);
375                 }
376             }
377 
378             /** Sets the current frame for a skeletal animation */
setCurrentFrame(int frame,void * memory)379             void setCurrentFrame(int frame /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
380             {
381                 if (memory)
382                 {
383                     ((scene::IAnimatedMeshSceneNode*)(memory))->setCurrentFrame((float)frame);
384                 }
385             }
386 
387             /** @} */
388         }
389 
390         // ----------- Animator Object methods -----------
391 
392         namespace Animator
393         {
394             /**
395             * \addtogroup Scripting_Animator Animator (script binding)
396             * Type returned by trackObject.getIPOAnimator()
397             * @{
398             */
399 
400             /** Pause/resumes a curve-based animation */
setPaused(bool mode,void * memory)401             void setPaused(bool mode /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
402             {
403                 ((ThreeDAnimation*)(memory))->setPaused(mode);
404             }
405 
406             /** @} */
407         }
408 
409         // ----------- Light Object methods -----------
410 
411         namespace Light
412         {
413             /**
414             * @addtogroup Scripting_Light Light (script binding)
415             * Type returned by trackObject.getLight()
416             * @{
417             */
418 
setEnergy(float energy,void * memory)419             void setEnergy(float energy, /** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
420             {
421                 ((TrackObjectPresentationLight*)memory)->setEnergy(energy);
422             }
423 
animateEnergy(float energy,float duration,void * memory)424             void animateEnergy(float energy, float duration, /** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
425             {
426                 TrackObjectPresentationLight* light = ((TrackObjectPresentationLight*)memory);
427                 PropertyAnimator::get()->add(
428                     new AnimatedProperty(AP_LIGHT_ENERGY, 1,
429                     new double[1] { light->getEnergy() },
430                     new double[1] { energy }, duration, light)
431                 );
432             }
433 
434             /** @} */
435         }
436 
437 
438         // ----------- Sound Object methods -----------
439 
440         namespace SoundEmitter
441         {
442             /**
443             * @addtogroup Scripting_SoundEmitter SoundEmitter (script binding)
444             * Type returned by trackObject.getSoundEmitter()
445             * @{
446             */
447 
448             // TODO: adjust all signatures to type "void*" parameters if possible
449             /** Stop a sound */
stop(void * memory)450             void stop(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
451             {
452                 ((TrackObjectPresentationSound*)memory)->stopSound();
453             }
454 
455             /** Play the specified sound once */
playOnce(void * memory)456             void playOnce(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
457             {
458                 ((TrackObjectPresentationSound*)memory)->triggerSound(false); //false = once
459             }
460 
461             /** Play the specified sound continuously */
playLoop(void * memory)462             void playLoop(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
463             {
464                 ((TrackObjectPresentationSound*)memory)->triggerSound(true); //true = loop
465             }
466             /** @} */
467         }
468 
469         // ----------- ParticleEmitter Object methods -----------
470 
471         namespace ParticleEmitter
472         {
473             /**
474             * @addtogroup Scripting_ParticleEmitter ParticleEmitter (script binding)
475             * Type returned by trackObject.getParticleEmitter()
476             * @{
477             */
478 
479             /** Stop particle emission */
stop(void * memory)480             void stop(/** \cond DOXYGEN_IGNORE */ void *memory /** \endcond */)
481             {
482                 ((TrackObjectPresentationParticles*)memory)->stop();
483             }
484 
485             /** Stop particle emission */
stopIn(float delay,void * memory)486             void stopIn(float delay, /** \cond DOXYGEN_IGNORE */ void *memory /** \endcond */)
487             {
488                 ((TrackObjectPresentationParticles*)memory)->stopIn(delay);
489             }
490 
491             /** Play the specified sound once */
setEmissionRate(float rate,void * memory)492             void setEmissionRate(float rate /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
493             {
494                 ((TrackObjectPresentationParticles*)memory)->setRate(rate);
495             }
496             /** @} */
497         }
498 
499         /** @}*/
500         /** @}*/
501 
registerScriptFunctions(asIScriptEngine * engine)502         void registerScriptFunctions(asIScriptEngine *engine)
503         {
504             engine->SetDefaultNamespace("Track");
505 
506             bool mp = strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY");
507             asDWORD call_conv = mp ? asCALL_GENERIC : asCALL_CDECL;
508             asDWORD call_conv_objlast = mp ? asCALL_GENERIC : asCALL_CDECL_OBJLAST;
509             asDWORD call_conv_thiscall = mp ? asCALL_GENERIC : asCALL_THISCALL;
510             int r; // of type asERetCodes
511 
512             r = engine->RegisterObjectType("TrackObject", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0);
513             r = engine->RegisterObjectType("PhysicalObject", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0);
514             r = engine->RegisterObjectType("Mesh", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0); // TrackObjectPresentationMesh
515             r = engine->RegisterObjectType("ParticleEmitter", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0);
516             r = engine->RegisterObjectType("SoundEmitter", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0);
517             r = engine->RegisterObjectType("Animator", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0);
518             r = engine->RegisterObjectType("Light", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0);
519 
520             //r = engine->RegisterGlobalFunction("void disableTrackObject(const string &in)",
521             //                                   mp ? WRAP_FN(disableTrackObject) : asFUNCTION(disableTrackObject),
522             //                                   call_conv); assert(r >= 0);
523 
524             //r = engine->RegisterGlobalFunction("void enableTrackObject(const string &in)",
525             //                                   mp ? WRAP_FN(enableTrackObject) : asFUNCTION(enableTrackObject),
526             //                                   call_conv); assert(r >= 0);
527 
528             //r = engine->RegisterGlobalFunction("void enableTrigger(const string &in)",
529             //                                   mp ? WRAP_FN(enableTrigger) : asFUNCTION(enableTrigger),
530             //                                   call_conv); assert(r >= 0);
531 
532             //r = engine->RegisterGlobalFunction("void disableTrigger(const string &in)",
533             //                                   mp ? WRAP_FN(disableTrigger) : asFUNCTION(disableTrigger),
534             //                                   call_conv); assert(r >= 0);
535 
536             r = engine->RegisterGlobalFunction("void createTrigger(const string &in, const Vec3 &in, float distance)",
537                                                mp ? WRAP_FN(createTrigger) : asFUNCTION(createTrigger),
538                                                call_conv); assert(r >= 0);
539 
540             r = engine->RegisterGlobalFunction("void createTextBillboard(const string &in, const Vec3 &in)",
541                                                mp ? WRAP_FN(createTextBillboard) : asFUNCTION(createTextBillboard),
542                                                call_conv); assert(r >= 0);
543 
544             r = engine->RegisterGlobalFunction("void setTriggerReenableTimeout(const string &in, const string &in, float reenable_time)",
545                                                mp ? WRAP_FN(setTriggerReenableTimeout) : asFUNCTION(setTriggerReenableTimeout),
546                                                call_conv); assert(r >= 0);
547 
548             r = engine->RegisterGlobalFunction("TrackObject@ getTrackObject(const string &in, const string &in)",
549                                                mp ? WRAP_FN(getTrackObject) : asFUNCTION(getTrackObject),
550                                                call_conv); assert(r >= 0);
551 
552             r = engine->RegisterGlobalFunction("array<TrackObject@>@ getTrackObjectList()",
553                                                mp ? WRAP_FN(getTrackObjectList) : asFUNCTION(getTrackObjectList),
554                                                call_conv); assert(r >= 0);
555 
556             r = engine->RegisterGlobalFunction("void exitRace()",
557                                                mp ? WRAP_FN(exitRace) : asFUNCTION(exitRace),
558                                                call_conv); assert(r >= 0);
559 
560             r = engine->RegisterGlobalFunction("void pauseRace()",
561                                                mp ? WRAP_FN(pauseRace) : asFUNCTION(pauseRace),
562                                                call_conv); assert(r >= 0);
563 
564             r = engine->RegisterGlobalFunction("void setFog(float maxDensity, float start, float end, int r, int g, int b, float duration)",
565                                                mp ? WRAP_FN(setFog) : asFUNCTION(setFog),
566                                                call_conv); assert(r >= 0);
567 
568             r = engine->RegisterGlobalFunction("int getNumberOfKarts()",
569                                                mp ? WRAP_FN(getNumberOfKarts) : asFUNCTION(getNumberOfKarts),
570                                                call_conv); assert(r >= 0);
571 
572             r = engine->RegisterGlobalFunction("int getNumLocalPlayers()",
573                                                mp ? WRAP_FN(getNumLocalPlayers) : asFUNCTION(getNumLocalPlayers),
574                                                call_conv); assert(r >= 0);
575 
576             r = engine->RegisterGlobalFunction("int getKartType(int kartId)",
577                                                mp ? WRAP_FN(getKartType) : asFUNCTION(getKartType),
578                                                call_conv); assert(r >= 0);
579 
580             r = engine->RegisterGlobalFunction("bool isReverse()",
581                                                mp ? WRAP_FN(isTrackReverse) : asFUNCTION(isTrackReverse),
582                                                call_conv); assert(r >= 0);
583 
584             r = engine->RegisterGlobalFunction("int getDifficulty()",
585                                                mp ? WRAP_FN(getDifficulty) : asFUNCTION(getDifficulty),
586                                                call_conv); assert(r >= 0);
587 
588             r = engine->RegisterGlobalFunction("int getMajorRaceMode()",
589                                                mp ? WRAP_FN(getMajorRaceMode) : asFUNCTION(getMajorRaceMode),
590                                                call_conv); assert(r >= 0);
591 
592             r = engine->RegisterGlobalFunction("uint getItemManagerRandomSeed()",
593                                                mp ? WRAP_FN(getItemManagerRandomSeed) : asFUNCTION(getItemManagerRandomSeed),
594                                                call_conv); assert(r >= 0);
595 
596             r = engine->RegisterGlobalFunction("int getMinorRaceMode()",
597                                                mp ? WRAP_FN(getMinorRaceMode) : asFUNCTION(getMinorRaceMode),
598                                                call_conv); assert(r >= 0);
599 
600             r = engine->RegisterGlobalFunction("bool isDuringDay()",
601                                                mp ? WRAP_FN(isDuringDay) : asFUNCTION(isDuringDay),
602                                                call_conv); assert(r >= 0);
603 
604             // TrackObject
605             r = engine->RegisterObjectMethod("TrackObject", "void setEnabled(bool status)",
606                                              mp ? WRAP_MFN(::TrackObject, setEnabled) : asMETHOD(::TrackObject, setEnabled),
607                                              call_conv_thiscall); assert(r >= 0);
608 
609             r = engine->RegisterObjectMethod("TrackObject", "SoundEmitter@ getSoundEmitter()",
610                                              mp ? WRAP_MFN(::TrackObject, getSoundEmitter) : asMETHOD(::TrackObject, getSoundEmitter),
611                                              call_conv_thiscall); assert(r >= 0);
612 
613             r = engine->RegisterObjectMethod("TrackObject", "Light@ getLight()",
614                                              mp ? WRAP_MFN(::TrackObject, getLight) : asMETHOD(::TrackObject, getLight),
615                                              call_conv_thiscall); assert(r >= 0);
616 
617             r = engine->RegisterObjectMethod("TrackObject", "PhysicalObject@ getPhysics()",
618                                              mp ? WRAP_MFN(::TrackObject, getPhysics): asMETHOD(::TrackObject, getPhysics),
619                                              call_conv_thiscall); assert(r >= 0);
620 
621             r = engine->RegisterObjectMethod("TrackObject", "Mesh@ getMesh()",
622                                              mp ? WRAP_MFN(::TrackObject, getMesh) : asMETHOD(::TrackObject, getMesh),
623                                              call_conv_thiscall); assert(r >= 0);
624 
625             r = engine->RegisterObjectMethod("TrackObject", "ParticleEmitter@ getParticleEmitter()",
626                                              mp ? WRAP_MFN(::TrackObject, getParticleEmitter) : asMETHOD(::TrackObject, getParticleEmitter),
627                                              call_conv_thiscall); assert(r >= 0);
628 
629             r = engine->RegisterObjectMethod("TrackObject", "Animator@ getIPOAnimator()",
630                                              mp ? WRAP_MFN(::TrackObject, getIPOAnimator): asMETHOD(::TrackObject, getIPOAnimator),
631                                              call_conv_thiscall); assert(r >= 0);
632 
633             r = engine->RegisterObjectMethod("TrackObject", "void moveTo(const Vec3 &in, bool)",
634                                              mp ? WRAP_MFN(::TrackObject, moveTo) : asMETHOD(::TrackObject, moveTo),
635                                              call_conv_thiscall); assert(r >= 0);
636 
637             r = engine->RegisterObjectMethod("TrackObject", "void reset()",
638                                              mp ? WRAP_MFN(::TrackObject, reset) : asMETHOD(::TrackObject, reset),
639                                              call_conv_thiscall); assert(r >= 0);
640 
641             r = engine->RegisterObjectMethod("TrackObject", "Vec3 getCenterPosition()",
642                                              mp ? WRAP_OBJ_LAST(TrackObject::getCenterPosition): asFUNCTION(TrackObject::getCenterPosition),
643                                              call_conv_objlast); assert(r >= 0);
644 
645             r = engine->RegisterObjectMethod("TrackObject", "Vec3 getOrigin()",
646                                              mp ? WRAP_OBJ_LAST(TrackObject::getOrigin) : asFUNCTION(TrackObject::getOrigin),
647                                              call_conv_objlast); assert(r >= 0);
648 
649             r = engine->RegisterObjectMethod("TrackObject", "TrackObject@ getParentLibrary()",
650                                              mp ? WRAP_MFN(::TrackObject, getParentLibrary): asMETHOD(::TrackObject, getParentLibrary),
651                                              call_conv_thiscall); assert(r >= 0);
652 
653             r = engine->RegisterObjectMethod("TrackObject", "string getName()",
654                                              mp ? WRAP_MFN(::TrackObject, getName) : asMETHOD(::TrackObject, getName),
655                                              call_conv_thiscall); assert(r >= 0);
656 
657             r = engine->RegisterObjectMethod("TrackObject", "string getID()",
658                                              mp ? WRAP_MFN(::TrackObject, getID) : asMETHOD(::TrackObject, getID),
659                                              call_conv_thiscall); assert(r >= 0);
660 
661             // PhysicalObject
662             r = engine->RegisterObjectMethod("PhysicalObject", "bool isFlattenKartObject()",
663                                              mp ? WRAP_MFN(PhysicalObject, isFlattenKartObject) : asMETHOD(PhysicalObject,
664                                              isFlattenKartObject), call_conv_thiscall); assert(r >= 0);
665 
666             r = engine->RegisterObjectMethod("PhysicalObject", "void disable()",
667                                              mp ? WRAP_MFN(PhysicalObject, disable) : asMETHOD(PhysicalObject, disable),
668                                              call_conv_thiscall); assert(r >= 0);
669 
670             r = engine->RegisterObjectMethod("PhysicalObject", "void enable()",
671                                              mp ? WRAP_MFN(PhysicalObject, enable) : asMETHOD(PhysicalObject, enable),
672                                              call_conv_thiscall); assert(r >= 0);
673 
674             // Animated Mesh
675             r = engine->RegisterObjectMethod("Mesh", "void setFrameLoop(int start, int end)",
676                                              mp ? WRAP_OBJ_LAST(Mesh::setFrameLoop) : asFUNCTION(Mesh::setFrameLoop),
677                                              call_conv_objlast); assert(r >= 0);
678 
679             r = engine->RegisterObjectMethod("Mesh", "void setFrameLoopOnce(int start, int end)",
680                                              mp ? WRAP_OBJ_LAST(Mesh::setFrameLoopOnce) : asFUNCTION(Mesh::setFrameLoopOnce),
681                                              call_conv_objlast); assert(r >= 0);
682 
683             r = engine->RegisterObjectMethod("Mesh", "int getFrameNr()",
684                                              mp ? WRAP_OBJ_LAST(Mesh::getFrameNr) : asFUNCTION(Mesh::getFrameNr),
685                                              call_conv_objlast); assert(r >= 0);
686 
687             r = engine->RegisterObjectMethod("Mesh", "int getAnimationSet()",
688                                              mp ? WRAP_OBJ_LAST(Mesh::getAnimationSet) : asFUNCTION(Mesh::getAnimationSet),
689                                              call_conv_objlast); assert(r >= 0);
690 
691             r = engine->RegisterObjectMethod("Mesh", "array<uint>@ getAnimationSetFrames()",
692                                              mp ? WRAP_OBJ_LAST(Mesh::getAnimationSetFrames) : asFUNCTION(Mesh::getAnimationSetFrames),
693                                              call_conv_objlast); assert(r >= 0);
694 
695             r = engine->RegisterObjectMethod("Mesh", "int getAnimationSetNum()",
696                                              mp ? WRAP_OBJ_LAST(Mesh::getAnimationSetNum) : asFUNCTION(Mesh::getAnimationSetNum),
697                                              call_conv_objlast); assert(r >= 0);
698 
699             r = engine->RegisterObjectMethod("Mesh", "void useAnimationSet(int set_num)",
700                                              mp ? WRAP_OBJ_LAST(Mesh::useAnimationSet) : asFUNCTION(Mesh::useAnimationSet),
701                                              call_conv_objlast); assert(r >= 0);
702 
703             r = engine->RegisterObjectMethod("Mesh", "void addAnimationSet(int start, int end)",
704                                              mp ? WRAP_OBJ_LAST(Mesh::addAnimationSet) : asFUNCTION(Mesh::addAnimationSet),
705                                              call_conv_objlast); assert(r >= 0);
706 
707             r = engine->RegisterObjectMethod("Mesh", "void removeAllAnimationSet()",
708                                              mp ? WRAP_OBJ_LAST(Mesh::removeAllAnimationSet) : asFUNCTION(Mesh::removeAllAnimationSet),
709                                              call_conv_objlast); assert(r >= 0);
710 
711             r = engine->RegisterObjectMethod("Mesh", "void setCurrentFrame(int frame)",
712                                              mp ? WRAP_OBJ_LAST(Mesh::setCurrentFrame) : asFUNCTION(Mesh::setCurrentFrame),
713                                              call_conv_objlast); assert(r >= 0);
714 
715             //r = engine->RegisterObjectMethod("Mesh", "void move(Vec3 &in)",
716             //                                 mp ? WRAP_OBJ_LAST(movePresentation) : asFUNCTION(movePresentation),
717             //                                 call_conv_objlast); assert(r >= 0);
718 
719             // Particle Emitter
720             r = engine->RegisterObjectMethod("ParticleEmitter", "void stop()",
721                                              mp ? WRAP_OBJ_LAST(ParticleEmitter::stop) : asFUNCTION(ParticleEmitter::stop),
722                                              call_conv_objlast); assert(r >= 0);
723 
724             r = engine->RegisterObjectMethod("ParticleEmitter", "void stopIn(float)",
725                                              mp ? WRAP_OBJ_LAST(ParticleEmitter::stopIn) : asFUNCTION(ParticleEmitter::stopIn),
726                                              call_conv_objlast); assert(r >= 0);
727 
728             r = engine->RegisterObjectMethod("ParticleEmitter", "void setEmissionRate(float)",
729                                              mp ? WRAP_OBJ_LAST(ParticleEmitter::setEmissionRate) : asFUNCTION(ParticleEmitter::setEmissionRate),
730                                              call_conv_objlast); assert(r >= 0);
731 
732             // Sound Effect
733             //r = engine->RegisterObjectMethod("SoundEmitter", "void move(Vec3 &in)",
734             //                                 mp ? WRAP_OBJ_LAST(movePresentation) : asFUNCTION(movePresentation),
735             //                                 call_conv_objlast); assert(r >= 0);
736 
737             r = engine->RegisterObjectMethod("SoundEmitter", "void stop()",
738                                              mp ? WRAP_OBJ_LAST(SoundEmitter::stop) : asFUNCTION(SoundEmitter::stop),
739                                              call_conv_objlast); assert(r >= 0);
740 
741             r = engine->RegisterObjectMethod("SoundEmitter", "void playOnce()",
742                                              mp ? WRAP_OBJ_LAST(SoundEmitter::playOnce) : asFUNCTION(SoundEmitter::playOnce),
743                                              call_conv_objlast); assert(r >= 0);
744 
745             r = engine->RegisterObjectMethod("SoundEmitter", "void playLoop()",
746                                              mp ? WRAP_OBJ_LAST(SoundEmitter::playLoop) : asFUNCTION(SoundEmitter::playLoop),
747                                              call_conv_objlast); assert(r >= 0);
748 
749             // Light
750             r = engine->RegisterObjectMethod("Light", "void setEnergy(float)",
751                                              mp ? WRAP_OBJ_LAST(Light::setEnergy) : asFUNCTION(Light::setEnergy),
752                                              call_conv_objlast); assert(r >= 0);
753 
754             r = engine->RegisterObjectMethod("Light", "void animateEnergy(float, float)",
755                                              mp ? WRAP_OBJ_LAST(Light::animateEnergy) : asFUNCTION(Light::animateEnergy),
756                                              call_conv_objlast); assert(r >= 0);
757 
758             // Curve based Animation
759             //fails due to insufficient visibility to scripts TODO : Decide whether to fix visibility or introduce wrappers
760             //r = engine->RegisterObjectMethod("Animator", "void setPaused(bool mode)",
761             //                                 mp ? WRAP_MFN(ThreeDAnimation, setPaused) : asMETHOD(ThreeDAnimation, setPaused),
762             //                                 call_conv_thiscall); assert(r >= 0);
763 
764             r = engine->RegisterObjectMethod("Animator", "void setPaused(bool mode)",
765                                              mp ? WRAP_OBJ_LAST(Animator::setPaused) : asFUNCTION(Animator::setPaused),
766                                              call_conv_objlast); assert(r >= 0);
767 
768             // TODO: add method to set current frame
769             // TODO: add method to launch playback from frame X to frame Y
770             // TODO: add method to register onAnimationComplete notifications ?
771         }
772 
773 /** \cond DOXYGEN_IGNORE */
774     }
775 }
776 /** \endcond */
777 
778