diff --git a/data/scripts/collisions.as b/data/scripts/collisions.as index 944d327c1..cce471835 100644 --- a/data/scripts/collisions.as +++ b/data/scripts/collisions.as @@ -3,5 +3,5 @@ void onCollision() /* Currently activates on Kart collisions */ - displayMessage("Whoa! Road rage..."); + displayMessage("Whoa! Road rage... between Kart: " + getCollidingKart1() + " - " + getCollidingKart2()); } diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 7bfcb0459..3c9e1024b 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -171,6 +171,9 @@ void Physics::update(float dt) p->getUserPointer(1)->getPointerKart(), p->getContactPointCS(1) ); ScriptEngine* script_engine = World::getWorld()->getScriptEngine(); + int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId(); + int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId(); + script_engine->setCollision(kartid1,kartid2); script_engine->runScript("collisions"); continue; } // if kart-kart collision diff --git a/src/scriptengine/script_engine.cpp b/src/scriptengine/script_engine.cpp index d7fecdb62..1c9520338 100644 --- a/src/scriptengine/script_engine.cpp +++ b/src/scriptengine/script_engine.cpp @@ -36,226 +36,242 @@ using namespace irr; // Function prototypes for binding. - void displayMessage(asIScriptGeneric *gen); - void disableAnimation(asIScriptGeneric *gen); - void enableAnimation(asIScriptGeneric *gen); - void squashKart(asIScriptGeneric *gen); - void enableTrigger(asIScriptGeneric *gen); - void disableTrigger(asIScriptGeneric *gen); - + void displayMessage(asIScriptGeneric *gen); + void disableAnimation(asIScriptGeneric *gen); + void enableAnimation(asIScriptGeneric *gen); + void squashKart(asIScriptGeneric *gen); + void enableTrigger(asIScriptGeneric *gen); + void disableTrigger(asIScriptGeneric *gen); + + int m_collidingkartid1; + int m_collidingkartid2; + ScriptEngine::ScriptEngine() { - // Create the script engine - m_engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); - if( m_engine == 0 ) - { - std::cout << "Failed to create script engine." << std::endl; - } - - - // Configure the script engine with all the functions, - // and variables that the script should be able to use. - configureEngine(m_engine); + // Create the script engine + m_engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); + if( m_engine == 0 ) + { + std::cout << "Failed to create script engine." << std::endl; + } + m_collidingkartid1 = 0; + m_collidingkartid2 = 0; + // Configure the script engine with all the functions, + // and variables that the script should be able to use. + configureEngine(m_engine); } ScriptEngine::~ScriptEngine() { - // Release the engine - m_engine->Release(); + // Release the engine + m_engine->Release(); } // Displays the message specified in displayMessage( string message ) within the script void displayMessage(asIScriptGeneric *gen) { - std::string *input = (std::string*)gen->GetArgAddress(0); - irr::core::stringw out = irr::core::stringw((*input).c_str()); //irr::core::stringw supported by message dialogs - new TutorialMessageDialog((out),true); + std::string *input = (std::string*)gen->GetArgAddress(0); + irr::core::stringw out = irr::core::stringw((*input).c_str()); //irr::core::stringw supported by message dialogs + new TutorialMessageDialog((out),true); } void disableAnimation(asIScriptGeneric *gen) { - std::string *str = (std::string*)gen->GetArgAddress(0); - std::string type = "mesh"; - World::getWorld()->getTrack()->getTrackObjectManager()->disable(*str,type); + std::string *str = (std::string*)gen->GetArgAddress(0); + std::string type = "mesh"; + World::getWorld()->getTrack()->getTrackObjectManager()->disable(*str,type); } void enableAnimation(asIScriptGeneric *gen) { - std::string *str = (std::string*)gen->GetArgAddress(0); - std::string type = "mesh"; - World::getWorld()->getTrack()->getTrackObjectManager()->enable(*str,type); + std::string *str = (std::string*)gen->GetArgAddress(0); + std::string type = "mesh"; + World::getWorld()->getTrack()->getTrackObjectManager()->enable(*str,type); } void disableTrigger(asIScriptGeneric *gen) { - std::string *str = (std::string*)gen->GetArgAddress(0); - std::string type = "action-trigger"; - World::getWorld()->getTrack()->getTrackObjectManager()->disable(*str,type); + std::string *str = (std::string*)gen->GetArgAddress(0); + std::string type = "action-trigger"; + World::getWorld()->getTrack()->getTrackObjectManager()->disable(*str,type); } void enableTrigger(asIScriptGeneric *gen) { - std::string *str = (std::string*)gen->GetArgAddress(0); - std::string type = "action-trigger"; - World::getWorld()->getTrack()->getTrackObjectManager()->enable(*str,type); + std::string *str = (std::string*)gen->GetArgAddress(0); + std::string type = "action-trigger"; + World::getWorld()->getTrack()->getTrackObjectManager()->enable(*str,type); } void squashKart(asIScriptGeneric *gen) { - int id = (int)gen->GetArgDWord(0); - float time = gen->GetArgFloat(1); - AbstractKart* kart = World::getWorld()->getKart(id); - kart->setSquash(time,0.5); //0.5 * max speed is new max for squashed duration + int id = (int)gen->GetArgDWord(0); + float time = gen->GetArgFloat(1); + AbstractKart* kart = World::getWorld()->getKart(id); + kart->setSquash(time,0.5); //0.5 * max speed is new max for squashed duration +} +void getCollidingKart1(asIScriptGeneric *gen) +{ + gen->SetReturnDWord(m_collidingkartid1); +} +void getCollidingKart2(asIScriptGeneric *gen) +{ + gen->SetReturnDWord(m_collidingkartid2); } - std::string getScript(std::string scriptName) { - std::string script_dir = file_manager->getAsset(FileManager::SCRIPT, ""); - - script_dir += scriptName + ".as"; - FILE *f = fopen(script_dir.c_str(), "rb"); - if( f == 0 ) - { - std::cout << "Failed to open the script file " + scriptName + ".as" << std::endl; - } + std::string script_dir = file_manager->getAsset(FileManager::SCRIPT, ""); + + script_dir += scriptName + ".as"; + FILE *f = fopen(script_dir.c_str(), "rb"); + if( f == 0 ) + { + std::cout << "Failed to open the script file " + scriptName + ".as" << std::endl; + } - // Determine the size of the file - fseek(f, 0, SEEK_END); - int len = ftell(f); - fseek(f, 0, SEEK_SET); + // Determine the size of the file + fseek(f, 0, SEEK_END); + int len = ftell(f); + fseek(f, 0, SEEK_SET); - // Read the entire file - std::string script; - script.resize(len); - int c = fread(&script[0], len, 1, f); - fclose(f); - if( c == 0 ) - { - std::cout << "Failed to load script file." << std::endl; - } - return script; + // Read the entire file + std::string script; + script.resize(len); + int c = fread(&script[0], len, 1, f); + fclose(f); + if( c == 0 ) + { + std::cout << "Failed to load script file." << std::endl; + } + return script; } void ScriptEngine::runScript(std::string scriptName) { - int r; - // Compile the script code - r = compileScript(m_engine,scriptName); - if( r < 0 ) - { - m_engine->Release(); - return; - } + int r; + // Compile the script code + r = compileScript(m_engine,scriptName); + if( r < 0 ) + { + m_engine->Release(); + return; + } - // Create a context that will execute the script. - asIScriptContext *ctx = m_engine->CreateContext(); - if( ctx == 0 ) - { - std::cout << "Failed to create the context." << std::endl; - m_engine->Release(); - return; - } + // Create a context that will execute the script. + asIScriptContext *ctx = m_engine->CreateContext(); + if( ctx == 0 ) + { + std::cout << "Failed to create the context." << std::endl; + m_engine->Release(); + return; + } - if( r < 0 ) - { - std::cout << "Failed to set the line callback function." << std::endl; - ctx->Release(); - m_engine->Release(); - return; - } + if( r < 0 ) + { + std::cout << "Failed to set the line callback function." << std::endl; + ctx->Release(); + m_engine->Release(); + return; + } - // Find the function for the function we want to execute. - //This is how you call a normal function with arguments - //asIScriptFunction *func = engine->GetModule(0)->GetFunctionByDecl("void func(arg1Type, arg2Type)"); - asIScriptFunction *func; - if (scriptName=="collisions")//TODO Better way to handle this? - { - func = m_engine->GetModule(0)->GetFunctionByDecl("void onCollision()"); - } - else - { + // Find the function for the function we want to execute. + //This is how you call a normal function with arguments + //asIScriptFunction *func = engine->GetModule(0)->GetFunctionByDecl("void func(arg1Type, arg2Type)"); + asIScriptFunction *func; + if (scriptName=="collisions")//TODO Better way to handle this? + { + func = m_engine->GetModule(0)->GetFunctionByDecl("void onCollision()"); + } + else + { func = m_engine->GetModule(0)->GetFunctionByDecl("void onTrigger()"); } - if( func == 0 ) - { - std::cout << "The required function was not found." << std::endl; - ctx->Release(); - m_engine->Release(); - return; - } + if( func == 0 ) + { + std::cout << "The required function was not found." << std::endl; + ctx->Release(); + m_engine->Release(); + return; + } - // Prepare the script context with the function we wish to execute. Prepare() - // must be called on the context before each new script function that will be - // executed. Note, that if you intend to execute the same function several - // times, it might be a good idea to store the function returned by - // GetFunctionByDecl(), so that this relatively slow call can be skipped. - r = ctx->Prepare(func); - if( r < 0 ) - { - std::cout << "Failed to prepare the context." << std::endl; - ctx->Release(); - m_engine->Release(); - return; - } + // Prepare the script context with the function we wish to execute. Prepare() + // must be called on the context before each new script function that will be + // executed. Note, that if you intend to execute the same function several + // times, it might be a good idea to store the function returned by + // GetFunctionByDecl(), so that this relatively slow call can be skipped. + r = ctx->Prepare(func); + if( r < 0 ) + { + std::cout << "Failed to prepare the context." << std::endl; + ctx->Release(); + m_engine->Release(); + return; + } - // Here, we can pass parameters to the script functions. - //ctx->setArgType(index, value); - //for example : ctx->SetArgFloat(0, 3.14159265359f); + // Here, we can pass parameters to the script functions. + //ctx->setArgType(index, value); + //for example : ctx->SetArgFloat(0, 3.14159265359f); - // 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 ) - std::cout << "The script was aborted before it could finish. Probably it timed out." << std::endl; - else if( r == asEXECUTION_EXCEPTION ) - { - std::cout << "The script ended with an exception." << std::endl; + // 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 ) + std::cout << "The script was aborted before it could finish. Probably it timed out." << std::endl; + else if( r == asEXECUTION_EXCEPTION ) + { + std::cout << "The script ended with an exception." << std::endl; - // Write some information about the script exception - asIScriptFunction *func = ctx->GetExceptionFunction(); - std::cout << "func: " << func->GetDeclaration() << std::endl; - std::cout << "modl: " << func->GetModuleName() << std::endl; - std::cout << "sect: " << func->GetScriptSectionName() << std::endl; - std::cout << "line: " << ctx->GetExceptionLineNumber() << std::endl; - std::cout << "desc: " << ctx->GetExceptionString() << std::endl; - } - else - std::cout << "The script ended for some unforeseen reason (" << r << ")." << std::endl; - } - else - { - // Retrieve the return value from the context here (for scripts that return values) - // returnValue = ctx->getReturnType(); for example - //float returnValue = ctx->GetReturnFloat(); - } + // Write some information about the script exception + asIScriptFunction *func = ctx->GetExceptionFunction(); + std::cout << "func: " << func->GetDeclaration() << std::endl; + std::cout << "modl: " << func->GetModuleName() << std::endl; + std::cout << "sect: " << func->GetScriptSectionName() << std::endl; + std::cout << "line: " << ctx->GetExceptionLineNumber() << std::endl; + std::cout << "desc: " << ctx->GetExceptionString() << std::endl; + } + else + std::cout << "The script ended for some unforeseen reason (" << r << ")." << std::endl; + } + else + { + // Retrieve the return value from the context here (for scripts that return values) + // returnValue = ctx->getReturnType(); for example + //float returnValue = ctx->GetReturnFloat(); + } - // We must release the contexts when no longer using them - ctx->Release(); + // We must release the contexts when no longer using them + ctx->Release(); } - +void ScriptEngine::setCollision(int collider1,int collider2) +{ + m_collidingkartid1 = collider1; + m_collidingkartid2 = collider2; +} void ScriptEngine::configureEngine(asIScriptEngine *engine) { - int r; + int r; - // Register the script string type - RegisterStdString(engine); + // Register the script string type + RegisterStdString(engine); - r = engine->RegisterGlobalFunction("void displayMessage(string &in)", asFUNCTION(displayMessage), asCALL_GENERIC); assert(r>=0); - r = engine->RegisterGlobalFunction("void disableAnimation(string &in)", asFUNCTION(disableAnimation), asCALL_GENERIC); assert(r>=0); - r = engine->RegisterGlobalFunction("void enableAnimation(string &in)", asFUNCTION(enableAnimation), asCALL_GENERIC); assert(r>=0); - r = engine->RegisterGlobalFunction("void squashKart(int id, float time)", asFUNCTION(squashKart), asCALL_GENERIC); assert(r>=0); - r = engine->RegisterGlobalFunction("void enableTrigger(string &in)", asFUNCTION(enableTrigger), asCALL_GENERIC); assert(r>=0); - r = engine->RegisterGlobalFunction("void disableTrigger(string &in)", asFUNCTION(disableTrigger), asCALL_GENERIC); assert(r>=0); + r = engine->RegisterGlobalFunction("void displayMessage(string &in)", asFUNCTION(displayMessage), asCALL_GENERIC); assert(r>=0); + r = engine->RegisterGlobalFunction("void disableAnimation(string &in)", asFUNCTION(disableAnimation), asCALL_GENERIC); assert(r>=0); + r = engine->RegisterGlobalFunction("void enableAnimation(string &in)", asFUNCTION(enableAnimation), asCALL_GENERIC); assert(r>=0); + r = engine->RegisterGlobalFunction("void squashKart(int id, float time)", asFUNCTION(squashKart), asCALL_GENERIC); assert(r>=0); + r = engine->RegisterGlobalFunction("void enableTrigger(string &in)", asFUNCTION(enableTrigger), asCALL_GENERIC); assert(r>=0); + r = engine->RegisterGlobalFunction("void disableTrigger(string &in)", asFUNCTION(disableTrigger), asCALL_GENERIC); assert(r>=0); + r = engine->RegisterGlobalFunction("uint getCollidingKart1()", asFUNCTION(getCollidingKart1), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("uint getCollidingKart2()", asFUNCTION(getCollidingKart2), asCALL_GENERIC); assert( r >= 0 ); - // It is possible to register the functions, properties, and types in - // configuration groups as well. When compiling the scripts it can then - // be defined which configuration groups should be available for that - // script. If necessary a configuration group can also be removed from - // the engine, so that the engine configuration could be changed - // without having to recompile all the scripts. + // It is possible to register the functions, properties, and types in + // configuration groups as well. When compiling the scripts it can then + // be defined which configuration groups should be available for that + // script. If necessary a configuration group can also be removed from + // the engine, so that the engine configuration could be changed + // without having to recompile all the scripts. } @@ -263,42 +279,42 @@ void ScriptEngine::configureEngine(asIScriptEngine *engine) int ScriptEngine::compileScript(asIScriptEngine *engine, std::string scriptName) { - int r; + int r; - std::string script = getScript(scriptName); - // Add the script sections that will be compiled into executable code. - // If we want to combine more than one file into the same script, then - // we can call AddScriptSection() several times for the same module and - // the script engine will treat them all as if they were one. The script - // section name, will allow us to localize any errors in the script code. - asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); - r = mod->AddScriptSection("script", &script[0], script.size()); - if( r < 0 ) - { - std::cout << "AddScriptSection() failed" << std::endl; - return -1; - } - - // Compile the script. If there are any compiler messages they will - // be written to the message stream that we set right after creating the - // script engine. If there are no errors, and no warnings, nothing will - // be written to the stream. - r = mod->Build(); - if( r < 0 ) - { - std::cout << "Build() failed" << std::endl; - return -1; - } + std::string script = getScript(scriptName); + // Add the script sections that will be compiled into executable code. + // If we want to combine more than one file into the same script, then + // we can call AddScriptSection() several times for the same module and + // the script engine will treat them all as if they were one. The script + // section name, will allow us to localize any errors in the script code. + asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); + r = mod->AddScriptSection("script", &script[0], script.size()); + if( r < 0 ) + { + std::cout << "AddScriptSection() failed" << std::endl; + return -1; + } + + // Compile the script. If there are any compiler messages they will + // be written to the message stream that we set right after creating the + // script engine. If there are no errors, and no warnings, nothing will + // be written to the stream. + r = mod->Build(); + if( r < 0 ) + { + std::cout << "Build() failed" << std::endl; + return -1; + } - // The engine doesn't keep a copy of the script sections after Build() has - // returned. So if the script needs to be recompiled, then all the script - // sections must be added again. + // The engine doesn't keep a copy of the script sections after Build() has + // returned. So if the script needs to be recompiled, then all the script + // sections must be added again. - // If we want to have several scripts executing at different times but - // that have no direct relation with each other, then we can compile them - // into separate script modules. Each module uses their own namespace and - // scope, so function names, and global variables will not conflict with - // each other. + // If we want to have several scripts executing at different times but + // that have no direct relation with each other, then we can compile them + // into separate script modules. Each module uses their own namespace and + // scope, so function names, and global variables will not conflict with + // each other. - return 0; + return 0; } diff --git a/src/scriptengine/script_engine.hpp b/src/scriptengine/script_engine.hpp index 7a3e7db6f..a3320e0fc 100644 --- a/src/scriptengine/script_engine.hpp +++ b/src/scriptengine/script_engine.hpp @@ -29,15 +29,18 @@ class ScriptEngine public: ScriptEngine(); - ~ScriptEngine(); - - void runScript(std::string scriptName); - + ~ScriptEngine(); + + void runScript(std::string scriptName); + + void setCollision(int kartid1,int kartid2); + private: - asIScriptEngine *m_engine; - - void configureEngine(asIScriptEngine *engine); - int compileScript(asIScriptEngine *engine,std::string scriptName); + asIScriptEngine *m_engine; + + + void configureEngine(asIScriptEngine *engine); + int compileScript(asIScriptEngine *engine,std::string scriptName); }; // class ScriptEngine #endif diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index e12120810..0635d7462 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -91,7 +91,7 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, m_physical_object = NULL; - xml_node.get("model", &m_name ); + xml_node.get("model", &m_name ); xml_node.get("xyz", &m_init_xyz ); xml_node.get("hpr", &m_init_hpr ); xml_node.get("scale", &m_init_scale);