1 module as.engine; 2 import as.def; 3 import std..string; 4 import std.exception; 5 import std.traits; 6 import as; 7 8 class ScriptEngine { 9 private: 10 asIScriptEngine* engine; 11 12 ~this() { 13 this.shutDownAndRelease(); 14 } 15 16 this(asIScriptEngine* engine) { 17 this.engine = engine; 18 } 19 20 public: 21 22 /** 23 Creates a new script engine 24 */ 25 static ScriptEngine create(asDWORD version_ = ANGELSCRIPT_VERSION) { 26 return new ScriptEngine(asCreateScriptEngine(version_)); 27 } 28 29 /** 30 Adds reference 31 */ 32 int addRef() { 33 return asEngine_AddRef(engine); 34 } 35 36 /** 37 Releases reference 38 */ 39 int release() { 40 return asEngine_Release(engine); 41 } 42 43 /** 44 Shuts down the scripting engine and releases it 45 */ 46 int shutDownAndRelease() { 47 return asEngine_ShutDownAndRelease(engine); 48 } 49 50 /** 51 Sets an engine property 52 */ 53 void setProperty(asEEngineProp property, asPWORD value) { 54 int err = asEngine_SetEngineProperty(engine, property, value); 55 enforce(err != asERetCodes.asINVALID_ARG, "Invalid argument"); 56 } 57 58 /** 59 Gets an engine property 60 */ 61 asPWORD getProperty(asEEngineProp property) { 62 return asEngine_GetEngineProperty(engine, property); 63 } 64 65 /** 66 Sets the message callback 67 68 BUG: Writing message will cause a crash currently. 69 */ 70 void setMessageCallback(MessageCallback callback) { 71 72 73 int err = asEngine_SetMessageCallback(engine, cast(asFUNCTION_t)callback, null, DCallConv); 74 enforce(err != asERetCodes.asINVALID_ARG, "Invalid argument"); 75 enforce(err != asERetCodes.asNOT_SUPPORTED, "Not supported"); 76 } 77 78 /** 79 Clears the message callback 80 */ 81 void clearMessageCallback() { 82 asEngine_ClearMessageCallback(engine); 83 } 84 85 /** 86 Writes a message 87 */ 88 void writeMessage(string section, int row, int col, MessageType type, string message) { 89 asEngine_WriteMessage(engine, section.toStringz, row, col, cast(asEMsgType)type, message.toStringz); 90 } 91 92 // TODO: Jit Compiler 93 94 /** 95 Register a global function 96 */ 97 void registerGlobalFunction(T)(string declaration, T func, void* aux = null) if (isFunctionPointer!T) { 98 int err = asEngine_RegisterGlobalFunction(engine, declaration.toStringz, cast(asFUNCTION_t)func, DCallConv, aux); 99 enforce(err != asERetCodes.asNOT_SUPPORTED, "Not supported"); 100 enforce(err != asERetCodes.asWRONG_CALLING_CONV, "Wrong calling convetion"); 101 enforce(err != asERetCodes.asINVALID_DECLARATION, "Function declaration is invalid"); 102 enforce(err != asERetCodes.asNAME_TAKEN, "Function name is already taken"); 103 enforce(err != asERetCodes.asALREADY_REGISTERED, "Function is already registered"); 104 enforce(err != asERetCodes.asINVALID_ARG, "Invalid argument"); 105 } 106 107 /** 108 Gets the amount of global functions 109 */ 110 asUINT getGlobalFunctionCount() { 111 return asEngine_GetGlobalFunctionCount(engine); 112 } 113 114 /** 115 Gets a global function by its index 116 */ 117 Function getGlobalFunctionByIndex(uint index) { 118 return new Function(this, asEngine_GetGlobalFunctionByIndex(engine, index)); 119 } 120 121 /** 122 Gets a global function by its declaration 123 */ 124 Function getGlobalFunctionByDecl(string decl) { 125 return new Function(this, asEngine_GetGlobalFunctionByDecl(engine, decl.toStringz)); 126 } 127 128 /** 129 Registers a global property 130 */ 131 void registerGlobalProperty(T)(string declaration, ref T pointer) { 132 int err = asEngine_RegisterGlobalProperty(engine, declaration.toStringz, cast(void*)&pointer); 133 enforce(err != asERetCodes.asINVALID_DECLARATION, "Declaration is invalid"); 134 enforce(err != asERetCodes.asINVALID_TYPE, "Declaration type is invalid"); 135 enforce(err != asERetCodes.asINVALID_ARG, "Reference is null"); 136 enforce(err != asERetCodes.asNAME_TAKEN, "Name is already taken"); 137 } 138 139 /** 140 Gets the count of global properties 141 */ 142 asUINT getGlobalPropertyCount() { 143 return asEngine_GetGlobalPropertyCount(engine); 144 } 145 146 /** 147 Gets a global property by its index 148 */ 149 void getGlobalPropertyByIndex(uint index, ref string name, ref string namespace, ref int typeId, ref bool isConst, ref string configGroup, void* ptr, ref asDWORD accessMask) { 150 const(char)* c_name; 151 const(char)* c_namespace; 152 int c_typeId; 153 bool c_isConst; 154 const(char)* c_configGroup; 155 void* c_ptr; 156 asDWORD c_accessMask; 157 158 int err = asEngine_GetGlobalPropertyByIndex(engine, index, &c_name, &c_namespace, &c_typeId, &c_isConst, &c_configGroup, &c_ptr, &c_accessMask); 159 // TODO: Report errors 160 161 // move all this data to the appropriate place 162 name = cast(string)c_name.fromStringz.idup; 163 namespace = cast(string)c_namespace.fromStringz.idup; 164 typeId = c_typeId; 165 isConst = c_isConst; 166 configGroup = cast(string)c_configGroup.fromStringz.idup; 167 ptr = c_ptr; 168 accessMask = c_accessMask; 169 } 170 171 /** 172 Gets the index of a global property by its name 173 */ 174 int getGlobalPropertyIndexByName(string name) { 175 return asEngine_GetGlobalPropertyIndexByName(engine, name.toStringz); 176 } 177 178 /** 179 Gets the index of a global property by its declaration 180 */ 181 int getGlobalPropertyIndexByDecl(string decl) { 182 return asEngine_GetGlobalPropertyIndexByDecl(engine, decl.toStringz); 183 } 184 185 /** 186 Registers an object type 187 */ 188 void registerObjectType(string name, int byteSize, asDWORD flags) { 189 asEngine_RegisterObjectType(engine, name.toStringz, byteSize, flags); 190 } 191 192 /** 193 Registers a property for an object 194 */ 195 void registerObjectProperty(string obj, string decl, int byteOffset) { 196 asEngine_RegisterObjectProperty(engine, obj.toStringz, decl.toStringz, byteOffset); 197 } 198 199 /** 200 Registers a method for an object 201 */ 202 void registerObjectMethod(T)(string obj, string decl, T func, asDWORD callConv = DCallConv, void* aux = null) if (isFunctionPointer!T) { 203 asEngine_RegisterObjectMethod(engine, obj.toStringz, decl.toStringz, cast(asFUNCTION_t)func, callConv, aux); 204 } 205 206 /** 207 Registers a behaviour for an object 208 */ 209 void registerObjectBehaviour(T)(string dataType, asEBehaviours behaviour, string decl, T func, asDWORD callConv = DCallConv, void* aux = null) if (isFunctionPointer!T) { 210 asEngine_RegisterObjectBehaviour(engine, dataType.toStringz, behaviour, decl.toStringz, cast(asFUNCTION_t)func, callConv, aux); 211 } 212 213 // TODO: String Factory and Default Array Type 214 215 /** 216 Registers a string factory type with the specified creation functions 217 */ 218 void registerStringFactory(string type, asGETSTRINGCONSTFUNC_t getStr, asRELEASESTRINGCONSTFUNC_t releaseStr, asGETRAWSTRINGDATAFUNC_t getRawStr) { 219 asEngine_RegisterStringFactory(engine, type.toStringz, getStr, releaseStr, getRawStr); 220 } 221 222 /** 223 Registers a D enum in Angelscript 224 */ 225 void registerEnum(T)() if (is(T == enum)) { 226 mixin("import ", moduleName!T, ";"); 227 registerEnum(T.stringof); 228 static foreach(member; __traits(allMembers, T)) { 229 registerEnumValue(T.stringof, member, cast(int)mixin(T.stringof, ".", member)); 230 } 231 } 232 233 /** 234 Registers an enum 235 */ 236 void registerEnum(string type) { 237 int err = asEngine_RegisterEnum(engine, type.toStringz); 238 enforce(err != asERetCodes.asINVALID_NAME, "Invalid name"); 239 enforce(err != asERetCodes.asALREADY_REGISTERED, "Already registered"); 240 enforce(err != asERetCodes.asERROR, "Couldn't parse type"); 241 enforce(err != asERetCodes.asNAME_TAKEN, "Name already taken"); 242 } 243 244 /** 245 Registers a value for the enum 246 */ 247 void registerEnumValue(string type, string name, int value) { 248 int err = asEngine_RegisterEnumValue(engine, type.toStringz, name.toStringz, value); 249 enforce(err != asERetCodes.asWRONG_CONFIG_GROUP, "Wrong config group"); 250 enforce(err != asERetCodes.asINVALID_TYPE, "Invalid type"); 251 enforce(err != asERetCodes.asALREADY_REGISTERED, "Already registered"); 252 } 253 254 /** 255 Gets the amount of enums registered 256 */ 257 asUINT getEnumCount() { 258 return asEngine_GetEnumCount(engine); 259 } 260 261 262 /** 263 Sets the default namespace 264 */ 265 void setDefaultNamespace(string namespace) { 266 int err = asEngine_SetDefaultNamespace(engine, namespace.toStringz); 267 enforce(err != asERetCodes.asINVALID_ARG, "Invalid namespace"); 268 } 269 270 /** 271 Gets the default namespace 272 */ 273 string getDefaultNamespace() { 274 return cast(string)asEngine_GetDefaultNamespace(engine).fromStringz; 275 } 276 277 /** 278 Gets a module in the engine by name 279 */ 280 Module getModule(string name, ModuleCreateFlags flags = ModuleCreateFlags.OnlyIfExists) { 281 return new Module(this, asEngine_GetModule(engine, name.toStringz, flags)); 282 } 283 284 /** 285 Gets a module in the engine by index 286 */ 287 Module getModule(asUINT index) { 288 return new Module(this, asEngine_GetModuleByIndex(engine, index)); 289 } 290 291 /** 292 Discards a module by name 293 Note: Any class instances of the module in question will be rendered invalid. 294 */ 295 void discardModule(string name) { 296 asEngine_DiscardModule(engine, name.toStringz); 297 } 298 299 /** 300 Gets the count of modules 301 */ 302 asUINT getModuleCount() { 303 return asEngine_GetModuleCount(engine); 304 } 305 306 /** 307 Get a function by its ID in the engine 308 */ 309 Function getFunctionById(int funcId) { 310 return new Function(this, asEngine_GetFunctionById(engine, funcId)); 311 } 312 313 /** 314 Creates a new script context 315 */ 316 ScriptContext createContext() { 317 return new ScriptContext(this, asEngine_CreateContext(engine)); 318 } 319 }