Example #1
0
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);
	}
}