Browse Source

resource generation

Laserlicht 1 year ago
parent
commit
fff0159ef6

+ 2 - 0
client/CMakeLists.txt

@@ -82,6 +82,7 @@ set(client_SRCS
 	media/CSoundHandler.cpp
 	media/CVideoHandler.cpp
 
+	render/AssetGenerator.cpp
 	render/CAnimation.cpp
 	render/CBitmapHandler.cpp
 	render/CDefFile.cpp
@@ -280,6 +281,7 @@ set(client_HEADERS
 	media/ISoundPlayer.h
 	media/IVideoPlayer.h
 
+	render/AssetGenerator.h
 	render/CAnimation.h
 	render/CBitmapHandler.h
 	render/CDefFile.h

+ 3 - 0
client/gui/CGuiHandler.cpp

@@ -24,6 +24,7 @@
 #include "../render/Graphics.h"
 #include "../render/IFont.h"
 #include "../render/EFont.h"
+#include "../render/AssetGenerator.h"
 #include "../renderSDL/ScreenHandler.h"
 #include "../renderSDL/RenderHandler.h"
 #include "../CMT.h"
@@ -63,6 +64,8 @@ void CGuiHandler::init()
 	shortcutsHandlerInstance = std::make_unique<ShortcutHandler>();
 	inputHandlerInstance = std::make_unique<InputHandler>(); // Must be after windowHandlerInstance and shortcutsHandlerInstance
 	framerateManagerInstance = std::make_unique<FramerateManager>(settings["video"]["targetfps"].Integer());
+
+	AssetGenerator::generate();
 }
 
 void CGuiHandler::handleEvents()

+ 86 - 0
client/render/AssetGenerator.cpp

@@ -0,0 +1,86 @@
+/*
+ * AssetGenerator.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#include "StdInc.h"
+#include "AssetGenerator.h"
+
+#include "../gui/CGuiHandler.h"
+#include "../render/IImage.h"
+#include "../render/IImageLoader.h"
+#include "../render/Canvas.h"
+#include "../render/IRenderHandler.h"
+
+#include "../lib/filesystem/Filesystem.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+void AssetGenerator::generate()
+{
+    createBigSpellBook("data/SpelBk2.bmp");
+}
+
+void AssetGenerator::createBigSpellBook(std::string filename)
+{
+	if(!CResourceHandler::get("local")->createResource(filename))
+		return;
+
+    auto res = ImagePath::builtin("SpelBack");
+    res.setOriginalResource(true);
+
+	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(res, EImageBlitMode::OPAQUE);
+	Canvas canvas = Canvas(Point(800, 600));
+	// edges
+	canvas.draw(img, Point(0, 0), Rect(15, 38, 90, 45));
+	canvas.draw(img, Point(0, 460), Rect(15, 400, 90, 141));
+	canvas.draw(img, Point(705, 0), Rect(509, 38, 95, 45));
+	canvas.draw(img, Point(705, 460), Rect(509, 400, 95, 141));
+	// left / right
+	Canvas tmp1 = Canvas(Point(90, 355 - 45));
+	tmp1.draw(img, Point(0, 0), Rect(15, 38 + 45, 90, 355 - 45));
+	canvas.drawScaled(tmp1, Point(0, 45), Point(90, 415));
+	Canvas tmp2 = Canvas(Point(95, 355 - 45));
+	tmp2.draw(img, Point(0, 0), Rect(509, 38 + 45, 95, 355 - 45));
+	canvas.drawScaled(tmp2, Point(705, 45), Point(95, 415));
+	// top / bottom
+	Canvas tmp3 = Canvas(Point(409, 45));
+	tmp3.draw(img, Point(0, 0), Rect(100, 38, 409, 45));
+	canvas.drawScaled(tmp3, Point(90, 0), Point(615, 45));
+	Canvas tmp4 = Canvas(Point(409, 141));
+	tmp4.draw(img, Point(0, 0), Rect(100, 400, 409, 141));
+	canvas.drawScaled(tmp4, Point(90, 460), Point(615, 141));
+	// middle
+	Canvas tmp5 = Canvas(Point(409, 141));
+	tmp5.draw(img, Point(0, 0), Rect(100, 38 + 45, 509 - 15, 400 - 38));
+	canvas.drawScaled(tmp5, Point(90, 45), Point(615, 415));
+	// carpet
+	Canvas tmp6 = Canvas(Point(590, 59));
+	tmp6.draw(img, Point(0, 0), Rect(15, 484, 590, 59));
+	canvas.drawScaled(tmp6, Point(0, 545), Point(800, 59));
+	// remove bookmarks
+	for (int i = 0; i < 56; i++)
+		canvas.draw(Canvas(canvas, Rect(i < 30 ? 268 : 327, 464, 1, 46)), Point(269 + i, 464));
+	for (int i = 0; i < 56; i++)
+		canvas.draw(Canvas(canvas, Rect(469, 464, 1, 42)), Point(470 + i, 464));
+	for (int i = 0; i < 57; i++)
+		canvas.draw(Canvas(canvas, Rect(i < 30 ? 564 : 630, 464, 1, 44)), Point(565 + i, 464));
+	for (int i = 0; i < 56; i++)
+		canvas.draw(Canvas(canvas, Rect(656, 464, 1, 47)), Point(657 + i, 464));
+	// draw bookmarks
+	canvas.draw(img, Point(278, 464), Rect(220, 405, 37, 47));
+	canvas.draw(img, Point(481, 465), Rect(354, 406, 37, 41));
+	canvas.draw(img, Point(575, 465), Rect(417, 406, 37, 45));
+	canvas.draw(img, Point(667, 465), Rect(478, 406, 37, 47));
+
+    std::shared_ptr<IImage> image = GH.renderHandler().createImage(canvas.getInternalSurface());
+
+    ResourcePath savePath(filename, EResType::IMAGE);
+    image->exportBitmap(*CResourceHandler::get("local")->getResourceName(savePath));
+}
+
+VCMI_LIB_NAMESPACE_END

+ 23 - 0
client/render/AssetGenerator.h

@@ -0,0 +1,23 @@
+/*
+ * AssetGenerator.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+
+class DLL_LINKAGE AssetGenerator
+{
+    static void createBigSpellBook(std::string filename);
+
+public:
+    static void generate();
+};
+
+VCMI_LIB_NAMESPACE_END

+ 1 - 54
client/windows/CSpellWindow.cpp

@@ -31,10 +31,6 @@
 #include "../widgets/TextControls.h"
 #include "../widgets/Buttons.h"
 #include "../adventureMap/AdventureMapInterface.h"
-#include "../render/IRenderHandler.h"
-#include "../render/IImage.h"
-#include "../render/IImageLoader.h"
-#include "../render/Canvas.h"
 
 #include "../../CCallback.h"
 
@@ -119,7 +115,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 
 	if(isBigSpellbook)
 	{
-		background = std::make_shared<CPicture>(createBigSpellBook(), Point(0, 0));
+		background = std::make_shared<CPicture>(ImagePath::builtin("SpelBk2"), 0, 0);
 		updateShadow();
 	}
 	else
@@ -221,55 +217,6 @@ CSpellWindow::~CSpellWindow()
 {
 }
 
-std::shared_ptr<IImage> CSpellWindow::createBigSpellBook()
-{
-	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(ImagePath::builtin("SpelBack"), EImageBlitMode::OPAQUE);
-	Canvas canvas = Canvas(Point(800, 600));
-	// edges
-	canvas.draw(img, Point(0, 0), Rect(15, 38, 90, 45));
-	canvas.draw(img, Point(0, 460), Rect(15, 400, 90, 141));
-	canvas.draw(img, Point(705, 0), Rect(509, 38, 95, 45));
-	canvas.draw(img, Point(705, 460), Rect(509, 400, 95, 141));
-	// left / right
-	Canvas tmp1 = Canvas(Point(90, 355 - 45));
-	tmp1.draw(img, Point(0, 0), Rect(15, 38 + 45, 90, 355 - 45));
-	canvas.drawScaled(tmp1, Point(0, 45), Point(90, 415));
-	Canvas tmp2 = Canvas(Point(95, 355 - 45));
-	tmp2.draw(img, Point(0, 0), Rect(509, 38 + 45, 95, 355 - 45));
-	canvas.drawScaled(tmp2, Point(705, 45), Point(95, 415));
-	// top / bottom
-	Canvas tmp3 = Canvas(Point(409, 45));
-	tmp3.draw(img, Point(0, 0), Rect(100, 38, 409, 45));
-	canvas.drawScaled(tmp3, Point(90, 0), Point(615, 45));
-	Canvas tmp4 = Canvas(Point(409, 141));
-	tmp4.draw(img, Point(0, 0), Rect(100, 400, 409, 141));
-	canvas.drawScaled(tmp4, Point(90, 460), Point(615, 141));
-	// middle
-	Canvas tmp5 = Canvas(Point(409, 141));
-	tmp5.draw(img, Point(0, 0), Rect(100, 38 + 45, 509 - 15, 400 - 38));
-	canvas.drawScaled(tmp5, Point(90, 45), Point(615, 415));
-	// carpet
-	Canvas tmp6 = Canvas(Point(590, 59));
-	tmp6.draw(img, Point(0, 0), Rect(15, 484, 590, 59));
-	canvas.drawScaled(tmp6, Point(0, 545), Point(800, 59));
-	// remove bookmarks
-	for (int i = 0; i < 56; i++)
-		canvas.draw(Canvas(canvas, Rect(i < 30 ? 268 : 327, 464, 1, 46)), Point(269 + i, 464));
-	for (int i = 0; i < 56; i++)
-		canvas.draw(Canvas(canvas, Rect(469, 464, 1, 42)), Point(470 + i, 464));
-	for (int i = 0; i < 57; i++)
-		canvas.draw(Canvas(canvas, Rect(i < 30 ? 564 : 630, 464, 1, 44)), Point(565 + i, 464));
-	for (int i = 0; i < 56; i++)
-		canvas.draw(Canvas(canvas, Rect(656, 464, 1, 47)), Point(657 + i, 464));
-	// draw bookmarks
-	canvas.draw(img, Point(278, 464), Rect(220, 405, 37, 47));
-	canvas.draw(img, Point(481, 465), Rect(354, 406, 37, 41));
-	canvas.draw(img, Point(575, 465), Rect(417, 406, 37, 45));
-	canvas.draw(img, Point(667, 465), Rect(478, 406, 37, 47));
-
-	return GH.renderHandler().createImage(canvas.getInternalSurface());
-}
-
 void CSpellWindow::searchInput()
 {
 	if(searchBox)

+ 0 - 2
client/windows/CSpellWindow.h

@@ -113,8 +113,6 @@ class CSpellWindow : public CWindowObject
 	void turnPageLeft();
 	void turnPageRight();
 
-	std::shared_ptr<IImage> createBigSpellBook();
-
 	bool openOnBattleSpells;
 	std::function<void(SpellID)> onSpellSelect; //external processing of selected spell
 

+ 15 - 4
lib/filesystem/AdapterLoaders.cpp

@@ -66,11 +66,22 @@ CFilesystemList::~CFilesystemList()
 
 std::unique_ptr<CInputStream> CFilesystemList::load(const ResourcePath & resourceName) const
 {
-	// load resource from last loader that have it (last overridden version)
-	for(const auto & loader : boost::adaptors::reverse(loaders))
+	if(resourceName.getOriginalResource())
 	{
-		if (loader->existsResource(resourceName))
-			return loader->load(resourceName);
+		for(const auto & loader : loaders)
+		{
+			if (loader->existsResource(resourceName))
+				return loader->load(resourceName);
+		}
+	}
+	else
+	{
+		// load resource from last loader that have it (last overridden version)
+		for(const auto & loader : boost::adaptors::reverse(loaders))
+		{
+			if (loader->existsResource(resourceName))
+				return loader->load(resourceName);
+		}
 	}
 
 	throw std::runtime_error("Resource with name " + resourceName.getName() + " and type "

+ 3 - 2
lib/filesystem/CFilesystemLoader.cpp

@@ -118,10 +118,11 @@ std::unordered_map<ResourcePath, boost::filesystem::path> CFilesystemLoader::lis
 		EResType::ARCHIVE_SND,
 		EResType::ARCHIVE_ZIP };
 	static const std::set<EResType> initialTypes(initArray, initArray + std::size(initArray));
-
-	assert(boost::filesystem::is_directory(baseDirectory));
 	std::unordered_map<ResourcePath, boost::filesystem::path> fileList;
 
+	if(!boost::filesystem::is_directory(baseDirectory))
+		return fileList;
+
 	std::vector<boost::filesystem::path> path; //vector holding relative path to our file
 
 	boost::filesystem::recursive_directory_iterator enddir;

+ 4 - 0
lib/filesystem/Filesystem.cpp

@@ -182,10 +182,14 @@ void CResourceHandler::initialize()
 	knownLoaders["root"] = globalResourceHandler.rootLoader.get();
 	knownLoaders["saves"] = new CFilesystemLoader("SAVES/", VCMIDirs::get().userSavePath());
 	knownLoaders["config"] = new CFilesystemLoader("CONFIG/", VCMIDirs::get().userConfigPath());
+	knownLoaders["gen_data"] = new CFilesystemLoader("DATA/", VCMIDirs::get().userDataPath() / "Generated" / "Data");
+	knownLoaders["gen_sprites"] = new CFilesystemLoader("SPRITES/", VCMIDirs::get().userDataPath() / "Generated" / "Sprites");
 
 	auto * localFS = new CFilesystemList();
 	localFS->addLoader(knownLoaders["saves"], true);
 	localFS->addLoader(knownLoaders["config"], true);
+	localFS->addLoader(knownLoaders["gen_data"], true);
+	localFS->addLoader(knownLoaders["gen_sprites"], true);
 
 	addFilesystem("root", "initial", createInitial());
 	addFilesystem("root", "data", new CFilesystemList());

+ 6 - 3
lib/filesystem/ResourcePath.cpp

@@ -51,19 +51,22 @@ static inline std::string readName(std::string name, bool uppercase)
 ResourcePath::ResourcePath(const std::string & name_):
 	type(readType(name_)),
 	name(readName(name_, true)),
-	originalName(readName(name_, false))
+	originalName(readName(name_, false)),
+	originalResource(false)
 {}
 
 ResourcePath::ResourcePath(const std::string & name_, EResType type_):
 	type(type_),
 	name(readName(name_, true)),
-	originalName(readName(name_, false))
+	originalName(readName(name_, false)),
+	originalResource(false)
 {}
 
 ResourcePath::ResourcePath(const JsonNode & name, EResType type):
 	type(type),
 	name(readName(name.String(), true)),
-	originalName(readName(name.String(), false))
+	originalName(readName(name.String(), false)),
+	originalResource(false)
 {
 }
 

+ 17 - 0
lib/filesystem/ResourcePath.h

@@ -99,6 +99,7 @@ public:
 	bool empty() const {return name.empty();}
 	std::string getName() const {return name;}
 	std::string getOriginalName() const {return originalName;}
+	bool getOriginalResource() const {return originalResource;}
 	EResType getType() const {return type;}
 
 	void serializeJson(JsonSerializeFormat & handler);
@@ -108,6 +109,8 @@ public:
 		h & type;
 		h & name;
 		h & originalName;
+		if (h.version >= Handler::Version::RESOURCE_GENERATION)
+			h & originalResource;
 	}
 
 protected:
@@ -120,6 +123,9 @@ protected:
 
 	/// name in original case
 	std::string originalName;
+
+	/// flag for requesting unmodded, original resource
+	bool originalResource;
 };
 
 template<EResType Type>
@@ -180,6 +186,17 @@ public:
 		ResourcePathTempl result;
 		result.name = prefix + this->getName();
 		result.originalName = prefix + this->getOriginalName();
+		result.originalResource = this->getOriginalResource();
+
+		return result;
+	}
+
+	ResourcePathTempl setOriginalResource(bool original) const
+	{
+		ResourcePathTempl result;
+		result.name = this->getName();
+		result.originalName = this->getOriginalName();
+		result.originalResource = original;
 
 		return result;
 	}

+ 2 - 1
lib/serializer/ESerializationVersion.h

@@ -63,6 +63,7 @@ enum class ESerializationVersion : int32_t
 	STATISTICS, // 852 - removed random number generators from library classes
 	CAMPAIGN_REGIONS, // 853 - configurable campaign regions
 	EVENTS_PLAYER_SET, // 854 - map & town events use std::set instead of bitmask to store player list
+	RESOURCE_GENERATION, // 855 - resource generation
 
-	CURRENT = EVENTS_PLAYER_SET
+	CURRENT = RESOURCE_GENERATION
 };