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 }