Browse Source

Merge pull request #5352 from IvanSavenko/assets_generation

[1.6.5] In-memory assets generation
Ivan Savenko 10 months ago
parent
commit
c5a75b20ad

+ 1 - 2
client/ClientCommandManager.cpp

@@ -18,7 +18,6 @@
 #include "gui/CGuiHandler.h"
 #include "gui/CGuiHandler.h"
 #include "gui/WindowHandler.h"
 #include "gui/WindowHandler.h"
 #include "render/IRenderHandler.h"
 #include "render/IRenderHandler.h"
-#include "render/AssetGenerator.h"
 #include "ClientNetPackVisitors.h"
 #include "ClientNetPackVisitors.h"
 #include "../lib/CConfigHandler.h"
 #include "../lib/CConfigHandler.h"
 #include "../lib/gameState/CGameState.h"
 #include "../lib/gameState/CGameState.h"
@@ -510,7 +509,7 @@ void ClientCommandManager::handleVsLog(std::istringstream & singleWordBuffer)
 
 
 void ClientCommandManager::handleGenerateAssets()
 void ClientCommandManager::handleGenerateAssets()
 {
 {
-	AssetGenerator::generateAll();
+	GH.renderHandler().exportGeneratedAssets();
 	printCommandMessage("All assets generated");
 	printCommandMessage("All assets generated");
 }
 }
 
 

+ 0 - 3
client/adventureMap/AdventureMapInterface.cpp

@@ -34,7 +34,6 @@
 #include "../render/IImage.h"
 #include "../render/IImage.h"
 #include "../render/IRenderHandler.h"
 #include "../render/IRenderHandler.h"
 #include "../render/IScreenHandler.h"
 #include "../render/IScreenHandler.h"
-#include "../render/AssetGenerator.h"
 #include "../CMT.h"
 #include "../CMT.h"
 #include "../PlayerLocalState.h"
 #include "../PlayerLocalState.h"
 #include "../CPlayerInterface.h"
 #include "../CPlayerInterface.h"
@@ -65,8 +64,6 @@ AdventureMapInterface::AdventureMapInterface():
 	pos.w = GH.screenDimensions().x;
 	pos.w = GH.screenDimensions().x;
 	pos.h = GH.screenDimensions().y;
 	pos.h = GH.screenDimensions().y;
 
 
-	AssetGenerator::createPaletteShiftedSprites();
-
 	shortcuts = std::make_shared<AdventureMapShortcuts>(*this);
 	shortcuts = std::make_shared<AdventureMapShortcuts>(*this);
 
 
 	widget = std::make_shared<AdventureMapWidget>(shortcuts);
 	widget = std::make_shared<AdventureMapWidget>(shortcuts);

+ 0 - 2
client/battle/BattleStacksController.cpp

@@ -27,7 +27,6 @@
 #include "../gui/CGuiHandler.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/WindowHandler.h"
 #include "../gui/WindowHandler.h"
 #include "../media/ISoundPlayer.h"
 #include "../media/ISoundPlayer.h"
-#include "../render/AssetGenerator.h"
 #include "../render/Colors.h"
 #include "../render/Colors.h"
 #include "../render/Canvas.h"
 #include "../render/Canvas.h"
 #include "../render/IRenderHandler.h"
 #include "../render/IRenderHandler.h"
