bluecore/engine/ScriptSystem.cpp

204 lines
4.6 KiB
C++
Raw Normal View History

2008-01-16 11:45:17 +00:00
#include "ScriptSystem.h"
#include "Utilities/Log.h"
// library includes
#include "physfs.h"
// system includes
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <stdarg.h>
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);
}
}