#include "ag.h" #include "anaglym.h" #include "Engine.h" #include "Video.h" #include #include "wfobj/WFObj.hh" #include /* usleep() */ #include #include #include #include #include #ifdef _WIN32 #include /* Sleep() */ #endif using namespace std; namespace ag { void register_functions(lua_State * L) { static const luaL_Reg functions[] = { { "print", print }, { "println", println }, { "loadModel", loadModel }, { "loadStaticModel", loadStaticModel }, { "sleep", sleep }, { "startFrame", startFrame }, { "endFrame", endFrame }, { "setCamera", setCamera }, { "elapsedTime", elapsedTime }, { "doPhysics", doPhysics }, { "drawObjects", drawObjects }, { "setAutoPhysics", setAutoPhysics }, { "setAutoStartFrame", setAutoStartFrame }, { "setAutoEndFrame", setAutoEndFrame }, { NULL, NULL } }; luaL_register(L, "ag", functions); } static void print_val(lua_State * L, int index) { int type = lua_type(L, index); switch (type) { case LUA_TNUMBER: cout << lua_tonumber(L, index); break; case LUA_TSTRING: cout << lua_tostring(L, index); break; case LUA_TTABLE: cout << "{ "; /* traverse the table and print the keys/values */ lua_checkstack(L, 3); lua_pushnil(L); for (bool first = true; lua_next(L, index) != 0; first = false) { if (!first) cout << ", "; cout << '['; print_val(L, lua_gettop(L) - 1); cout << ']'; cout << " => "; print_val(L, lua_gettop(L)); lua_pop(L, 1); } cout << " }"; break; case LUA_TFUNCTION: cout << ""; break; case LUA_TUSERDATA: cout << ""; break; case LUA_TTHREAD: cout << ""; break; case LUA_TLIGHTUSERDATA: cout << ""; break; } } int print(lua_State * L) { int argc = lua_gettop(L); for ( int n = 1; n <= argc; n++ ) { print_val(L, n); } return 0; } int println(lua_State * L) { int ret = print(L); cout << endl; return ret; } static void createLuaObject(lua_State * L, int id) { lua_newtable(L); lua_pushinteger(L, id); lua_setfield(L, -2, "id"); lua_pushcfunction(L, object::draw); lua_setfield(L, -2, "draw"); lua_pushcfunction(L, object::setPosition); lua_setfield(L, -2, "setPosition"); lua_pushcfunction(L, object::getPosition); lua_setfield(L, -2, "getPosition"); lua_pushcfunction(L, object::clone); lua_setfield(L, -2, "clone"); lua_pushcfunction(L, object::destroy); lua_setfield(L, -2, "destroy"); lua_pushcfunction(L, object::setVisible); lua_setfield(L, -2, "setVisible"); } static int loadModelSpecify(lua_State * L, bool static_data) { float scale = 1.0f; int argc = lua_gettop(L); if (argc >= 2 && lua_isnumber(L, 2)) { scale = lua_tonumber(L, 2); } if (argc >= 1 && lua_isstring(L, 1)) { string modelname = lua_tostring(L, 1); size_t pos = modelname.find_first_not_of(FILENAME_SAFE_CHARS); if (pos == string::npos) { string path = g_engine->locateResource(modelname + ".obj"); string physpath = g_engine->locateResource(modelname + ".phy"); if (path != "") { WFObj * obj = new WFObj(); if (obj->load(path)) { int id = g_engine->addObject(obj, static_data, scale); createLuaObject(L, id); if (physpath != "") { Engine::Object * obj = g_engine->getObject(id); if (obj != NULL) { obj->loadPhy(physpath); } } return 1; } else { delete obj; cerr << "error loading object" << endl; } } } } lua_pushnil(L); return 1; } int loadModel(lua_State * L) { return loadModelSpecify(L, false); } int loadStaticModel(lua_State * L) { return loadModelSpecify(L, true); } int sleep(lua_State * L) { int argc = lua_gettop(L); if (argc == 1) { if (lua_isnumber(L, -1)) { double seconds = lua_tonumber(L, -1); #ifdef _WIN32 Sleep((DWORD)(seconds * 1000)); #else usleep((useconds_t) (seconds * 1000000)); #endif } } return 0; } int startFrame(lua_State * L) { g_engine->startFrame(); return 0; } int endFrame(lua_State * L) { g_engine->endFrame(); return 0; } int setCamera(lua_State * L) { return g_engine->setCamera(L); } int elapsedTime(lua_State * L) { lua_pushinteger(L, SDL_GetTicks()); return 1; } int doPhysics(lua_State * L) { g_engine->doPhysics(); return 0; } int drawObjects(lua_State * L) { g_engine->drawObjects(); return 0; } int setAutoPhysics(lua_State * L) { int argc = lua_gettop(L); if (argc == 1 && lua_isboolean(L, 1)) g_engine->setAutoPhysics(lua_toboolean(L, 1)); return 0; } int setAutoStartFrame(lua_State * L) { int argc = lua_gettop(L); if (argc == 1 && lua_isboolean(L, 1)) g_engine->setAutoStartFrame(lua_toboolean(L, 1)); return 0; } int setAutoEndFrame(lua_State * L) { int argc = lua_gettop(L); if (argc == 1 && lua_isboolean(L, 1)) g_engine->setAutoEndFrame(lua_toboolean(L, 1)); return 0; } namespace object { static Engine::Object * getObject(lua_State * L, int index) { Engine::Object * ret = NULL; lua_getfield(L, index, "id"); if (lua_isnumber(L, -1)) { int id = lua_tointeger(L, -1); ret = g_engine->getObject(id); } lua_pop(L, 1); return ret; } int draw(lua_State * L) { int argc = lua_gettop(L); if (argc == 1 && lua_istable(L, -1)) { Engine::Object * obj = getObject(L, -1); if (obj != NULL) obj->draw(); } return 0; } int setPosition(lua_State * L) { int argc = lua_gettop(L); if (argc == 4) { Engine::Object * obj = getObject(L, 1); if (obj != NULL) { double position[3]; for (int i = 0; i < 3; i++) { if (lua_isnumber(L, i + 2)) { position[i] = lua_tonumber(L, i + 2); } } obj->setPosition(position[0], position[1], position[2]); } } return 0; } int getPosition(lua_State * L) { int argc = lua_gettop(L); if (argc == 1) { Engine::Object * obj = getObject(L, 1); if (obj != NULL) { double x, y, z; obj->getPosition(&x, &y, &z); lua_pushnumber(L, x); lua_pushnumber(L, y); lua_pushnumber(L, z); return 3; } } return 0; } int clone(lua_State * L) { int argc = lua_gettop(L); bool found = false; if (argc == 1) { Engine::Object * obj = getObject(L, 1); if (obj != NULL) { found = true; int id = g_engine->cloneObject(obj); createLuaObject(L, id); } } if (!found) lua_pushnil(L); return 1; } static void clearLuaTable(lua_State * L, int index) { lua_pushnil(L); /* * lua_next pops the key from the stack * it pushes the key, value pair if there is one */ while (lua_next(L, index) != 0) { lua_pop(L, 1); /* pop old value */ lua_pushvalue(L, -1); /* duplicate the key */ lua_pushnil(L); lua_settable(L, index); /* set table[key] = nil */ } } int destroy(lua_State * L) { int argc = lua_gettop(L); if (argc == 1) { lua_getfield(L, 1, "id"); if (lua_isnumber(L, -1)) { int id = lua_tointeger(L, -1); g_engine->removeObject(id); } lua_pop(L, 1); clearLuaTable(L, 1); } return 0; } int setVisible(lua_State * L) { int argc = lua_gettop(L); if (argc == 2) { Engine::Object * obj = getObject(L, 1); if (obj != NULL && lua_isboolean(L, 2)) { obj->setVisible(lua_toboolean(L, 2)); } } return 0; } } }