@@ -80,7 +79,6 @@ BattleStacksController::BattleStacksController(BattleInterface & owner):
 	stackToActivate(nullptr),
 	stackToActivate(nullptr),
 	animIDhelper(0)
 	animIDhelper(0)
 {
 {
-	AssetGenerator::createCombatUnitNumberWindow();
 	//preparing graphics for displaying amounts of creatures
 	//preparing graphics for displaying amounts of creatures
 	amountNormal     = GH.renderHandler().loadImage(ImagePath::builtin("combatUnitNumberWindowDefault"), EImageBlitMode::COLORKEY);
 	amountNormal     = GH.renderHandler().loadImage(ImagePath::builtin("combatUnitNumberWindowDefault"), EImageBlitMode::COLORKEY);
 	amountPositive   = GH.renderHandler().loadImage(ImagePath::builtin("combatUnitNumberWindowPositive"), EImageBlitMode::COLORKEY);
 	amountPositive   = GH.renderHandler().loadImage(ImagePath::builtin("combatUnitNumberWindowPositive"), EImageBlitMode::COLORKEY);

+ 0 - 3
client/lobby/OptionsTabBase.cpp

@@ -18,7 +18,6 @@
 #include "../widgets/TextControls.h"
 #include "../widgets/TextControls.h"
 #include "../CServerHandler.h"
 #include "../CServerHandler.h"
 #include "../CGameInfo.h"
 #include "../CGameInfo.h"
-#include "../render/AssetGenerator.h"
 
 
 #include "../../lib/StartInfo.h"
 #include "../../lib/StartInfo.h"
 #include "../../lib/texts/CGeneralTextHandler.h"
 #include "../../lib/texts/CGeneralTextHandler.h"
@@ -69,8 +68,6 @@ std::vector<SimturnsInfo> OptionsTabBase::getSimturnsPresets() const
 
 
 OptionsTabBase::OptionsTabBase(const JsonPath & configPath)
 OptionsTabBase::OptionsTabBase(const JsonPath & configPath)
 {
 {
-	AssetGenerator::createAdventureOptionsCleanBackground();
-
 	recActions = 0;
 	recActions = 0;
 
 
 	auto setTimerPresetCallback = [this](int index){
 	auto setTimerPresetCallback = [this](int index){

+ 0 - 4
client/mainmenu/CMainMenu.cpp

@@ -38,7 +38,6 @@
 #include "../widgets/VideoWidget.h"
 #include "../widgets/VideoWidget.h"
 #include "../windows/InfoWindows.h"
 #include "../windows/InfoWindows.h"
 #include "../CServerHandler.h"
 #include "../CServerHandler.h"
-#include "../render/AssetGenerator.h"
 
 
 #include "../CGameInfo.h"
 #include "../CGameInfo.h"
 #include "../CPlayerInterface.h"
 #include "../CPlayerInterface.h"
@@ -428,9 +427,6 @@ void CMainMenu::openCampaignScreen(std::string name)
 {
 {
 	auto const & config = CMainMenuConfig::get().getCampaigns();
 	auto const & config = CMainMenuConfig::get().getCampaigns();
 
 
-	AssetGenerator::createCampaignBackground();
-	AssetGenerator::createChroniclesCampaignImages();
-
 	if(!vstd::contains(config.Struct(), name))
 	if(!vstd::contains(config.Struct(), name))
 	{
 	{
 		logGlobal->error("Unknown campaign set: %s", name);
 		logGlobal->error("Unknown campaign set: %s", name);

+ 146 - 227
client/render/AssetGenerator.cpp

@@ -29,36 +29,60 @@
 #include "../lib/RoadHandler.h"
 #include "../lib/RoadHandler.h"
 #include "../lib/TerrainHandler.h"
 #include "../lib/TerrainHandler.h"
 
 
-void AssetGenerator::clear()
+AssetGenerator::AssetGenerator()
+{
+}
+
+void AssetGenerator::initialize()
 {
 {
 	// clear to avoid non updated sprites after mod change (if base imnages are used)
 	// clear to avoid non updated sprites after mod change (if base imnages are used)
 	if(boost::filesystem::is_directory(VCMIDirs::get().userDataPath() / "Generated"))
 	if(boost::filesystem::is_directory(VCMIDirs::get().userDataPath() / "Generated"))
 		boost::filesystem::remove_all(VCMIDirs::get().userDataPath() / "Generated");
 		boost::filesystem::remove_all(VCMIDirs::get().userDataPath() / "Generated");
+
+	imageFiles[ImagePath::builtin("AdventureOptionsBackgroundClear.png")] = [this](){ return createAdventureOptionsCleanBackground();};
+	imageFiles[ImagePath::builtin("SpellBookLarge.png")] = [this](){ return createBigSpellBook();};
+
+	imageFiles[ImagePath::builtin("combatUnitNumberWindowDefault.png")]  = [this](){ return createCombatUnitNumberWindow(0.6f, 0.2f, 1.0f);};
+	imageFiles[ImagePath::builtin("combatUnitNumberWindowNeutral.png")]  = [this](){ return createCombatUnitNumberWindow(1.0f, 1.0f, 2.0f);};
+	imageFiles[ImagePath::builtin("combatUnitNumberWindowPositive.png")] = [this](){ return createCombatUnitNumberWindow(0.2f, 1.0f, 0.2f);};
+	imageFiles[ImagePath::builtin("combatUnitNumberWindowNegative.png")] = [this](){ return createCombatUnitNumberWindow(1.0f, 0.2f, 0.2f);};
+
+	imageFiles[ImagePath::builtin("CampaignBackground8.png")] = [this](){ return createCampaignBackground();};
+
+	for (PlayerColor color(0); color < PlayerColor::PLAYER_LIMIT; ++color)
+		imageFiles[ImagePath::builtin("DialogBoxBackground_" + color.toString())] = [this, color](){ return createPlayerColoredBackground(color);};
+
+	for(int i = 1; i < 9; i++)
+		imageFiles[ImagePath::builtin("CampaignHc" + std::to_string(i) + "Image.png")] = [this, i](){ return createChroniclesCampaignImages(i);};
+
+	createPaletteShiftedSprites();
 }
 }
 
 
-void AssetGenerator::generateAll()
+std::shared_ptr<ISharedImage> AssetGenerator::generateImage(const ImagePath & image)
 {
 {
-	createBigSpellBook();
-	createAdventureOptionsCleanBackground();
-	for (int i = 0; i < PlayerColor::PLAYER_LIMIT_I; ++i)
-		createPlayerColoredBackground(PlayerColor(i));
-	createCombatUnitNumberWindow();
-	createCampaignBackground();
-	createChroniclesCampaignImages();
-	createPaletteShiftedSprites();
+	if (imageFiles.count(image))
+		return imageFiles.at(image)()->toSharedImage(); // TODO: cache?
+	else
+		return nullptr;
 }
 }
 
 
-void AssetGenerator::createAdventureOptionsCleanBackground()
+std::map<ImagePath, std::shared_ptr<ISharedImage>> AssetGenerator::generateAllImages()
 {
 {
-	std::string filename = "data/AdventureOptionsBackgroundClear.png";
+	std::map<ImagePath, std::shared_ptr<ISharedImage>> result;
+
+	for (const auto & entry : imageFiles)
+		result[entry.first] = entry.second()->toSharedImage();
 
 
-	if(CResourceHandler::get()->existsResource(ResourcePath(filename))) // overridden by mod, no generation
-		return;
+	return result;
+}
 
 
-	if(!CResourceHandler::get("local")->createResource(filename))
-		return;
-	ResourcePath savePath(filename, EResType::IMAGE);
+std::map<AnimationPath, AssetGenerator::AnimationLayoutMap> AssetGenerator::generateAllAnimations()
+{
+	return animationFiles;
+}
 
 
+AssetGenerator::CanvasPtr AssetGenerator::createAdventureOptionsCleanBackground()
+{
 	auto locator = ImageLocator(ImagePath::builtin("ADVOPTBK"), EImageBlitMode::OPAQUE);
 	auto locator = ImageLocator(ImagePath::builtin("ADVOPTBK"), EImageBlitMode::OPAQUE);
 
 
 	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);
 	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);
@@ -74,20 +98,11 @@ void AssetGenerator::createAdventureOptionsCleanBackground()
 	canvas.draw(img, Point(53, 567), Rect(53, 520, 339, 3));
 	canvas.draw(img, Point(53, 567), Rect(53, 520, 339, 3));
 	canvas.draw(img, Point(53, 520), Rect(53, 264, 339, 47));
 	canvas.draw(img, Point(53, 520), Rect(53, 264, 339, 47));
 
 
-	image->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePath));
+	return image;
 }
 }
 
 
-void AssetGenerator::createBigSpellBook()
+AssetGenerator::CanvasPtr AssetGenerator::createBigSpellBook()
 {
 {
-	std::string filename = "data/SpellBookLarge.png";
-
-	if(CResourceHandler::get()->existsResource(ResourcePath(filename))) // overridden by mod, no generation
-		return;
-
-	if(!CResourceHandler::get("local")->createResource(filename))
-		return;
-	ResourcePath savePath(filename, EResType::IMAGE);
-
 	auto locator = ImageLocator(ImagePath::builtin("SpelBack"), EImageBlitMode::OPAQUE);
 	auto locator = ImageLocator(ImagePath::builtin("SpelBack"), EImageBlitMode::OPAQUE);
 
 
 	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);
 	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);
@@ -135,21 +150,11 @@ void AssetGenerator::createBigSpellBook()
 	canvas.draw(img, Point(575, 465), Rect(417, 406, 37, 45));
 	canvas.draw(img, Point(575, 465), Rect(417, 406, 37, 45));
 	canvas.draw(img, Point(667, 465), Rect(478, 406, 37, 47));
 	canvas.draw(img, Point(667, 465), Rect(478, 406, 37, 47));
 
 
-	image->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePath));
+	return image;
 }
 }
 
 
-void AssetGenerator::createPlayerColoredBackground(const PlayerColor & player)
+AssetGenerator::CanvasPtr AssetGenerator::createPlayerColoredBackground(const PlayerColor & player)
 {
 {
-	std::string filename = "data/DialogBoxBackground_" + player.toString() + ".png";
-
-	if(CResourceHandler::get()->existsResource(ResourcePath(filename))) // overridden by mod, no generation
-		return;
-
-	if(!CResourceHandler::get("local")->createResource(filename))
-		return;
-
-	ResourcePath savePath(filename, EResType::IMAGE);
-
 	auto locator = ImageLocator(ImagePath::builtin("DiBoxBck"), EImageBlitMode::OPAQUE);
 	auto locator = ImageLocator(ImagePath::builtin("DiBoxBck"), EImageBlitMode::OPAQUE);
 
 
 	std::shared_ptr<IImage> texture = GH.renderHandler().loadImage(locator);
 	std::shared_ptr<IImage> texture = GH.renderHandler().loadImage(locator);
@@ -169,71 +174,44 @@ void AssetGenerator::createPlayerColoredBackground(const PlayerColor & player)
 
 
 	assert(player.isValidPlayer());
 	assert(player.isValidPlayer());
 	if (!player.isValidPlayer())
 	if (!player.isValidPlayer())
-	{
-		logGlobal->error("Unable to colorize to invalid player color %d!", player.getNum());
-		return;
-	}
+		throw std::runtime_error("Unable to colorize to invalid player color" + std::to_string(player.getNum()));
 
 
 	texture->adjustPalette(filters[player.getNum()], 0);
 	texture->adjustPalette(filters[player.getNum()], 0);
-	texture->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePath));
-}
-
-void AssetGenerator::createCombatUnitNumberWindow()
-{
-	std::string filenameToSave = "data/combatUnitNumberWindow";
 
 
-	ResourcePath savePathDefault(filenameToSave + "Default.png", EResType::IMAGE);
-	ResourcePath savePathNeutral(filenameToSave + "Neutral.png", EResType::IMAGE);
-	ResourcePath savePathPositive(filenameToSave + "Positive.png", EResType::IMAGE);
-	ResourcePath savePathNegative(filenameToSave + "Negative.png", EResType::IMAGE);
-
-	if(CResourceHandler::get()->existsResource(savePathDefault)) // overridden by mod, no generation
-		return;
+	auto image = GH.renderHandler().createImage(texture->dimensions(), CanvasScalingPolicy::IGNORE);
+	Canvas canvas = image->getCanvas();
+	canvas.draw(texture, Point(0,0));
 
 
-	if(!CResourceHandler::get("local")->createResource(savePathDefault.getOriginalName() + ".png") ||
-	   !CResourceHandler::get("local")->createResource(savePathNeutral.getOriginalName() + ".png") ||
-	   !CResourceHandler::get("local")->createResource(savePathPositive.getOriginalName() + ".png") ||
-	   !CResourceHandler::get("local")->createResource(savePathNegative.getOriginalName() + ".png"))
-		return;
+	return image;
+}
 
 
+AssetGenerator::CanvasPtr AssetGenerator::createCombatUnitNumberWindow(float multR, float multG, float multB)
+{
 	auto locator = ImageLocator(ImagePath::builtin("CMNUMWIN"), EImageBlitMode::OPAQUE);
 	auto locator = ImageLocator(ImagePath::builtin("CMNUMWIN"), EImageBlitMode::OPAQUE);
 	locator.layer = EImageBlitMode::OPAQUE;
 	locator.layer = EImageBlitMode::OPAQUE;
 
 
 	std::shared_ptr<IImage> texture = GH.renderHandler().loadImage(locator);
 	std::shared_ptr<IImage> texture = GH.renderHandler().loadImage(locator);
 
 
-	static const auto shifterNormal   = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 0.6f, 0.2f, 1.0f );
-	static const auto shifterPositive = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 0.2f, 1.0f, 0.2f );
-	static const auto shifterNegative = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 1.0f, 0.2f, 0.2f );
-	static const auto shifterNeutral  = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 1.0f, 1.0f, 0.2f );
+	const auto shifter= ColorFilter::genRangeShifter(0.f, 0.f, 0.f, multR, multG, multB);
 
 
 	// do not change border color
 	// do not change border color
 	static const int32_t ignoredMask = 1 << 26;
 	static const int32_t ignoredMask = 1 << 26;
 
 
