12 #include <angelscript.h>
13 #include <scriptstdstring/scriptstdstring.h>
14 #include <scriptarray/scriptarray.h>
15 #include <scriptdictionary/scriptdictionary.h>
16 #include <scriptmath/scriptmath.h>
17 #include <scriptmath/scriptmathcomplex.h>
18 #include <scriptbuilder/scriptbuilder.h>
27 ScriptEngine::~ScriptEngine()
33 engine->ShutDownAndRelease();
36 void ScriptEngine::init()
39 engine = asCreateScriptEngine();
40 engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES,
true);
43 int r = engine->SetMessageCallback(asMETHOD(ScriptEngine, messageCallback),
this, asCALL_THISCALL);
50 RegisterStdString(engine);
51 RegisterScriptArray(engine,
true);
52 RegisterScriptDictionary(engine);
53 RegisterScriptMath(engine);
54 RegisterScriptMathComplex(engine);
61 r = engine->RegisterGlobalFunction(
"void print(const string &in)", asFUNCTION(
print), asCALL_CDECL);
64 context = engine->CreateContext();
67 int ScriptEngine::framestep(
float dt)
70 if (!engine || !context)
73 for (
auto &m_addon_scrip : m_addon_scrips)
75 if (!m_addon_scrip.frameStepFunctionPtr)
80 context->Prepare(m_addon_scrip.frameStepFunctionPtr);
83 context->SetArgFloat(0, dt);
85 int r = context->Execute();
86 if (r == asEXECUTION_FINISHED)
89 asDWORD ret = context->GetReturnDWord();
95 int ScriptEngine::loadScript(
const string &scriptName, ScriptCategory category )
102 int unit_id = (
int)m_addon_scrips.size();
103 m_addon_scrips.resize(m_addon_scrips.size() + 1);
104 m_addon_scrips[unit_id].scriptName = scriptName;
105 m_addon_scrips[unit_id].scriptCategory = category;
108 int result = this->setupScriptUnit(unit_id);
113 m_addon_scrips.pop_back();
119 int ScriptEngine::setupScriptUnit(
int unit_id)
122 if (!engine || !context)
125 string moduleName = this->composeModuleName(m_addon_scrips[unit_id].scriptName, m_addon_scrips[unit_id].scriptCategory);
126 if (moduleName.empty())
132 CScriptBuilder builder;
136 result = builder.StartNewModule(engine, moduleName.c_str());
139 LOG(
LOG_ERROR) <<
"Could not load script " << moduleName <<
" - failed to create module.";
142 m_addon_scrips[unit_id].scriptModule = engine->GetModule(moduleName.c_str(), asGM_ONLY_IF_EXISTS);
145 result = builder.AddSectionFromFile(m_addon_scrips[unit_id].scriptName.c_str());
148 LOG(
LOG_ERROR) <<
"Could not load script " << moduleName <<
" - failed to process file.";
152 result = builder.BuildModule();
155 LOG(
LOG_ERROR) <<
"Could not load script " << moduleName <<
" - failed to build module.";
160 m_addon_scrips[unit_id].frameStepFunctionPtr = m_addon_scrips[unit_id].scriptModule->GetFunctionByDecl(
"void frameStep(float)");
162 m_addon_scrips[unit_id].eventCallbackFunctionPtr =
163 m_addon_scrips[unit_id].scriptModule->GetFunctionByDecl(
"void eventCallback(int, int)");
165 m_addon_scrips[unit_id].defaultEventCallbackFunctionPtr =
166 m_addon_scrips[unit_id].scriptModule->GetFunctionByDecl(
"void defaultEventCallback(int, string, string, int)");
169 auto main_func = m_addon_scrips[unit_id].scriptModule->GetFunctionByDecl(
"void main()");
170 if (main_func ==
nullptr)
174 LOG(
LOG_ERROR) <<
"Could not load script " << moduleName <<
" - there is no function `main()";
183 result = context->Prepare(main_func);
186 LOG(
LOG_ERROR) <<
"Could not load script " << moduleName <<
" - failed to build module.";
194 result = context->Execute();
195 if (result != asEXECUTION_FINISHED)
198 if (result == asEXECUTION_ABORTED)
200 LOG(
LOG_DEBUG) <<
"The script was aborted before it could finish. Probably it timed out.";
202 else if (result == asEXECUTION_EXCEPTION)
205 LOG(
LOG_ERROR) <<
"An exception '" << context->GetExceptionString() <<
"' occurred. Please correct the code in file '"
206 << m_addon_scrips[unit_id].scriptName <<
"' and try again.";
209 asIScriptFunction *func = context->GetExceptionFunction();
212 LOG(
LOG_DEBUG) <<
"sect: " << func->GetScriptSectionName();
213 LOG(
LOG_DEBUG) <<
"line: " << context->GetExceptionLineNumber();
214 LOG(
LOG_DEBUG) <<
"desc: " << context->GetExceptionString();
218 LOG(
LOG_DEBUG) <<
"The script ended for some unforeseen reason " << result;
221 LOG(
LOG_ERROR) <<
"Could not load script " << moduleName <<
" - error running function `main()`, check AngelScript.log";
231 void ScriptEngine::unloadScript(
const string &scriptName, ScriptCategory category)
233 string module_name = this->composeModuleName(scriptName, category);
234 if (module_name.empty())
237 for (
size_t i = 0; i < m_addon_scrips.size(); i++)
239 if (m_addon_scrips[i].scriptModule->GetName() == module_name)
241 m_addon_scrips.erase(m_addon_scrips.begin() + i);
246 string ScriptEngine::composeModuleName(
string const &scriptName, ScriptCategory origin)
250 case ScriptCategory::BUILD_IN:
251 return "BUILD_IN: " + scriptName;
253 case ScriptCategory::ADDON:
254 return "ADDON: " + scriptName;
256 case ScriptCategory::CUSTOM:
257 return "CUSTOM: " + scriptName;
264 void ScriptEngine::messageCallback(
const asSMessageInfo *msg)
268 case asMSGTYPE_INFORMATION:
269 LOG(
LOG_INFO) << msg->section <<
" (" << msg->row <<
"," << msg->col <<
") " << msg->message;
272 case asMSGTYPE_WARNING:
273 LOG(
LOG_WARNING) << msg->section <<
" (" << msg->row <<
"," << msg->col <<
") " << msg->message;
276 case asMSGTYPE_ERROR:
277 LOG(
LOG_ERROR) << msg->section <<
" (" << msg->row <<
"," << msg->col <<
") " << msg->message;
281 LOG(
LOG_DEBUG) << msg->section <<
" (" << msg->row <<
"," << msg->col <<
") " << msg->message;