Scripting : add ability to use delegates for timeouts (enabling complex timeouts)
This commit is contained in:
parent
bd9f435190
commit
15b35b76ac
@ -172,6 +172,99 @@ namespace Scripting
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ScriptEngine::runDelegate(asIScriptFunction* delegate)
|
||||
{
|
||||
asIScriptContext *ctx = m_engine->CreateContext();
|
||||
if (ctx == NULL)
|
||||
{
|
||||
Log::error("Scripting", "runMethod: Failed to create the context.");
|
||||
//m_engine->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
int r = ctx->Prepare(delegate);
|
||||
if (r < 0)
|
||||
{
|
||||
Log::error("Scripting", "runMethod: Failed to prepare the context.");
|
||||
ctx->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the function
|
||||
r = ctx->Execute();
|
||||
if (r != asEXECUTION_FINISHED)
|
||||
{
|
||||
// The execution didn't finish as we had planned. Determine why.
|
||||
if (r == asEXECUTION_ABORTED)
|
||||
{
|
||||
Log::error("Scripting", "The script was aborted before it could finish. Probably it timed out.");
|
||||
}
|
||||
else if (r == asEXECUTION_EXCEPTION)
|
||||
{
|
||||
Log::error("Scripting", "The script ended with an exception : (line %i) %s",
|
||||
ctx->GetExceptionLineNumber(),
|
||||
ctx->GetExceptionString());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("Scripting", "The script ended for some unforeseen reason (%i)", r);
|
||||
}
|
||||
}
|
||||
|
||||
ctx->Release();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
void ScriptEngine::runMethod(asIScriptObject* obj, std::string methodName)
|
||||
{
|
||||
asIObjectType* type = obj->GetObjectType();
|
||||
asIScriptFunction* method = type->GetMethodByName(methodName.c_str());
|
||||
if (method == NULL)
|
||||
Log::error("Scripting", ("runMethod: object does not implement method " + methodName).c_str());
|
||||
|
||||
|
||||
asIScriptContext *ctx = m_engine->CreateContext();
|
||||
if (ctx == NULL)
|
||||
{
|
||||
Log::error("Scripting", "runMethod: Failed to create the context.");
|
||||
//m_engine->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
int r = ctx->Prepare(method);
|
||||
if (r < 0)
|
||||
{
|
||||
Log::error("Scripting", "runMethod: Failed to prepare the context.");
|
||||
ctx->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the function
|
||||
r = ctx->Execute();
|
||||
if (r != asEXECUTION_FINISHED)
|
||||
{
|
||||
// The execution didn't finish as we had planned. Determine why.
|
||||
if (r == asEXECUTION_ABORTED)
|
||||
{
|
||||
Log::error("Scripting", "The script was aborted before it could finish. Probably it timed out.");
|
||||
}
|
||||
else if (r == asEXECUTION_EXCEPTION)
|
||||
{
|
||||
Log::error("Scripting", "The script ended with an exception.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("Scripting", "The script ended for some unforeseen reason (%i)", r);
|
||||
}
|
||||
}
|
||||
|
||||
ctx->Release();
|
||||
}
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** runs the specified script
|
||||
* \param string scriptName = name of script to run
|
||||
*/
|
||||
@ -415,9 +508,36 @@ namespace Scripting
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PendingTimeout::PendingTimeout(double time, asIScriptFunction* callback_delegate)
|
||||
: PendingTimeout()
|
||||
{
|
||||
m_time = time;
|
||||
m_callback_delegate = callback_delegate;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PendingTimeout::~PendingTimeout()
|
||||
{
|
||||
if (m_callback_delegate != NULL)
|
||||
{
|
||||
asIScriptEngine* engine = World::getWorld()->getScriptEngine()->getEngine();
|
||||
m_callback_delegate->Release();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ScriptEngine::addPendingTimeout(double time, const std::string& callback_name)
|
||||
{
|
||||
m_pending_timeouts.push_back(PendingTimeout(time, callback_name));
|
||||
m_pending_timeouts.push_back(new PendingTimeout(time, callback_name));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ScriptEngine::addPendingTimeout(double time, asIScriptFunction* delegate)
|
||||
{
|
||||
m_pending_timeouts.push_back(new PendingTimeout(time, delegate));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -430,8 +550,16 @@ namespace Scripting
|
||||
curr.m_time -= dt;
|
||||
if (curr.m_time <= 0.0)
|
||||
{
|
||||
runFunction(true, "void " + curr.m_callback_name + "()");
|
||||
m_pending_timeouts.erase(m_pending_timeouts.begin() + i);
|
||||
if (curr.m_callback_delegate != NULL)
|
||||
{
|
||||
runDelegate(curr.m_callback_delegate);
|
||||
}
|
||||
else
|
||||
{
|
||||
runFunction(true, "void " + curr.m_callback_name + "()");
|
||||
}
|
||||
|
||||
m_pending_timeouts.erase(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,21 +23,38 @@
|
||||
#include <angelscript.h>
|
||||
#include <functional>
|
||||
|
||||
#include "scriptengine/script_utils.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
class TrackObjectPresentation;
|
||||
|
||||
namespace Scripting
|
||||
{
|
||||
/** Represents a scripting function to execute after a given time */
|
||||
struct PendingTimeout
|
||||
struct PendingTimeout : NoCopy
|
||||
{
|
||||
double m_time;
|
||||
std::string m_callback_name;
|
||||
|
||||
PendingTimeout(double time, const std::string& callback_name)
|
||||
/** We have two callback types: a string containing the name of the function
|
||||
* to call (simple callback) or a "TimeoutBase" object (advanced callback)
|
||||
*/
|
||||
std::string m_callback_name;
|
||||
asIScriptFunction* m_callback_delegate;
|
||||
|
||||
PendingTimeout()
|
||||
{
|
||||
m_callback_delegate = NULL;
|
||||
}
|
||||
|
||||
PendingTimeout(double time, const std::string& callback_name) : PendingTimeout()
|
||||
{
|
||||
m_time = time;
|
||||
m_callback_name = callback_name;
|
||||
}
|
||||
|
||||
PendingTimeout(double time, asIScriptFunction* callback_delegate);
|
||||
|
||||
~PendingTimeout();
|
||||
};
|
||||
|
||||
class ScriptEngine
|
||||
@ -53,6 +70,7 @@ namespace Scripting
|
||||
void runFunction(bool warn_if_not_found, std::string function_name,
|
||||
std::function<void(asIScriptContext*)> callback,
|
||||
std::function<void(asIScriptContext*)> get_return_value);
|
||||
void runDelegate(asIScriptFunction* delegate_fn);
|
||||
void evalScript(std::string script_fragment);
|
||||
void cleanupCache();
|
||||
|
||||
@ -60,12 +78,15 @@ namespace Scripting
|
||||
bool compileLoadedScripts();
|
||||
|
||||
void addPendingTimeout(double time, const std::string& callback_name);
|
||||
void addPendingTimeout(double time, asIScriptFunction* delegate_fn);
|
||||
void update(double dt);
|
||||
|
||||
asIScriptEngine* getEngine() { return m_engine; }
|
||||
|
||||
private:
|
||||
asIScriptEngine *m_engine;
|
||||
std::map<std::string, asIScriptFunction*> m_functions_cache;
|
||||
std::vector<PendingTimeout> m_pending_timeouts;
|
||||
PtrVector<PendingTimeout> m_pending_timeouts;
|
||||
|
||||
void configureEngine(asIScriptEngine *engine);
|
||||
}; // class ScriptEngine
|
||||
|
@ -16,7 +16,7 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "script_track.hpp"
|
||||
#include "script_utils.hpp"
|
||||
|
||||
#include "animations/three_d_animation.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
@ -132,6 +132,12 @@ namespace Scripting
|
||||
World::getWorld()->getScriptEngine()->addPendingTimeout(delay, *callback_name);
|
||||
}
|
||||
|
||||
/** Call a method from the given object after the specified delay */
|
||||
void setTimeoutDelegate(asIScriptFunction* obj, float delay)
|
||||
{
|
||||
World::getWorld()->getScriptEngine()->addPendingTimeout(delay, obj);
|
||||
}
|
||||
|
||||
/** Log to the console */
|
||||
void logInfo(std::string* log)
|
||||
{
|
||||
@ -180,6 +186,7 @@ namespace Scripting
|
||||
{
|
||||
int r; // of type asERetCodes
|
||||
engine->SetDefaultNamespace("Utils");
|
||||
|
||||
r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &in)", asFUNCTION(proxy_insertValues1), asCALL_CDECL); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &in, const string &in)", asFUNCTION(proxy_insertValues2), asCALL_CDECL); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &in, const string &in, const string &in)", asFUNCTION(proxy_insertValues3), asCALL_CDECL); assert(r >= 0);
|
||||
@ -190,6 +197,9 @@ namespace Scripting
|
||||
r = engine->RegisterGlobalFunction("int randomInt(int, int)", asFUNCTION(randomInt), asCALL_CDECL); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("float randomFloat(int, int)", asFUNCTION(randomFloat), asCALL_CDECL); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("void setTimeout(const string &in, float)", asFUNCTION(setTimeout), asCALL_CDECL); assert(r >= 0);
|
||||
|
||||
r = engine->RegisterFuncdef("void TimeoutCallback()"); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("void setTimeoutDelegate(TimeoutCallback@, float)", asFUNCTION(setTimeoutDelegate), asCALL_CDECL); assert(r >= 0);
|
||||
|
||||
r = engine->RegisterGlobalFunction("void logInfo(const string &in)", asFUNCTION(logInfo), asCALL_CDECL); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("void logWarning(const string &in)", asFUNCTION(logWarning), asCALL_CDECL); assert(r >= 0);
|
||||
|
Loading…
Reference in New Issue
Block a user