-	texture->adjustPalette(shifterNormal, ignoredMask);
-	texture->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePathDefault));
-	texture->adjustPalette(shifterPositive, ignoredMask);
-	texture->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePathPositive));
-	texture->adjustPalette(shifterNegative, ignoredMask);
-	texture->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePathNegative));
-	texture->adjustPalette(shifterNeutral, ignoredMask);
-	texture->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePathNeutral));
-}
-
-void AssetGenerator::createCampaignBackground()
-{
-	std::string filename = "data/CampaignBackground8.png";
+	texture->adjustPalette(shifter, ignoredMask);
 
 
-	if(CResourceHandler::get()->existsResource(ResourcePath(filename))) // overridden by mod, no generation
-		return;
+	auto image = GH.renderHandler().createImage(texture->dimensions(), CanvasScalingPolicy::IGNORE);
+	Canvas canvas = image->getCanvas();
+	canvas.draw(texture, Point(0,0));
 
 
-	if(!CResourceHandler::get("local")->createResource(filename))
-		return;
-	ResourcePath savePath(filename, EResType::IMAGE);
+	return image;
+}
 
 
+AssetGenerator::CanvasPtr AssetGenerator::createCampaignBackground()
+{
 	auto locator = ImageLocator(ImagePath::builtin("CAMPBACK"), EImageBlitMode::OPAQUE);
 	auto locator = ImageLocator(ImagePath::builtin("CAMPBACK"), EImageBlitMode::OPAQUE);
 
 
 	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);
 	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);
