void LuaUtils::ParseCommandOptions(lua_State* L, const char* caller, int index, Command& cmd) { if (lua_isnumber(L, index)) { cmd.options = (unsigned char)lua_tonumber(L, index); } else if (lua_istable(L, index)) { const int optionTable = index; for (lua_pushnil(L); lua_next(L, optionTable) != 0; lua_pop(L, 1)) { if (lua_israwnumber(L, -2)) { // avoid 'n' if (!lua_isstring(L, -1)) { luaL_error(L, "%s(): bad option table entry", caller); } const string value = lua_tostring(L, -1); if (value == "right") { cmd.options |= RIGHT_MOUSE_KEY; } else if (value == "alt") { cmd.options |= ALT_KEY; } else if (value == "ctrl") { cmd.options |= CONTROL_KEY; } else if (value == "shift") { cmd.options |= SHIFT_KEY; } else if (value == "meta") { cmd.options |= META_KEY; } } } } else { luaL_error(L, "%s(): bad options", caller); } }
Command LuaUtils::ParseCommand(lua_State* L, const char* caller, int idIndex) { // cmdID if (!lua_isnumber(L, idIndex)) { luaL_error(L, "%s(): bad command ID", caller); } const int id = lua_toint(L, idIndex); Command cmd(id); // params const int paramTable = (idIndex + 1); if (!lua_istable(L, paramTable)) { luaL_error(L, "%s(): bad param table", caller); } for (lua_pushnil(L); lua_next(L, paramTable) != 0; lua_pop(L, 1)) { if (lua_israwnumber(L, -2)) { // avoid 'n' if (!lua_isnumber(L, -1)) { luaL_error(L, "%s(): bad param table entry", caller); } const float value = lua_tofloat(L, -1); cmd.PushParam(value); } } // options ParseCommandOptions(L, caller, (idIndex + 2), cmd); // XXX should do some sanity checking? return cmd; }
void LuaUtils::ParseCommandTable(lua_State* L, const char* caller, int table, Command& cmd) { // cmdID lua_rawgeti(L, table, 1); if (!lua_isnumber(L, -1)) { luaL_error(L, "%s(): bad command ID", caller); } cmd.id = lua_toint(L, -1); lua_pop(L, 1); // params lua_rawgeti(L, table, 2); if (!lua_istable(L, -1)) { luaL_error(L, "%s(): bad param table", caller); } const int paramTable = lua_gettop(L); for (lua_pushnil(L); lua_next(L, paramTable) != 0; lua_pop(L, 1)) { if (lua_israwnumber(L, -2)) { // avoid 'n' if (!lua_isnumber(L, -1)) { luaL_error(L, "%s(): bad param table entry", caller); } const float value = lua_tofloat(L, -1); cmd.params.push_back(value); } } lua_pop(L, 1); // options lua_rawgeti(L, table, 3); ParseCommandOptions(L, caller, lua_gettop(L), cmd); lua_pop(L, 1); // NOTE: should do some sanity checking? }
int LuaUtils::Echo(lua_State* L) { // copied from lua/src/lib/lbaselib.c string msg = ""; const int args = lua_gettop(L); // number of arguments lua_getglobal(L, "tostring"); for (int i = 1; i <= args; i++) { const char *s; lua_pushvalue(L, -1); // function to be called lua_pushvalue(L, i); // value to print lua_call(L, 1, 1); s = lua_tostring(L, -1); // get result if (s == NULL) { return luaL_error(L, "`tostring' must return a string to `print'"); } if (i > 1) { msg += ", "; } msg += s; lua_pop(L, 1); // pop result } logOutput.Print(msg); if ((args != 1) || !lua_istable(L, 1)) { return 0; } // print solo tables (array style) msg = "TABLE: "; bool first = true; const int table = 1; for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) { if (lua_israwnumber(L, -2)) { // only numeric keys const char *s; lua_pushvalue(L, -3); // function to be called lua_pushvalue(L, -2 ); // value to print lua_call(L, 1, 1); s = lua_tostring(L, -1); // get result if (s == NULL) { return luaL_error(L, "`tostring' must return a string to `print'"); } if (!first) { msg += ", "; } msg += s; first = false; lua_pop(L, 1); // pop result } } logOutput.Print(msg); return 0; }
bool LuaTable::GetKeys(vector<int>& data) const { if (!PushTable()) { return false; } const int table = lua_gettop(L); for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) { if (lua_israwnumber(L, -2)) { const int value = lua_toint(L, -2); data.push_back(value); } } std::sort(data.begin(), data.end()); return true; }
bool LuaTable::GetMap(map<int, string>& data) const { if (!PushTable()) { return false; } const int table = lua_gettop(L); for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) { if (lua_israwnumber(L, -2) && lua_isstring(L, -1)) { const int key = lua_toint(L, -2); const string value = lua_tostring(L, -1); data[key] = value; } } return true; }
static std::string getprintf_msg(lua_State* L, int index) { // copied from lua/src/lib/lbaselib.c string msg = ""; const int args = lua_gettop(L); // number of arguments lua_getglobal(L, "tostring"); for (int i = index; i <= args; i++) { const char* s; lua_pushvalue(L, -1); // function to be called lua_pushvalue(L, i); // value to print lua_call(L, 1, 1); s = lua_tostring(L, -1); // get result if (i > index) { msg += ", "; } msg += s; lua_pop(L, 1); // pop result } if ((args != index) || !lua_istable(L, index)) { return msg; } // print solo tables (array style) msg = "TABLE: "; bool first = true; for (lua_pushnil(L); lua_next(L, index) != 0; lua_pop(L, 1)) { if (lua_israwnumber(L, -2)) { // only numeric keys const char *s; lua_pushvalue(L, -3); // function to be called lua_pushvalue(L, -2); // value to print lua_call(L, 1, 1); s = lua_tostring(L, -1); // get result if (!first) { msg += ", "; } msg += s; first = false; lua_pop(L, 1); // pop result } } return msg; }
/*- Logs a msg to the logfile / console @param loglevel loglevel that will be used for the message @param msg string to be logged @fn Spring.Log(string logsection, int loglevel, ...) @fn Spring.Log(string logsection, string loglevel, ...) */ int LuaUtils::Log(lua_State* L) { const int args = lua_gettop(L); // number of arguments if (args < 2) return luaL_error(L, "Incorrect arguments to Spring.Log(logsection, loglevel, ...)"); if (args < 3) return 0; const std::string section = luaL_checkstring(L, 1); int loglevel; if (lua_israwnumber(L, 2)) { loglevel = lua_tonumber(L, 2); } else if (lua_israwstring(L, 2)) { std::string loglvlstr = lua_tostring(L, 2); StringToLowerInPlace(loglvlstr); if (loglvlstr == "debug") { loglevel = LOG_LEVEL_DEBUG; } else if (loglvlstr == "info") { loglevel = LOG_LEVEL_INFO; } else if (loglvlstr == "warning") { loglevel = LOG_LEVEL_WARNING; } else if (loglvlstr == "error") { loglevel = LOG_LEVEL_ERROR; } else if (loglvlstr == "fatal") { loglevel = LOG_LEVEL_FATAL; } else { return luaL_error(L, "Incorrect arguments to Spring.Log(logsection, loglevel, ...)"); } } else { return luaL_error(L, "Incorrect arguments to Spring.Log(logsection, loglevel, ...)"); } const std::string msg = getprintf_msg(L, 3); LOG_SI(section.c_str(), loglevel, "%s", msg.c_str()); return 0; }
int LuaUtils::ParseFacing(lua_State* L, const char* caller, int index) { if (lua_israwnumber(L, index)) { return std::max(0, std::min(3, lua_toint(L, index))); } else if (lua_israwstring(L, index)) { const string dir = StringToLower(lua_tostring(L, index)); if (dir == "s") { return 0; } if (dir == "e") { return 1; } if (dir == "n") { return 2; } if (dir == "w") { return 3; } if (dir == "south") { return 0; } if (dir == "east") { return 1; } if (dir == "north") { return 2; } if (dir == "west") { return 3; } luaL_error(L, "%s(): bad facing string", caller); } luaL_error(L, "%s(): bad facing parameter", caller); return 0; }
void CLuaRules::CreateRulesParams(lua_State* L, const char* caller, int offset, vector<float>& params, map<string, int>& paramsMap) { const int table = offset + 1; if (!lua_istable(L, table)) { luaL_error(L, "Incorrect arguments to %s()", caller); } params.clear(); paramsMap.clear(); for (int i = 1; /* no test */; i++) { lua_rawgeti(L, table, i); if (lua_isnil(L, -1)) { lua_pop(L, 1); return; } else if (lua_israwnumber(L, -1)) { const float value = lua_tofloat(L, -1); params.push_back(value); } else if (lua_istable(L, -1)) { lua_pushnil(L); if (lua_next(L, -2)) { if (lua_israwstring(L, -2) && lua_isnumber(L, -1)) { const string name = lua_tostring(L, -2); const float value = lua_tonumber(L, -1); paramsMap[name] = params.size(); params.push_back(value); } lua_pop(L, 2); } } lua_pop(L, 1); } return; }
void CLuaRules::SetRulesParam(lua_State* L, const char* caller, int offset, vector<float>& params, map<string, int>& paramsMap) { const int index = offset + 1; const int valIndex = offset + 2; int pIndex = -1; if (lua_israwnumber(L, index)) { pIndex = lua_toint(L, index) - 1; } else if (lua_israwstring(L, index)) { const string pName = lua_tostring(L, index); map<string, int>::const_iterator it = paramsMap.find(pName); if (it != paramsMap.end()) { pIndex = it->second; } else { // create a new parameter pIndex = params.size(); paramsMap[pName] = params.size(); params.push_back(0.0f); // dummy value } } else { luaL_error(L, "Incorrect arguments to %s()", caller); } if ((pIndex < 0) || (pIndex >= (int)params.size())) { return; } if (!lua_isnumber(L, valIndex)) { luaL_error(L, "Incorrect arguments to %s()", caller); } params[pIndex] = lua_tofloat(L, valIndex); return; }
void LuaMaterial::Parse( lua_State* L, const int tableIdx, std::function<void(lua_State*, int, LuaMatShader&)> ParseShader, std::function<void(lua_State*, int, LuaMatTexture&)> ParseTexture, std::function<GLuint(lua_State*, int)> ParseDisplayList ) { for (lua_pushnil(L); lua_next(L, tableIdx) != 0; lua_pop(L, 1)) { if (!lua_israwstring(L, -2)) continue; const std::string key = StringToLower(lua_tostring(L, -2)); // uniforms if (key.find("uniforms") != std::string::npos) { if (!lua_istable(L, -1)) continue; if (key.find("standard") != std::string::npos) { uniforms[LuaMatShader::LUASHADER_PASS_FWD].Parse(L, lua_gettop(L)); continue; } if (key.find("deferred") != std::string::npos) { uniforms[LuaMatShader::LUASHADER_PASS_DFR].Parse(L, lua_gettop(L)); continue; } // fallback uniforms[LuaMatShader::LUASHADER_PASS_FWD].Parse(L, lua_gettop(L)); continue; } // shaders if (key.find("shader") != std::string::npos) { if (key.find("standard") != std::string::npos) { ParseShader(L, -1, shaders[LuaMatShader::LUASHADER_PASS_FWD]); continue; } if (key.find("deferred") != std::string::npos) { ParseShader(L, -1, shaders[LuaMatShader::LUASHADER_PASS_DFR]); continue; } // fallback ParseShader(L, -1, shaders[LuaMatShader::LUASHADER_PASS_FWD]); continue; } // textures if (key.substr(0, 7) == "texunit") { if (key.size() < 8) continue; if (key[7] == 's') { // "texunits" = {[0] = string|table, ...} if (!lua_istable(L, -1)) continue; const int texTable = lua_gettop(L); for (lua_pushnil(L); lua_next(L, texTable) != 0; lua_pop(L, 1)) { if (!lua_israwnumber(L, -2)) continue; const unsigned int texUnit = lua_toint(L, -2); if (texUnit >= LuaMatTexture::maxTexUnits) continue; ParseTexture(L, -1, textures[texUnit]); } } else { // "texunitX" = string|table const unsigned int texUnit = atoi(key.c_str() + 7); if (texUnit >= LuaMatTexture::maxTexUnits) continue; ParseTexture(L, -1, textures[texUnit]); } continue; } // dlists if (key == "prelist") { preList = ParseDisplayList(L, -1); continue; } if (key == "postlist") { postList = ParseDisplayList(L, -1); continue; } // misc if (key == "order") { order = luaL_checkint(L, -1); continue; } if (key == "culling") { if (lua_isnumber(L, -1)) cullingMode = (GLenum)lua_tonumber(L, -1); continue; } if (key == "usecamera") { useCamera = lua_isboolean(L, -1) && lua_toboolean(L, -1); continue; } LOG_L(L_WARNING, "LuaMaterial: incorrect key \"%s\"", key.c_str()); } }