/* * PPOGL - PlanetPenguin Open Game Library * Copyright (C) 2005 Volker Stroebel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ppogl_script.h" #include "base/errors.h" // classes/functions to bind #include "translation.h" #include "font.h" #include "textures.h" #include "audio/audiomgr.h" #include #include #include #include #include #include #include #include #include #include "base/os.h" #define DEFAULT_STACKSIZE 2048 // some utility functions static int my_chdir(ppogl::Script *vm) { std::string dir=vm->getString(1); bool result = ppogl::os::chdir(dir); vm->pushBool(result); return 1; } static int my_cwd(ppogl::Script *vm) { std::string dir = ppogl::os::cwd(); if(dir.empty()){ return 0; }else{ vm->pushString(dir); return 1; } } static int my_dir(ppogl::Script *vm) { std::string path = vm->getString(1); bool only_dirs=false; if(vm->getTop()>=2){ only_dirs = vm->getBool(2); } vm->pushRootTable(); vm->newArray(); ppogl::os::dir dir(path,only_dirs); ppogl::os::dir::iterator it; for(it=dir.begin(); it!=dir.end();it++){ vm->pushString(*it); vm->arrayAppend(); } return 1; } static int my_isFile(ppogl::Script *vm) { std::string path=vm->getString(1); bool result = ppogl::os::isFile(path); vm->pushBool(result); return 1; } static int my_isDirectory(ppogl::Script *vm) { std::string path=vm->getString(1); bool result = ppogl::os::isDirectory(path); vm->pushBool(result); return 1; } static void my_printfunc(HSQUIRRELVM vm, const SQChar *s, ...) { va_list arglist; va_start(arglist, s); vprintf(s, arglist); va_end(arglist); fflush(stdout); } namespace ppogl{ static const struct ppogl::Script::Lib ppogllib[]={ {"cd",my_chdir}, {"cwd",my_cwd}, {"dir",my_dir}, {"isFile",my_isFile}, {"isDirectory",my_isDirectory}, {NULL, NULL} }; static const struct ppogl::Script::Lib translationlib[]={ {"set", ppogl::Translation::sqSet}, {"get", ppogl::Translation::sqGet}, {"addLanguage", ppogl::Translation::sqAddLanguage}, {NULL, NULL} }; static const struct ppogl::Script::Lib fontlib[]={ {"load", ppogl::FontMgr::sqLoad}, {"bind", ppogl::FontMgr::sqBind}, {NULL, NULL} }; static const struct ppogl::Script::Lib texturelib[]={ {"load", ppogl::TextureMgr::sqLoad}, {"bind", ppogl::TextureMgr::sqBind}, {NULL, NULL} }; static const struct ppogl::Script::Lib audiolib[]={ {"loadSound", ppogl::AudioMgr::sqLoadSound}, {"bindSound", ppogl::AudioMgr::sqBindSound}, {"loadMusic", ppogl::AudioMgr::sqLoadMusic}, {"bindMusic", ppogl::AudioMgr::sqBindMusic}, {NULL, NULL} }; Script::Script() { m_vm = sq_open(DEFAULT_STACKSIZE); sqstd_seterrorhandlers(m_vm); sq_setprintfunc(m_vm, my_printfunc); //sets the print function if(m_vm==NULL){ PP_ERROR("Unable to create squirrel vm"); } sq_pushroottable(m_vm); sqstd_register_iolib(m_vm); sqstd_register_stringlib(m_vm); registerLib("ppogl", ppogllib); registerLib("Translation", translationlib); registerLib("Fonts", fontlib); registerLib("Textures", texturelib); registerLib("Audio", audiolib); } Script::~Script() { sq_close(m_vm); } bool Script::doFile(const std::string& filename) { std::string::size_type pos; pos = filename.find_last_of('/'); if(pos!=std::string::npos){ ppogl::os::chdir(filename.substr(0,pos)); } sq_pushroottable(m_vm); if(SQ_SUCCEEDED(sqstd_dofile(m_vm, _SC(filename.c_str()), SQFalse, SQTrue))) { }else{ //todo: implement error handling PP_WARNING("Error parsing script: " << filename.c_str()); } sq_pop(m_vm,1); return true; } void Script::registerLib(const std::string& name, const Script::Lib *callbacks) { sq_pushstring(m_vm,name.c_str(),-1); if(SQ_FAILED(sq_get(m_vm,-2))){ sq_pushroottable(m_vm); sq_pushstring(m_vm,name.c_str(),-1); sq_newtable(m_vm); } for(int i=0; callbacks[i].name!=NULL; i++){ sq_pushstring(m_vm,callbacks[i].name,-1); sq_pushuserpointer(m_vm,(SQUserPointer *)this); sq_pushuserpointer(m_vm,*((SQUserPointer *)&(callbacks[i].function) )); sq_newclosure(m_vm,Script::defaultCb,2); sq_createslot(m_vm,-3); } sq_rawset(m_vm,-3); } int Script::defaultCb(HSQUIRRELVM vm) { Script *script; ScriptFunc *func; sq_getuserpointer(vm,-1,(SQUserPointer *)&script); sq_getuserpointer(vm,-2,(SQUserPointer *)&func); sq_pop(vm,2); sq_remove(vm,1); return (*func)(script); } bool Script::isKeyInTable(const std::string& key, int index) { bool exists=false; pushString(key); if(get(index-1)){ exists=true; pop(); } return exists; } const std::string Script::getStringFromTable(const std::string& key, int index) { pushString(key); std::string string; if(get(index-1)){ string = getString(); pop(); } return string; } double Script::getFloatFromTable(const std::string& key, int index) { pushString(key); double value = 0; if(get(index-1)){ value = getFloat(); pop(); } return value; } int Script::getIntFromTable(const std::string& key, int index) { pushString(key); int value = 0; if(get(index-1)){ value = getInt(); pop(); } return value; } bool Script::getBoolFromTable(const std::string& key, int index) { pushString(key); bool boolean = false; if(get(index-1)){ boolean = getBool(); pop(); } return boolean; } const std::string Script::getString(int index) { const SQChar* value; sq_getstring(m_vm, index, &value); if(value != NULL){ return value; }else{ return ""; } } double Script::getFloat(int index) { SQFloat value=0; sq_getfloat(m_vm, index, &value); return value; } int Script::getInt(int index) { SQInteger value=0; sq_getinteger(m_vm, index, &value); return value; } bool Script::getBool(int index) { SQBool value; sq_getbool(m_vm, index, &value); return value; } bool Script::isNull(int index) { return sq_gettype(m_vm, index)==OT_NULL; } bool Script::isString(int index) { return sq_gettype(m_vm, index)==OT_STRING; } bool Script::isFloat(int index) { return sq_gettype(m_vm, index)==OT_FLOAT; } bool Script::isInt(int index) { return sq_gettype(m_vm, index)==OT_INTEGER; } bool Script::isBool(int index) { return sq_gettype(m_vm, index)==OT_BOOL; } bool Script::isTable(int index) { return sq_gettype(m_vm, index)==OT_TABLE; } bool Script::isArray(int index) { return sq_gettype(m_vm, index)==OT_ARRAY; } void Script::pushNull() { sq_pushnull(m_vm); } void Script::pushString(const std::string& string) { sq_pushstring(m_vm, string.c_str(), -1); } void Script::pushFloat(double number) { sq_pushfloat(m_vm, number); } void Script::pushInt(int number) { sq_pushinteger(m_vm, number); } void Script::pushBool(bool boolean) { sq_pushbool(m_vm, boolean); } void Script::newArray(int size) { sq_newarray(m_vm,size); } bool Script::get(int index) { return SQ_SUCCEEDED(sq_get(m_vm, index)); } void Script::set(int index) { sq_set(m_vm, index); } bool Script::rawGet(int index) { return SQ_SUCCEEDED(sq_rawget(m_vm, index)); } void Script::rawSet(int index) { sq_rawset(m_vm, index); } void Script::arrayAppend(int index) { sq_arrayappend(m_vm, index); } bool Script::next(int index) { return SQ_SUCCEEDED(sq_next(m_vm, index)); } void Script::pop(int n) { sq_pop(m_vm,n); } int Script::getTop() { return sq_gettop(m_vm); } void Script::pushRootTable() { sq_pushroottable(m_vm); } bool Script::call(int arguments, bool retValue) { return SQ_SUCCEEDED(sq_call(m_vm,arguments,retValue)); } } // namespace ppogl