-	auto image = GH.renderHandler().createImage(Point(800, 600), CanvasScalingPolicy::IGNORE);
+	auto image = GH.renderHandler().createImage(Point(200, 116), CanvasScalingPolicy::IGNORE);
 	Canvas canvas = image->getCanvas();
 	Canvas canvas = image->getCanvas();
 
 
 	canvas.draw(img, Point(0, 0), Rect(0, 0, 800, 600));
 	canvas.draw(img, Point(0, 0), Rect(0, 0, 800, 600));
@@ -264,171 +242,112 @@ void AssetGenerator::createCampaignBackground()
 	std::shared_ptr<IImage> imgSkull = GH.renderHandler().loadImage(locatorSkull);
 	std::shared_ptr<IImage> imgSkull = GH.renderHandler().loadImage(locatorSkull);
 	canvas.draw(imgSkull, Point(562, 509), Rect(178, 108, 43, 19));
 	canvas.draw(imgSkull, Point(562, 509), Rect(178, 108, 43, 19));
 
 
-	image->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePath));
+	return image;
 }
 }
 
 
-void AssetGenerator::createChroniclesCampaignImages()
+AssetGenerator::CanvasPtr AssetGenerator::createChroniclesCampaignImages(int chronicle)
 {
 {
-	for(int i = 1; i < 9; i++)
-	{
-		std::string filename = "data/CampaignHc" + std::to_string(i) + "Image.png";
-
-		if(CResourceHandler::get()->existsResource(ResourcePath(filename))) // overridden by mod, no generation
-			continue;
-			
-		auto imgPathBg = ImagePath::builtin("data/chronicles_" + std::to_string(i) + "/GamSelBk");
-		if(!CResourceHandler::get()->existsResource(imgPathBg)) // Chronicle episode not installed
-			continue;
-
-		if(!CResourceHandler::get("local")->createResource(filename))
-			continue;
-		ResourcePath savePath(filename, EResType::IMAGE);
+	auto imgPathBg = ImagePath::builtin("data/chronicles_" + std::to_string(chronicle) + "/GamSelBk");
+	auto locator = ImageLocator(imgPathBg, EImageBlitMode::OPAQUE);
 
 
-		auto locator = ImageLocator(imgPathBg, EImageBlitMode::OPAQUE);
+	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);
+	auto image = GH.renderHandler().createImage(Point(800, 600), CanvasScalingPolicy::IGNORE);
+	Canvas canvas = image->getCanvas();
 
 
-		std::shared_ptr<IImage> img = GH.renderHandler().loadImage(locator);
-		auto image = GH.renderHandler().createImage(Point(800, 600), CanvasScalingPolicy::IGNORE);
-		Canvas canvas = image->getCanvas();
-		
-		switch (i)
-		{
-		case 1:
-			canvas.draw(img, Point(0, 0), Rect(149, 144, 200, 116));
-			break;
-		case 2:
-			canvas.draw(img, Point(0, 0), Rect(156, 150, 200, 116));
-			break;
-		case 3:
-			canvas.draw(img, Point(0, 0), Rect(171, 153, 200, 116));
-			break;
-		case 4:
-			canvas.draw(img, Point(0, 0), Rect(35, 358, 200, 116));
-			break;
-		case 5:
-			canvas.draw(img, Point(0, 0), Rect(216, 248, 200, 116));
-			break;
-		case 6:
-			canvas.draw(img, Point(0, 0), Rect(58, 234, 200, 116));
-			break;
-		case 7:
-			canvas.draw(img, Point(0, 0), Rect(184, 219, 200, 116));
-			break;
-		case 8:
-			canvas.draw(img, Point(0, 0), Rect(268, 210, 200, 116));
-
-			//skull
-			auto locatorSkull = ImageLocator(ImagePath::builtin("CampSP1"), EImageBlitMode::OPAQUE);
-			std::shared_ptr<IImage> imgSkull = GH.renderHandler().loadImage(locatorSkull);
-			canvas.draw(imgSkull, Point(162, 94), Rect(162, 94, 41, 22));
-			canvas.draw(img, Point(162, 94), Rect(424, 304, 14, 4));
-			canvas.draw(img, Point(162, 98), Rect(424, 308, 10, 4));
-			canvas.draw(img, Point(158, 102), Rect(424, 312, 10, 4));
-			canvas.draw(img, Point(154, 106), Rect(424, 316, 10, 4));
-			break;
-		}
+	std::array sourceRect = {
+		Rect(149, 144, 200, 116),
+		Rect(156, 150, 200, 116),
+		Rect(171, 153, 200, 116),
+		Rect(35, 358, 200, 116),
+		Rect(216, 248, 200, 116),
+		Rect(58, 234, 200, 116),
+		Rect(184, 219, 200, 116),
+		Rect(268, 210, 200, 116),
+	};
+	
+	canvas.draw(img, Point(0, 0), sourceRect.at(chronicle-1));
 
 
-		image->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePath));
+	if (chronicle == 8)
+	{
+		//skull
+		auto locatorSkull = ImageLocator(ImagePath::builtin("CampSP1"), EImageBlitMode::OPAQUE);
+		std::shared_ptr<IImage> imgSkull = GH.renderHandler().loadImage(locatorSkull);
+		canvas.draw(imgSkull, Point(162, 94), Rect(162, 94, 41, 22));
+		canvas.draw(img, Point(162, 94), Rect(424, 304, 14, 4));
+		canvas.draw(img, Point(162, 98), Rect(424, 308, 10, 4));
+		canvas.draw(img, Point(158, 102), Rect(424, 312, 10, 4));
+		canvas.draw(img, Point(154, 106), Rect(424, 316, 10, 4));
 	}
 	}
