TEST_F(LUATest, testGlobal) { LUA lua; const char *buf = "settings = { a = false, b = true, c = 1, }"; ASSERT_TRUE(lua.loadBuffer(buf, "testGlobal")); ASSERT_EQ(0, lua.stackCount()); ASSERT_TRUE(lua.getGlobalKeyValue("settings")); // we expect settings and nil ASSERT_EQ(2, lua.stackCount()) << lua.getStackDump(); int i = 0; while (lua.getNextKeyValue()) { const std::string& id = lua.getLuaValue(-2); const std::string& value = lua.getLuaValue(-1); lua.pop(); SCOPED_TRACE(string::toString(i)); if (id == "a") { ASSERT_EQ("false", value); } else if (id == "b") { ASSERT_EQ("true", value); } else if (id == "c") { ASSERT_EQ("1", value); } else { EXPECT_TRUE(false) << "id is: " << id; } ++i; } ASSERT_EQ(1, lua.stackCount()) << lua.getStackDump(); lua.pop(); ASSERT_EQ(0, lua.stackCount()) << lua.getStackDump(); ASSERT_EQ(3, i); }
void ConfigManager::getBindingMap (LUA& lua, std::map<std::string, std::string>* map, const char *key, BindingType type) { if (!lua.getGlobalKeyValue(key)) return; while (lua.getNextKeyValue()) { const std::string id = lua.getKey(); if (id.empty()) { lua.pop(); continue; } lua_pushnil(lua.getState()); std::map<std::string, std::string> strMap; while (lua.getNextKeyValue()) { const std::string& _key = lua.getLuaValue(-2); const std::string& _value = lua.getLuaValue(-1); strMap[_key] = _value; lua.pop(); } BindingSpace bindingSpace = BINDINGS_UI; if (id == "map") bindingSpace = BINDINGS_MAP; for (std::map<std::string, std::string>::const_iterator i = strMap.begin(); i != strMap.end(); ++i) { if (type == KEYBOARD) { map[bindingSpace][i->first] = i->second; } else if (type == CONTROLLER) { const SDL_GameControllerButton button = SDL_GameControllerGetButtonFromString(i->first.c_str()); const char *buttonStr = SDL_GameControllerGetStringForButton(button); map[bindingSpace][buttonStr] = i->second; } } lua_pop(lua.getState(), 1); } }
void ConfigManager::getBindingMap (LUA& lua, std::map<int, std::string>* map, const char *key, BindingType type) { if (type == CONTROLLER) return; if (!lua.getGlobalKeyValue(key)) return; while (lua.getNextKeyValue()) { const std::string id = lua.getKey(); if (id.empty()) { lua.pop(); continue; } lua_pushnil(lua.getState()); std::map<std::string, std::string> strMap; while (lua.getNextKeyValue()) { const std::string& _key = lua.getLuaValue(-2); const std::string& _value = lua.getLuaValue(-1); strMap[_key] = _value; lua.pop(); } BindingSpace bindingSpace = BINDINGS_UI; if (id == "map") bindingSpace = BINDINGS_MAP; for (std::map<std::string, std::string>::const_iterator i = strMap.begin(); i != strMap.end(); ++i) { if (type == KEYBOARD) { map[bindingSpace][mapKey(i->first)] = i->second; } } lua_pop(lua.getState(), 1); } }
void ConfigManager::getBindingMap (LUA& lua, std::map<std::string, std::string>* map, const char *key, BindingType type) { lua.getGlobalKeyValue(key); while (lua.getNextKeyValue()) { const std::string id = lua.getKey(); if (id.empty()) { lua.pop(); continue; } lua_pushnil(lua.getState()); std::map<std::string, std::string> strMap; while (lua_next(lua.getState(), -2) != 0) { const char *_key = lua_tostring(lua.getState(), -2); assert(_key); std::string _value; if (lua_isstring(lua.getState(), -1)) { _value = lua_tostring(lua.getState(), -1); } else if (lua_isnumber(lua.getState(), -1)) { _value = string::toString(lua_tonumber(lua.getState(), -1)); } else if (lua_isboolean(lua.getState(), -1)) { _value = lua_toboolean(lua.getState(), -1) ? "true" : "false"; } strMap[_key] = _value; lua_pop(lua.getState(), 1); } BindingSpace bindingSpace = BINDINGS_UI; if (id == "map") bindingSpace = BINDINGS_MAP; for (std::map<std::string, std::string>::const_iterator i = strMap.begin(); i != strMap.end(); ++i) { if (type == KEYBOARD) { map[bindingSpace][i->first] = i->second; } else if (type == JOYSTICK) { const std::string index = i->first.substr(3); map[bindingSpace][index] = i->second; } else if (type == CONTROLLER) { const SDL_GameControllerButton button = SDL_GameControllerGetButtonFromString(i->first.c_str()); const char *buttonStr = SDL_GameControllerGetStringForButton(button); map[bindingSpace][buttonStr] = i->second; } } lua_pop(lua.getState(), 1); } }
void SpriteDefinition::init (const TextureDefinition& textureDefinition) { ExecutionTime e("Sprites loading"); LUA lua; if (!lua.load("sprites.lua")) { System.exit("could not load sprites", 1); return; } lua.getGlobalKeyValue("sprites"); while (lua.getNextKeyValue()) { const std::string id = lua.getKey(); if (id.empty()) { lua.pop(); continue; } SpriteDefMapConstIter findIter = _spriteDefs.find(id); if (findIter != _spriteDefs.end()) { error(LOG_GENERAL, "sprite def already defined: " + id); lua.pop(); continue; } const std::string typeStr = lua.getValueStringFromTable("type").str(); const SpriteType& type = SpriteType::getByName(typeStr); if (!type && !typeStr.empty()) { error(LOG_GENERAL, "invalid sprite type given: " + typeStr); } const ThemeType& theme = ThemeType::getByName(lua.getValueStringFromTable("theme").str()); SpriteDef *def = new SpriteDef(id, type, theme); def->fps = lua.getValueIntegerFromTable("fps", 20); def->redirect = lua.getValueStringFromTable("redirect").str(); def->width = lua.getValueFloatFromTable("width", 1.0f); def->height = lua.getValueFloatFromTable("height", 1.0f); def->angle = lua.getValueIntegerFromTable("angle", 0); def->rotateable = lua.getValueIntegerFromTable("rotateable", 0); def->friction = lua.getValueFloatFromTable("friction", 0.2f); def->restitution = lua.getValueFloatFromTable("restitution", 0.0f); // push the frames table const int layers = lua.getTable("frames"); for (Layer layer = LAYER_BACK; layer < layers; layer++) { lua_pushinteger(lua.getState(), layer + 1); lua_gettable(lua.getState(), -2); // push the frame table const int framesOnLayer = lua_rawlen(lua.getState(), -1); for (int i = 1; i <= framesOnLayer; ++i) { const std::string texture = lua.getTableString(i); const SpriteDefFrame frame(texture, 0, true); def->textures[layer].push_back(frame); } // pop the frame table lua.pop(); } // pop the frames table lua.pop(); // push the polygons table const int polygons = lua.getTable("polygons"); if (polygons > 0) { for (int j = 1; j <= polygons; j++) { lua_pushinteger(lua.getState(), j); lua_gettable(lua.getState(), -2); // push the polygon table const int vertices = lua_rawlen(lua.getState(), -1) - 1; const std::string userData = lua.getTableString(1); SpritePolygon p(userData); for (int i = 2; i <= vertices; i += 2) { const float x = lua.getTableInteger(i) / 100.0f; const float y = lua.getTableInteger(i + 1) / 100.0f; p.vertices.push_back(SpriteVertex(x, y)); } // pop the polygon table lua.pop(); def->polygons.push_back(p); } } // pop the polygons table lua.pop(); // push the circles table const int circles = lua.getTable("circles"); for (int j = 1; j <= circles; j++) { lua_pushinteger(lua.getState(), j); lua_gettable(lua.getState(), -2); // push the circle table const int entries = lua_rawlen(lua.getState(), -1); if (entries == 4) { const std::string userData = lua.getTableString(1); SpriteCircle p(userData); const float x = lua.getTableInteger(2) / 100.0f; const float y = lua.getTableInteger(3) / 100.0f; p.center = SpriteVertex(x, y); p.radius = lua.getTableInteger(4) / 100.0f; def->circles.push_back(p); } else { error(LOG_GENERAL, "invalid amount of entries for the circle shape"); } // pop the circle table lua.pop(); } // pop the circles table lua.pop(); for (Layer layer = LAYER_BACK; layer <= MAX_LAYERS; layer++) { if (layer == MAX_LAYERS || def->textures[layer].empty()) { int frame = 1; std::string spriteFrameName = def->id; switch (layer) { case LAYER_BACK: spriteFrameName += "-back-01"; break; case LAYER_FRONT: spriteFrameName += "-front-01"; break; case LAYER_MIDDLE: spriteFrameName += "-middle-01"; break; case MAX_LAYERS: // fallback spriteFrameName += "-01"; break; default: break; } const size_t length = spriteFrameName.size(); char frameNumbers[] = { '0', '1', '\0' }; Layer layerToUse = layer; if (layerToUse == MAX_LAYERS) layerToUse = LAYER_MIDDLE; for (;;) { if (!textureDefinition.exists(spriteFrameName)) break; def->textures[layerToUse].push_back(SpriteDefFrame(spriteFrameName, 0, true)); frame++; const char first = frame / 10 + '0'; const char second = frame % 10 + '0'; frameNumbers[0] = first; frameNumbers[1] = second; spriteFrameName.replace(length - 2, length, frameNumbers); } } } const int actives = lua.getTable("active"); for (int i = 1; i <= actives; ++i) { const bool active = lua.getTableBool(i); for (Layer layer = LAYER_BACK; layer < MAX_LAYERS; layer++) { const size_t textures = def->textures[layer].size(); if (textures < i) continue; SpriteDef::SpriteDefFrames& frames = def->textures[layer]; frames[i - 1].active = active; } } // pop the active table lua.pop(); const int delays = lua.getTable("delays"); for (int i = 1; i <= delays; ++i) { const int delay = lua.getTableInteger(i); for (Layer layer = LAYER_BACK; layer < MAX_LAYERS; layer++) { const size_t textures = def->textures[layer].size(); if (textures >= i) def->textures[layer][i - 1].delay = delay; } } // pop the delays table lua.pop(); lua.pop(); def->calcDelay(); _spriteDefs[id] = SpriteDefPtr(def); } }
void SpriteDefinition::init (const TextureDefinition& textureDefinition) { ExecutionTime e("Sprites loading"); Log::debug(LOG_COMMON, "Sprites loading"); LUA lua; if (!lua.load("sprites.lua")) { System.exit("could not load sprites", 1); return; } LUA_checkStack2(lua.getState()); if (!lua.getGlobalKeyValue("sprites")) { Log::error(LOG_COMMON, "spritedef: Could not find the global sprites map"); return; } while (lua.getNextKeyValue()) { LUA_checkStack2(lua.getState()); const std::string id = lua.getKey(); if (id.empty()) { Log::error(LOG_COMMON, "spritedef: no key found in definition: %s", lua.getStackDump().c_str()); lua.pop(); continue; } Log::debug(LOG_COMMON, "id: %s", id.c_str()); SpriteDefMapConstIter findIter = _spriteDefs.find(id); if (findIter != _spriteDefs.end()) { Log::error(LOG_COMMON, "sprite def already defined: %s", id.c_str()); lua.pop(); continue; } const std::string& typeStr = lua.getValueStringFromTable("type"); Log::debug(LOG_COMMON, "id: %s, type %s", id.c_str(), typeStr.c_str()); const SpriteType& type = SpriteType::getByName(typeStr); if (!type && !typeStr.empty()) { Log::error(LOG_COMMON, "invalid sprite type given: %s", typeStr.c_str()); } const ThemeType& theme = ThemeType::getByName(lua.getValueStringFromTable("theme")); SpriteDef *def = new SpriteDef(id, type, theme); def->fps = lua.getValueIntegerFromTable("fps", 20); def->redirect = lua.getValueStringFromTable("redirect"); def->width = lua.getValueFloatFromTable("width", 1.0f); def->height = lua.getValueFloatFromTable("height", 1.0f); def->angle = lua.getValueIntegerFromTable("angle", 0); def->rotateable = lua.getValueIntegerFromTable("rotateable", 0); def->friction = lua.getValueFloatFromTable("friction", 0.2f); def->restitution = lua.getValueFloatFromTable("restitution", 0.0f); // push the frames table const int layers = lua.getTable("frames"); Log::debug(LOG_COMMON, "id: %s => %i frames", id.c_str(), layers); if (layers > MAX_LAYERS) { Log::error(LOG_COMMON, "invalid sprite layer amount given for %s: %i", id.c_str(), layers); } if (layers > 0) { LUA_checkStack2(lua.getState()); lua_State* L = lua.getState(); lua_pushvalue(L, -1); lua_pushnil(L); Layer layer = LAYER_BACK; while (lua_next(L, -2)) { if (!lua_istable(lua.getState(), -1)) { Log::error(LOG_COMMON, "spritedef: expected frame table on the stack: %s", lua.getStackDump().c_str()); lua.pop(); continue; } // push the frame table const int framesOnLayer = lua_rawlen(lua.getState(), -1); Log::debug(LOG_COMMON, "id: %s => %i frames on layer %i", id.c_str(), framesOnLayer, layer); for (int i = 1; i <= framesOnLayer; ++i) { const std::string& texture = lua.getTableString(i); Log::debug(LOG_COMMON, "id: %s => texture %s on layer %i", id.c_str(), texture.c_str(), layer); const SpriteDefFrame frame(texture, 0, true); if (layer < MAX_LAYERS) def->textures[layer].push_back(frame); } lua.pop(); ++layer; } // pop the frame table lua.pop(); } // pop the frames table if (layers != -1) lua.pop(); // push the polygons table const int polygons = lua.getTable("polygons"); Log::debug(LOG_COMMON, "id: %s => %i polygons", id.c_str(), polygons); if (polygons > 0) { LUA_checkStack2(lua.getState()); lua_State* L = lua.getState(); lua_pushvalue(L, -1); lua_pushnil(L); while (lua_next(L, -2)) { if (!lua_istable(L, -1)) { Log::error(LOG_COMMON, "spritedef: expected polygon table on the stack: %s", lua.getStackDump().c_str()); lua.pop(); continue; } // push the polygon table const int vertices = lua_rawlen(L, -1) - 1; Log::debug(LOG_COMMON, "id: %s => %i vertices", id.c_str(), vertices); const std::string& userData = lua.getTableString(1); SpritePolygon p(userData); Log::debug(LOG_COMMON, "id: %s => %s userdata", id.c_str(), userData.c_str()); for (int i = 2; i <= vertices; i += 2) { const float x = lua.getTableFloat(i) / 100.0f; const float y = lua.getTableFloat(i + 1) / 100.0f; p.vertices.push_back(SpriteVertex(x, y)); } // pop the polygon table lua.pop(); def->polygons.push_back(p); } lua.pop(); } // pop the polygons table if (polygons != -1) lua.pop(); // push the circles table const int circles = lua.getTable("circles"); Log::debug(LOG_COMMON, "id: %s => %i circles", id.c_str(), circles); if (circles > 0) { LUA_checkStack2(lua.getState()); lua_State* L = lua.getState(); lua_pushvalue(L, -1); lua_pushnil(L); while (lua_next(L, -2)) { if (!lua_istable(L, -1)) { Log::error(LOG_COMMON, "spritedef: expected circle table on the stack: %s", lua.getStackDump().c_str()); lua.pop(); continue; } // push the circle table const int entries = lua_rawlen(lua.getState(), -1); if (entries == 4) { const std::string& userData = lua.getTableString(1); SpriteCircle p(userData); const float x = lua.getTableInteger(2) / 100.0f; const float y = lua.getTableInteger(3) / 100.0f; p.center = SpriteVertex(x, y); p.radius = lua.getTableInteger(4) / 100.0f; def->circles.push_back(p); } else { Log::error(LOG_COMMON, "invalid amount of entries for the circle shape"); } // pop the circle table lua.pop(); } lua.pop(); } // pop the circles table if (circles != -1) lua.pop(); for (Layer layer = LAYER_BACK; layer <= MAX_LAYERS; layer++) { if (layer == MAX_LAYERS || def->textures[layer].empty()) { int frame = 1; std::string spriteFrameName = def->id; switch (layer) { case LAYER_BACK: spriteFrameName += "-back-01"; break; case LAYER_FRONT: spriteFrameName += "-front-01"; break; case LAYER_MIDDLE: spriteFrameName += "-middle-01"; break; case MAX_LAYERS: // fallback spriteFrameName += "-01"; break; default: break; } const size_t length = spriteFrameName.size(); char frameNumbers[] = { '0', '1', '\0' }; Layer layerToUse = layer; if (layerToUse == MAX_LAYERS) layerToUse = LAYER_MIDDLE; for (;;) { if (!textureDefinition.exists(spriteFrameName)) break; def->textures[layerToUse].push_back(SpriteDefFrame(spriteFrameName, 0, true)); frame++; const char first = frame / 10 + '0'; const char second = frame % 10 + '0'; frameNumbers[0] = first; frameNumbers[1] = second; spriteFrameName.replace(length - 2, length, frameNumbers); } } } const int actives = lua.getTable("active"); for (int i = 1; i <= actives; ++i) { LUA_checkStack2(lua.getState()); const bool active = lua.getTableBool(i); for (Layer layer = LAYER_BACK; layer < MAX_LAYERS; layer++) { const int textures = def->textures[layer].size(); if (textures < i) continue; SpriteDef::SpriteDefFrames& frames = def->textures[layer]; frames[i - 1].active = active; } } // pop the active table if (actives != -1) lua.pop(); const int delays = lua.getTable("delays"); for (int i = 1; i <= delays; ++i) { LUA_checkStack2(lua.getState()); const int delay = lua.getTableInteger(i); for (Layer layer = LAYER_BACK; layer < MAX_LAYERS; layer++) { const int textures = def->textures[layer].size(); if (textures >= i) def->textures[layer][i - 1].delay = delay; } } // pop the delays table if (delays != -1) lua.pop(); lua.pop(); def->calcDelay(); _spriteDefs[id] = SpriteDefPtr(def); } }
TextureDefinition::TextureDefinition (const std::string& textureSize, IProgressCallback* progress) : _textureSize(textureSize), _cnt(0) { if (textureSize != "big" && textureSize != "small") { System.exit("invalid texturesize value given: " + textureSize + ". Valid values are: auto, big, small", 1); } ExecutionTime e("Texture definition loading for " + textureSize); const std::string& path = FS.getTexturesDir(); const DirectoryEntries& entries = FS.listDirectory(path); LUA lua; for (DirectoryEntries::const_iterator i = entries.begin(); i != entries.end(); ++i) { const std::string filename = path + *i; if (!FS.hasExtension(filename, "lua")) continue; if (!lua.load(filename)) { Log::error(LOG_CLIENT, "failed to load textures from %s", filename.c_str()); continue; } lua.getGlobalKeyValue("textures" + textureSize); while (lua.getNextKeyValue()) { String id = lua.getKey(); if (id.empty()) { lua.pop(); System.exit("Invalid texture entry found - invalid id", 1); } id = id.cutBeforeLastMatch("/"); if (progress != nullptr) { progress->progressStep(); } const std::string name = lua.getValueStringFromTable("image"); const float x0 = lua.getValueFloatFromTable("x0"); const float y0 = lua.getValueFloatFromTable("y0"); const float x1 = lua.getValueFloatFromTable("x1"); const float y1 = lua.getValueFloatFromTable("y1"); const int trimmedWidth = lua.getValueIntegerFromTable("trimmedwidth"); const int trimmedHeight = lua.getValueIntegerFromTable("trimmedheight"); const int untrimmedWidth = lua.getValueIntegerFromTable("untrimmedwidth"); const int untrimmedHeight = lua.getValueIntegerFromTable("untrimmedheight"); const int trimmedOffsetX = lua.getValueIntegerFromTable("trimmedoffsetx"); const int trimmedOffsetY = lua.getValueIntegerFromTable("trimmedoffsety"); const TextureDefinitionTrim trim(trimmedWidth, trimmedHeight, untrimmedWidth, untrimmedHeight, trimmedOffsetX, trimmedOffsetY); const TextureDefinitionCoords r = { x0, y0, x1, y1 }; if (id.contains(TEXTURE_DIRECTION)) { const String rightID = id.replaceAll(TEXTURE_DIRECTION, TEXTURE_DIRECTION_RIGHT); create(name, rightID, r, trim, false); const String leftID = id.replaceAll(TEXTURE_DIRECTION, TEXTURE_DIRECTION_LEFT); create(name, leftID, r, trim, true); } else { const bool mirror = lua.getValueBoolFromTable("mirror"); create(name, id, r, trim, mirror); } lua.pop(); ++_cnt; } } if (_textureDefs.empty()) Log::info(LOG_CLIENT, "could not load any texture definition"); Log::info(LOG_CLIENT, "loaded %i texture definitions", (int)_textureDefs.size()); }
FontDefinition::FontDefinition() { ExecutionTime e("Font definition loading"); LUA lua; if (!lua.load("fonts.lua")) { System.exit("could not load fonts", 1); return; } lua.getGlobalKeyValue("fonts"); while (lua.getNextKeyValue()) { const std::string id = lua.getKey(); if (id.empty()) { lua.pop(); continue; } FontDefMapConstIter findIter = _fontDefs.find(id); if (findIter != _fontDefs.end()) { error(LOG_GENERAL, "font def already defined: " + id); lua.pop(); continue; } const int height = lua.getValueIntegerFromTable("height"); // push the metrics table lua.getTable("metrics"); const int metricsHeight = lua.getValueIntegerFromTable("height"); const int metricsAscender = lua.getValueIntegerFromTable("ascender"); const int metricsDescender = lua.getValueIntegerFromTable("descender"); // pop the metrics table lua.pop(); FontDef *def = new FontDef(id, height, metricsHeight, metricsAscender, metricsDescender); // push the chars table const int chars = lua.getTable("chars"); for (int i = 0; i < chars; ++i) { lua_pushinteger(lua.getState(), i + 1); lua_gettable(lua.getState(), -2); // push the char entry const std::string character = lua.getValueStringFromTable("char"); const int width = lua.getValueIntegerFromTable("width"); const int x = lua.getValueIntegerFromTable("x"); const int y = lua.getValueIntegerFromTable("y"); const int w = lua.getValueIntegerFromTable("w"); const int h = lua.getValueIntegerFromTable("h"); const int ox = lua.getValueIntegerFromTable("ox"); const int oy = lua.getValueIntegerFromTable("oy"); const FontChar c(character, width, x, y, w, h, ox, oy); def->fontChars.push_back(c); // pop the char entry lua.pop(); } // pop the chars table lua.pop(); // push the texture table lua.getTable("texture"); def->textureHeight = lua.getValueIntegerFromTable("height"); def->textureWidth = lua.getValueIntegerFromTable("width"); def->textureName = lua.getValueStringFromTable("file").str(); // pop the texture table lua.pop(); lua.pop(); _fontDefs[id] = FontDefPtr(def); } }