#include "ScriptSystem.h" #include "Utilities/Log.h" // library includes #include "physfs.h" // system includes #include #include #include #include using namespace std; namespace BlueCore { //-------------------------------------------------------------------------- static ScriptSystem* gScriptSystem = 0; //-------------------------------------------------------------------------- void _sq_compiler_error_handler(HSQUIRRELVM vm, const SQChar *error, const SQChar *source, SQInteger line, SQInteger column) { clog << "!!! Error compiling script '"<< source << ":"<< line << ": " << error << endlog; } //-------------------------------------------------------------------------- static SQInteger _sq_runtime_error_handler(HSQUIRRELVM vm) { const SQChar *error = 0; if (sq_gettop(vm) >= 1) { if (SQ_SUCCEEDED(sq_getstring(vm, 2, &error) ) ) { clog << "!!! Script Error: "<< error << endlog; } else { clog << "!!! Script Error: unknown"<< endlog; } } return 0; } //-------------------------------------------------------------------------- void _sq_print(HSQUIRRELVM vm, const SQChar* s, ...) { va_list vl; va_start ( vl, s ); vprintf(s, vl); va_end ( vl ); } //-------------------------------------------------------------------------- static SQInteger _sq_require(HSQUIRRELVM v) { const SQChar *scriptname = 0; if (SQ_SUCCEEDED(sq_getstring(v, 2, &scriptname) )) { if (gScriptSystem) gScriptSystem->loadScript(scriptname); } return 0; } //-------------------------------------------------------------------------- SQInteger _sq_file_reader(SQUserPointer file) { char c; unsigned int count; count = PHYSFS_read( (PHYSFS_file *)file, &c, sizeof (c), 1); if (count > 0) return c; return 0; } //-------------------------------------------------------------------------- ScriptSystem::ScriptSystem() { gScriptSystem = this; _VM = sq_open( 1024); sq_setcompilererrorhandler(_VM, _sq_compiler_error_handler); sq_newclosure(_VM, _sq_runtime_error_handler, 0); sq_seterrorhandler(_VM); sq_setprintfunc(_VM, _sq_print); sq_pushroottable(_VM); sq_pushstring(_VM, "require", -1); sq_newclosure(_VM, _sq_require, 0); sq_setparamscheck(_VM, 2, ".s"); sq_newslot(_VM, -3, false); sq_pop(_VM, 1); clog << ">>> ScriptSystem constructed ..."<< endlog; } //-------------------------------------------------------------------------- ScriptSystem::~ScriptSystem() { sq_close(_VM); clog << ">>> ScriptSystem destructed ..."<< endlog; } //-------------------------------------------------------------------------- HSQUIRRELVM ScriptSystem::getVM() { return _VM; } //-------------------------------------------------------------------------- bool ScriptSystem::loadScript(const std::string &name) { for (unsigned int i = 0; i < _LoadedScripts.size(); i++) { if (_LoadedScripts[i] == name) return true; } if (executeScript(name) ) { _LoadedScripts.push_back(name); return true; } else clog << "!!! Script '"<< name << "' not found!"<< endlog; return false; } //-------------------------------------------------------------------------- bool ScriptSystem::executeScript(const std::string &name) { string filename = name + ".nut"; PHYSFS_file *file = PHYSFS_openRead(filename.c_str() ); if ( !file) { clog << "!!! Script '"<< name << "' not found!"<< endlog; return false; } SQInteger ret; ret = sq_compile(_VM, _sq_file_reader, file, name.c_str(), 1); PHYSFS_close(file); if (SQ_FAILED(ret) ) { return false; } sq_pushroottable(_VM); ret = sq_call(_VM, 1, SQFalse, SQTrue); sq_pop(_VM, 1); if (SQ_FAILED(ret) ) { clog << "!!! Script execution failed: "<< name << endlog; return false; } else return true; } //-------------------------------------------------------------------------- void ScriptSystem::callFunction(const std::string &name) { sq_pushroottable(_VM); sq_pushstring(_VM, name.c_str(), -1); if (SQ_SUCCEEDED(sq_get(_VM, -2)) ) { sq_pushroottable(_VM); if (sq_call(_VM, 1, SQTrue, SQTrue) ) sq_pop(_VM, 1); } sq_pop(_VM, 1); } //-------------------------------------------------------------------------- void ScriptSystem::callFunction(const std::string &name, double value) { sq_pushroottable(_VM); sq_pushstring(_VM, name.c_str(), -1); if (SQ_SUCCEEDED(sq_get(_VM, -2)) ) { sq_pushroottable(_VM); sq_pushfloat(_VM, value); if (sq_call(_VM, 2, SQTrue, SQTrue) ) sq_pop(_VM, 1); } sq_pop(_VM, 1); } }