+
+	return image;
 }
 }
 
 
 void AssetGenerator::createPaletteShiftedSprites()
 void AssetGenerator::createPaletteShiftedSprites()
 {
 {
-	std::vector<std::string> tiles;
-	std::vector<std::vector<std::variant<TerrainPaletteAnimation, RiverPaletteAnimation>>> paletteAnimations;
 	for(auto entity : VLC->terrainTypeHandler->objects)
 	for(auto entity : VLC->terrainTypeHandler->objects)
 	{
 	{
-		if(entity->paletteAnimation.size())
-		{
-			tiles.push_back(entity->tilesFilename.getName());
-			std::vector<std::variant<TerrainPaletteAnimation, RiverPaletteAnimation>> tmpAnim;
-			for(auto & animEntity : entity->paletteAnimation)
-				tmpAnim.push_back(animEntity);
-			paletteAnimations.push_back(tmpAnim);
-		}
+		if(entity->paletteAnimation.empty())
+			continue;
+
+		std::vector<PaletteAnimation> paletteShifts;
+		for(auto & animEntity : entity->paletteAnimation)
+			paletteShifts.push_back({animEntity.start, animEntity.length});
+
+		generatePaletteShiftedAnimation(entity->tilesFilename, paletteShifts);
+
 	}
 	}
 	for(auto entity : VLC->riverTypeHandler->objects)
 	for(auto entity : VLC->riverTypeHandler->objects)
 	{
 	{
-		if(entity->paletteAnimation.size())
-		{
-			tiles.push_back(entity->tilesFilename.getName());
-			std::vector<std::variant<TerrainPaletteAnimation, RiverPaletteAnimation>> tmpAnim;
-			for(auto & animEntity : entity->paletteAnimation)
-				tmpAnim.push_back(animEntity);
-			paletteAnimations.push_back(tmpAnim);
-		}
+		if(entity->paletteAnimation.empty())
+			continue;
+
+		std::vector<PaletteAnimation> paletteShifts;
+		for(auto & animEntity : entity->paletteAnimation)
+			paletteShifts.push_back({animEntity.start, animEntity.length});
+
+		generatePaletteShiftedAnimation(entity->tilesFilename, paletteShifts);
 	}
 	}
+}
 
 
-	for(int i = 0; i < tiles.size(); i++)
-	{
-		auto sprite = tiles[i];
+void AssetGenerator::generatePaletteShiftedAnimation(const AnimationPath & sprite, const std::vector<PaletteAnimation> & paletteAnimations)
+{
+	AnimationLayoutMap layout;
 
 
-		JsonNode config;
-		config["basepath"].String() = sprite + "_Shifted/";
-		config["images"].Vector();
+	auto animation = GH.renderHandler().loadAnimation(sprite, EImageBlitMode::COLORKEY);
 
 
-		auto filename = AnimationPath::builtin(sprite).addPrefix("SPRITES/");
-		auto filenameNew = AnimationPath::builtin(sprite + "_Shifted").addPrefix("SPRITES/");
+	int paletteTransformLength = 1;
+	for (const auto & transform : paletteAnimations)
+		paletteTransformLength = std::lcm(paletteTransformLength, transform.length);
 
 
-		if(CResourceHandler::get()->existsResource(ResourcePath(filenameNew.getName(), EResType::JSON))) // overridden by mod, no generation
-			return;
-		
-		auto anim = GH.renderHandler().loadAnimation(filename, EImageBlitMode::COLORKEY);
-		for(int j = 0; j < anim->size(); j++)
+	for(int tileIndex = 0; tileIndex < animation->size(); tileIndex++)
+	{
+		for(int paletteIndex = 0; paletteIndex < paletteTransformLength; paletteIndex++)
 		{
 		{
-			int maxLen = 1;
-			for(int k = 0; k < paletteAnimations[i].size(); k++)
-			{
-				auto element = paletteAnimations[i][k];
-				if(std::holds_alternative<TerrainPaletteAnimation>(element))
-					maxLen = std::lcm(maxLen, std::get<TerrainPaletteAnimation>(element).length);
-				else
-					maxLen = std::lcm(maxLen, std::get<RiverPaletteAnimation>(element).length);
-			}
-			for(int l = 0; l < maxLen; l++)
-			{
-				std::string spriteName = sprite + boost::str(boost::format("%02d") % j) + "_" + std::to_string(l) + ".png";
-				std::string filenameNewImg = "sprites/" + sprite + "_Shifted" + "/" + spriteName;
-				ResourcePath savePath(filenameNewImg, EResType::IMAGE);
-
-				if(!CResourceHandler::get("local")->createResource(filenameNewImg))
-					return;
-
-				auto imgLoc = anim->getImageLocator(j, 0);
-				auto img = GH.renderHandler().loadImage(imgLoc);
-				for(int k = 0; k < paletteAnimations[i].size(); k++)
-				{
-					auto element = paletteAnimations[i][k];
-					if(std::holds_alternative<TerrainPaletteAnimation>(element))
-					{
-						auto tmp = std::get<TerrainPaletteAnimation>(element);
-						img->shiftPalette(tmp.start, tmp.length, l % tmp.length);
-					}
-					else
-					{
-						auto tmp = std::get<RiverPaletteAnimation>(element);
-						img->shiftPalette(tmp.start, tmp.length, l % tmp.length);
-					}
-				}
-				
-				auto image = GH.renderHandler().createImage(Point(32, 32), CanvasScalingPolicy::IGNORE);
-				Canvas canvas = image->getCanvas();
-				canvas.draw(img, Point((32 - img->dimensions().x) / 2, (32 - img->dimensions().y) / 2));
-				image->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePath));
-
-				JsonNode node(JsonMap{
-					{ "group", JsonNode(l) },
-					{ "frame", JsonNode(j) },
-					{ "file", JsonNode(spriteName) }
-				});
-				config["images"].Vector().push_back(node);
-			}
+			ImagePath spriteName = ImagePath::builtin(sprite.getName() + boost::str(boost::format("%02d") % tileIndex) + "_" + std::to_string(paletteIndex) + ".png");
+			layout[paletteIndex].push_back(ImageLocator(spriteName, EImageBlitMode::SIMPLE));
+
+			imageFiles[spriteName]  = [=](){ return createPaletteShiftedImage(sprite, paletteAnimations, tileIndex, paletteIndex);};
 		}
 		}
+	}
 
 
-		ResourcePath savePath(filenameNew.getOriginalName(), EResType::JSON);
-		if(!CResourceHandler::get("local")->createResource(filenameNew.getOriginalName() + ".json"))
-			return;
+	AnimationPath shiftedPath = AnimationPath::builtin("SPRITES/" + sprite.getName() + "_SHIFTED");
+	animationFiles[shiftedPath] = layout;
+}
+
+AssetGenerator::CanvasPtr AssetGenerator::createPaletteShiftedImage(const AnimationPath & source, const std::vector<PaletteAnimation> & palette, int frameIndex, int paletteShiftCounter)
+{
+	auto animation = GH.renderHandler().loadAnimation(source, EImageBlitMode::COLORKEY);
+
+	auto imgLoc = animation->getImageLocator(frameIndex, 0);
+	auto img = GH.renderHandler().loadImage(imgLoc);
+
+	for(const auto & element : palette)
+		img->shiftPalette(element.start, element.length, paletteShiftCounter % element.length);
+
+	auto image = GH.renderHandler().createImage(Point(32, 32), CanvasScalingPolicy::IGNORE);
+	Canvas canvas = image->getCanvas();
+	canvas.draw(img, Point((32 - img->dimensions().x) / 2, (32 - img->dimensions().y) / 2));
+
+	return image;
 
 
-		std::fstream file(CResourceHandler::get("local")->getResourceName(savePath)->c_str(), std::ofstream::out | std::ofstream::trunc);
-		file << config.toString();
-	}
 }
 }

