NLS Engine  v0.1
The Next Logical Step in game engine design.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines
ScriptModule.cpp
Go to the documentation of this file.
00001 
00012 #include "ScriptModule.h"
00013 
00014 // Standard Includes
00015 #include <cassert>
00016 
00017 // Library Includes
00018 #include <angelscript/scriptany/scriptany.h>
00019 #include <angelscript/scriptarray/scriptarray.h>
00020 #include <angelscript/scriptdictionary/scriptdictionary.h>
00021 #include <boost/lexical_cast.hpp>
00022 #include <angelscript/scriptstdstring/scriptstdstring.h>
00023 
00024 // Local Includes
00025 #include "../sharedbase/MessageRouter.h"
00026 #include "../sharedbase/PropertyMap.h"
00027 #include "../sharedbase/EntityList.h"
00028 #include "../sharedbase/OSInterface.h"
00029 #include "EntityFactory.h"
00030 #include "customtypes.h"
00031 #include "sptrtypes.h"
00032 
00033 // *HACK: This is indicating that we need to re-think how modules register their information with the script engine.
00034 #include "../GraphicsDLL/component/RenderableComponent.h"
00035 
00036 // Forward declares (functions in same order at bottom of file)
00037 void ScriptLog(const LOG_PRIORITY::TYPE&, const std::string&);
00038 void RegisterEventLogger(asIScriptEngine* const);
00039 
00040 // Static class member initialization
00041 
00042 // Class methods in the order they are defined within the class header
00043 
00044 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00045 CreateEntityFactory* CreateEntityFactoryFact( void ) {
00046   return new CreateEntityFactory();
00047 }
00048 
00049 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00050 unsigned long gRandomSeed = 0;
00051 
00052 void RandomSetSeed(unsigned long seed) {
00053   gRandomSeed = seed;
00054 }
00055 
00056 unsigned long RandomULong(unsigned long max_value) {
00057   // Simple linear congruential generator using the constants for Borland Delphi,
00058   // and Visual Pascal as given on http://en.wikipedia.org/w/index.php?title=Linear_congruential_generator&oldid=375235243
00059   // These contants were chosen semi-randomly; I simply ported this code over from a project of mine that required Delphi compatability. ~Ricky
00060   gRandomSeed = ((unsigned long long)gRandomSeed * 134775813ul + 1ul) & 0xFFFFFFFFul;
00061   return (unsigned long long) gRandomSeed * max_value / 0xFFFFFFFFul;
00062 }
00063 
00064 float RandomFloat(float max_value) {
00065   float value = float(RandomULong(0x7FFFFFFFul) | 0x00800000ul); // Never get so high it sets the sign bit, and prevent both Inf and NaN before conversion.
00066   
00067   return float( double(value) * max_value / float(0x7F7FFFFFul));
00068 }
00069 
00070 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00071 void SaveToDisk(const EnvelopeSPTR* envelopep, const std::string str) {
00072   EnvelopeSPTR env(*envelopep);
00073   SaveToDisk(env, str);
00074 }
00075 
00076 bool LoadFromDisk(const EnvelopeSPTR* envelopep, const std::string str) {
00077   EnvelopeSPTR env(*envelopep);
00078   return LoadFromDisk(env, str);
00079 }
00080 
00081 template<typename Target>
00082 Target stringCast(const std::string src) {
00083   try
00084   {
00085     return boost::lexical_cast<Target>(src);
00086   }
00087   catch(boost::bad_lexical_cast &)
00088   {
00089     return Target();
00090   }
00091 }
00092 
00093 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00094 ScriptModule::ScriptModule( PropertyMap* gprops, MessageRouter* msgrouter, EntityList* elist ) :
00095   ModuleInterface(gprops, msgrouter, elist),
00096   deltaAccumulator(0.0)
00097 {
00098   this->eventScriptManager.InitAngelScript();
00099   this->updateScriptManager.InitAngelScript();
00100   this->eventScriptManager.CreateModule("module1");
00101   
00102   int ret = 0;
00103   asIScriptEngine* engine = ScriptManager::GetEngine();
00104 
00105   // Custom types
00106   RegisterScriptAny(engine);
00107   RegisterScriptMath(engine);
00108   RegisterScriptArray(engine, true);
00109   RegisterStdString(engine); // Must be AFTER array registration
00110   RegisterStdStringUtils(engine);
00111   RegisterScriptDictionary(engine); // Must be AFTER string registration
00112   
00113   // Register random number system
00114   ret = engine->RegisterGlobalFunction("void RandomSetSeed(uint)", asFUNCTION(RandomSetSeed), asCALL_CDECL); assert(ret >= 0);
00115   ret = engine->RegisterGlobalFunction("uint RandomUInt(uint)", asFUNCTION(RandomULong), asCALL_CDECL); assert(ret >= 0);
00116   ret = engine->RegisterGlobalFunction("float RandomFloat(float)", asFUNCTION(RandomFloat), asCALL_CDECL); assert(ret >= 0);
00117 
00118   // Cast functions
00119   ret = engine->RegisterGlobalFunction("int stoi(string)", asFUNCTION(stringCast<int>), asCALL_CDECL); assert(ret >= 0);
00120   ret = engine->RegisterGlobalFunction("uint stou(string)", asFUNCTION(stringCast<unsigned int>), asCALL_CDECL); assert(ret >= 0);
00121   ret = engine->RegisterGlobalFunction("float stof(string)", asFUNCTION(stringCast<float>), asCALL_CDECL); assert(ret >= 0);
00122   ret = engine->RegisterGlobalFunction("double stod(string)", asFUNCTION(stringCast<double>), asCALL_CDECL); assert(ret >= 0);
00123   
00124   // Register object types
00125   ret = engine->RegisterObjectType("ScriptModule", 0, asOBJ_REF | asOBJ_NOHANDLE); assert(ret >= 0);
00126   ret = engine->RegisterObjectType("EntityList", 0, asOBJ_REF | asOBJ_NOHANDLE); assert(ret >= 0);
00127   ret = engine->RegisterObjectType("Envelope", 0, asOBJ_REF | asOBJ_NOHANDLE); assert(ret >= 0);
00128   ret = engine->RegisterObjectType("PropertyMap", 0, asOBJ_REF | asOBJ_NOHANDLE); assert(ret >= 0);
00129   ret = engine->RegisterObjectType("CreateEntityFactory", 0, asOBJ_REF); assert(ret >= 0);
00130 
00131   RegisterCustomScriptTypes(engine); // After the base type delcarations in case any custom types have them for member variables
00132   
00133   this->RegisterSharedPointer<Envelope>("EnvelopeSPTR", "Envelope");
00134   
00135 
00136   // Register the core messages enum
00137   ret = engine->RegisterEnum("CORE_MESSAGE__TYPE");
00138   ret = engine->RegisterEnumValue("CORE_MESSAGE__TYPE", "CORE_MESSAGE__STARTUP", CORE_MESSAGE::STARTUP); assert(ret >= 0);
00139   ret = engine->RegisterEnumValue("CORE_MESSAGE__TYPE", "CORE_MESSAGE__SHUTDOWN", CORE_MESSAGE::SHUTDOWN); assert(ret >= 0);
00140   ret = engine->RegisterEnumValue("CORE_MESSAGE__TYPE", "CORE_MESSAGE__CREATE", CORE_MESSAGE::CREATE); assert(ret >= 0);
00141   ret = engine->RegisterEnumValue("CORE_MESSAGE__TYPE", "CORE_MESSAGE__LOADLIBRARY", CORE_MESSAGE::LOADLIBRARY); assert(ret >= 0);
00142   ret = engine->RegisterEnumValue("CORE_MESSAGE__TYPE", "CORE_MESSAGE__MODULESTARTED", CORE_MESSAGE::MODULESTARTED); assert(ret >= 0);
00143   ret = engine->RegisterEnumValue("CORE_MESSAGE__TYPE", "CORE_MESSAGE__QUIT", CORE_MESSAGE::QUIT); assert(ret >= 0);
00144 
00145   // Register the render space enum
00146   ret = engine->RegisterEnum("ProjectionStyle");
00147   ret = engine->RegisterEnumValue("ProjectionStyle", "PROJECTION__ORTHOGRAPHIC", GraphicsCore::ECoordinateSpace::CS_SCREEN); assert(ret >= 0);
00148   ret = engine->RegisterEnumValue("ProjectionStyle", "PROJECTION__PERSPECTIVE", GraphicsCore::ECoordinateSpace::CS_WORLD); assert(ret >= 0);
00149   
00150   // Register the directory location enum
00151   ret = engine->RegisterEnum("DIRS__TYPE");
00152   ret = engine->RegisterEnumValue("DIRS__TYPE", "DIRS__USER",      ::DIRS::USER     ); assert(ret >= 0);
00153   ret = engine->RegisterEnumValue("DIRS__TYPE", "DIRS__DOCUMENTS", ::DIRS::DOCUMENTS); assert(ret >= 0);
00154   ret = engine->RegisterEnumValue("DIRS__TYPE", "DIRS__PICTURES",  ::DIRS::PICTURES ); assert(ret >= 0);
00155   ret = engine->RegisterEnumValue("DIRS__TYPE", "DIRS__MUSIC",     ::DIRS::MUSIC    ); assert(ret >= 0);
00156   ret = engine->RegisterEnumValue("DIRS__TYPE", "DIRS__VIDEO",     ::DIRS::VIDEO    ); assert(ret >= 0);
00157   ret = engine->RegisterEnumValue("DIRS__TYPE", "DIRS__DESKTOP",   ::DIRS::DESKTOP  ); assert(ret >= 0);
00158   
00159   // Register the ScriptModule message event registration methods
00160   ret = engine->RegisterGlobalProperty("ScriptModule Engine", this); assert(ret >= 0);
00161   ret = engine->RegisterObjectMethod("ScriptModule", "int RegisterMessageHandler(string, uint)",       asMETHOD(ScriptModule, RegisterMessageHandler),       asCALL_THISCALL); assert(ret >= 0);
00162   ret = engine->RegisterObjectMethod("ScriptModule", "int RegisterMessageHandlerByName(string, uint)", asMETHOD(ScriptModule, RegisterMessageHandlerByName), asCALL_THISCALL); assert(ret >= 0);
00163   ret = engine->RegisterObjectMethod("ScriptModule", "int RegisterMessageHandlerByDecl(string, uint)", asMETHOD(ScriptModule, RegisterMessageHandlerByDecl), asCALL_THISCALL); assert(ret >= 0);
00164   ret = engine->RegisterObjectMethod("ScriptModule", "int UnregisterMessageHandler(string, uint)",       asMETHOD(ScriptModule, UnregisterMessageHandler),       asCALL_THISCALL); assert(ret >= 0);
00165   ret = engine->RegisterObjectMethod("ScriptModule", "int UnregisterMessageHandlerByName(string, uint)", asMETHOD(ScriptModule, UnregisterMessageHandlerByName), asCALL_THISCALL); assert(ret >= 0);
00166   ret = engine->RegisterObjectMethod("ScriptModule", "int UnregisterMessageHandlerByDecl(string, uint)", asMETHOD(ScriptModule, UnregisterMessageHandlerByDecl), asCALL_THISCALL); assert(ret >= 0);
00167   ret = engine->RegisterObjectMethod("ScriptModule", "int RegisterUpdateHandler(string)",       asMETHOD(ScriptModule, RegisterUpdateHandler),       asCALL_THISCALL); assert(ret >= 0);
00168   ret = engine->RegisterObjectMethod("ScriptModule", "int RegisterUpdateHandlerByName(string)", asMETHOD(ScriptModule, RegisterUpdateHandlerByName), asCALL_THISCALL); assert(ret >= 0);
00169   ret = engine->RegisterObjectMethod("ScriptModule", "string GetFolder(const DIRS__TYPE& in)",  asMETHOD(ScriptModule, OSGetFolder), asCALL_THISCALL); assert(ret >= 0);
00170 
00171   // Register the PropertyMap
00172   ret = engine->RegisterObjectMethod("PropertyMap", "bool PropertyExists(string)", asMETHOD(PropertyMap, PropertyExists), asCALL_THISCALL); assert(ret >= 0);
00173   
00174   ret = engine->RegisterObjectMethod("PropertyMap", "bool   GetBool(string)",       asMETHOD(PropertyMap, GetPropertyValue<bool>),       asCALL_THISCALL); assert(ret >= 0);
00175   ret = engine->RegisterObjectMethod("PropertyMap", "int    GetInt(string)",       asMETHOD(PropertyMap, GetPropertyValue<int>),       asCALL_THISCALL); assert(ret >= 0);
00176   ret = engine->RegisterObjectMethod("PropertyMap", "uint   GetUInt(string)", asMETHOD(PropertyMap, GetPropertyValue<unsigned int>), asCALL_THISCALL); assert(ret >= 0);
00177   ret = engine->RegisterObjectMethod("PropertyMap", "float  GetFloat(string)", asMETHOD(PropertyMap, GetPropertyValue<float>), asCALL_THISCALL); assert(ret >= 0);
00178   ret = engine->RegisterObjectMethod("PropertyMap", "double GetDouble(string)", asMETHOD(PropertyMap, GetPropertyValue<double>), asCALL_THISCALL); assert(ret >= 0);
00179   ret = engine->RegisterObjectMethod("PropertyMap", "string GetString(string)", asMETHOD(PropertyMap, GetPropertyValue<std::string>), asCALL_THISCALL); assert(ret >= 0);
00180   ret = engine->RegisterObjectMethod("PropertyMap", "Color  GetColor(string)", asMETHOD(PropertyMap, GetPropertyValue<D3DXCOLOR>), asCALL_THISCALL); assert(ret >= 0);
00181   
00182   ret = engine->RegisterObjectMethod("PropertyMap", "void Set(string, bool)", asMETHODPR(PropertyMap, SetProperty<bool>, (std::string, bool), void), asCALL_THISCALL); assert(ret >= 0);
00183   ret = engine->RegisterObjectMethod("PropertyMap", "void Set(string, int)", asMETHODPR(PropertyMap, SetProperty<int>, (std::string, int), void), asCALL_THISCALL); assert(ret >= 0);
00184   ret = engine->RegisterObjectMethod("PropertyMap", "void Set(string, uint)", asMETHODPR(PropertyMap, SetProperty<unsigned int>, (std::string, unsigned int), void), asCALL_THISCALL); assert(ret >= 0);
00185   ret = engine->RegisterObjectMethod("PropertyMap", "void Set(string, float)", asMETHODPR(PropertyMap, SetProperty<float>, (std::string, float), void), asCALL_THISCALL); assert(ret >= 0);
00186   ret = engine->RegisterObjectMethod("PropertyMap", "void Set(string, double)", asMETHODPR(PropertyMap, SetProperty<double>, (std::string, double), void), asCALL_THISCALL); assert(ret >= 0);
00187   ret = engine->RegisterObjectMethod("PropertyMap", "void Set(string, string)", asMETHODPR(PropertyMap, SetProperty<std::string>, (std::string, std::string), void), asCALL_THISCALL); assert(ret >= 0);
00188   ret = engine->RegisterObjectMethod("PropertyMap", "void Set(string, Color)", asMETHODPR(PropertyMap, SetProperty<D3DXCOLOR>, (std::string, D3DXCOLOR), void), asCALL_THISCALL); assert(ret >= 0);
00189 
00190   // Register the GlobalProperties manager
00191   ret = engine->RegisterGlobalProperty("PropertyMap GlobalProperties", this->gprops); assert(ret >= 0);
00192 
00193   // Logger
00194   RegisterEventLogger(engine);
00195 
00196   // Entity
00197   RegisterEntity(engine);
00198 
00199   // Register the Envelope type and methods
00200   ret = engine->RegisterObjectProperty("Envelope", "int msgid", offsetof(Envelope, msgid)); assert (ret >= 0);
00201   
00202   ret = engine->RegisterObjectMethod("Envelope", "uint GetCount()", asMETHOD(Envelope, GetCount), asCALL_THISCALL); assert(ret >= 0);
00203   
00204   ret = engine->RegisterObjectMethod("Envelope", "bool         GetBool        (const uint &in)", asMETHOD(Envelope, GetDataValue<bool          >), asCALL_THISCALL); assert(ret >= 0);
00205   ret = engine->RegisterObjectMethod("Envelope", "int          GetInt         (const uint &in)", asMETHOD(Envelope, GetDataValue<int           >), asCALL_THISCALL); assert(ret >= 0);
00206   ret = engine->RegisterObjectMethod("Envelope", "int64        GetLong        (const uint &in)", asMETHOD(Envelope, GetDataValue<long          >), asCALL_THISCALL); assert(ret >= 0);
00207   ret = engine->RegisterObjectMethod("Envelope", "uint         GetUInt        (const uint &in)", asMETHOD(Envelope, GetDataValue<unsigned int  >), asCALL_THISCALL); assert(ret >= 0);
00208   ret = engine->RegisterObjectMethod("Envelope", "float        GetFloat       (const uint &in)", asMETHOD(Envelope, GetDataValue<float         >), asCALL_THISCALL); assert(ret >= 0);
00209   ret = engine->RegisterObjectMethod("Envelope", "string       GetString      (const uint &in)", asMETHOD(Envelope, GetDataValue<std::string   >), asCALL_THISCALL); assert(ret >= 0);
00210   ret = engine->RegisterObjectMethod("Envelope", "Vector       GetVector      (const uint &in)", asMETHOD(Envelope, GetDataValue<D3DXVECTOR3   >), asCALL_THISCALL); assert(ret >= 0);
00211   ret = engine->RegisterObjectMethod("Envelope", "Rotation     GetQuat        (const uint &in)", asMETHOD(Envelope, GetDataValue<D3DXQUATERNION>), asCALL_THISCALL); assert(ret >= 0);
00212   ret = engine->RegisterObjectMethod("Envelope", "Color        GetColor       (const uint &in)", asMETHOD(Envelope, GetDataValue<D3DXCOLOR     >), asCALL_THISCALL); assert(ret >= 0);
00213   ret = engine->RegisterObjectMethod("Envelope", "Entity       GetEntity      (const uint &in)", asMETHOD(Envelope, GetDataReference<EntitySPTR  >), asCALL_THISCALL); assert(ret >= 0);
00214   ret = engine->RegisterObjectMethod("Envelope", "EnvelopeSPTR GetEnvelopeSPTR(const uint &in)", asMETHOD(Envelope, GetDataReference<EnvelopeSPTR>), asCALL_THISCALL); assert(ret >= 0);
00215 
00216   ret = engine->RegisterObjectMethod("Envelope", "void Add(const bool &in)",         asMETHOD(Envelope, AddDataValue<bool>          ), asCALL_THISCALL); assert(ret >= 0);
00217   ret = engine->RegisterObjectMethod("Envelope", "void Add(const int &in)",          asMETHOD(Envelope, AddDataValue<int>           ), asCALL_THISCALL); assert(ret >= 0);
00218   ret = engine->RegisterObjectMethod("Envelope", "void Add(const uint &in)",         asMETHOD(Envelope, AddDataValue<unsigned int>  ), asCALL_THISCALL); assert(ret >= 0);
00219   ret = engine->RegisterObjectMethod("Envelope", "void Add(const float &in)",        asMETHOD(Envelope, AddDataValue<float>         ), asCALL_THISCALL); assert(ret >= 0);
00220   ret = engine->RegisterObjectMethod("Envelope", "void Add(const string &in)",       asMETHOD(Envelope, AddDataValue<std::string>   ), asCALL_THISCALL); assert(ret >= 0);
00221   ret = engine->RegisterObjectMethod("Envelope", "void Add(const Vector &in)",       asMETHOD(Envelope, AddDataValue<D3DXVECTOR3>   ), asCALL_THISCALL); assert(ret >= 0);
00222   ret = engine->RegisterObjectMethod("Envelope", "void Add(const Rotation &in)",     asMETHOD(Envelope, AddDataValue<D3DXQUATERNION>), asCALL_THISCALL); assert(ret >= 0);
00223   ret = engine->RegisterObjectMethod("Envelope", "void Add(const Color &in)",        asMETHOD(Envelope, AddDataValue<D3DXCOLOR>     ), asCALL_THISCALL); assert(ret >= 0);
00224   ret = engine->RegisterObjectMethod("Envelope", "void Add(Entity)",       asMETHOD(Envelope, AddDataReference<EntitySPTR>    ), asCALL_THISCALL); assert(ret >= 0);
00225   ret = engine->RegisterObjectMethod("Envelope", "void Add(EnvelopeSPTR)", asMETHOD(Envelope, AddDataReference<EnvelopeSPTR>  ), asCALL_THISCALL); assert(ret >= 0);
00226   
00227   ret = engine->RegisterObjectMethod("EnvelopeSPTR", "void SaveToDisk(const string)",   asFUNCTIONPR(SaveToDisk  , (const EnvelopeSPTR*, const std::string), void), asCALL_CDECL_OBJFIRST); assert(ret >= 0);
00228   ret = engine->RegisterObjectMethod("EnvelopeSPTR", "bool LoadFromDisk(const string)", asFUNCTIONPR(LoadFromDisk, (const EnvelopeSPTR*, const std::string), bool), asCALL_CDECL_OBJFIRST); assert(ret >= 0);
00229 
00230   ret = engine->RegisterObjectMethod("ScriptModule", "EnvelopeSPTR EnvelopeSPTRFactory()", asMETHOD(ScriptModule, EnvelopeSPTRFactory), asCALL_THISCALL); assert(ret >= 0);
00231   ret = engine->RegisterObjectMethod("ScriptModule", "void Send(EnvelopeSPTR)", asMETHOD(ScriptModule, SendMessage), asCALL_THISCALL); assert(ret >= 0);
00232   ret = engine->RegisterObjectMethod("ScriptModule", "void PrioritySend(EnvelopeSPTR)", asMETHOD(ScriptModule, PrioritySend), asCALL_THISCALL); assert(ret >= 0);
00233   ret = engine->RegisterObjectMethod("ScriptModule", "EnvelopeSPTR DirectedSend(EnvelopeSPTR)", asMETHOD(ScriptModule, DirectedSend), asCALL_THISCALL); assert(ret >= 0);
00234 
00235   // Entity Manager
00236   ret = engine->RegisterGlobalProperty("EntityList EntList", this->elist); assert(ret >= 0);
00237   ret = engine->RegisterObjectMethod("EntityList", "bool AddEntity(Entity)", asMETHODPR(EntityList, AddEntity, (EntitySPTR const), bool), asCALL_THISCALL); assert(ret >= 0);
00238   ret = engine->RegisterObjectMethod("EntityList", "bool AddEntity(string, Entity)", asMETHODPR(EntityList, AddEntity, (const std::string, EntitySPTR const), bool), asCALL_THISCALL); assert(ret >= 0);
00239   ret = engine->RegisterObjectMethod("EntityList", "Entity FindEntity(string)", asMETHODPR(EntityList, FindEntity, (const std::string) const, EntitySPTR), asCALL_THISCALL); assert(ret >= 0);
00240   ret = engine->RegisterObjectMethod("EntityList", "bool RemoveEntity(string)", asMETHODPR(EntityList, RemoveEntity, (const std::string), bool), asCALL_THISCALL); assert(ret >= 0);
00241 
00242   CreateEntityFactory::engine = engine;
00243 
00244   // CreateEntityFactory
00245   ret = engine->RegisterObjectBehaviour("CreateEntityFactory", asBEHAVE_ADDREF,  "void f()", asMETHOD(CreateEntityFactory, Addref),  asCALL_THISCALL); assert(ret >= 0);
00246   ret = engine->RegisterObjectBehaviour("CreateEntityFactory", asBEHAVE_RELEASE, "void f()", asMETHOD(CreateEntityFactory, Release), asCALL_THISCALL); assert(ret >= 0);
00247   ret = engine->RegisterObjectMethod("CreateEntityFactory", "void SetName(string)", asMETHOD(CreateEntityFactory, SetName), asCALL_THISCALL);
00248   ret = engine->RegisterObjectMethod("CreateEntityFactory", "void AddAttribute(string, string, string)", asMETHODPR(CreateEntityFactory, AddAttribute, (std::string, std::string, std::string), void), asCALL_THISCALL);
00249   ret = engine->RegisterObjectMethod("CreateEntityFactory", "void AddAttribute(string, string, any@)", asMETHODPR(CreateEntityFactory, AddAttribute, (std::string, std::string, CScriptAny*), void), asCALL_THISCALL);
00250   ret = engine->RegisterObjectMethod("CreateEntityFactory", "void SetEntity(Entity)", asMETHOD(CreateEntityFactory, SetEntity), asCALL_THISCALL);
00251   ret = engine->RegisterObjectMethod("CreateEntityFactory", "void CreateEntity(int)", asMETHOD(CreateEntityFactory, CreateEntity), asCALL_THISCALL);
00252   ret = engine->RegisterObjectMethod("CreateEntityFactory", "void Finalize(EnvelopeSPTR)", asMETHOD(CreateEntityFactory, Finalize), asCALL_THISCALL);
00253   ret = engine->RegisterObjectBehaviour("CreateEntityFactory", asBEHAVE_FACTORY, "CreateEntityFactory@ CreateEntityFactoryFact()", asFUNCTION(CreateEntityFactoryFact), asCALL_CDECL); assert(ret >= 0);
00254   ret = 0;
00255 
00256 }
00257 
00258 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00259 ScriptModule::~ScriptModule() {
00260 }
00261 
00262 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00263 void ScriptModule::SendMessage( EnvelopeSPTR envelope ) const {
00264   this->msgrouter->SendSP(envelope);
00265 }
00266 
00267 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00268 void ScriptModule::PrioritySend( EnvelopeSPTR envelope ) const {
00269   this->msgrouter->SendSP(envelope, false);
00270 }
00271 
00272 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00273 EnvelopeSPTR ScriptModule::DirectedSend( EnvelopeSPTR envelope ) const {
00274   return this->msgrouter->SendDirected(envelope, envelope->msgid);
00275 }
00276 
00277 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00278 void ScriptModule::Message( EnvelopeSPTR envelope ) {
00279   event_handler_list_type event_handlers;
00280   
00281   {
00282     Threading::ReadLock r_lock(this->eventHandlersMutex);
00283     
00284     event_handler_map_type::iterator iter = this->eventHandlers.find(envelope->msgid);
00285     if (iter != this->eventHandlers.end()) {
00286       event_handlers = (*iter).second;
00287     }
00288   }
00289   
00290   BOOST_FOREACH (event_handler_type handler, event_handlers) {
00291     int ret = 0;
00292     ret = this->eventScriptManager.PrepareFunction(handler);
00293     
00294     ret = this->eventScriptManager.SetFunctionParamObject(0, &envelope);
00295     
00296     ret = this->eventScriptManager.ExecuteFunction();
00297     if (ret == asEXECUTION_FINISHED) {
00298       // Handle return value.  None in this case.
00299     }
00300   }
00301 }
00302 
00303 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00304 unsigned int ScriptModule::RegisterMessageHandler( std::string funcName, event_handler_key_type eventID ) {
00305   return RegisterMessageHandlerByName(funcName, eventID);
00306 }
00307 
00308 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00309 unsigned int ScriptModule::RegisterMessageHandlerByName( std::string funcName, event_handler_key_type eventID ) {
00310   unsigned int funcID = this->eventScriptManager.GetEngine()->GetModule("module1")->GetFunctionIdByName(funcName.c_str());
00311   return RegisterMessageHandlerByID(funcID, eventID);
00312 }
00313 
00314 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00315 unsigned int ScriptModule::RegisterMessageHandlerByDecl( std::string funcDeclaration, event_handler_key_type eventID ) {
00316   unsigned int funcID = this->eventScriptManager.GetEngine()->GetModule("module1")->GetFunctionIdByDecl(funcDeclaration.c_str());
00317   return RegisterMessageHandlerByID(funcID, eventID);
00318 }
00319 
00320 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00321 unsigned int ScriptModule::RegisterMessageHandlerByID( unsigned int func_id, event_handler_key_type event_id ) {
00322   event_handler_list_type* handlers;
00323   
00324   Threading::UpgradeLock up_lock(this->eventHandlersMutex);
00325   
00326   // Find the event ID in the handlers list.
00327   event_handler_map_type::iterator handlers_it = this->eventHandlers.find(event_id);
00328   
00329   // If it was found, go get it
00330   if (handlers_it != this->eventHandlers.end()) {
00331     handlers = &handlers_it->second;
00332   }
00333   else { // Otherwise, set it up
00334     // Subscribe the script module's message handler to the event id
00335     std::shared_ptr<Subscriber> s2(new Subscriber(boost::bind(&ScriptModule::Message, this, _1)));
00336     this->msgrouter->Subscribe(event_id, s2);
00337     
00338     Threading::UpgradeToUniqueLock unique_lock(up_lock);
00339     
00340     // Create the handler set
00341     handlers = &this->eventHandlers[event_id];
00342   }
00343   
00344   // Only add the handler if it doesn't exist already (which will never be the case if this is the first subscription call!)
00345   if (handlers->find(event_handler_type(func_id)) == handlers->end()) {
00346     Threading::UpgradeToUniqueLock unique_lock(up_lock);
00347     
00348     // Append the script handler function id to the end of the set.
00349     handlers->insert(event_handler_type(func_id));
00350   }
00351 
00352   return func_id;
00353 }
00354 
00355 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00356 unsigned int ScriptModule::UnregisterMessageHandler( std::string funcName, event_handler_key_type eventID ) {
00357   return UnregisterMessageHandlerByName(funcName, eventID);
00358 }
00359 
00360 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00361 unsigned int ScriptModule::UnregisterMessageHandlerByName( std::string funcName, event_handler_key_type eventID ) {
00362   unsigned int funcID = this->eventScriptManager.GetEngine()->GetModule("module1")->GetFunctionIdByName(funcName.c_str());
00363   return UnregisterMessageHandlerByID(funcID, eventID);
00364 }
00365 
00366 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00367 unsigned int ScriptModule::UnregisterMessageHandlerByDecl( std::string funcDeclaration, event_handler_key_type eventID ) {
00368   unsigned int funcID = this->eventScriptManager.GetEngine()->GetModule("module1")->GetFunctionIdByDecl(funcDeclaration.c_str());
00369   return UnregisterMessageHandlerByID(funcID, eventID);
00370 }
00371 
00372 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00373 unsigned int ScriptModule::UnregisterMessageHandlerByID( unsigned int funcID, event_handler_key_type eventID ) {
00374   if (funcID >= 0) {
00375     Threading::WriteLock w_lock(this->eventHandlersMutex);
00376     
00377     event_handler_list_type* handlers = &this->eventHandlers[eventID];
00378     
00379     // Remove the handler from the set.
00380     handlers->erase(event_handler_type(funcID));
00381     
00382     // *TODO: If the memory leak gets to be too much, then check if the handler set is empty.  If it is, remove it's entry from the eventHandlers map and unsubscribe ScriptModule::Message from that event ID.
00383   }
00384 
00385   return funcID;
00386 }
00387 
00388 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00389 void ScriptModule::CreateComponent( std::string type, std::map< std::string, boost::any > &attributes, EntitySPTR entity ) {
00390   if (type == "Script_File") {
00391     int ret;
00392     ret = this->eventScriptManager.AddSectionFromFile(boost::any_cast<std::string>(attributes["filename"]).c_str()); assert(ret >= 0);
00393     ret = this->eventScriptManager.BuildModule(); assert(ret >= 0);
00394     ret = this->eventScriptManager.PrepareFunction(boost::any_cast<std::string>(attributes["function"]).c_str(), "module1"); assert(ret >= 0);
00395     ret = this->eventScriptManager.ExecuteFunction(); assert(ret >= 0);
00396   }
00397 }
00398 
00399 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00400 WHO_DELETES::TYPE ScriptModule::RemoveComponent(ComponentInterface* component) {
00401   // Nothing to do here
00402   return WHO_DELETES::CALLEE;
00403 }
00404 
00405 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00406 void ScriptModule::ExecuteFile(const std::string& script_path, const std::string& script_function_sig) {
00407   int ret = 0;
00408 
00409   ret = this->eventScriptManager.AddSectionFromFile(script_path.c_str());
00410   if (ret < 0) {
00411     LOG(LOG_PRIORITY::SYSERR, "Script '" + script_path + "' failed to load!  Does the file exist at the given path?");
00412     
00413     throw(ScriptException::FAILED_LOAD);
00414   }
00415 
00416   ret = this->eventScriptManager.BuildModule();
00417   if (ret < 0) {
00418     LOG(LOG_PRIORITY::SYSERR, "Script '" + script_path + "' failed to build. Possibly a syntax error in the script?");
00419     
00420     throw(ScriptException::FAILED_BUILD);
00421   }
00422 
00423   this->eventScriptManager.PrepareFunction(script_function_sig, "module1");
00424   this->eventScriptManager.ExecuteFunction();
00425 
00426   LOG(LOG_PRIORITY::INFO, "Script '" + script_path + "':'" + script_function_sig + "' completed.");
00427 }
00428 
00429 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00430 void ScriptModule::Update( double dt ) {
00431   this->deltaAccumulator += dt;
00432 
00433   if (this->deltaAccumulator >= 1.0f / 30.0f) {
00434     int ret = 0, handler = -1, size;
00435     
00436     // Iterate through ONLY the items added before this update round,
00437     // not through any added during.
00438     size = this->updateHandlers.size();
00439     while (--size >= 0) {
00440       {
00441         Threading::WriteLock w_lock(this->updateHandlersMutex);
00442         handler = this->updateHandlers.front();
00443         this->updateHandlers.pop();
00444       }
00445       
00446       ret = this->updateScriptManager.PrepareFunction(handler);
00447       
00448       ret = this->updateScriptManager.SetFunctionParamDouble(0, dt);
00449       
00450       ret = this->updateScriptManager.ExecuteFunction();
00451       if (ret == asEXECUTION_FINISHED) {
00452         // Handle return value.  None in this case.
00453       }
00454     }
00455   }
00456 }
00457 
00458 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00459 unsigned int ScriptModule::RegisterUpdateHandler( std::string funcName ) {
00460   return RegisterUpdateHandlerByName(funcName);
00461 }
00462 
00463 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00464 unsigned int ScriptModule::RegisterUpdateHandlerByName( std::string funcName ) {
00465   unsigned int funcID = this->updateScriptManager.GetEngine()->GetModule("module1")->GetFunctionIdByName(funcName.c_str());
00466   return RegisterUpdateHandlerByID(funcID);
00467 }
00468 
00469 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00470 unsigned int ScriptModule::RegisterUpdateHandlerByID( unsigned int funcID ) {
00471   Threading::WriteLock w_lock(this->updateHandlersMutex);
00472   
00473   // Append the handler to the end of the queue.
00474   this->updateHandlers.push(event_handler_type(funcID));
00475   
00476   return funcID;
00477 }
00478 
00479 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00480 template <typename Type>
00481 void ScriptModule::RegisterSharedPointer( const std::string& ptrTypeName, const std::string& typeName ) {
00482   asIScriptEngine* engine = this->eventScriptManager.GetEngine();
00483 
00484   int r;
00485 
00486   r = engine->RegisterObjectType(ptrTypeName.c_str(), sizeof(std::shared_ptr<Type>), asOBJ_VALUE | asOBJ_APP_CLASS_CDA); assert(r >= 0);
00487 
00488   r = engine->RegisterObjectBehaviour(ptrTypeName.c_str(), asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(SharedPointerWrapper<Type>::construct), asCALL_CDECL_OBJLAST); assert(r >= 0);
00489   r = engine->RegisterObjectBehaviour(ptrTypeName.c_str(), asBEHAVE_DESTRUCT, "void f()", asFUNCTION(SharedPointerWrapper<Type>::destruct), asCALL_CDECL_OBJLAST); assert(r >= 0);
00490 
00491   r = engine->RegisterObjectMethod(ptrTypeName.c_str(), (ptrTypeName + "& opAssign(const " + ptrTypeName + " &in other)").c_str(), asMETHODPR(std::shared_ptr<Type>, operator=, (std::shared_ptr<Type> const &), std::shared_ptr<Type>&), asCALL_THISCALL); assert(r >= 0);
00492   r = engine->RegisterObjectMethod(ptrTypeName.c_str(), (typeName + "& get()").c_str(), asMETHOD(std::shared_ptr<Type>, get), asCALL_THISCALL); assert(r >= 0);
00493 }
00494 
00495 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00496 EnvelopeSPTR ScriptModule::EnvelopeSPTRFactory() {
00497   EnvelopeSPTR ptr(new Envelope);
00498   return ptr;
00499 }
00500 
00501 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00502 std::string ScriptModule::OSGetFolder(const ::DIRS::TYPE& type) {
00503   OSInterfaceSPTR os(OSInterface::GetOS());
00504   
00505   if (os.get() != nullptr) {
00506     return os->GetPath(type);
00507   }
00508   
00509   return "";
00510 }
00511 
00512 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00513 void ScriptLog(const LOG_PRIORITY::TYPE& priority, const std::string& string) {
00514   asIScriptContext *ctx = asGetActiveContext();
00515   
00516   std::string message;
00517   
00518   if (ctx != nullptr) {
00519     asIScriptFunction* func = ctx->GetFunction();
00520     ::EventLogger::GetEventLogger()->LogToDisk(priority, string, func->GetScriptSectionName(), static_cast<unsigned int>(ctx->GetLineNumber()), func->GetDeclaration());
00521   }
00522   else {
00523     ::EventLogger::GetEventLogger()->LogToDisk(priority, string);
00524   }
00525 }
00526 
00527 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00528 void RegisterEventLogger(asIScriptEngine* const engine) {
00529   int ret;
00530   
00531   ret = engine->RegisterEnum("LOG_PRIORITY__TYPE");
00532   ret = engine->RegisterEnumValue("LOG_PRIORITY__TYPE", "LOG_PRIORITY__INFO", LOG_PRIORITY::INFO); assert(ret >= 0);
00533   ret = engine->RegisterEnumValue("LOG_PRIORITY__TYPE", "LOG_PRIORITY__FLOW", LOG_PRIORITY::FLOW); assert(ret >= 0);
00534   ret = engine->RegisterEnumValue("LOG_PRIORITY__TYPE", "LOG_PRIORITY__WARN", LOG_PRIORITY::WARN); assert(ret >= 0);
00535   ret = engine->RegisterEnumValue("LOG_PRIORITY__TYPE", "LOG_PRIORITY__CONFIG", LOG_PRIORITY::CONFIG); assert(ret >= 0);
00536   ret = engine->RegisterEnumValue("LOG_PRIORITY__TYPE", "LOG_PRIORITY__ERR", LOG_PRIORITY::ERR); assert(ret >= 0);
00537   ret = engine->RegisterEnumValue("LOG_PRIORITY__TYPE", "LOG_PRIORITY__MISSRESS", LOG_PRIORITY::MISSRESS); assert(ret >= 0);
00538   ret = engine->RegisterEnumValue("LOG_PRIORITY__TYPE", "LOG_PRIORITY__DEPRICATE", LOG_PRIORITY::DEPRICATE); assert(ret >= 0);
00539   
00540   ret = engine->RegisterGlobalFunction("void LOG(const LOG_PRIORITY__TYPE& in, const string& in)", asFUNCTION(ScriptLog), asCALL_CDECL); assert(ret >= 0);
00541 }
00542