+ 42 - 9
client/render/AssetGenerator.h

@@ -9,20 +9,53 @@
  */
  */
 #pragma once
 #pragma once
 
 
+#include "ImageLocator.h"
+
 VCMI_LIB_NAMESPACE_BEGIN
 VCMI_LIB_NAMESPACE_BEGIN
 class PlayerColor;
 class PlayerColor;
 VCMI_LIB_NAMESPACE_END
 VCMI_LIB_NAMESPACE_END
 
 
+class ISharedImage;
+class CanvasImage;
+
 class AssetGenerator
 class AssetGenerator
 {
 {
 public:
 public:
-	static void clear();
-	static void generateAll();
-	static void createAdventureOptionsCleanBackground();
-	static void createBigSpellBook();
-	static void createPlayerColoredBackground(const PlayerColor & player);
-	static void createCombatUnitNumberWindow();
-	static void createCampaignBackground();
-	static void createChroniclesCampaignImages();
-	static void createPaletteShiftedSprites();
+	using AnimationLayoutMap = std::map<size_t, std::vector<ImageLocator>>;
+	using CanvasPtr = std::shared_ptr<CanvasImage>;
+
+	AssetGenerator();
+
+	void initialize();
+
+	std::shared_ptr<ISharedImage> generateImage(const ImagePath & image);
+
+	std::map<ImagePath, std::shared_ptr<ISharedImage>> generateAllImages();
+	std::map<AnimationPath, AnimationLayoutMap> generateAllAnimations();
+
+private:
+	using ImageGenerationFunctor = std::function<CanvasPtr()>;
+
+	struct PaletteAnimation
+	{
+		/// index of first color to cycle
+		int32_t start;
+		/// total numbers of colors to cycle
+		int32_t length;
+	};
+
+	std::map<ImagePath, ImageGenerationFunctor> imageFiles;
+	std::map<AnimationPath, AnimationLayoutMap> animationFiles;
+
+	CanvasPtr createAdventureOptionsCleanBackground();
+	CanvasPtr createBigSpellBook();
+	CanvasPtr createPlayerColoredBackground(const PlayerColor & player);
+	CanvasPtr createCombatUnitNumberWindow(float multR, float multG, float multB);
+	CanvasPtr createCampaignBackground();
+	CanvasPtr createChroniclesCampaignImages(int chronicle);
+	CanvasPtr createPaletteShiftedImage(const AnimationPath & source, const std::vector<PaletteAnimation> & animation, int frameIndex, int paletteShiftCounter);
+
+	void createPaletteShiftedSprites();
+	void generatePaletteShiftedAnimation(const AnimationPath & source, const std::vector<PaletteAnimation> & animation);
+
 };
 };

+ 6 - 0
client/render/CanvasImage.cpp

@@ -14,6 +14,7 @@
 #include "../render/IScreenHandler.h"
 #include "../render/IScreenHandler.h"
 #include "../renderSDL/SDL_Extensions.h"
 #include "../renderSDL/SDL_Extensions.h"
 #include "../renderSDL/SDLImageScaler.h"
 #include "../renderSDL/SDLImageScaler.h"
+#include "../renderSDL/SDLImage.h"
 
 
 #include <SDL_image.h>
 #include <SDL_image.h>
 #include <SDL_surface.h>
 #include <SDL_surface.h>
@@ -61,3 +62,8 @@ Point CanvasImage::dimensions() const
 {
 {
 	return {surface->w, surface->h};
 	return {surface->w, surface->h};
 }
 }
+
+std::shared_ptr<ISharedImage> CanvasImage::toSharedImage()
+{
+	return std::make_shared<SDLImageShared>(surface);
+}

+ 2 - 0
client/render/CanvasImage.h

@@ -34,6 +34,8 @@ public:
 	void shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) override{};
 	void shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) override{};
 	void adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) override{};
 	void adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) override{};
 
 
+	std::shared_ptr<ISharedImage> toSharedImage();
+
 private:
 private:
 	SDL_Surface * surface;
 	SDL_Surface * surface;
 	CanvasScalingPolicy scalingPolicy;
 	CanvasScalingPolicy scalingPolicy;

+ 2 - 0
client/render/IRenderHandler.h

@@ -50,4 +50,6 @@ public:
 
 
 	/// Returns font with specified identifer
 	/// Returns font with specified identifer
 	virtual std::shared_ptr<const IFont> loadFont(EFonts font) = 0;
 	virtual std::shared_ptr<const IFont> loadFont(EFonts font) = 0;
+
+	virtual void exportGeneratedAssets() = 0;
 };
 };

+ 37 - 3
client/renderSDL/RenderHandler.cpp

@@ -16,6 +16,7 @@
 
 
 #include "../gui/CGuiHandler.h"
 #include "../gui/CGuiHandler.h"
 
 
+#include "../render/AssetGenerator.h"
 #include "../render/CAnimation.h"
 #include "../render/CAnimation.h"
 #include "../render/CanvasImage.h"
 #include "../render/CanvasImage.h"
 #include "../render/CDefFile.h"
 #include "../render/CDefFile.h"
@@ -43,6 +44,13 @@
 #include <vcmi/SkillService.h>
 #include <vcmi/SkillService.h>
 #include <vcmi/spells/Service.h>
 #include <vcmi/spells/Service.h>
 
 
+RenderHandler::RenderHandler()
+	:assetGenerator(std::make_unique<AssetGenerator>())
+{
+}
+
+RenderHandler::~RenderHandler() = default;
+
 std::shared_ptr<CDefFile> RenderHandler::getAnimationFile(const AnimationPath & path)
 std::shared_ptr<CDefFile> RenderHandler::getAnimationFile(const AnimationPath & path)
 {
 {
 	AnimationPath actualPath = boost::starts_with(path.getName(), "SPRITES") ? path : path.addPrefix("SPRITES/");
 	AnimationPath actualPath = boost::starts_with(path.getName(), "SPRITES") ? path : path.addPrefix("SPRITES/");
@@ -201,12 +209,28 @@ std::shared_ptr<ScalableImageShared> RenderHandler::loadImageImpl(const ImageLoc
 	return scaledImage;
 	return scaledImage;
 }
 }
 
 
-std::shared_ptr<SDLImageShared> RenderHandler::loadImageFromFileUncached(const ImageLocator & locator)
+std::shared_ptr<ISharedImage> RenderHandler::loadImageFromFileUncached(const ImageLocator & locator)
 {
 {
 	if(locator.image)
 	if(locator.image)
 	{
 	{
-		// TODO: create EmptySharedImage class that will be instantiated if image does not exists or fails to load
-		return std::make_shared<SDLImageShared>(*locator.image);
+		auto imagePath = *locator.image;
+		auto imagePathSprites = imagePath.addPrefix("SPRITES/");
+		auto imagePathData = imagePath.addPrefix("DATA/");
+
+		if(CResourceHandler::get()->existsResource(imagePathSprites))
+			return std::make_shared<SDLImageShared>(imagePathSprites);
+
+		if(CResourceHandler::get()->existsResource(imagePathData))
+			return std::make_shared<SDLImageShared>(imagePathData);
+
+		if(CResourceHandler::get()->existsResource(imagePath))
+			return std::make_shared<SDLImageShared>(imagePath);
+
+		auto generated = assetGenerator->generateImage(imagePath);
+		if (generated)
+			return generated;
+
+		return std::make_shared<SDLImageShared>(ImagePath::builtin("DEFAULT"));
 	}
 	}
 
 
 	if(locator.defFile)
 	if(locator.defFile)
@@ -423,6 +447,10 @@ static void detectOverlappingBuildings(RenderHandler * renderHandler, const Fact
 
 
 void RenderHandler::onLibraryLoadingFinished(const Services * services)
 void RenderHandler::onLibraryLoadingFinished(const Services * services)
 {
 {
+	assert(animationLayouts.empty());
+	assetGenerator->initialize();
+	animationLayouts = assetGenerator->generateAllAnimations();
+
 	addImageListEntries(services->creatures());
 	addImageListEntries(services->creatures());
 	addImageListEntries(services->heroTypes());
 	addImageListEntries(services->heroTypes());
 	addImageListEntries(services->artifacts());
 	addImageListEntries(services->artifacts());
@@ -469,3 +497,9 @@ std::shared_ptr<const IFont> RenderHandler::loadFont(EFonts font)
 	fonts[font] = loadedFont;
 	fonts[font] = loadedFont;
 	return loadedFont;
 	return loadedFont;
 }
 }
+
+void RenderHandler::exportGeneratedAssets()
+{
+	for (const auto & entry : assetGenerator->generateAllImages())
+		entry.second->exportBitmap(VCMIDirs::get().userDataPath() / "Generated" / (entry.first.getOriginalName() + ".png"), nullptr);
+}

+ 8 - 2
client/renderSDL/RenderHandler.h

@@ -18,8 +18,9 @@ VCMI_LIB_NAMESPACE_END
 class CDefFile;
 class CDefFile;
 class SDLImageShared;
 class SDLImageShared;
 class ScalableImageShared;
 class ScalableImageShared;
+class AssetGenerator;
 
 
-class RenderHandler : public IRenderHandler
+class RenderHandler final : public IRenderHandler
 {
 {
 	using AnimationLayoutMap = std::map<size_t, std::vector<ImageLocator>>;
 	using AnimationLayoutMap = std::map<size_t, std::vector<ImageLocator>>;
 
 
@@ -27,6 +28,7 @@ class RenderHandler : public IRenderHandler
 	std::map<AnimationPath, AnimationLayoutMap> animationLayouts;
 	std::map<AnimationPath, AnimationLayoutMap> animationLayouts;
 	std::map<SharedImageLocator, std::shared_ptr<ScalableImageShared>> imageFiles;
 	std::map<SharedImageLocator, std::shared_ptr<ScalableImageShared>> imageFiles;
 	std::map<EFonts, std::shared_ptr<const IFont>> fonts;
 	std::map<EFonts, std::shared_ptr<const IFont>> fonts;
+	std::unique_ptr<AssetGenerator> assetGenerator;
 
 
 	std::shared_ptr<CDefFile> getAnimationFile(const AnimationPath & path);
 	std::shared_ptr<CDefFile> getAnimationFile(const AnimationPath & path);
 	AnimationLayoutMap & getAnimationLayout(const AnimationPath & path, int scalingFactor, EImageBlitMode mode);
 	AnimationLayoutMap & getAnimationLayout(const AnimationPath & path, int scalingFactor, EImageBlitMode mode);
@@ -38,13 +40,15 @@ class RenderHandler : public IRenderHandler
 
 
 	std::shared_ptr<ScalableImageShared> loadImageImpl(const ImageLocator & config);
 	std::shared_ptr<ScalableImageShared> loadImageImpl(const ImageLocator & config);
 
 
-	std::shared_ptr<SDLImageShared> loadImageFromFileUncached(const ImageLocator & locator);
+	std::shared_ptr<ISharedImage> loadImageFromFileUncached(const ImageLocator & locator);
 
 
 	ImageLocator getLocatorForAnimationFrame(const AnimationPath & path, int frame, int group, int scaling, EImageBlitMode mode);
 	ImageLocator getLocatorForAnimationFrame(const AnimationPath & path, int frame, int group, int scaling, EImageBlitMode mode);
 
 
 	int getScalingFactor() const;
 	int getScalingFactor() const;
 
 
 public:
 public:
+	RenderHandler();
+	~RenderHandler();
 
 
 	// IRenderHandler implementation
 	// IRenderHandler implementation
 	void onLibraryLoadingFinished(const Services * services) override;
 	void onLibraryLoadingFinished(const Services * services) override;
@@ -61,4 +65,6 @@ public:
 
 
 	/// Returns font with specified identifer
 	/// Returns font with specified identifer
 	std::shared_ptr<const IFont> loadFont(EFonts font) override;
 	std::shared_ptr<const IFont> loadFont(EFonts font) override;
+
+	void exportGeneratedAssets() override;
 };
 };

+ 4 - 0
client/renderSDL/SDLImage.cpp

@@ -306,6 +306,10 @@ std::shared_ptr<const ISharedImage> SDLImageShared::scaleTo(const Point & size,
 
 
 void SDLImageShared::exportBitmap(const boost::filesystem::path& path, SDL_Palette * palette) const
 void SDLImageShared::exportBitmap(const boost::filesystem::path& path, SDL_Palette * palette) const
 {
 {
+	auto directory = path;
+	directory.remove_filename();
+	boost::filesystem::create_directories(directory);
+
 	assert(upscalingInProgress == false);
 	assert(upscalingInProgress == false);
 	if (!surf)
 	if (!surf)
 		return;
 		return;

+ 0 - 3
client/widgets/Images.cpp

@@ -13,7 +13,6 @@
 #include "MiscWidgets.h"
 #include "MiscWidgets.h"
 
 
 #include "../gui/CGuiHandler.h"
 #include "../gui/CGuiHandler.h"
-#include "../render/AssetGenerator.h"
 #include "../render/IImage.h"
 #include "../render/IImage.h"
 #include "../render/IRenderHandler.h"
 #include "../render/IRenderHandler.h"
 #include "../render/CAnimation.h"
 #include "../render/CAnimation.h"
@@ -184,8 +183,6 @@ FilledTexturePlayerColored::FilledTexturePlayerColored(Rect position)
 
 
 void FilledTexturePlayerColored::setPlayerColor(PlayerColor player)
 void FilledTexturePlayerColored::setPlayerColor(PlayerColor player)
 {
 {
-	AssetGenerator::createPlayerColoredBackground(player);
-
 	ImagePath imagePath = ImagePath::builtin("DialogBoxBackground_" + player.toString() + ".bmp");
 	ImagePath imagePath = ImagePath::builtin("DialogBoxBackground_" + player.toString() + ".bmp");
 
 
 	texture = GH.renderHandler().loadImage(imagePath, EImageBlitMode::COLORKEY);
 	texture = GH.renderHandler().loadImage(imagePath, EImageBlitMode::COLORKEY);

+ 0 - 2
client/windows/CSpellWindow.cpp

@@ -32,7 +32,6 @@
 #include "../widgets/Buttons.h"
 #include "../widgets/Buttons.h"
 #include "../widgets/VideoWidget.h"
 #include "../widgets/VideoWidget.h"
 #include "../adventureMap/AdventureMapInterface.h"
 #include "../adventureMap/AdventureMapInterface.h"
-#include "../render/AssetGenerator.h"
 
 
 #include "../../CCallback.h"
 #include "../../CCallback.h"
 
 
@@ -118,7 +117,6 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 
 
 	if(isBigSpellbook)
 	if(isBigSpellbook)
 	{
 	{
-		AssetGenerator::createBigSpellBook();
 		background = std::make_shared<CPicture>(ImagePath::builtin("SpellBookLarge"), 0, 0);
 		background = std::make_shared<CPicture>(ImagePath::builtin("SpellBookLarge"), 0, 0);
 		updateShadow();
 		updateShadow();
 	}
 	}

+ 0 - 3
clientapp/EntryPoint.cpp

@@ -27,7 +27,6 @@
 #include "../client/media/CMusicHandler.h"
 #include "../client/media/CMusicHandler.h"
 #include "../client/media/CSoundHandler.h"
 #include "../client/media/CSoundHandler.h"
 #include "../client/media/CVideoHandler.h"
 #include "../client/media/CVideoHandler.h"
-#include "../client/render/AssetGenerator.h"
 #include "../client/render/Graphics.h"
 #include "../client/render/Graphics.h"
 #include "../client/render/IRenderHandler.h"
 #include "../client/render/IRenderHandler.h"
 #include "../client/render/IScreenHandler.h"
 #include "../client/render/IScreenHandler.h"
@@ -235,8 +234,6 @@ int main(int argc, char * argv[])
 	logGlobal->info("Creating console and configuring logger: %d ms", pomtime.getDiff());
 	logGlobal->info("Creating console and configuring logger: %d ms", pomtime.getDiff());
 	logGlobal->info("The log file will be saved to %s", logPath);
 	logGlobal->info("The log file will be saved to %s", logPath);
 
 
-	AssetGenerator::clear();
-
 	// Init filesystem and settings
 	// Init filesystem and settings
 	try
 	try
 	{
 	{