2
0
Laserlicht 5 сар өмнө
parent
commit
ddd422a075

+ 1 - 1
CI/before_install/linux_qt5.sh

@@ -8,6 +8,6 @@ sudo apt-get update
 # - debian build settings at debian/control
 sudo apt-get install libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev libboost-iostreams-dev \
 libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev \
-qtbase5-dev qttools5-dev \
+qtbase5-dev qttools5-dev libqt5svg5-dev \
 ninja-build zlib1g-dev libavformat-dev libswscale-dev libtbb-dev libluajit-5.1-dev \
 libminizip-dev libfuzzylite-dev libsqlite3-dev # Optional dependencies

+ 1 - 1
CI/before_install/linux_qt6.sh

@@ -8,6 +8,6 @@ sudo apt-get update
 # - debian build settings at debian/control
 sudo apt-get install libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev libboost-iostreams-dev \
 libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev \
-qt6-base-dev qt6-base-dev-tools qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools \
+qt6-base-dev qt6-base-dev-tools qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools qt6-svg-dev libqt6svg6-dev \
 ninja-build zlib1g-dev libavformat-dev libswscale-dev libtbb-dev libluajit-5.1-dev \
 libminizip-dev libfuzzylite-dev libsqlite3-dev # Optional dependencies

+ 15 - 0
CMakeLists.txt

@@ -108,6 +108,7 @@ endif()
 include(CMakeDependentOption)
 cmake_dependent_option(ENABLE_INNOEXTRACT "Enable innoextract for GOG file extraction in launcher" ON "ENABLE_LAUNCHER" OFF)
 cmake_dependent_option(ENABLE_GITVERSION "Enable Version.cpp with Git commit hash" ON "NOT ENABLE_GOLDMASTER" OFF)
+cmake_dependent_option(ENABLE_TEMPLATE_EDITOR "Enable template editor inside map editor" ON "ENABLE_EDITOR" OFF)
 
 option(VCMI_PORTMASTER "PortMaster build" OFF)
 
@@ -253,6 +254,10 @@ if(ENABLE_EDITOR)
 	add_definitions(-DENABLE_EDITOR)
 endif()
 
+if(ENABLE_TEMPLATE_EDITOR)
+	add_definitions(-DENABLE_TEMPLATE_EDITOR)
+endif()
+
 if(ENABLE_SINGLE_APP_BUILD)
 	add_definitions(-DENABLE_SINGLE_APP_BUILD)
 endif()
@@ -521,6 +526,16 @@ if(ENABLE_LAUNCHER OR ENABLE_EDITOR)
 	find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network)
 	find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network)
 
+	if(ENABLE_TEMPLATE_EDITOR)
+		find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Svg Xml)
+		find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Svg Xml)
+
+		if(QT_VERSION_MAJOR EQUAL 6)
+			find_package(QT NAMES Qt6 REQUIRED COMPONENTS SvgWidgets)
+			find_package(Qt6 REQUIRED COMPONENTS SvgWidgets)
+		endif()
+	endif()
+
 	if(ENABLE_TRANSLATIONS)
 		find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS LinguistTools)
 		add_definitions(-DENABLE_QT_TRANSLATIONS)

+ 4 - 2
CMakePresets.json

@@ -189,7 +189,8 @@
             ],
             "cacheVariables": {
                 "CMAKE_BUILD_TYPE": "Release",
-                "FORCE_BUNDLED_FL": "ON"
+                "FORCE_BUNDLED_FL": "ON",
+                "ENABLE_TEMPLATE_EDITOR": "OFF"
             }
         },
         {
@@ -207,7 +208,8 @@
                 "default-release"
             ],
             "cacheVariables": {
-                "CMAKE_BUILD_TYPE": "Release"
+                "CMAKE_BUILD_TYPE": "Release",
+                "ENABLE_TEMPLATE_EDITOR": "OFF"
             }
         },
         {

+ 4 - 0
config/schemas/template.json

@@ -43,6 +43,10 @@
 				"terrainTypeLikeZone" : { "type" : "number" },
 				"treasureLikeZone" : { "type" : "number" },
 				"customObjectsLikeZone" : { "type" : "number" },
+
+				"visPositionX" : { "type" : "number" },
+				"visPositionY" : { "type" : "number" },
+				"visSize" : { "type" : "number" },
 				
 				"terrainTypes": {"$ref" : "#/definitions/stringArray"},
 				"bannedTerrains": {"$ref" : "#/definitions/stringArray"},

+ 1 - 1
docs/developers/Building_Linux.md

@@ -25,7 +25,7 @@ To compile, the following packages (and their development counterparts) are need
 
 For Ubuntu and Debian you need to install this list of packages:
 
-`sudo apt-get install cmake g++ clang libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev zlib1g-dev libavformat-dev libswscale-dev libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev libboost-iostreams-dev qtbase5-dev libtbb-dev libluajit-5.1-dev liblzma-dev libsqlite3-dev qttools5-dev ninja-build ccache`
+`sudo apt-get install cmake g++ clang libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev zlib1g-dev libavformat-dev libswscale-dev libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev libboost-iostreams-dev qtbase5-dev libqt5svg5-dev libtbb-dev libluajit-5.1-dev liblzma-dev libsqlite3-dev qttools5-dev ninja-build ccache`
 
 Alternatively if you have VCMI installed from repository or PPA you can use:
 

+ 28 - 2
lib/rmg/CRmgTemplate.cpp

@@ -144,14 +144,17 @@ ZoneOptions::ZoneOptions():
 	type(ETemplateZoneType::PLAYER_START),
 	size(1),
 	maxTreasureValue(0),
-	owner(std::nullopt),
+	owner(PlayerColor(0)),
 	matchTerrainToTown(true),
 	townsAreSameType(false),
 	monsterStrength(EMonsterStrength::ZONE_NORMAL),
 	townsLikeZone(NO_ZONE),
 	minesLikeZone(NO_ZONE),
 	terrainTypeLikeZone(NO_ZONE),
-	treasureLikeZone(NO_ZONE)
+	treasureLikeZone(NO_ZONE),
+	customObjectsLikeZone(NO_ZONE),
+	visPosition(Point(0, 0)),
+	visSize(1.0)
 {
 }
 
@@ -331,6 +334,26 @@ TRmgTemplateZoneId ZoneOptions::getTownsLikeZone() const
 	return townsLikeZone;
 }
 
+Point ZoneOptions::getVisPosition() const
+{
+	return visPosition;
+}
+
+void ZoneOptions::setVisPosition(Point value)
+{
+	visPosition = value;
+}
+
+float ZoneOptions::getVisSize() const
+{
+	return visSize;
+}
+
+void ZoneOptions::setVisSize(float value)
+{
+	visSize = value;
+}
+
 void ZoneOptions::addConnection(const ZoneConnection & connection)
 {
 	connectedZoneIds.push_back(connection.getOtherZoneId(getId()));
@@ -496,6 +519,9 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
 	}
 
 	handler.serializeStruct("customObjects", objectConfig);
+	handler.serializeInt("visPositionX", visPosition.x);
+	handler.serializeInt("visPositionY", visPosition.y);
+	handler.serializeFloat("visSize", visSize);
 }
 
 ZoneConnection::ZoneConnection():

+ 29 - 0
lib/rmg/CRmgTemplate.h

@@ -12,6 +12,7 @@
 
 #include "../int3.h"
 #include "../GameConstants.h"
+#include "../Point.h"
 #include "../ResourceSet.h"
 #include "ObjectInfo.h"
 #include "ObjectConfig.h"
@@ -21,6 +22,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 class JsonSerializeFormat;
 struct CompoundMapObjectID;
+class TemplateEditor;
 
 enum class ETemplateZoneType
 {
@@ -93,6 +95,10 @@ enum class ERoadOption
 
 class DLL_LINKAGE ZoneConnection
 {
+#ifdef ENABLE_TEMPLATE_EDITOR
+	friend class ::TemplateEditor;
+#endif
+
 public:
 
 	ZoneConnection();
@@ -120,11 +126,18 @@ private:
 
 class DLL_LINKAGE ZoneOptions
 {
+#ifdef ENABLE_TEMPLATE_EDITOR
+	friend class ::TemplateEditor;
+#endif
+
 public:
 	static const TRmgTemplateZoneId NO_ZONE;
 
 	class DLL_LINKAGE CTownInfo
 	{
+#ifdef ENABLE_TEMPLATE_EDITOR
+		friend class ::TemplateEditor;
+#endif
 	public:
 		CTownInfo();
 
@@ -228,6 +241,12 @@ public:
 	TRmgTemplateZoneId getCustomObjectsLikeZone() const;
 	TRmgTemplateZoneId getTownsLikeZone() const;
 
+	Point getVisPosition() const;
+	void setVisPosition(Point value);
+
+	float getVisSize() const;
+	void setVisSize(float value);
+
 protected:
 	TRmgTemplateZoneId id;
 	ETemplateZoneType type;
@@ -235,6 +254,9 @@ protected:
 	ui32 maxTreasureValue;
 	std::optional<int> owner;
 
+	Point visPosition;
+	float visSize;
+
 	ObjectConfig objectConfig;
 	CTownInfo playerTowns;
 	CTownInfo neutralTowns;
@@ -268,11 +290,18 @@ protected:
 /// The CRmgTemplate describes a random map template.
 class DLL_LINKAGE CRmgTemplate : boost::noncopyable
 {
+#ifdef ENABLE_TEMPLATE_EDITOR
+	friend class ::TemplateEditor;
+#endif
+
 public:
 	using Zones = std::map<TRmgTemplateZoneId, std::shared_ptr<rmg::ZoneOptions>>;
 
 	class DLL_LINKAGE CPlayerCountRange
 	{
+#ifdef ENABLE_TEMPLATE_EDITOR
+		friend class ::TemplateEditor;
+#endif
 	public:
 		void addRange(int lower, int upper);
 		void addNumber(int value);

+ 34 - 0
mapeditor/CMakeLists.txt

@@ -49,6 +49,15 @@ set(editor_SRCS
 		campaigneditor/startingbonus.cpp
 		campaigneditor/campaignview.cpp
 )
+if(ENABLE_TEMPLATE_EDITOR)
+	set(editor_SRCS
+		${editor_SRCS}
+		templateeditor/templateeditor.cpp
+		templateeditor/templateview.cpp
+		templateeditor/graphicelements.cpp
+		templateeditor/algorithm.cpp
+	)
+endif()
 
 set(editor_HEADERS
 		StdInc.h
@@ -102,6 +111,15 @@ set(editor_HEADERS
 		campaigneditor/startingbonus.h
 		campaigneditor/campaignview.h
 )
+if(ENABLE_TEMPLATE_EDITOR)
+	set(editor_HEADERS
+		${editor_HEADERS}
+		templateeditor/templateeditor.h
+		templateeditor/templateview.h
+		templateeditor/graphicelements.h
+		templateeditor/algorithm.h
+	)
+endif()
 
 set(editor_FORMS
 		mainwindow.ui
@@ -137,6 +155,12 @@ set(editor_FORMS
 		campaigneditor/scenarioproperties.ui
 		campaigneditor/startingbonus.ui
 )
+if(ENABLE_TEMPLATE_EDITOR)
+	set(editor_FORMS
+		${editor_FORMS}
+		templateeditor/templateeditor.ui
+	)
+endif()
 
 set(editor_RESOURCES
 	resources.qrc
@@ -254,6 +278,10 @@ if(APPLE)
 	set_property(GLOBAL PROPERTY AUTOGEN_TARGETS_FOLDER vcmieditor)
 endif()
 
+if(ENABLE_TEMPLATE_EDITOR)
+	target_compile_definitions(vcmieditor PRIVATE ENABLE_TEMPLATE_EDITOR)
+endif()
+
 # Qt defines 'emit' as macros, which conflicts with TBB definition of method with same name
 target_compile_definitions(vcmieditor PRIVATE QT_NO_EMIT)
 
@@ -262,6 +290,12 @@ if(ENABLE_STATIC_LIBS OR NOT (ENABLE_EDITOR AND ENABLE_LAUNCHER))
 endif()
 
 target_link_libraries(vcmieditor vcmi vcmiqt Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network)
+if(ENABLE_TEMPLATE_EDITOR)
+	target_link_libraries(vcmieditor vcmi vcmiqt Qt${QT_VERSION_MAJOR}::Svg Qt${QT_VERSION_MAJOR}::Xml)
+	if(QT_VERSION_MAJOR EQUAL 6)
+		target_link_libraries(vcmieditor vcmi vcmiqt Qt6::SvgWidgets)
+	endif()
+endif()
 target_include_directories(vcmieditor
 	PUBLIC	${CMAKE_CURRENT_SOURCE_DIR}
 )

+ 5 - 0
mapeditor/StdInc.h

@@ -12,6 +12,11 @@
 #include "../Global.h"
 
 #include <QtWidgets>
+#ifdef ENABLE_TEMPLATE_EDITOR
+#include <QtSvg>
+#include <QSvgRenderer>
+#include <QDomDocument>
+#endif
 #include <QStringList>
 #include <QSet>
 #include <QVector>

+ 58 - 0
mapeditor/helper.cpp

@@ -22,6 +22,10 @@
 #include "../lib/mapping/CMap.h"
 #include "../lib/mapping/MapFormatJson.h"
 #include "../lib/modding/ModIncompatibility.h"
+#include "../lib/rmg/CRmgTemplate.h"
+#include "../lib/serializer/JsonSerializer.h"
+#include "../lib/serializer/JsonDeserializer.h"
+#include "../lib/serializer/CSaveFile.h"
 
 std::unique_ptr<CMap> Helper::openMapInternal(const QString & filenameSelect)
 {
@@ -77,6 +81,38 @@ std::shared_ptr<CampaignState> Helper::openCampaignInternal(const QString & file
 		throw std::runtime_error("Corrupted campaign");
 }
 
+std::map<std::string, std::shared_ptr<CRmgTemplate>> Helper::openTemplateInternal(const QString & filenameSelect)
+{
+	QFileInfo fi(filenameSelect);
+	std::string fname = fi.fileName().toStdString();
+	std::string fdir = fi.dir().path().toStdString();
+	
+	ResourcePath resId("MAPEDITOR/" + fname, EResType::JSON);
+	
+	//addFilesystem takes care about memory deallocation if case of failure, no memory leak here
+	auto mapEditorFilesystem = std::make_unique<CFilesystemLoader>("MAPEDITOR/", fdir, 0);
+	CResourceHandler::removeFilesystem("local", "mapEditor");
+	CResourceHandler::addFilesystem("local", "mapEditor", std::move(mapEditorFilesystem));
+	
+	if(!CResourceHandler::get("mapEditor")->existsResource(resId))
+		throw std::runtime_error("Cannot open template from this folder");
+
+	auto data = CResourceHandler::get()->load(resId)->readAll();
+	JsonNode nodes(reinterpret_cast<std::byte *>(data.first.get()), data.second, resId.getName());
+
+	std::map<std::string, std::shared_ptr<CRmgTemplate>> templates;
+	for(auto & node : nodes.Struct())
+	{
+		JsonDeserializer handler(nullptr, node.second);
+		auto rmg = std::make_shared<CRmgTemplate>();
+		rmg->serializeJson(handler);
+		rmg->validate();
+		templates[node.first] = rmg;
+	}
+	
+	return templates;
+}
+
 void Helper::saveCampaign(std::shared_ptr<CampaignState> campaignState, const QString & filename)
 {
 	auto jsonCampaign = CampaignHandler::writeHeaderToJson(*campaignState);
@@ -107,3 +143,25 @@ void Helper::saveCampaign(std::shared_ptr<CampaignState> campaignState, const QS
 	auto jsonCampaignStr = jsonCampaign.toString();
 	saver->addFile("header.json")->write(reinterpret_cast<const ui8 *>(jsonCampaignStr.data()), jsonCampaignStr.length());
 }
+
+void Helper::saveTemplate(std::map<std::string, std::shared_ptr<CRmgTemplate>> tpl, const QString & filename)
+{
+	JsonMap data;
+
+	for(auto & node : tpl)
+	{
+		JsonNode actual;
+		{
+			JsonSerializer handler(nullptr, actual);
+			node.second->serializeJson(handler);
+		}
+		data[node.first] = actual;
+	}
+	
+	auto byteData = JsonNode(data).toBytes();
+	QByteArray byteDataArray = QByteArray(reinterpret_cast<const char*>(byteData.data()), static_cast<int>(byteData.size()));
+	QFile file(filename);
+
+	if(file.open(QIODevice::WriteOnly))
+    	file.write(byteDataArray);
+}

+ 3 - 0
mapeditor/helper.h

@@ -12,10 +12,13 @@
 
 class CMap;
 class CampaignState;
+class CRmgTemplate;
 
 namespace Helper
 {
 	std::unique_ptr<CMap> openMapInternal(const QString &);
 	std::shared_ptr<CampaignState> openCampaignInternal(const QString &);
+	std::map<std::string, std::shared_ptr<CRmgTemplate>> openTemplateInternal(const QString &);
 	void saveCampaign(std::shared_ptr<CampaignState> campaignState, const QString & filename);
+	void saveTemplate(std::map<std::string, std::shared_ptr<CRmgTemplate>> tpl, const QString & filename);
 }

BIN
mapeditor/icons/dice.png


+ 1147 - 0
mapeditor/icons/templateSquare.svg

@@ -0,0 +1,1147 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="130"
+   height="130"
+   viewBox="0 0 30 30"
+   version="1.1"
+   id="svg"
+   xml:space="preserve"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+	<defs
+   id="defs">
+		<linearGradient
+   id="gradientExtraColor">
+			<stop
+   style="stop-color:#a57d37;stop-opacity:1;"
+   offset="0"
+   id="gradientExtraColorStop1" />
+			<stop
+   style="stop-color:#fae59d;stop-opacity:1;"
+   offset="0.29932213"
+   id="gradientExtraColorStop2" />
+			<stop
+   style="stop-color:#a57d37;stop-opacity:1;"
+   offset="0.60331047"
+   id="gradientExtraColorStop3" />
+			<stop
+   style="stop-color:#fae59d;stop-opacity:1;"
+   offset="0.81806767"
+   id="gradientExtraColorStop4" />
+			<stop
+   style="stop-color:#a57d37;stop-opacity:1;"
+   offset="1"
+   id="gradientExtraColorStop5" />
+		</linearGradient>
+		<linearGradient
+   id="gradientPlayerColor">
+			<stop
+   style="stop-color:#ff0000;stop-opacity:1;"
+   offset="0"
+   id="gradientPlayerColorStop1" />
+			<stop
+   style="stop-color:#960000;stop-opacity:1;"
+   offset="1"
+   id="gradientPlayerColorStop2" />
+		</linearGradient>
+		<radialGradient
+   xlink:href="#gradientPlayerColor"
+   id="gradientPlayer"
+   cx="83.813713"
+   cy="143.22746"
+   fx="83.813713"
+   fy="143.22746"
+   r="15.00021"
+   gradientTransform="matrix(-1.4954132,0,0,-1.4375908,206.11843,351.2311)"
+   gradientUnits="userSpaceOnUse" />
+		<path
+   id="rectPath"
+   width="29.000496"
+   height="29.000496"
+   x="60.12542"
+   y="136.52895"
+   d="m 64.09417,136.52895 h 21.062996 a 3.96875,3.96875 45 0 1 3.96875,3.96875 v 21.06299 a 3.96875,3.96875 135 0 1 -3.96875,3.96875 H 64.09417 a 3.96875,3.96875 45 0 1 -3.96875,-3.96875 V 140.4977 a 3.96875,3.96875 135 0 1 3.96875,-3.96875 z" />
+		<linearGradient
+   xlink:href="#gradientExtraColor"
+   id="gradientExtra"
+   x1="59.75042"
+   y1="136.11623"
+   x2="89.583023"
+   y2="166.02512"
+   gradientUnits="userSpaceOnUse"
+   spreadMethod="pad" />
+		<radialGradient
+   xlink:href="#linearGradient90"
+   id="radialGradient91"
+   cx="118.0668"
+   cy="162.93146"
+   fx="118.0668"
+   fy="162.93146"
+   r="1.7656782"
+   gradientTransform="matrix(0.92099277,0,0,0.54408579,-20.618076,103.78665)"
+   gradientUnits="userSpaceOnUse" />
+		<linearGradient
+   id="linearGradient90">
+			<stop
+   style="stop-color:#e7e6e4;stop-opacity:1;"
+   offset="0"
+   id="stop90" />
+			<stop
+   style="stop-color:#3c3833;stop-opacity:1;"
+   offset="1"
+   id="stop91" />
+		</linearGradient>
+<g
+   id="iconSword"
+   transform="matrix(-0.84629065,0.21100396,0.21100396,0.84629065,102.89409,-134.05354)"><path
+     style="fill:#d8be73;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+     d="m 125.04024,133.37126 -0.23547,0.23547 0.45278,0.46348 1.15643,-1.17782 -0.45232,-0.46302 -0.27643,0.27642"
+     id="path139" /><path
+     style="fill:#9e8745;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+     d="m 125.67114,133.65767 0.79494,0.77263 0.39261,-0.3926 -0.78521,-0.7852 z"
+     id="path141" /><path
+     style="fill:#d9d4cf;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+     d="m 123.44312,131.73319 1.65855,1.65854 0.52868,-0.1177 0.0856,-0.53752 -1.60736,-1.60736 -1.07499,-0.35833 z"
+     id="path138" /><circle
+     style="fill:#db0c03;fill-opacity:1;stroke:#000000;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="path140-0"
+     cx="125.09741"
+     cy="133.75952"
+     r="0.24289261" /><circle
+     style="fill:#db0c03;fill-opacity:1;stroke:#000000;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="path140-0-8"
+     cx="126.08116"
+     cy="132.77298"
+     r="0.24289261" /><path
+     style="fill:#db0c03;fill-opacity:1;stroke:#000000;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     d="m 123.03556,130.75467 2.58344,2.5305"
+     id="path142" /><path
+     style="fill:#a4a29f;fill-opacity:1;stroke:none;stroke-width:0.05;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     d="m 123.25735,131.04124 0.26813,0.63341 1.60578,1.60887 0.34114,-0.0738 z"
+     id="path143" /><path
+     style="fill:#9fe2ff;fill-opacity:1;stroke:none;stroke-width:0.0499999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="path144"
+     d="m 122.79431,131.88763 0.78747,-0.69218 -0.75723,-0.72513 0.90164,0.53502 0.45565,-0.94424 -0.23022,1.02285 1.03883,0.14155 -1.04392,0.0971 0.18638,1.03173 -0.41496,-0.96282 z" /></g>
+	</defs>
+	<clipPath
+   id="clipRect">
+		<use
+   xlink:href="#rectPath"
+   id="use19" />
+	</clipPath>
+	<g
+   id="layer"
+   transform="translate(-59.625668,-136.02919)"
+   style="stroke:#000000;stroke-width:6.0;stroke-dasharray:none;stroke-opacity:0.5">
+		<use
+   xlink:href="#rectPath"
+   id="rect"
+   style="fill:url(#gradientPlayer);fill-opacity:1;stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
+		<use
+   xlink:href="#rectPath"
+   id="rectJunction"
+   style="fill-opacity:0;stroke:#000000;stroke-width:10;stroke-dasharray:none;stroke-opacity:0.3;"
+   clip-path="url(#clipRect)" />
+	</g>
+	<text
+   style="font-size:5px;fill:#ffffff;"
+   x="27.651252"
+   y="27.532862"
+   id="textId"
+   text-anchor="end">999</text>
+	<text
+   style="font-size:3.07692px;fill:#ffffff;"
+   x="4.0261083"
+   y="21.015579"
+   id="textWood"
+   text-anchor="middle">99</text>
+	<text
+   style="font-size:3.07692px;fill:#ffffff;"
+   x="8.2191515"
+   y="21.010046"
+   id="textOre"
+   text-anchor="middle">99</text>
+	<text
+   style="font-size:3.07692px;fill:#ffffff;"
+   x="12.484079"
+   y="21.049248"
+   id="textMercury"
+   text-anchor="middle">99</text>
+	<text
+   style="font-size:3.07692px;fill:#ffffff;"
+   x="16.661751"
+   y="21.020365"
+   id="textSulfur"
+   text-anchor="middle">99</text>
+	<text
+   style="font-size:3.07692px;fill:#ffffff;"
+   x="20.896933"
+   y="21.078743"
+   id="textCrystal"
+   text-anchor="middle">99</text>
+	<text
+   style="font-size:3.07692px;fill:#ffffff;"
+   x="25.133026"
+   y="21.049547"
+   id="textGems"
+   text-anchor="middle">99</text>
+	<text
+   style="font-size:3.07692px;fill:#ffffff;"
+   x="4.0413303"
+   y="27.417381"
+   id="textGold"
+   text-anchor="middle">99</text>
+	<g
+   id="iconSulfur"
+   opacity="1.0"
+   transform="matrix(0.87219868,0,0,0.87219868,-76.735738,-145.67812)">
+		<path
+   style="fill:#a16311;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 105.30403,187.53864 c 0,0 1.57603,1.29652 4.32312,-0.18915 -0.14016,-1.20536 -1.5861,-1.91702 -2.34295,-2.05718 -0.70079,0.47653 -2.28607,1.7785 -1.98017,2.24633 z"
+   id="path2-0" />
+		<path
+   style="fill:#f1bc5a;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 105.50034,187.04779 c 0,0 1.44239,1.04345 3.92228,-0.1087 -0.12652,-0.93476 -1.46607,-1.52177 -2.14931,-1.63046 -0.63263,0.36955 -1.97541,1.45656 -1.77297,1.73916 z"
+   id="path2" />
+		<path
+   style="fill:#f7e5a0;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.30687,187.48004 c 0.80916,-0.0425 1.2935,-0.20252 1.81258,-0.41075 -0.23837,-0.89817 -1.15548,-1.30057 -1.8378,-1.50087 0.0274,0.095 0.21448,0.2338 0.23065,0.32644 0.0162,0.0926 -0.35976,0.16022 -0.35225,0.24978 0.008,0.0896 0.36949,0.15632 0.37096,0.24207 0.001,0.0857 -0.38654,0.21419 -0.3885,0.29542 -0.002,0.0812 0.36369,0.13105 0.3609,0.20705 -0.003,0.076 -0.3345,0.18079 -0.33549,0.25083 -9.9e-4,0.07 0.31294,0.0816 0.31635,0.145 0.003,0.0634 -0.18783,0.13904 -0.1774,0.19503 z"
+   id="path2-8" />
+		<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 105.21877,187.42919 c 0,0 1.5978,1.34551 4.34489,-0.14016 -0.14016,-1.20536 -1.56977,-1.90614 -2.32662,-2.0463 -0.70079,0.47653 -2.24252,1.82205 -2.01827,2.18646 z"
+   id="path1" />
+		<path
+   style="fill:#e9e9db;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 108.93289,187.14217 0.18914,-0.0713 c 0,0 -0.12661,-1.04081 -1.84257,-1.50055 0.0569,0.11392 0.13756,0.18103 0.13756,0.18103 0,0 1.15935,0.36348 1.51587,1.39083 z"
+   id="path3" />
+	</g>
+	<g
+   id="iconGold"
+   opacity="1.0"
+   transform="matrix(0.87219868,0,0,0.87219868,-90.060712,-144.27231)">
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 106.78565,191.70545 c 0,0 0.0966,-0.57982 0.59593,-0.48318 0.49929,0.0966 0.37044,0.40265 0.37044,0.40265 0,0 -0.0644,0.2577 -0.35434,0.31407 -0.28991,0.0564 -0.58787,-0.0564 -0.61203,-0.23354 z"
+   id="path4" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.80839,191.51218 c 0,0 0.31407,-0.68451 0.98247,0.26575 -0.16912,0.28991 -0.57177,0.23354 -0.7892,0.20133 -0.21743,-0.0322 -0.19327,-0.46708 -0.19327,-0.46708 z"
+   id="path5" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 108.69422,191.85846 c 0,0 0.83752,-0.20133 0.73283,0.58787 -0.30602,0.0805 -0.40265,0.16106 -0.57982,0.0805 -0.17717,-0.0805 -0.33823,-0.35433 -0.33017,-0.44292 0.008,-0.0886 0.17716,-0.22548 0.17716,-0.22548 z"
+   id="path6" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 109.31431,192.52686 c 0,0 0.44292,0.0725 0.4107,0.64425 -0.0322,0.57176 -0.73282,0.31407 -0.83751,0.24159 -0.10469,-0.0725 -0.14496,-0.6684 -0.0564,-0.74088 0.21748,-0.0966 0.48319,-0.14496 0.48319,-0.14496 z"
+   id="path7" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.95334,191.9712 c 0,0 -0.44291,0.45903 -0.34628,0.62009 0.0966,0.16106 0.43487,0.16106 0.62814,0.153 0.19327,-0.008 0.45902,0 0.48318,-0.11274 0.0242,-0.11274 -0.0805,-0.29796 -0.12079,-0.3946 -0.0403,-0.0966 -0.0725,-0.24159 -0.16106,-0.25769 -0.0886,-0.0161 -0.48319,-0.008 -0.48319,-0.008 z"
+   id="path8" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 108.04998,192.71208 c 0,0 -0.24964,0.18522 -0.2577,0.33018 -0.008,0.14495 0.1208,0.53955 0.23354,0.61203 0.11274,0.0725 0.45097,0.0805 0.53956,0.008 0.0886,-0.0725 0.20132,-0.0161 0.23353,-0.23354 0.0322,-0.21743 -0.0644,-0.59592 -0.12885,-0.63619 -0.0644,-0.0403 -0.62008,-0.0805 -0.62008,-0.0805 z"
+   id="path9" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.76007,193.04226 c 0,0 -0.47513,0.12885 -0.45097,0.29796 0.0242,0.16911 -0.0644,0.3785 0.12079,0.49124 0.18523,0.11274 0.62814,-0.0403 0.6523,-0.10469 0.0242,-0.0644 -0.12885,-0.0725 -0.14495,-0.17717 -0.0161,-0.10469 -0.17717,-0.50734 -0.17717,-0.50734 z"
+   id="path10" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.19636,191.9551 c 0,0 -0.0966,0.0161 -0.0725,0.25769 0.0242,0.2416 0.31407,0.45903 0.3946,0.45903 0.0805,0 0.0644,-0.21743 0.0886,-0.27381 0.0242,-0.0564 0.21743,-0.31407 0.24965,-0.35433 0.0322,-0.0403 -0.0644,-0.26575 -0.0644,-0.26575 l -0.153,0.0403 -0.24965,0.13691 z"
+   id="path11" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.16414,192.41412 c 0,0 -0.47513,0.16106 -0.38654,0.35433 0.0886,0.19328 0.14495,0.37044 0.26575,0.40266 0.12079,0.0322 0.28991,0.0241 0.28991,0.0241 l 0.37044,-0.12079 0.1369,-0.1208 0.0483,-0.22548 -0.20133,-0.10469 -0.19327,0.0483 z"
+   id="path12" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 106.80981,191.76988 c 0,0 -0.59592,0.52345 -0.57177,0.68451 0.0242,0.16106 0.17717,0.2899 0.32213,0.32212 0.14495,0.0322 0.23353,0 0.23353,0 0,0 -0.0725,-0.20133 -0.008,-0.20938 0.0644,-0.008 0.34628,-0.15301 0.34628,-0.15301 l 0.0161,-0.15301 -0.0403,-0.28991 v -0.0403 z"
+   id="path13" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 106.89034,193.03421 c 0,0 -0.49929,-0.21744 -0.48318,0.10468 0.0161,0.32213 -0.008,0.42682 0.16106,0.46708 0.16911,0.0403 0.69256,0.0805 0.69256,0.0805 l 0.0483,-0.29796 -0.008,-0.20133 h -0.20133 z"
+   id="path14" />
+		<path
+   style="fill:#884a2a;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 106.35884,192.65571 c 0,0 -0.18522,-0.0564 -0.28991,0.11274 -0.10469,0.16912 -0.1369,0.43487 -0.1369,0.43487 0,0 0.008,0.0483 0.0886,0.11274 0.0805,0.0644 0.32212,0.17717 0.38655,0.18522 0.0644,0.008 -0.0242,-0.37044 -0.0242,-0.37044 l 0.21743,-0.22548 v -0.12885 z"
+   id="path15" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 108.33815,192.22539 -0.29312,-0.0216 -0.14893,0.25836 0.17428,-0.0151 0.34768,0.0526 z"
+   id="path16" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 108.02897,191.59116 c 0,0 -0.003,0.0716 0.0332,0.15586 0.0725,-0.004 0.34472,0.0163 0.36667,0.0132 0.0219,-0.004 0.0228,-0.0325 0.0246,-0.0434 0.002,-0.011 -0.28725,-0.35446 -0.42075,-0.14233 z"
+   id="path17" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 108.77202,192.09877 0.061,-0.0407 c 0,0 0.31335,-0.061 0.38663,0.20757 -0.0773,0.0732 -0.23198,0.0692 -0.23198,0.0692 z"
+   id="path18" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 106.46383,192.42423 0.35881,-0.39124 0.0821,0.0346 c 0,0 0.0216,0.17508 0.0151,0.20102 -0.006,0.0259 -0.13834,0.0886 -0.20751,0.10375 -0.0692,0.0151 -0.13833,0.10808 -0.14482,0.12969 -0.006,0.0216 -0.10375,-0.0778 -0.10375,-0.0778 z"
+   id="path19" />
+		<path
+   style="fill:#e6d998;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.18834,191.49354 c 0,0 0.11632,-0.0953 0.23138,0.0287 0.11506,0.12427 0.0717,0.0901 0.0717,0.0901 l -0.14399,0.0533 c 0,0 -0.0657,0.0697 -0.16701,0.0237 -0.10126,-0.046 -0.10256,-0.0684 -0.10716,-0.096 -0.005,-0.0276 0.0776,-0.0841 0.0776,-0.0841 z"
+   id="path20" />
+		<path
+   style="fill:#e6d998;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 106.99986,192.73004 c 0,0 0.0439,0.11169 0.0743,0.14508 0.0303,0.0334 0.0663,0.0732 0.10881,0.0732 0.0425,0 0.29063,-2.6e-4 0.32098,-0.0246 0.0303,-0.0243 0.13947,-0.0419 0.14251,-0.0571 0.003,-0.0152 -0.082,0.006 -0.11534,0.006 -0.0334,0 -0.17241,0.039 -0.2058,-0.004 -0.0334,-0.0425 -0.18227,-0.15373 -0.19745,-0.17195 -0.0152,-0.0182 -0.0885,-0.007 -0.12794,0.0328 z"
+   id="path21" />
+		<path
+   style="fill:#e6d998;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.33452,192.18809 c 0,0 0.0323,0.1217 0.0597,0.13384 0.0273,0.0121 0.18817,-0.24979 0.18817,-0.24979 0,0 -0.0786,0.10243 -0.11199,0.10547 -0.0334,0.003 -0.10819,-0.005 -0.10819,-0.005 z"
+   id="path22" />
+		<path
+   style="fill:#e6d998;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 106.64443,193.39143 c 0,0 -0.0246,-0.15859 -0.0125,-0.18591 0.0121,-0.0273 0.13658,0.0197 0.20943,0.0985 0.0729,0.0789 0.13417,0.0574 0.17666,0.0635 0.0425,0.006 0.084,0.0267 0.084,0.0267 l -0.01,0.0578"
+   id="path23" />
+		<path
+   style="fill:#e6d998;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 106.2037,193.19383 -0.0615,-0.0496 c 0,0 0.0704,-0.26589 0.0917,-0.25982 0.0251,-0.008 0.0906,-0.0312 0.0997,-0.01 0.009,0.0213 -0.0562,0.0864 -0.0562,0.0864 0,0 -0.0668,0.0516 -0.0728,0.088 -0.006,0.0364 -0.003,0.13522 -0.003,0.13522 z"
+   id="path24" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 107.51843,193.369 c 0,0 -0.002,0.19674 0.004,0.23013 0.006,0.0334 0.0295,0.074 0.1995,0.0285 0.006,-0.11835 -0.0773,-0.29658 -0.0773,-0.29658 z"
+   id="path25" />
+		<path
+   style="fill:#e6d998;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 108.07213,193.12944 c 0,0 0.0645,0.25353 0.0889,0.29299 0.0243,0.0395 0.2151,0.0652 0.25153,0.0166 0.0364,-0.0486 0.15433,-0.0581 0.15433,-0.0581 0,0 -0.006,-0.33631 -0.0513,-0.38184 -0.0455,-0.0455 -0.33828,-0.0338 -0.3747,-0.0217 -0.0364,0.0121 -0.0374,0.0478 -0.0587,0.0903 z"
+   id="path26" />
+		<path
+   style="fill:#e6d998;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 109.02246,192.85836 c 0,0 0.0183,0.25967 0.0303,0.31431 0.0121,0.0546 0.11029,0.10326 0.22867,0.079 0.11838,-0.0243 0.19836,-0.0197 0.18925,-0.12643 -0.009,-0.10624 0.005,-0.16473 -0.0286,-0.2224 -0.0334,-0.0577 -0.0938,-0.10213 -0.1181,-0.1082 -0.0243,-0.006 -0.2999,0.0477 -0.2999,0.0477 z"
+   id="path27" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path28"
+   d="m 193.69828,158.32655 -0.32693,-0.90354 -0.87976,0.35842 0.75829,-0.59014 -0.61275,-0.72594 0.79559,0.53881 0.50106,-0.80708 -0.26659,0.92315 0.92241,0.22713 -0.96034,0.0317 z"
+   transform="translate(-84.553401,34.893164)" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path29"
+   d="m 191.4923,158.12687 -0.42106,-0.45469 -0.43774,0.43866 0.30231,-0.54096 -0.55246,-0.28076 0.60791,0.12035 0.0963,-0.61218 0.0734,0.61535 0.61198,-0.0976 -0.56255,0.25995 z"
+   transform="translate(-84.553401,34.893164)" />
+	</g>
+	<g
+   id="iconOre"
+   opacity="1.0"
+   transform="matrix(0.87219868,0,0,0.87219868,-97.429655,-129.12754)">
+		<path
+   style="fill:#48484b;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 121.60298,167.48721 c 0,0 -0.32168,-0.34061 -0.34061,-0.54876 -0.0189,-0.20815 0.17977,-0.59607 0.46361,-0.61499 0.28384,-0.0189 0.58874,0.14135 0.85758,0.30043 0.39816,0.23561 0.34806,0.53683 0.31968,0.6409 -0.0284,0.10408 -0.61904,0.2508 -0.83665,0.2508 -0.21761,0 -0.46361,-0.0284 -0.46361,-0.0284 z"
+   id="path30" />
+		<path
+   style="fill:#48484b;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 120.66631,166.46538 c -0.40777,0.15851 -0.73505,0.16286 -0.82486,0.56101 -0.0803,0.37832 0.18145,0.39212 0.24725,0.52458 0.0662,0.13246 0.246,0.12547 0.51092,0.12547 0.26492,0 0.38791,-0.0478 0.51091,-0.17031 0.123,-0.12299 0.17977,-0.19869 0.20815,-0.30276 0.0284,-0.10408 0,-0.32169 -0.0757,-0.45415 -0.0757,-0.13246 -0.14192,-0.23653 -0.30276,-0.28384 -0.16085,-0.0473 -0.27438,0 -0.27438,0 z"
+   id="path31" />
+		<path
+   style="fill:#48484b;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 121.33806,167.18445 c 0,0 -0.2933,-0.11354 -0.38791,0.12299 -0.0946,0.23654 -0.16085,0.27438 -0.0851,0.42577 0.0757,0.15138 0.0662,0.35953 0.21761,0.35953 0.15138,0 0.35953,0.21761 0.52983,0 0.17031,-0.21761 0.17977,-0.22707 0.13246,-0.37846 -0.0473,-0.15138 -0.246,-0.42575 -0.246,-0.42575 z"
+   id="path32" />
+		<path
+   style="fill:#48484b;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 120.25001,167.35475 c 0,0 -0.28385,-0.17977 -0.52038,0.0851 -0.23653,0.26492 -0.5131,0.55063 -0.5131,0.71147 0,0.16084 0.0142,0.4101 0.25482,0.58987 0.15138,0.17976 0.45694,0.12733 0.62725,0.11787 0.1703,-0.009 0.45414,-0.0946 0.52983,-0.18923 0.0757,-0.0946 0.18923,-0.123 0.19869,-0.39738 0.009,-0.27438 0.0284,-0.4163 -0.0662,-0.52983 -0.0946,-0.11354 -0.51091,-0.38792 -0.51091,-0.38792 z"
+   id="path33" />
+		<path
+   style="fill:#48484b;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 122.42612,167.24122 c 0,0 0.32975,0.0957 0.5818,0.32168 0.35985,0.32262 0.42329,0.51091 0.43275,0.7096 0.009,0.19869 -0.4101,0.49292 -0.76855,0.5393 -0.18999,0.0246 -0.58661,0.20815 -0.71907,0.0946 -0.13246,-0.11354 -0.32168,-0.33115 -0.34061,-0.52984 -0.0189,-0.19869 -0.11353,-0.73799 0.009,-0.86099 0.12299,-0.12299 0.60552,-0.25545 0.80421,-0.27437 z"
+   id="path34" />
+		<path
+   style="fill:#48484b;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 120.68523,168.2725 c 0,0 0.22707,-0.25545 0.4163,-0.25545 0.18923,0 0.26492,-0.0662 0.42576,0.15138 0.16085,0.21761 0.19869,0.14192 0.19869,0.42576 0,0.28384 0.0284,0.35007 -0.22707,0.38792 -0.25546,0.0378 -0.63392,0.0284 -0.71907,-0.12302 -0.0851,-0.15138 -0.23653,-0.1703 -0.0946,-0.5866 z"
+   id="path35" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 120.14459,166.81994 c 0.19976,-0.11263 0.61861,-0.22467 0.7212,-0.20053 0.1026,0.0241 0.21616,0.17723 0.21616,0.17723 0,0 0.057,0.0875 0.0238,0.0966 -0.0332,0.009 -0.28998,-0.0378 -0.36844,-0.0257 -0.0785,0.0121 -0.4219,0.0891 -0.50941,0.0861 -0.0875,-0.003 -0.23989,-0.001 -0.20558,-0.0304 0,0 6.7e-4,-0.04 0.12223,-0.10323 z"
+   id="path36" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 121.47458,166.80186 c 0,0 0.10006,-0.28276 0.21897,-0.304 0.11894,-0.0213 0.26478,0.0129 0.38783,0.0494 0.1132,0.0343 0.36602,0.15697 0.59116,0.36513 0.13168,0.10484 0.0995,0.1723 0.0848,0.21494 -0.10827,-0.0295 -0.24762,-0.14102 -0.34929,-0.22138 -0.099,-0.0782 -0.31322,-0.21318 -0.42473,-0.20663 -0.11151,0.007 -0.29681,0.0344 -0.33289,0.0689 -0.0361,0.0344 -0.041,0.0951 -0.0853,0.10659 -0.0443,0.0115 -0.1106,-0.0195 -0.0906,-0.0729 z"
+   id="path37" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 120.9956,167.61957 c 0,0 0.0756,-0.24746 0.12299,-0.28005 0.0474,-0.0326 0.18374,0.0193 0.1867,0.0267 0.003,0.007 0.12151,0.0815 0.12447,0.12743 0.003,0.0459 -0.0704,0.0611 -0.0704,0.0611 0,0 -0.10087,-0.0549 -0.14386,-0.049 -0.043,0.006 -0.091,0.0649 -0.10283,0.0916 -0.0119,0.0267 -0.0504,0.0652 -0.0711,0.0608 -0.0207,-0.004 -0.0459,-0.0385 -0.0459,-0.0385 z"
+   id="path38" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 119.56477,167.89965 c 0,0 0.27359,-0.34386 0.34168,-0.381 0.0681,-0.0371 0.16096,-0.0495 0.20223,-0.0227 0.0413,0.0268 0.487,0.31572 0.49732,0.37556 0.0103,0.0598 0.0206,0.0949 0,0.14032 -0.0206,0.0454 -0.0206,0.0722 -0.0475,0.0867 -0.0268,0.0145 -0.10479,-0.11439 -0.15755,-0.19564 -0.12135,-0.0996 -0.22437,-0.16765 -0.29453,-0.16353 -0.0702,0.004 -0.19693,0.0207 -0.29007,0.12354 -0.0803,0.0886 -0.20708,0.26659 -0.2793,0.27277 -0.0722,0.006 -0.16096,0.031 -0.15889,-0.006 0.002,-0.0371 0.1025,-0.12305 0.1025,-0.12305 z"
+   id="path39" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 120.80796,168.41377 c 0,0 0.0414,-0.10549 0.10964,-0.15307 0.0683,-0.0476 0.17582,-0.089 0.2234,-0.0869 0.0476,0.002 0.1117,0 0.17376,0.0496 0.0621,0.0497 0.14066,0.11378 0.16342,0.15308 0.0228,0.0393 0.029,0.0807 0.0352,0.0951 0.006,0.0145 -0.029,0.10757 -0.10963,0.0207 -0.0807,-0.0869 -0.16417,-0.16265 -0.23038,-0.17299 -0.0662,-0.0104 -0.0887,0.0178 -0.18181,0.0653 -0.0931,0.0476 -0.0822,0.10977 -0.13391,0.0912 -0.0517,-0.0186 -0.0496,-0.0621 -0.0496,-0.0621 z"
+   id="path40" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 121.77613,168.12101 c 0,0 -0.0447,-0.19555 -0.0391,-0.27377 0.006,-0.0782 -0.0112,-0.17041 0.0391,-0.20114 0.0503,-0.0307 0.3883,-0.20951 0.59223,-0.18716 0.20393,0.0224 0.36037,0.1285 0.39389,0.1704 0.0335,0.0419 0.17599,0.1313 0.20672,0.18997 0.0307,0.0587 -0.0112,0.10894 -0.0503,0.1285 -0.0391,0.0196 -0.0866,0.0434 -0.15362,0.0239 -0.0624,-0.0745 -0.0899,-0.11409 -0.19754,-0.18651 -0.11226,-0.0583 -0.19217,-0.0523 -0.29274,-0.0411 -0.10057,0.0112 -0.11306,0.0486 -0.18011,0.10945 -0.067,0.0615 -0.0879,0.0604 -0.12697,0.12976 -0.0369,0.0655 -0.0547,0.11249 -0.0886,0.14042 -0.0335,0.0279 -0.067,0.0307 -0.10336,-0.003 z"
+   id="path41" />
+		<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 119.41178,168.5416 c 0,0 0.1403,0.15937 0.18797,0.18389 0.0477,0.0245 0.15937,0.0518 0.27106,0.0531 0.1117,0.001 0.33781,-0.0245 0.41136,-0.0436 0.0736,-0.0191 0.25471,-0.0953 0.2588,-0.10761 0.004,-0.0122 -0.0109,-0.0313 -0.0109,-0.0695 0,-0.0381 0.01,-0.1117 0.0109,-0.11851 0.001,-0.007 -0.20704,0.0967 -0.29558,0.10761 -0.0885,0.0109 -0.28604,0.0953 -0.50398,0.0409 -0.21793,-0.0545 -0.32963,-0.0463 -0.32963,-0.0463 z"
+   id="path42" />
+		<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 121.0014,167.81508 0.0341,0.11162 c 0,0 0.0744,-0.008 0.0961,-0.008 0.0217,0 0.12816,-0.0114 0.15813,-0.008 0.03,0.003 0.0858,0.006 0.10646,0.0217 0.0207,0.0155 0.0672,0.0351 0.0744,0.0372 0.007,0.002 -0.004,-0.0517 -0.008,-0.12609 -0.004,-0.0744 -0.0155,0.002 -0.0858,0.0114 -0.0703,0.009 -0.20567,0.0155 -0.23254,0.003 -0.0269,-0.0124 -0.0424,0.004 -0.14263,-0.0424 z"
+   id="path43" />
+		<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 119.92311,167.14432 0.005,0.0678 c 0,0 0.0208,-0.0104 0.073,-0.0115 0.0521,-10e-4 0.097,-10e-4 0.20124,0.025 0.0981,0.0323 0.23774,0.13764 0.24921,0.14911 0.0115,0.0115 0.26589,0.20229 0.27215,0.20229 0.006,0 0.0135,-0.002 0.0156,-0.008 0.002,-0.006 0.0438,-0.13555 0.0918,-0.22731 0.048,-0.0918 0.0532,-0.11678 0.074,-0.14702 0.0209,-0.0302 0.0709,-0.074 0.12096,-0.0991 0.05,-0.025 0.0886,-0.0334 0.11782,-0.0344 0.0292,-0.001 0.0876,10e-4 0.0876,10e-4 l -0.0238,-0.13039 c 0,0 -0.12169,0.069 -0.13733,0.0711 -0.0714,0.0134 -0.1093,0.0177 -0.16978,0.0729 -0.0605,0.0553 -0.14527,0.20375 -0.15048,0.24338 -0.005,0.0396 -0.0717,0.0423 -0.0781,0.0423 -0.0163,-3e-5 -0.0411,0.003 -0.0869,-0.03 -0.0459,-0.0334 -0.13763,-0.0986 -0.18038,-0.11837 -0.0428,-0.0198 -0.13407,-0.0581 -0.19142,-0.0654 -0.0573,-0.007 -0.17487,-0.0199 -0.19565,-0.024 -0.0327,-0.006 -0.0858,-0.0518 -0.0858,-0.0518 z"
+   id="path44" />
+		<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 120.73785,168.62743 c 0,0 0.0682,0.12092 0.13643,0.19534 0.0682,0.0744 0.32349,0.0816 0.33589,0.0816 0.0124,0 0.29662,-0.009 0.34623,-0.0279 0.0496,-0.0186 0.0579,-0.0134 0.0662,-0.0362 0.008,-0.0227 0.0103,-0.13539 0.008,-0.16123 -0.002,-0.0258 -0.003,-0.0693 -0.003,-0.0765 0,-0.007 -0.0372,0.0775 -0.0579,0.0909 -0.0207,0.0134 -0.0403,0.0682 -0.12092,0.0734 -0.0806,0.005 -0.29249,0.0238 -0.35657,0.0176 -0.0641,-0.006 -0.13642,-0.0124 -0.15606,-0.0227 -0.0196,-0.0103 -0.094,-0.0899 -0.10129,-0.0992 -0.007,-0.009 -0.0744,-0.0382 -0.0971,-0.0351 z"
+   id="path45" />
+		<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 121.41318,166.95482 c 0,0 0,0.10854 0.0125,0.14597 0.0125,0.0374 0.0362,0.0586 0.0611,0.0724 0.025,0.0137 0.0873,0.0736 0.10479,0.0998 0.0175,0.0262 0.0586,0.0886 0.0686,0.0948 0.01,0.006 0.0349,-0.01 0.0487,-0.0162 0.0137,-0.006 0.18089,-0.0911 0.51275,-0.16718 0.33186,-0.0761 0.46909,0.0873 0.50153,0.0823 0.0324,-0.005 0.0711,-0.0249 0.0823,-0.0349 0.0112,-0.01 0.0237,-0.0474 0.0237,-0.0823 0,-0.0349 -0.0337,0.0112 -0.0337,0.0112 0,0 -0.0337,0.0387 -0.0736,0.0287 -0.0399,-0.01 -0.0511,-0.0287 -0.10231,-0.0561 -0.0511,-0.0274 -0.0923,-0.0674 -0.17217,-0.0773 -0.0798,-0.01 -0.16842,0.001 -0.24702,0.006 -0.0786,0.005 -0.18089,0.0399 -0.257,0.0362 -0.0761,-0.004 -0.18838,0.0312 -0.27696,0.005 -0.0886,-0.0262 -0.11104,-0.0437 -0.14846,-0.0786 -0.0374,-0.0349 -0.1048,-0.0699 -0.1048,-0.0699 z"
+   id="path46" />
+		<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 121.76755,168.29729 c 0,0 0.0383,0.25119 0.0488,0.33275 -0.006,0.0763 0.1861,0.20201 0.20678,0.21315 0.0207,0.0111 0.18292,0.002 0.20519,-0.0127 0.0223,-0.0143 0.30858,-0.0795 0.36743,-0.097 0.0589,-0.0175 0.30858,-0.0589 0.32131,-0.0811 0.0127,-0.0223 0.33085,-0.13361 0.38652,-0.25927 0.0557,-0.12566 0.0557,-0.11134 0.0525,-0.1527 -0.003,-0.0413 -0.0239,-0.1018 -0.0334,-0.13361 -0.01,-0.0318 -0.027,-0.0875 -0.0541,-0.12248 -0.027,-0.035 -0.0668,-0.0763 -0.0668,-0.0763 0,0 0.0127,0.13043 -0.006,0.18928 -0.0191,0.0589 -0.01,0.16066 -0.0716,0.20678 -0.062,0.0461 -0.24495,0.1368 -0.32607,0.15112 -0.0811,0.0143 -0.34199,0.0891 -0.39607,0.0875 -0.0541,-0.002 -0.1861,0.0318 -0.25291,0.0191 -0.0668,-0.0127 -0.18451,-0.0493 -0.20837,-0.0843 -0.0239,-0.035 -0.15947,-0.16351 -0.15947,-0.16351 z"
+   id="path47" />
+	</g>
+	<g
+   id="iconWood"
+   opacity="1.0"
+   transform="matrix(0.95215139,5.818528e-4,-0.16788999,0.88218099,-70.889511,-135.64427)"
+   style="stroke-width:0.951609">
+		<g
+   id="g52-2-4"
+   transform="translate(-1.3480237,-0.65969341)"
+   style="stroke-width:0.951609">
+			<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.69351,172.75071 1.504,0.85362 0.0949,0.18969 -0.0881,0.37262 -0.19647,0.12195 -0.25744,-0.0339 -0.25744,-0.19647 -1.16527,-0.66393 -0.0135,-0.33197 0.19647,-0.23711 z"
+   id="path51-0-5" />
+			<ellipse
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-6-2"
+   cx="164.72643"
+   cy="125.13451"
+   rx="0.29228276"
+   ry="0.37996763"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-1-5"
+   cx="164.73143"
+   cy="125.13288"
+   rx="0.15645675"
+   ry="0.24053945"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#e5bea3;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-6-5-4"
+   cx="164.7372"
+   cy="125.13261"
+   rx="0.095285773"
+   ry="0.14649406"
+   transform="rotate(20)" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 111.82232,174.26789 -1.50198,-0.88819"
+   id="path49-54-7" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.12519,173.56969 -1.41758,-0.8184 c -0.61379,0.14615 -0.37265,0.64303 -0.37265,0.64303"
+   id="path50-7-4" />
+			<path
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.55997,173.02014 1.13347,0.6422 c 0,0 0.0407,-0.0633 0.10578,-0.11573 -0.16245,-0.1236 -1.10853,-0.62889 -1.10853,-0.62889 0,0 -0.11302,0.06 -0.13068,0.10239 z"
+   id="path52-6-4" />
+		</g>
+		<g
+   id="g52"
+   transform="translate(-1.9189556,-0.3070329)"
+   style="stroke-width:0.951609">
+			<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.69351,172.75071 1.504,0.85362 0.0949,0.18969 -0.0881,0.37262 -0.19647,0.12195 -0.25744,-0.0339 -0.25744,-0.19647 -1.16527,-0.66393 -0.0135,-0.33197 0.19647,-0.23711 z"
+   id="path51" />
+			<ellipse
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48"
+   cx="164.72643"
+   cy="125.13451"
+   rx="0.29228276"
+   ry="0.37996763"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2"
+   cx="164.73143"
+   cy="125.13288"
+   rx="0.15645675"
+   ry="0.24053945"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#e5bea3;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-6"
+   cx="164.7372"
+   cy="125.13261"
+   rx="0.095285773"
+   ry="0.14649406"
+   transform="rotate(20)" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 111.82232,174.26789 -1.50198,-0.88819"
+   id="path49" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.12519,173.56969 -1.41758,-0.8184 c -0.61379,0.14615 -0.37265,0.64303 -0.37265,0.64303"
+   id="path50" />
+			<path
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.55997,173.02014 1.13347,0.6422 c 0,0 0.0407,-0.0633 0.10578,-0.11573 -0.16245,-0.1236 -1.10853,-0.62889 -1.10853,-0.62889 0,0 -0.11302,0.06 -0.13068,0.10239 z"
+   id="path52" />
+		</g>
+		<g
+   id="g52-2-6"
+   transform="translate(-1.856268,-1.0044852)"
+   style="stroke-width:0.951609">
+			<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.69351,172.75071 1.504,0.85362 0.0949,0.18969 -0.0881,0.37262 -0.19647,0.12195 -0.25744,-0.0339 -0.25744,-0.19647 -1.16527,-0.66393 -0.0135,-0.33197 0.19647,-0.23711 z"
+   id="path51-0-8" />
+			<ellipse
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-6-8"
+   cx="164.72643"
+   cy="125.13451"
+   rx="0.29228276"
+   ry="0.37996763"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-1-4"
+   cx="164.73143"
+   cy="125.13288"
+   rx="0.15645675"
+   ry="0.24053945"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#e5bea3;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-6-5-3"
+   cx="164.7372"
+   cy="125.13261"
+   rx="0.095285773"
+   ry="0.14649406"
+   transform="rotate(20)" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 111.82232,174.26789 -1.50198,-0.88819"
+   id="path49-54-1" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.12519,173.56969 -1.41758,-0.8184 c -0.61379,0.14615 -0.37265,0.64303 -0.37265,0.64303"
+   id="path50-7-49" />
+			<path
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.55997,173.02014 1.13347,0.6422 c 0,0 0.0407,-0.0633 0.10578,-0.11573 -0.16245,-0.1236 -1.10853,-0.62889 -1.10853,-0.62889 0,0 -0.11302,0.06 -0.13068,0.10239 z"
+   id="path52-6-2" />
+		</g>
+		<g
+   id="g52-9"
+   transform="translate(-2.5929213,0.104711)"
+   style="stroke-width:0.951609">
+			<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.69351,172.75071 1.504,0.85362 0.0949,0.18969 -0.0881,0.37262 -0.19647,0.12195 -0.25744,-0.0339 -0.25744,-0.19647 -1.16527,-0.66393 -0.0135,-0.33197 0.19647,-0.23711 z"
+   id="path51-4" />
+			<ellipse
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-7"
+   cx="164.72643"
+   cy="125.13451"
+   rx="0.29228276"
+   ry="0.37996763"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-8"
+   cx="164.73143"
+   cy="125.13288"
+   rx="0.15645675"
+   ry="0.24053945"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#e5bea3;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-6-4"
+   cx="164.7372"
+   cy="125.13261"
+   rx="0.095285773"
+   ry="0.14649406"
+   transform="rotate(20)" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 111.82232,174.26789 -1.50198,-0.88819"
+   id="path49-5" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.12519,173.56969 -1.41758,-0.8184 c -0.61379,0.14615 -0.37265,0.64303 -0.37265,0.64303"
+   id="path50-0" />
+			<path
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.55997,173.02014 1.13347,0.6422 c 0,0 0.0407,-0.0633 0.10578,-0.11573 -0.16245,-0.1236 -1.10853,-0.62889 -1.10853,-0.62889 0,0 -0.11302,0.06 -0.13068,0.10239 z"
+   id="path52-3" />
+		</g>
+		<g
+   id="g52-2"
+   transform="translate(-2.4529425,-0.66141122)"
+   style="stroke-width:0.951609">
+			<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.69351,172.75071 1.504,0.85362 0.0949,0.18969 -0.0881,0.37262 -0.19647,0.12195 -0.25744,-0.0339 -0.25744,-0.19647 -1.16527,-0.66393 -0.0135,-0.33197 0.19647,-0.23711 z"
+   id="path51-0" />
+			<ellipse
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-6"
+   cx="164.72643"
+   cy="125.13451"
+   rx="0.29228276"
+   ry="0.37996763"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-1"
+   cx="164.73143"
+   cy="125.13288"
+   rx="0.15645675"
+   ry="0.24053945"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#e5bea3;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-6-5"
+   cx="164.7372"
+   cy="125.13261"
+   rx="0.095285773"
+   ry="0.14649406"
+   transform="rotate(20)" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 111.82232,174.26789 -1.50198,-0.88819"
+   id="path49-54" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.12519,173.56969 -1.41758,-0.8184 c -0.61379,0.14615 -0.37265,0.64303 -0.37265,0.64303"
+   id="path50-7" />
+			<path
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.55997,173.02014 1.13347,0.6422 c 0,0 0.0407,-0.0633 0.10578,-0.11573 -0.16245,-0.1236 -1.10853,-0.62889 -1.10853,-0.62889 0,0 -0.11302,0.06 -0.13068,0.10239 z"
+   id="path52-6" />
+		</g>
+		<g
+   id="g52-2-2"
+   transform="translate(-2.3358554,-1.3903673)"
+   style="stroke-width:0.951609">
+			<path
+   style="fill:#603210;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.69351,172.75071 1.504,0.85362 0.0949,0.18969 -0.0881,0.37262 -0.19647,0.12195 -0.25744,-0.0339 -0.25744,-0.19647 -1.16527,-0.66393 -0.0135,-0.33197 0.19647,-0.23711 z"
+   id="path51-0-6" />
+			<ellipse
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-6-6"
+   cx="164.72643"
+   cy="125.13451"
+   rx="0.29228276"
+   ry="0.37996763"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-1-49"
+   cx="164.73143"
+   cy="125.13288"
+   rx="0.15645675"
+   ry="0.24053945"
+   transform="rotate(20)" />
+			<ellipse
+   style="fill:#e5bea3;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path48-2-6-5-5"
+   cx="164.7372"
+   cy="125.13261"
+   rx="0.095285773"
+   ry="0.14649406"
+   transform="rotate(20)" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 111.82232,174.26789 -1.50198,-0.88819"
+   id="path49-54-0" />
+			<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.12519,173.56969 -1.41758,-0.8184 c -0.61379,0.14615 -0.37265,0.64303 -0.37265,0.64303"
+   id="path50-7-48" />
+			<path
+   style="fill:#a4612f;fill-opacity:1;stroke:none;stroke-width:0.190322;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 110.55997,173.02014 1.13347,0.6422 c 0,0 0.0407,-0.0633 0.10578,-0.11573 -0.16245,-0.1236 -1.10853,-0.62889 -1.10853,-0.62889 0,0 -0.11302,0.06 -0.13068,0.10239 z"
+   id="path52-6-7" />
+		</g>
+	</g>
+	<g
+   id="iconGems"
+   opacity="1.0"
+   transform="matrix(0.87219868,0,0,0.87219868,-74.159393,-117.99296)">
+		<path
+   style="fill:#276ad4;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.8188,153.93724 h 0.75954 l 0.25893,0.24167 -0.0777,0.49197 -0.5265,0.0949 -0.58691,-0.069 -0.17263,-0.47471 z"
+   id="path53" />
+		<path
+   style="fill:#bb1617;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.49944,154.29111 -0.66459,0.0691 -0.49715,0.39214 0.12168,0.65568 0.51097,0.32767 0.4773,-0.64186 0.19851,-0.4143 z"
+   id="path54" />
+		<path
+   style="fill:#619743;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.82864,154.21343 0.56102,-0.22441 0.46608,0.20715 0.095,0.37977 -0.0345,0.41429 -0.60418,0.0777 -0.5265,-0.3884 z"
+   id="path55" />
+		<path
+   style="fill:#b25584;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.44766,155.10244 0.26756,0.1381 0.5524,-0.17263 0.069,-0.29346 -0.51787,-0.0604 -0.18989,-0.0259 z"
+   id="path56" />
+		<path
+   style="fill:#bb1617;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.29351,155.05928 0.0604,0.28483 0.35437,0.32272 0.5519,-0.16736 0.43155,-0.44882 -0.37114,0.0173 -0.57828,-0.42293 -0.43156,0.12947 z"
+   id="path57" />
+		<path
+   style="fill:#619743;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.31077,155.12833 -1.07889,-0.009 -0.51787,0.51786 0.0173,0.3884 0.37114,0.18989 1.053,-0.0259 0.26757,-0.31936 0.0259,-0.45744 z"
+   id="path58" />
+		<path
+   style="fill:#b25584;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.24172,156.12091 0.69912,0.1381 0.69913,-0.24167 0.1381,-0.42293 -0.2069,-0.27608 -0.43968,-0.0186 -0.4098,0.0289 -0.27395,0.28206 -0.0161,0.28583 z"
+   id="path59" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.53844,154.90325 0.36986,-0.36182 0.48369,-0.0541 -0.42873,0.14523 z"
+   id="path60" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.67353,154.32498 0.20214,-0.2167 0.6389,0.004 0.13717,0.1155 -0.55183,-0.0141 z"
+   id="path61" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.90108,155.70733 0.38984,-0.42954 0.91323,0.0144 0.0758,0.16604 -0.72865,0.0461 z"
+   id="path62" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.94978,154.44328 0.43831,-0.24837 0.30682,0.1516 0.0505,0.19853 -0.38017,-0.14689 z"
+   id="path63" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.59398,155.72177 0.19853,-0.22741 0.37179,-0.0217 0.32125,0.0289 0.0794,0.12273 -0.0108,0.0902 -0.48008,-0.12146 z"
+   id="path64" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.45445,154.90771 0.22836,-0.0725 0.30087,0.18487 z"
+   id="path65" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.71136,154.84971 0.22111,0.0254 -0.25374,0.029 z"
+   id="path66" />
+		<path
+   style="fill:#ffffff;fill-opacity:0.333333;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 112.58633,155.22645 0.14698,0.17064 0.40556,-0.41915 z"
+   id="path67" />
+		<path
+   style="fill:#ffffff;fill-opacity:0.333333;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.18004,156.07699 0.89005,-0.0438 0.21698,-0.31037 -0.38101,0.18862 z"
+   id="path68" />
+		<path
+   style="fill:#ffffff;fill-opacity:0.333333;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.55852,156.05081 0.34694,0.0703 0.56673,-0.20507 0.0602,-0.0987 -0.60144,0.14452 z"
+   id="path69" />
+		<path
+   style="fill:#ffffff;fill-opacity:0.333333;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 115.34916,154.9269 0.4289,-0.0508 0.006,-0.12008 -0.41414,0.0308 -0.4012,-0.14036 z"
+   id="path70" />
+		<path
+   style="fill:#ffffff;fill-opacity:0.333333;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.54343,155.311 0.12583,-0.11259 0.15011,-0.009 -0.33554,-0.0221 z"
+   id="path71" />
+		<path
+   style="fill:#ffffff;fill-opacity:0.333333;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.81276,154.58474 0.40838,0.0486 0.41191,-0.0896 -0.42515,-0.01 -0.48157,-0.0766 z"
+   id="path72" />
+		<path
+   style="fill:#ffffff;fill-opacity:0.333333;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.93859,155.00416 0.10595,0.004 0.10155,-0.0375 z"
+   id="path73" />
+	</g>
+	<g
+   id="iconMercury"
+   opacity="1.0"
+   transform="matrix(0.87219868,0,0,0.87219868,-64.001803,-150.87368)">
+		<path
+   style="fill:#3e2916;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 86.121017,193.31065 -0.0326,-0.5113 0.781398,-0.0959 2.46792,-0.0895 -0.01953,0.71581 -0.905124,0.26204 -0.813955,0.0703 -0.898603,-0.16617 z"
+   id="path88" />
+		<path
+   style="fill:url(#radialGradient91);fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 86.508994,191.49183 c 0,0 -0.427405,0.79841 -0.289533,1.13671 0.137873,0.33831 0.482555,0.54129 0.978896,0.58189 0.496341,0.0406 1.323586,0.0541 1.695842,-0.23005 0.372257,-0.28418 0.372257,-0.3383 0.358469,-0.62248 -0.01381,-0.28418 -0.317107,-0.75781 -0.344681,-0.82547"
+   id="path75" />
+		<path
+   style="fill:#a8a49d;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 86.717571,190.8484 c 0.333584,-0.19164 0.807002,-0.3372 1.25022,-0.29729 0.302915,0.0273 0.623089,0.0341 0.843685,0.33177 0.220596,0.29771 0.275745,0.56835 -0.04135,0.67661 -0.317107,0.10826 -0.608011,0.19775 -1.081208,0.21521 -0.345538,0.0127 -0.890379,-0.0393 -1.110976,-0.22874 -0.220596,-0.18945 -0.102736,-0.55874 0.139632,-0.69756 z"
+   id="path74" />
+		<path
+   style="fill:#211c1b;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 87.071693,190.94018 c 0.240222,-0.1224 0.507108,-0.15975 0.826269,-0.13428 0.218128,0.0175 0.441091,-0.0156 0.599925,0.1746 0.158853,0.19012 0.190968,0.31823 -0.0373,0.38736 -0.228342,0.0692 -0.453027,0.13376 -0.793758,0.14492 -0.248815,0.007 -0.618373,0.0121 -0.777216,-0.10881 -0.158853,-0.121 -0.07386,-0.32412 0.100609,-0.41278 z"
+   id="path74-2" />
+		<ellipse
+   style="fill:#a77540;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path76"
+   cx="88.062714"
+   cy="193.71338"
+   rx="0.27214956"
+   ry="0.25227487" />
+		<ellipse
+   style="fill:#a77540;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path77"
+   cx="88.758209"
+   cy="193.56128"
+   rx="0.27214956"
+   ry="0.26340464" />
+		<ellipse
+   style="fill:#a77540;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path78"
+   cx="89.332733"
+   cy="193.35352"
+   rx="0.27214956"
+   ry="0.30050388" />
+		<ellipse
+   style="fill:#a77540;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path79"
+   cx="89.448036"
+   cy="192.74879"
+   rx="0.20220564"
+   ry="0.31163365" />
+		<ellipse
+   style="fill:#a77540;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path80"
+   cx="87.386116"
+   cy="193.57982"
+   rx="0.28348911"
+   ry="0.28195426" />
+		<ellipse
+   style="fill:#a77540;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path81"
+   cx="86.792686"
+   cy="193.47224"
+   rx="0.24947044"
+   ry="0.29308406" />
+		<ellipse
+   style="fill:#a77540;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path82"
+   cx="86.191681"
+   cy="193.37578"
+   rx="0.29860854"
+   ry="0.3301833" />
+		<ellipse
+   style="fill:#a77540;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path83"
+   cx="86.085854"
+   cy="192.79332"
+   rx="0.17765318"
+   ry="0.20775577" />
+		<path
+   style="fill:none;fill-opacity:0.333333;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 88.336133,193.60208 -0.114682,-0.38583"
+   id="path84" />
+		<path
+   style="fill:none;fill-opacity:0.333333;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 87.775442,193.63918 -0.06051,-0.37077"
+   id="path85" />
+		<path
+   style="fill:none;fill-opacity:0.333333;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 88.969877,193.35723 -0.15119,-0.32648"
+   id="path86" />
+		<path
+   style="fill:none;fill-opacity:0.333333;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 88.402896,193.61693 -0.09072,-0.4081"
+   id="path87" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 86.664329,191.10657 c 0,0 0.03177,-0.16834 0.508185,-0.30861 0.47643,-0.1403 0.511372,-0.12159 0.511372,-0.12159 0,0 0.104809,0.0187 0.06033,0.0467 -0.04448,0.028 -0.333501,0.0717 -0.431964,0.10287 -0.09846,0.0312 -0.327146,0.11222 -0.400199,0.16522 -0.07304,0.053 -0.196927,0.21511 -0.247738,0.11535 z"
+   id="path89" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 87.864926,191.57107 c 0,0 0.546305,-0.11222 0.625713,-0.15899 0.07939,-0.0467 0.184217,-0.0592 0.212804,-0.13092 0.02855,-0.0717 0.03813,-0.0842 0.08575,-0.0717 0.04762,0.0125 0.07304,0.0654 0.06668,0.0998 -0.0064,0.0343 -0.02855,0.0935 -0.06355,0.10911 -0.03491,0.0155 -0.416077,0.15587 -0.581247,0.18081 -0.165162,0.0249 -0.289026,0.0499 -0.317614,0.0374 -0.02855,-0.0125 -0.05084,-0.0218 -0.02855,-0.0654 z"
+   id="path90" />
+		<path
+   style="fill:#363636;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 87.066618,191.47843 c 0,0 -0.12648,-0.14582 -0.05222,-0.23253 0.07432,-0.0867 0.134511,-0.19705 0.315201,-0.24631 0.180689,-0.0493 0.503921,-0.1005 0.503921,-0.1005 l 0.469798,-0.0513 c 0,0 -0.446921,-0.12726 -0.764921,-0.0532 -0.313193,0.0729 -0.313193,0.0473 -0.602293,0.22858 -0.289108,0.18129 -0.05222,0.39804 -0.03417,0.4079 0.01805,0.01 0.164627,0.0473 0.164627,0.0473 z"
+   id="path91" />
+	</g>
+	<g
+   id="iconCrystal"
+   opacity="1.0"
+   transform="matrix(0.87219868,0,0,0.87219868,-78.871113,-144.49622)">
+		<path
+   style="fill:#960f0c;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.96237,185.45726 v -2.12749 l 0.6932,-0.6932 0.65992,0.65992 v 1.53059 l -0.16637,0.94275 -1.03148,0.26619 z"
+   id="path94" />
+		<path
+   style="fill:#960f0c;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.04065,186.61223 h 1.38383 l 1.24857,-1.38768 -0.0342,-0.71632 h -1.03082 l -1.58152,1.58153 z"
+   id="path92" />
+		<path
+   style="fill:#960f0c;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.47654,185.80284 -0.81003,-1.02889 -0.74839,-0.18725 0.072,0.90924 0.98046,1.11795 0.50837,-7e-5 -0.003,-0.81098"
+   id="path93" />
+		<path
+   style="fill:#f86a64;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.65475,182.7806 -0.22866,0.7088 -0.0113,2.06769 0.80687,-0.79458 v -1.43762 z"
+   id="path95" />
+		<path
+   style="fill:#f86a64;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 113.07811,185.4534 0.35963,-0.0889 0.93729,1.15058 0.004,-0.69295 -0.7665,-0.9678 -0.59617,-0.14711 z"
+   id="path96" />
+		<path
+   style="fill:#f86a64;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 116.56721,185.18032 -0.0217,-0.58533 -0.91139,0.004 -1.10835,1.12379 0.0351,0.0621 0.006,0.73345 c 0.54458,-0.59102 0.56103,-0.58772 1.66727,-1.72708 l -0.51656,0.002 0.51462,-0.0119 z"
+   id="path97" />
+		<path
+   style="fill:#fee2e1;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.38382,186.0085 v -0.19293 l -0.76557,-0.975 -0.60453,-0.13634 0.42429,0.66263 0.11747,-0.38735 z"
+   id="path98" />
+		<path
+   style="fill:#fee2e1;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.41656,185.55964 0.21247,-0.20938 -0.0101,-1.86514 0.60503,-0.16245 -0.56919,-0.54774 -0.24023,0.71067 z"
+   id="path99" />
+		<path
+   style="fill:#fee2e1;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.5181,185.71941 0.0446,0.0647 v 0.22967 l 1.1506,-1.21972 0.52135,-0.005 0.31408,-0.19495 -0.9198,-0.003 z"
+   id="path100" />
+		<path
+   style="fill:#6f0805;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.24729,183.42845 0.16594,0.0573 0.005,2.07903 -0.16504,-0.19847 z"
+   id="path101" />
+		<path
+   style="fill:#6f0805;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 114.55548,186.52094 0.29074,-0.007 1.51142,-1.58667 -0.11882,-0.14009 z"
+   id="path102" />
+	</g>
+	<text
+   style="font-size:3.07692px;fill:#ffffff;"
+   x="6.3129487"
+   y="5.0981655"
+   id="textChest"
+   text-anchor="start">99</text>
+	<g
+   id="iconChest"
+   opacity="1.0"
+   transform="matrix(0.87219868,0,0,0.87219868,-105.99897,-116.98721)">
+		<path
+   style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 124.64135,138.5534 2.73727,-0.75231 0.0521,0.33564 0.35301,0.36459 -2.34954,0.74653 z"
+   id="path108" />
+		<path
+   style="fill:#922f14;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 125.48715,140.97376 2.67219,-1.01726 -0.0304,-1.51829 -2.65702,0.77433 z"
+   id="path103" />
+		<path
+   style="fill:#922f14;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 125.45862,140.96853 -1.31275,-1.14667 0.0414,-1.53104 1.28277,0.96552 z"
+   id="path104" />
+		<path
+   style="fill:#d5b65e;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 127.38119,137.75908 0.69945,0.66691 -0.34972,0.0976 -0.34051,-0.31387 z"
+   id="path107" />
+		<path
+   style="fill:#922f14;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 125.38726,138.44254 2.60692,-0.76552 c 0,0 -0.17491,-0.81675 -0.80691,-0.66897 -1.12972,0.26415 -1.17829,0.29272 -2.5921,0.59111"
+   id="path106" />
+		<path
+   style="fill:#922f14;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 124.18725,138.63351 c 0,0 -0.10345,-0.92201 0.44828,-1.04615 0.55173,-0.12414 0.71722,0.58274 0.7655,0.85171 -0.84136,0.15862 -0.82068,0.15519 -0.82068,0.15519 z"
+   id="path105" />
+		<path
+   style="fill:none;fill-opacity:1;stroke:#d5b65e;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+   d="m 125.68325,140.68856 2.27698,-0.86797 -0.0213,-1.12112 -1.0529,0.29836 0.0164,1.21344 -0.0189,-1.21408 -1.20944,0.36428 z"
+   id="path109" />
+		<path
+   style="fill:none;fill-opacity:1;stroke:#d5b65e;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+   d="m 124.33981,139.7326 0.92521,0.80654 0.007,-1.18586 -0.7327,-0.55592 -0.17084,-7e-4 z"
+   id="path110" />
+		<path
+   style="fill:none;fill-opacity:1;stroke:#d5b65e;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+   d="m 124.36869,138.42985 c 0,0 -0.008,-0.6305 0.29273,-0.69305 0.32526,-0.065 0.49289,0.48289 0.5079,0.54543 -0.15604,0.027 -0.80063,0.14762 -0.80063,0.14762 z"
+   id="path111" />
+		<path
+   style="fill:none;fill-opacity:1;stroke:#d5b65e;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+   d="m 125.24315,137.59223 c 0.14823,0.14781 0.24996,0.39134 0.30266,0.59285 0.62105,-0.17314 0.0994,-0.0274 2.22494,-0.62836 -0.0745,-0.19287 -0.29216,-0.36002 -0.45006,-0.46466"
+   id="path112" />
+		<path
+   style="fill:none;fill-opacity:1;stroke:#d5b65e;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+   d="m 126.17744,137.28577 c 0,0 0.39911,0.0788 0.48144,0.55984"
+   id="path113" />
+		<path
+   style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 125.0488,137.50126 c 0,0 0.0184,-0.003 2.09407,-0.47323 0.23724,-0.0601 0.49192,0.0627 0.49192,0.0627"
+   id="path114" />
+		<path
+   style="fill:none;fill-opacity:1;stroke:#d5b65e;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   d="m 124.65833,139.44143 0.28917,0.22216"
+   id="path115" />
+		<ellipse
+   style="fill:#4c55aa;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path116"
+   cx="126.18096"
+   cy="138.65172"
+   rx="0.073261641"
+   ry="0.065121457" />
+		<ellipse
+   style="fill:#fff5b1;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path117"
+   cx="125.71352"
+   cy="138.89314"
+   rx="0.16457728"
+   ry="0.14106624" />
+		<ellipse
+   style="fill:#d5b65e;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path118"
+   cx="125.80756"
+   cy="138.50856"
+   rx="0.06717439"
+   ry="0.062136315" />
+		<ellipse
+   style="fill:#4c55aa;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path119"
+   cx="126.77151"
+   cy="138.34567"
+   rx="0.16457728"
+   ry="0.14442495" />
+		<ellipse
+   style="fill:#8b3c88;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path120"
+   cx="126.52634"
+   cy="138.4733"
+   rx="0.16121854"
+   ry="0.12427263" />
+		<ellipse
+   style="fill:#fff5b1;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path121"
+   cx="126.11825"
+   cy="138.54048"
+   rx="0.13938688"
+   ry="0.073891833" />
+		<ellipse
+   style="fill:#4c55aa;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path122"
+   cx="126.31474"
+   cy="138.37926"
+   rx="0.063815676"
+   ry="0.080609269" />
+		<ellipse
+   style="fill:#821510;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path123"
+   cx="125.32727"
+   cy="138.75375"
+   rx="0.17801215"
+   ry="0.13938688" />
+		<ellipse
+   style="fill:#205a17;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path124"
+   cx="126.30802"
+   cy="138.89986"
+   rx="0.10076159"
+   ry="0.087326713" />
+		<ellipse
+   style="fill:#821510;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path125"
+   cx="125.98055"
+   cy="138.74872"
+   rx="0.17633279"
+   ry="0.1511424" />
+		<ellipse
+   style="fill:#a06739;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path126"
+   cx="126.71442"
+   cy="138.65131"
+   rx="0.21159935"
+   ry="0.15785983" />
+		<ellipse
+   style="fill:#8b3c88;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path127"
+   cx="127.1477"
+   cy="138.3591"
+   rx="0.24182782"
+   ry="0.17801215" />
+		<ellipse
+   style="fill:#205a17;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path128"
+   cx="127.49364"
+   cy="138.46826"
+   rx="0.077250555"
+   ry="0.065495037" />
+		<ellipse
+   style="fill:#821510;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path129"
+   cx="127.03182"
+   cy="138.61604"
+   rx="0.10244095"
+   ry="0.072212473" />
+		<ellipse
+   style="fill:#fff5b1;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path130"
+   cx="127.19975"
+   cy="138.16599"
+   rx="0.15618047"
+   ry="0.13938688" />
+		<ellipse
+   style="fill:#8b3c88;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path131"
+   cx="126.37855"
+   cy="138.7084"
+   rx="0.10747903"
+   ry="0.083967999" />
+		<ellipse
+   style="fill:#205a17;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path132"
+   cx="125.62452"
+   cy="138.63618"
+   rx="0.10579967"
+   ry="0.1091584" />
+		<ellipse
+   style="fill:#205a17;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path133"
+   cx="125.49798"
+   cy="138.99409"
+   rx="0.067042269"
+   ry="0.072199367" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path134"
+   d="m 125.63045,139.2427 -0.38882,-0.43556 -0.40031,0.4245 0.29409,-0.50438 -0.52744,-0.24955 0.57058,0.12384 0.0743,-0.57874 0.0586,0.58092 0.57338,-0.10813 -0.53439,0.23519 z" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path135"
+   d="m 126.54153,138.63041 -0.25382,-0.23238 -0.20974,0.27282 0.14259,-0.3132 -0.32429,-0.11517 0.34193,0.0388 0.009,-0.344 0.0688,0.33719 0.33004,-0.0974 -0.29944,0.16958 z" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path136"
+   d="m 126.46804,139.14474 -0.12336,-0.17876 -0.1675,0.13825 0.13189,-0.17256 -0.18325,-0.11658 0.20487,0.0721 0.0542,-0.21031 -0.005,0.21713 0.21678,-0.0134 -0.20813,0.0621 z" />
+		<path
+   style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+   id="path137"
+   d="m 127.66253,139.09679 -0.40064,-0.58988 -0.5533,0.4498 0.4372,-0.56331 -0.59876,-0.38723 0.67084,0.24173 0.18325,-0.68912 -0.0226,0.71271 0.71202,-0.0387 -0.68481,0.19874 z" />
+	</g>
+		<use
+   xlink:href="#iconSword"
+   id="iconSword3"
+   opacity="1.0"
+   transform="translate(0,0)" />
+		<use
+   xlink:href="#iconSword"
+   id="iconSword2"
+   opacity="1.0"
+   transform="translate(-2,0)" />
+		<use
+   xlink:href="#iconSword"
+   id="iconSword1"
+   opacity="1.0"
+   transform="translate(-4,0)" />
+</svg>

+ 9 - 0
mapeditor/icons/zone-add.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="24" width="24" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <g transform="translate(0 -1028.4)">
+  <path d="m22 12c0 5.523-4.477 10-10 10-5.5228 0-10-4.477-10-10 0-5.5228 4.4772-10 10-10 5.523 0 10 4.4772 10 10z" transform="translate(0 1029.4)" fill="#27ae60"/>
+  <path d="m22 12c0 5.523-4.477 10-10 10-5.5228 0-10-4.477-10-10 0-5.5228 4.4772-10 10-10 5.523 0 10 4.4772 10 10z" transform="translate(0 1028.4)" fill="#2ecc71"/>
+  <path d="m6.0001 1042.4h4.9999v5h2v-5h5v-2h-5v-5h-2v5h-4.9999v2z" fill="#27ae60"/>
+  <path d="m6 1041.4h5v5h2v-5h5v-2h-5v-5h-2v5h-5v2z" fill="#ecf0f1"/>
+ </g>
+</svg>

+ 9 - 0
mapeditor/icons/zone-remove.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="24" width="24" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <g transform="translate(0 -1028.4)">
+  <path d="m22 12c0 5.523-4.477 10-10 10-5.5228 0-10-4.477-10-10 0-5.5228 4.4772-10 10-10 5.523 0 10 4.4772 10 10z" transform="translate(0 1029.4)" fill="#c0392b"/>
+  <path d="m22 12c0 5.523-4.477 10-10 10-5.5228 0-10-4.477-10-10 0-5.5228 4.4772-10 10-10 5.523 0 10 4.4772 10 10z" transform="translate(0 1028.4)" fill="#e74c3c"/>
+  <rect height="4" width="12" y="1039.4" x="6" fill="#c0392b"/>
+  <rect height="3" width="12" y="1039.4" x="6" fill="#ecf0f1"/>
+ </g>
+</svg>

+ 12 - 0
mapeditor/icons/zones-layout.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="24" width="24" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <g transform="translate(0 -1028.4)">
+  <path d="m1 1035.4v1 1 2 1 1 1 1 2 1 2 1c0 1.1 0.8954 2 2 2h9 9c1.105 0 2-0.9 2-2v-1-2-4-2-3-1-1h-22z" fill="#bdc3c7"/>
+  <path d="m3 2c-1.1046 0-2 0.8954-2 2v3h22v-3c0-1.1046-0.895-2-2-2h-9-9z" transform="translate(0 1028.4)" fill="#bdc3c7"/>
+  <path d="m1 6v1 1 2 1 1 1 1 2 1 2 1c0 1.105 0.8954 2 2 2h9 9c1.105 0 2-0.895 2-2v-1-2-4-2-3-1-1h-22z" transform="translate(0 1028.4)" fill="#ecf0f1"/>
+  <path d="m4 4a1 1 0 1 1 -2 0 1 1 0 1 1 2 0z" transform="translate(0 1028.4)" fill="#c0392b"/>
+  <path d="m4 4a1 1 0 1 1 -2 0 1 1 0 1 1 2 0z" transform="translate(3 1028.4)" fill="#27ae60"/>
+  <path d="m4 4a1 1 0 1 1 -2 0 1 1 0 1 1 2 0z" transform="translate(6 1028.4)" fill="#f39c12"/>
+  <path d="m3 1036.4v1 10 1h1 2 2v-12h-2-2zm6 0v1 2h12v-2-1h-1-10zm0 4v8h1 10 1v-1-6-1h-1-10z" fill="#bdc3c7"/>
+ </g>
+</svg>

+ 19 - 0
mapeditor/mainwindow.cpp

@@ -50,6 +50,9 @@
 #include "validator.h"
 #include "helper.h"
 #include "campaigneditor/campaigneditor.h"
+#ifdef ENABLE_TEMPLATE_EDITOR
+#include "templateeditor/templateeditor.h"
+#endif
 
 QJsonValue jsonFromPixmap(const QPixmap &p)
 {
@@ -261,6 +264,11 @@ MainWindow::MainWindow(QWidget* parent) :
 	ui->actionZoom_out->setIcon(QIcon{":/icons/zoom_minus.png"});
 	ui->actionZoom_reset->setIcon(QIcon{":/icons/zoom_zero.png"});
 	ui->actionCampaignEditor->setIcon(QIcon{":/icons/mapeditor.64x64.png"});
+	ui->actionTemplateEditor->setIcon(QIcon{":/icons/dice.png"});
+
+#ifndef ENABLE_TEMPLATE_EDITOR
+	ui->actionTemplateEditor->setVisible(false);
+#endif
 
 	loadUserSettings(); //For example window size
 	setTitle();
@@ -606,6 +614,17 @@ void MainWindow::on_actionCampaignEditor_triggered()
 	CampaignEditor::showCampaignEditor();
 }
 
+void MainWindow::on_actionTemplateEditor_triggered()
+{
+#ifdef ENABLE_TEMPLATE_EDITOR
+	if(!getAnswerAboutUnsavedChanges())
+		return;
+
+	hide();
+	TemplateEditor::showTemplateEditor();
+#endif
+}
+
 void MainWindow::on_actionNew_triggered()
 {
 	if(getAnswerAboutUnsavedChanges())

+ 2 - 0
mapeditor/mainwindow.h

@@ -80,6 +80,8 @@ private slots:
 
 	void on_actionCampaignEditor_triggered();
 
+	void on_actionTemplateEditor_triggered();
+
 	void on_actionNew_triggered();
 
 	void on_actionLevel_triggered();

+ 10 - 0
mapeditor/mainwindow.ui

@@ -72,6 +72,7 @@
     <addaction name="actionExport"/>
     <addaction name="separator"/>
     <addaction name="actionCampaignEditor"/>
+    <addaction name="actionTemplateEditor"/>
     <addaction name="separator"/>
     <addaction name="actionh3m_converter"/>
     <addaction name="actionh3c_converter"/>
@@ -148,6 +149,7 @@
    <addaction name="actionSave"/>
    <addaction name="separator"/>
    <addaction name="actionCampaignEditor"/>
+   <addaction name="actionTemplateEditor"/>
    <addaction name="separator"/>
    <addaction name="actionUndo"/>
    <addaction name="actionRedo"/>
@@ -1078,6 +1080,14 @@
     <string>Campaign editor</string>
    </property>
   </action>
+  <action name="actionTemplateEditor">
+   <property name="text">
+    <string>Template editor</string>
+   </property>
+   <property name="toolTip">
+    <string>Template editor</string>
+   </property>
+  </action>
   <action name="actionLevel">
    <property name="text">
     <string>View underground</string>

+ 6 - 0
mapeditor/resources.qrc

@@ -7,6 +7,7 @@
         <file>icons/document-open.png</file>
         <file>icons/document-open-recent.png</file>
         <file>icons/document-save.png</file>
+        <file>icons/dice.png</file>
         <file>icons/edit-clear.png</file>
         <file>icons/edit-copy.png</file>
         <file>icons/edit-cut.png</file>
@@ -42,5 +43,10 @@
         <file>icons/zoom_minus.png</file>
         <file>icons/zoom_plus.png</file>
         <file>icons/zoom_zero.png</file>
+        
+        <file>icons/templateSquare.svg</file>
+        <file>icons/zone-add.svg</file>
+        <file>icons/zone-remove.svg</file>
+        <file>icons/zones-layout.svg</file>
     </qresource>
 </RCC>

+ 133 - 0
mapeditor/templateeditor/algorithm.cpp

@@ -0,0 +1,133 @@
+/*
+ * algorithm.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 "algorithm.h"
+
+double Algorithm::distance(double x1, double y1, double x2, double y2)
+{
+    return std::sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)) + 1e-9;
+}
+
+bool Algorithm::edgesIntersect(const Node& a, const Node& b, const Node& c, const Node& d)
+{
+    auto cross = [](double x1, double y1, double x2, double y2) {
+        return x1 * y2 - y1 * x2;
+    };
+
+    double dx1 = b.x - a.x, dy1 = b.y - a.y;
+    double dx2 = d.x - c.x, dy2 = d.y - c.y;
+
+    double delta = cross(dx1, dy1, dx2, dy2);
+    if (std::abs(delta) < 1e-10) return false; // Parallel
+
+    // Compute intersection
+    double s = cross(c.x - a.x, c.y - a.y, dx2, dy2) / delta;
+    double t = cross(c.x - a.x, c.y - a.y, dx1, dy1) / delta;
+
+    return s > 0 && s < 1 && t > 0 && t < 1;
+}
+
+void Algorithm::forceDirectedLayout(std::vector<Node> & nodes, const std::vector<Edge> & edges, int iterations, double width, double height)
+{
+    const double area = width * height;
+    const double k = std::sqrt(area / nodes.size());
+
+    for (int it = 0; it < iterations; ++it)
+    {
+        // Reset forces
+        for (auto& node : nodes)
+            node.dx = node.dy = 0;
+
+        // Repulsive forces
+        for (size_t i = 0; i < nodes.size(); ++i)
+        {
+            for (size_t j = i + 1; j < nodes.size(); ++j)
+            {
+                double dx = nodes[i].x - nodes[j].x;
+                double dy = nodes[i].y - nodes[j].y;
+                double dist = distance(nodes[i].x, nodes[i].y, nodes[j].x, nodes[j].y);
+                double force = (k * k) / dist;
+
+                nodes[i].dx += (dx / dist) * force;
+                nodes[i].dy += (dy / dist) * force;
+                nodes[j].dx -= (dx / dist) * force;
+                nodes[j].dy -= (dy / dist) * force;
+            }
+        }
+
+        // Attractive forces
+        for (const auto& edge : edges)
+        {
+            Node& u = nodes[edge.from];
+            Node& v = nodes[edge.to];
+            double dx = u.x - v.x;
+            double dy = u.y - v.y;
+            double dist = distance(u.x, u.y, v.x, v.y);
+            double force = (dist * dist) / k;
+
+            double fx = (dx / dist) * force;
+            double fy = (dy / dist) * force;
+
+            u.dx -= fx;
+            u.dy -= fy;
+            v.dx += fx;
+            v.dy += fy;
+        }
+
+        // Edge crossing penalty
+        for (size_t i = 0; i < edges.size(); ++i) {
+            for (size_t j = i + 1; j < edges.size(); ++j) {
+                const Edge& e1 = edges[i];
+                const Edge& e2 = edges[j];
+
+                if (e1.from == e2.from || e1.from == e2.to ||
+                    e1.to == e2.from || e1.to == e2.to)
+                    continue; // Skip if they share nodes
+
+                Node& a = nodes[e1.from];
+                Node& b = nodes[e1.to];
+                Node& c = nodes[e2.from];
+                Node& d = nodes[e2.to];
+
+                if (edgesIntersect(a, b, c, d)) {
+                    double strength = 0.05;
+
+                    a.dx += strength * (a.x - c.x);
+                    a.dy += strength * (a.y - c.y);
+                    b.dx += strength * (b.x - d.x);
+                    b.dy += strength * (b.y - d.y);
+                    c.dx += strength * (c.x - a.x);
+                    c.dy += strength * (c.y - a.y);
+                    d.dx += strength * (d.x - b.x);
+                    d.dy += strength * (d.y - b.y);
+                }
+            }
+        }
+
+        // Apply displacement
+        for (auto& node : nodes)
+        {
+            node.x += std::max(-5.0, std::min(5.0, node.dx));
+            node.y += std::max(-5.0, std::min(5.0, node.dy));
+
+            // Keep within bounds
+            node.x = std::min(width, std::max(0.0, node.x));
+            node.y = std::min(height, std::max(0.0, node.y));
+        }
+    }
+
+    for (auto& node : nodes)
+    {
+        // Center around 0
+        node.x -= width / 2;
+        node.y -= height / 2;
+    }
+}

+ 32 - 0
mapeditor/templateeditor/algorithm.h

@@ -0,0 +1,32 @@
+/*
+ * algorithm.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
+
+#include "../StdInc.h"
+
+class Algorithm
+{
+public:
+    struct Node
+    {
+        double x, y;
+        double dx = 0, dy = 0;
+        int id;
+    };
+
+    struct Edge
+    {
+        int from, to;
+    };
+
+    static double distance(double x1, double y1, double x2, double y2);
+    static bool edgesIntersect(const Node& a, const Node& b, const Node& c, const Node& d);
+    static void forceDirectedLayout(std::vector<Node>& nodes, const std::vector<Edge>& edges, int iterations, double width, double height);
+};

+ 292 - 0
mapeditor/templateeditor/graphicelements.cpp

@@ -0,0 +1,292 @@
+/*
+ * graphicelements.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 "graphicelements.h"
+
+#include <QObject>
+
+#include "../../lib/constants/EntityIdentifiers.h"
+#include "../../lib/rmg/CRmgTemplate.h"
+
+QDomElement CardItem::getElementById(const QDomDocument& doc, const QString& id)
+{
+	QDomElement root = doc.documentElement();
+
+	std::function<QDomElement(const QDomElement&)> findById = [&](const QDomElement& elem) -> QDomElement {
+		if (elem.attribute("id") == id)
+			return elem;
+
+		QDomElement child = elem.firstChildElement();
+		while (!child.isNull())
+		{
+			QDomElement found = findById(child);
+			if (!found.isNull())
+				return found;
+			child = child.nextSiblingElement();
+		}
+		return QDomElement();
+	};
+
+	return findById(root);
+}
+
+bool isBlackTextNeeded(const QColor& bg)
+{
+    int r = bg.red();
+    int g = bg.green();
+    int b = bg.blue();
+
+    double luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
+    return luminance > 0.5;
+}
+
+CardItem::CardItem():
+	selectCallback(nullptr),
+	posChangeCallback(nullptr),
+	useBlackText(false),
+	mousePressed(false)
+{
+	QFile file(":/icons/templateSquare.svg");
+	file.open(QIODevice::ReadOnly);
+	QByteArray data = file.readAll();
+	doc.setContent(data);
+
+	updateContent();
+}
+
+void CardItem::setSelectCallback(std::function<void(bool)> func)
+{
+	selectCallback = func;
+}
+
+void CardItem::setPosChangeCallback(std::function<void(QPointF)> func)
+{
+	posChangeCallback = func;
+}
+
+void CardItem::updateContent()
+{
+	setSharedRenderer(new QSvgRenderer(doc.toByteArray()));
+}
+
+void CardItem::setFillColor(QColor color)
+{
+	auto squareElem = getElementById(doc, "rect");
+	squareElem.setAttribute("style", squareElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + color.name() + ";"));
+
+	useBlackText = isBlackTextNeeded(color);
+}
+
+void CardItem::setMultiFillColor(QColor color1, QColor color2)
+{
+	auto squareElem = getElementById(doc, "rect");
+	squareElem.setAttribute("style", squareElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:url(#gradientExtra);"));
+	auto gradientStopElem1 = getElementById(doc, "gradientExtraColorStop1");
+	auto gradientStopElem2 = getElementById(doc, "gradientExtraColorStop2");
+	auto gradientStopElem3 = getElementById(doc, "gradientExtraColorStop3");
+	auto gradientStopElem4 = getElementById(doc, "gradientExtraColorStop4");
+	auto gradientStopElem5 = getElementById(doc, "gradientExtraColorStop5");
+	gradientStopElem1.setAttribute("style", gradientStopElem1.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color1.name() + ";"));
+	gradientStopElem2.setAttribute("style", gradientStopElem2.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color2.name() + ";"));
+	gradientStopElem3.setAttribute("style", gradientStopElem3.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color1.name() + ";"));
+	gradientStopElem4.setAttribute("style", gradientStopElem4.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color2.name() + ";"));
+	gradientStopElem5.setAttribute("style", gradientStopElem5.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color1.name() + ";"));
+
+	useBlackText = isBlackTextNeeded(color1);
+}
+
+void CardItem::setPlayerColor(PlayerColor color)
+{
+	std::map<PlayerColor, std::pair<QString, QString>> colors =
+	{
+		{ PlayerColor(0), { "#F80000", "#920000" } }, //red
+		{ PlayerColor(1), { "#0000F8", "#000092" } }, //blue
+		{ PlayerColor(2), { "#9B7251", "#35271C" } }, //tan
+		{ PlayerColor(3), { "#00FC00", "#009600" } }, //green
+		{ PlayerColor(4), { "#F88000", "#924B00" } }, //orange
+		{ PlayerColor(5), { "#F800F8", "#920092" } }, //purple
+		{ PlayerColor(6), { "#00FCF8", "#009694" } }, //teal
+		{ PlayerColor(7), { "#C07888", "#5A3840" } }, //pink
+	};
+	auto squareElem = getElementById(doc, "rect");
+	squareElem.setAttribute("style", squareElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:url(#gradientPlayer);"));
+	auto gradientStopElem1 = getElementById(doc, "gradientPlayerColorStop1");
+	auto gradientStopElem2 = getElementById(doc, "gradientPlayerColorStop2");
+	gradientStopElem1.setAttribute("style", gradientStopElem1.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + colors[color].first + ";"));
+	gradientStopElem2.setAttribute("style", gradientStopElem2.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + colors[color].second + ";"));
+
+	useBlackText = isBlackTextNeeded(QColor(colors[color].first));
+}
+
+void CardItem::setJunction(bool val)
+{
+	auto squareElem = getElementById(doc, "rectJunction");
+	squareElem.setAttribute("style", squareElem.attribute("style").replace(QRegularExpression("stroke-opacity:.*?;"), "stroke-opacity:" + QString::fromStdString(val ? "0.3" : "0.0") + ";"));
+}
+
+void CardItem::setId(int val)
+{
+	auto textIdElem = getElementById(doc, "textId");
+	textIdElem.setAttribute("style", textIdElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + QColor(useBlackText ? Qt::black : Qt::white).name() + ";"));
+	textIdElem.firstChild().setNodeValue(QString::number(val));
+
+	id = val;
+}
+
+int CardItem::getId()
+{
+	return id;
+}
+
+void CardItem::setResAmount(GameResID res, int val)
+{
+	std::map<GameResID, QString> names =
+	{
+		{ GameResID::WOOD,    "Wood"    },
+		{ GameResID::ORE,     "Ore"     },
+		{ GameResID::MERCURY, "Mercury" },
+		{ GameResID::SULFUR,  "Sulfur"  },
+		{ GameResID::CRYSTAL, "Crystal" },
+		{ GameResID::GEMS,    "Gems"    },
+		{ GameResID::GOLD,    "Gold"    },
+	};
+	auto textElem = getElementById(doc, "text" + names[res]);
+	textElem.setAttribute("style", textElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + QColor(useBlackText ? Qt::black : Qt::white).name() + ";"));
+	textElem.firstChild().setNodeValue(val ? QString::number(val) : "");
+
+	auto iconElem = getElementById(doc, "icon" + names[res]);
+	iconElem.setAttribute("opacity", val ? "1.0" : "0.1");
+}
+
+void CardItem::setChestValue(int val)
+{
+	auto textElem = getElementById(doc, "textChest");
+	textElem.setAttribute("style", textElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + QColor(useBlackText ? Qt::black : Qt::white).name() + ";"));
+	textElem.firstChild().setNodeValue(val ? QString::number(val) : "");
+
+	auto iconElem = getElementById(doc, "iconChest");
+	iconElem.setAttribute("opacity", val ? "1.0" : "0.1");
+}
+
+void CardItem::setSword(EMonsterStrength::EMonsterStrength val)
+{
+	int level = 0;
+	if(val == EMonsterStrength::ZONE_WEAK || val == EMonsterStrength::GLOBAL_WEAK)
+		level = 1;
+	else if(val == EMonsterStrength::ZONE_NORMAL || val == EMonsterStrength::GLOBAL_NORMAL)
+		level = 2;
+	else if(val == EMonsterStrength::ZONE_STRONG || val == EMonsterStrength::GLOBAL_STRONG)
+		level = 3;
+		
+	getElementById(doc, "iconSword1").setAttribute("opacity", level > 0 ? "1.0" : "0.1");
+	getElementById(doc, "iconSword2").setAttribute("opacity", level > 1 ? "1.0" : "0.1");
+	getElementById(doc, "iconSword3").setAttribute("opacity", level > 2 ? "1.0" : "0.1");
+}
+
+void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+	if(event->button() == Qt::LeftButton)
+	{
+		// set element in grid
+		double xx = x() + (boundingRect().width() / 2);
+		double yy = y() + (boundingRect().height() / 2);
+		xx = GRID_SIZE * round(xx / GRID_SIZE);
+		yy = GRID_SIZE * round(yy / GRID_SIZE);
+		setPos(xx - (boundingRect().width() / 2), yy - (boundingRect().height() / 2));
+	}
+
+	QGraphicsSvgItem::mouseReleaseEvent(event);
+
+	if(posChangeCallback)
+		posChangeCallback(pos());
+
+	mousePressed = false;
+}
+
+void CardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+	QGraphicsSvgItem::mousePressEvent(event);
+
+	mousePressed = true;
+}
+
+QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+	if(change == ItemSelectedHasChanged && selectCallback)
+		selectCallback(isSelected());
+	else if(change == ItemPositionHasChanged && posChangeCallback && mousePressed)
+		posChangeCallback(pos());
+
+	return QGraphicsSvgItem::itemChange(change, value);
+}
+
+LineItem::LineItem():
+	clickCallback(nullptr)
+{
+	setZValue(-2);
+	for(int i = 0; i < 10; i++) // render multiple times to increase outline effect
+	{
+		auto tmpTextItem = new QGraphicsTextItem(this);
+		tmpTextItem->setZValue(-1);
+		QFont font;
+		font.setPointSize(18);
+		tmpTextItem->setFont(font);
+		QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect();
+		shadowEffect->setBlurRadius(10);
+		shadowEffect->setEnabled(true);
+		shadowEffect->setOffset(0, 0);
+		shadowEffect->setColor(Qt::black);
+		tmpTextItem->setGraphicsEffect(shadowEffect);
+		tmpTextItem->setDefaultTextColor(Qt::white);
+		textItem.push_back(tmpTextItem);
+	}
+}
+
+void LineItem::setLineToolTip(const QString &toolTip)
+{
+	for(auto & tmpTextItem : textItem)
+		tmpTextItem->setToolTip(toolTip);
+	setToolTip(toolTip);
+}
+
+void LineItem::setClickCallback(std::function<void()> func)
+{
+	clickCallback = func;
+}
+
+void LineItem::setText(QString text)
+{
+	for(auto & tmpTextItem : textItem)
+	{
+		tmpTextItem->setPlainText(text);
+		QRectF lineRect = boundingRect();
+		QRectF textRect = tmpTextItem->boundingRect();
+		tmpTextItem->setPos(QPointF(lineRect.x() + (lineRect.width() / 2) - (textRect.width() / 2), lineRect.y() + (lineRect.height() / 2) - (textRect.height() / 2)));
+	}
+}
+
+void LineItem::setId(int val)
+{
+	id = val;
+}
+
+int LineItem::getId()
+{
+	return id;
+}
+
+void LineItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+	if(event->button() == Qt::LeftButton && clickCallback)
+		clickCallback();
+
+	QGraphicsLineItem::mousePressEvent(event);
+}

+ 73 - 0
mapeditor/templateeditor/graphicelements.h

@@ -0,0 +1,73 @@
+/*
+ * graphicelements.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
+#include <QWidget>
+#include <QGraphicsSvgItem>
+
+#include "../StdInc.h"
+#include "../../lib/constants/EntityIdentifiers.h"
+#include "../../lib/rmg/CRmgTemplate.h"
+
+class CardItem : public QGraphicsSvgItem
+{
+private:
+	QDomElement getElementById(const QDomDocument& doc, const QString& id);
+
+	QDomDocument doc;
+	bool useBlackText;
+	int id = -1;
+	bool mousePressed;
+
+	std::function<void(bool)> selectCallback;
+	std::function<void(QPointF)> posChangeCallback;
+public:
+	CardItem();
+
+	static constexpr double GRID_SIZE = 10.;
+
+	void setSelectCallback(std::function<void(bool)> func);
+	void setPosChangeCallback(std::function<void(QPointF)> func);
+
+	void updateContent();
+	void setFillColor(QColor color);
+	void setMultiFillColor(QColor color1, QColor color2);
+	void setPlayerColor(PlayerColor color);
+	void setJunction(bool val);
+	void setId(int val);
+	int getId();
+	void setResAmount(GameResID res, int val);
+	void setChestValue(int val);
+	void setSword(EMonsterStrength::EMonsterStrength val);
+
+protected:
+	void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
+	void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
+	QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
+};
+
+class LineItem : public QGraphicsLineItem
+{
+private:
+	std::vector<QGraphicsTextItem *> textItem;
+	std::function<void()> clickCallback;
+	int id = -1;
+
+	static constexpr int CLICKABLE_PADDING_AROUND_LINE = 10;
+public:
+	LineItem();
+	void setClickCallback(std::function<void()> func);
+	void setText(QString text);
+	void setId(int val);
+	int getId();
+	void setLineToolTip(const QString &toolTip);
+
+protected:
+	void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
+};

+ 1070 - 0
mapeditor/templateeditor/templateeditor.cpp

@@ -0,0 +1,1070 @@
+/*
+ * templateeditor.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 "templateeditor.h"
+#include "ui_templateeditor.h"
+#include "graphicelements.h"
+#include "algorithm.h"
+
+#include "../helper.h"
+
+#include "../../lib/VCMIDirs.h"
+#include "../../lib/rmg/CRmgTemplate.h"
+#include "../../lib/texts/MetaString.h"
+
+TemplateEditor::TemplateEditor():
+	ui(new Ui::TemplateEditor)
+{
+	ui->setupUi(this);
+	
+	setWindowIcon(QIcon{":/icons/menu-game.png"});
+	ui->actionOpen->setIcon(QIcon{":/icons/document-open.png"});
+	ui->actionSave->setIcon(QIcon{":/icons/document-save.png"});
+	ui->actionNew->setIcon(QIcon{":/icons/document-new.png"});
+	ui->actionAddZone->setIcon(QIcon{":/icons/zone-add.svg"});
+	ui->actionRemoveZone->setIcon(QIcon{":/icons/zone-remove.svg"});
+	ui->actionAutoPosition->setIcon(QIcon{":/icons/zones-layout.svg"});
+	ui->actionZoom_in->setIcon(QIcon{":/icons/zoom_plus.png"});
+	ui->actionZoom_out->setIcon(QIcon{":/icons/zoom_minus.png"});
+	ui->actionZoom_auto->setIcon(QIcon{":/icons/zoom_base.png"});
+	ui->actionZoom_reset->setIcon(QIcon{":/icons/zoom_zero.png"});
+
+	templateScene.reset(new TemplateScene());
+	ui->templateView->setScene(templateScene.get());
+
+	ui->toolBox->setVisible(false);
+
+	ui->spinBoxZoneVisPosX->setSingleStep(CardItem::GRID_SIZE);
+	ui->spinBoxZoneVisPosY->setSingleStep(CardItem::GRID_SIZE);
+
+	ui->templateView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+	ui->templateView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+	ui->templateView->setSceneRect(-3000, -3000, 6000, 6000);
+	ui->templateView->centerOn(QPointF(0, 0));
+	ui->templateView->setDragMode(QGraphicsView::DragMode::ScrollHandDrag);
+
+	loadContent();
+
+	setTitle();
+	
+	setWindowModality(Qt::ApplicationModal);
+
+	show();
+}
+
+TemplateEditor::~TemplateEditor()
+{
+	delete ui;
+}
+
+void TemplateEditor::initContent()
+{
+	ui->comboBoxTemplateSelection->clear();
+
+	ui->toolBox->setVisible(false);
+	ui->pageZone->setEnabled(false);
+
+	if(templates.empty())
+		return;
+
+	ui->toolBox->setVisible(true);
+
+	selectedTemplate = templates.begin()->first;
+	for(auto & tpl : templates)
+		ui->comboBoxTemplateSelection->addItem(QString::fromStdString(tpl.first));
+}
+
+void TemplateEditor::autoPositionZones()
+{
+	auto & zones = templates[selectedTemplate]->getZones();
+
+	std::vector<Algorithm::Node> nodes;
+	std::default_random_engine rng(0);
+	std::uniform_real_distribution<double> distX(0.0, 500);
+	std::uniform_real_distribution<double> distY(0.0, 500);
+	for(auto & item : zones)
+	{
+		Algorithm::Node node;
+		node.x = distX(rng);
+		node.y = distY(rng);
+		node.id = item.first;
+		nodes.push_back(node);
+	}
+	std::vector<Algorithm::Edge> edges;
+	for(auto & item : templates[selectedTemplate]->getConnectedZoneIds())
+		edges.push_back({
+			vstd::find_pos_if(nodes, [item](auto & elem){ return elem.id == item.getZoneA(); }),
+			vstd::find_pos_if(nodes, [item](auto & elem){ return elem.id == item.getZoneB(); })
+		});
+		
+	Algorithm::forceDirectedLayout(nodes, edges, 1000, 500, 500);
+
+	for(auto & item : nodes)
+		zones.at(item.id)->setVisPosition(Point(CardItem::GRID_SIZE * round(item.x / CardItem::GRID_SIZE), CardItem::GRID_SIZE * round(item.y / CardItem::GRID_SIZE)));
+}
+
+void TemplateEditor::loadContent(bool autoPosition)
+{
+	cards.clear();
+	lines.clear();
+
+	selectedZone = -1;
+
+	templateScene->clear();
+
+	if(templates.empty())
+		return;
+
+	auto & zones = templates[selectedTemplate]->getZones();
+	if(autoPosition || std::all_of(zones.begin(), zones.end(), [](auto & item){ return item.second->getVisPosition().x == 0 && item.second->getVisPosition().y == 0; }))
+		autoPositionZones();
+	
+	for(auto & zone : zones)
+		if(zone.second->getVisSize() < 0.01)
+			zone.second->setVisSize(1.0);
+
+	for(auto & zone : zones)
+	{
+		auto svgItem = new CardItem();
+		svgItem->setSelectCallback([this, svgItem](bool selected){
+			ui->pageZone->setDisabled(!selected);
+			ui->toolBox->setCurrentIndex(selected ? 1 : 0);
+			ui->actionRemoveZone->setEnabled(selected);
+			if(selected)
+			{
+				selectedZone = svgItem->getId();
+				loadZoneMenuContent();
+			}
+			else
+				selectedZone = -1;
+		});
+		svgItem->setPosChangeCallback([this, svgItem](QPointF pos){
+			updateConnectionLines();
+			for(auto & zone : templates[selectedTemplate]->getZones())
+				if(zone.first == svgItem->getId())
+				{
+					zone.second->setVisPosition(Point(svgItem->pos().toPoint().rx() + (svgItem->boundingRect().width() * svgItem->scale() / 2), svgItem->pos().toPoint().ry() + (svgItem->boundingRect().height() * svgItem->scale() / 2)));
+					zone.second->setVisSize(svgItem->scale());
+				}
+			loadZoneMenuContent(true);
+		});
+		svgItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
+
+		templateScene->addItem(svgItem);
+		cards[zone.first] = svgItem;
+
+		updateZoneCards();
+	}
+	
+	updateConnectionLines(true);
+	updateZonePositions();
+
+	ui->templateView->show();
+
+	ui->toolBox->setCurrentIndex(0);
+	connect(ui->toolBox, &QToolBox::currentChanged, this, [this](int index) mutable {
+		if(!ui->pageZone->isEnabled() && index == 1)
+			ui->toolBox->setCurrentIndex(0);
+	});
+
+	ui->lineEditName->setText(QString::fromStdString(templates[selectedTemplate]->getName()));
+	ui->lineEditDescription->setText(QString::fromStdString(templates[selectedTemplate]->getDescription()));
+	ui->spinBoxMinSizeX->setValue(templates[selectedTemplate]->getMapSizes().first.x);
+	ui->spinBoxMinSizeY->setValue(templates[selectedTemplate]->getMapSizes().first.y);
+	ui->spinBoxMinSizeZ->setValue(templates[selectedTemplate]->getMapSizes().first.z);
+	ui->spinBoxMaxSizeX->setValue(templates[selectedTemplate]->getMapSizes().second.x);
+	ui->spinBoxMaxSizeY->setValue(templates[selectedTemplate]->getMapSizes().second.y);
+	ui->spinBoxMaxSizeZ->setValue(templates[selectedTemplate]->getMapSizes().second.z);
+	ui->checkBoxAllowedWaterContentNone->setChecked(templates[selectedTemplate]->allowedWaterContent.count(EWaterContent::EWaterContent::NONE));
+	ui->checkBoxAllowedWaterContentNormal->setChecked(templates[selectedTemplate]->allowedWaterContent.count(EWaterContent::EWaterContent::NORMAL));
+	ui->checkBoxAllowedWaterContentIslands->setChecked(templates[selectedTemplate]->allowedWaterContent.count(EWaterContent::EWaterContent::ISLANDS));
+
+	auto setPlayersTable = [this](QTableWidget * widget, std::vector<std::pair<int, int>> & range){
+		widget->clear();
+		widget->clearContents();
+		widget->setRowCount(0);
+		widget->setColumnCount(3);
+		widget->setHorizontalHeaderLabels({ tr("Min"), tr("Max"), tr("Action") });
+		widget->horizontalHeader()->setStretchLastSection(true);
+		for(int i = 0; i < range.size(); i++)
+		{
+			widget->insertRow(i);
+			QSpinBox* minSpin = new QSpinBox();
+			QSpinBox* maxSpin = new QSpinBox();
+			QPushButton* delButton = new QPushButton();
+			minSpin->setRange(0, 999);
+			maxSpin->setRange(0, 999);
+			minSpin->setValue(range.at(i).first);
+			maxSpin->setValue(range.at(i).second);
+			connect(minSpin, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [i, &range](int val){
+				range.at(i).first = val;
+			});
+			connect(maxSpin, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [i, &range](int val){
+				range.at(i).second = val;
+			});
+			delButton->setText(tr("Delete"));
+			connect(delButton, &QPushButton::clicked, this, [this, i, &range](){
+				range.erase(range.begin() + i);
+				loadContent();
+			});
+			widget->setCellWidget(i, 0, minSpin);
+			widget->setCellWidget(i, 1, maxSpin);
+			widget->setCellWidget(i, 2, delButton);
+		}
+		widget->insertRow(widget->rowCount());
+		QPushButton* addButton = new QPushButton();
+		addButton->setText(tr("Add"));
+		connect(addButton, &QPushButton::clicked, this, [this, &range](){
+			range.push_back(std::make_pair(0, 0));
+			loadContent();
+		});
+		widget->setCellWidget(widget->rowCount() - 1, 2, addButton);
+	};
+	setPlayersTable(ui->tableWidgetPlayersPlayer, templates[selectedTemplate]->players.range);
+	setPlayersTable(ui->tableWidgetPlayersHuman, templates[selectedTemplate]->humanPlayers.range);
+
+	loadZoneConnectionMenuContent();
+}
+
+void TemplateEditor::updateZonePositions()
+{
+	for(auto & card : cards)
+	{
+		auto & zone = templates[selectedTemplate]->getZones().at(card.first);
+		card.second->setPos(zone->getVisPosition().x - (card.second->boundingRect().width() * card.second->scale() / 2), zone->getVisPosition().y - (card.second->boundingRect().height() * card.second->scale() / 2));
+		card.second->setScale(zone->getVisSize());
+	}
+
+	updateConnectionLines();
+}
+
+QString TemplateEditor::getZoneToolTip(std::shared_ptr<rmg::ZoneOptions> zone)
+{
+	QString tmp{};
+	tmp.append(tr("ID: %1").arg(QString::number(zone->getId())));
+	tmp.append("\n");
+	tmp.append(tr("Max treasure: %1").arg(QString::number(zone->getMaxTreasureValue())));
+	//TODO: extend other interesting things (terrains, towns, ...)
+	return tmp;
+}
+
+void TemplateEditor::updateZoneCards(TRmgTemplateZoneId id)
+{
+	for(auto & card : cards)
+	{
+		if(card.first != id && id > -1)
+			continue;
+
+		auto & zone = templates[selectedTemplate]->getZones().at(card.first);
+		auto type = zone->getType();
+
+		if(type == ETemplateZoneType::PLAYER_START || type == ETemplateZoneType::CPU_START)
+			card.second->setPlayerColor(PlayerColor(*zone->getOwner()));
+		else if(type == ETemplateZoneType::TREASURE)
+			card.second->setMultiFillColor(QColor(165, 125, 55), QColor(250, 229, 157));
+		else if(type == ETemplateZoneType::WATER)
+			card.second->setMultiFillColor(QColor(55, 68, 165), QColor(157, 250, 247));
+		else
+			card.second->setFillColor(QColor(200, 200, 200));
+		card.second->setJunction(type == ETemplateZoneType::JUNCTION);
+
+		card.second->setId(card.first);
+		for(auto & res : {GameResID::WOOD, GameResID::ORE, GameResID::MERCURY, GameResID::SULFUR, GameResID::CRYSTAL, GameResID::GEMS, GameResID::GOLD})
+			card.second->setResAmount(res, zone->getMinesInfo().count(res) ? zone->getMinesInfo().at(res) : 0);
+		card.second->setChestValue(zone->getMaxTreasureValue());
+		card.second->setSword(zone->monsterStrength);
+		card.second->setToolTip(getZoneToolTip(zone));
+		card.second->setScale(zone->getVisSize());
+		card.second->updateContent();
+	}
+}
+
+void TemplateEditor::loadZoneMenuContent(bool onlyPosition)
+{
+	if(selectedZone < 0 || selectedTemplate.empty())
+		return;
+	
+	auto setValue = [](auto& target, const auto& newValue){ target->setValue(newValue); };
+	auto & zone = templates[selectedTemplate]->getZones().at(selectedZone);
+	setValue(ui->spinBoxZoneVisPosX, zone->getVisPosition().x);
+	setValue(ui->spinBoxZoneVisPosY, zone->getVisPosition().y);
+	setValue(ui->doubleSpinBoxZoneVisSize, zone->getVisSize());
+	
+	if(onlyPosition)
+		return;
+
+	setValue(ui->spinBoxZoneSize, zone->getSize());
+	setValue(ui->spinBoxTownCountPlayer, zone->playerTowns.townCount);
+	setValue(ui->spinBoxCastleCountPlayer, zone->playerTowns.castleCount);
+	setValue(ui->spinBoxTownDensityPlayer, zone->playerTowns.townDensity);
+	setValue(ui->spinBoxCastleDensityPlayer, zone->playerTowns.castleDensity);
+	setValue(ui->spinBoxTownCountNeutral, zone->neutralTowns.townCount);
+	setValue(ui->spinBoxCastleCountNeutral, zone->neutralTowns.castleCount);
+	setValue(ui->spinBoxTownDensityNeutral, zone->neutralTowns.townDensity);
+	setValue(ui->spinBoxCastleDensityNeutral, zone->neutralTowns.castleDensity);
+	ui->checkBoxMatchTerrainToTown->setChecked(zone->matchTerrainToTown);
+	ui->checkBoxTownsAreSameType->setChecked(zone->townsAreSameType);
+	ui->checkBoxZoneLinkTowns->setChecked(zone->townsLikeZone != rmg::ZoneOptions::NO_ZONE);
+	ui->checkBoxZoneLinkMines->setChecked(zone->minesLikeZone != rmg::ZoneOptions::NO_ZONE);
+	ui->checkBoxZoneLinkTerrain->setChecked(zone->terrainTypeLikeZone != rmg::ZoneOptions::NO_ZONE);
+	ui->checkBoxZoneLinkTreasure->setChecked(zone->treasureLikeZone != rmg::ZoneOptions::NO_ZONE);
+	ui->checkBoxZoneLinkCustomObjects->setChecked(zone->customObjectsLikeZone != rmg::ZoneOptions::NO_ZONE);
+	setValue(ui->spinBoxZoneLinkTowns, zone->townsLikeZone != rmg::ZoneOptions::NO_ZONE ? zone->townsLikeZone : 0);
+	setValue(ui->spinBoxZoneLinkMines, zone->minesLikeZone != rmg::ZoneOptions::NO_ZONE ? zone->minesLikeZone : 0);
+	setValue(ui->spinBoxZoneLinkTerrain, zone->terrainTypeLikeZone != rmg::ZoneOptions::NO_ZONE ? zone->terrainTypeLikeZone : 0);
+	setValue(ui->spinBoxZoneLinkTreasure, zone->treasureLikeZone != rmg::ZoneOptions::NO_ZONE ? zone->treasureLikeZone : 0);
+	setValue(ui->spinBoxZoneLinkCustomObjects, zone->customObjectsLikeZone != rmg::ZoneOptions::NO_ZONE ? zone->customObjectsLikeZone : 0);
+	ui->spinBoxZoneLinkTowns->setEnabled(zone->townsLikeZone != rmg::ZoneOptions::NO_ZONE);
+	ui->spinBoxZoneLinkMines->setEnabled(zone->minesLikeZone != rmg::ZoneOptions::NO_ZONE);
+	ui->spinBoxZoneLinkTerrain->setEnabled(zone->terrainTypeLikeZone != rmg::ZoneOptions::NO_ZONE);
+	ui->spinBoxZoneLinkTreasure->setEnabled(zone->treasureLikeZone != rmg::ZoneOptions::NO_ZONE);
+	ui->spinBoxZoneLinkCustomObjects->setEnabled(zone->customObjectsLikeZone != rmg::ZoneOptions::NO_ZONE);
+	
+	setValue(ui->spinBoxZoneId, zone->id);
+	ui->spinBoxZoneId->setEnabled(false);
+
+	ui->comboBoxZoneType->clear();
+	ui->comboBoxZoneType->addItem(tr("Player start"), QVariant(static_cast<int>(ETemplateZoneType::PLAYER_START)));
+	ui->comboBoxZoneType->addItem(tr("CPU start"), QVariant(static_cast<int>(ETemplateZoneType::CPU_START)));
+	ui->comboBoxZoneType->addItem(tr("Treasure"), QVariant(static_cast<int>(ETemplateZoneType::TREASURE)));
+	ui->comboBoxZoneType->addItem(tr("Junction"), QVariant(static_cast<int>(ETemplateZoneType::JUNCTION)));
+	ui->comboBoxZoneType->addItem(tr("Water"), QVariant(static_cast<int>(ETemplateZoneType::WATER)));
+	ui->comboBoxZoneType->addItem(tr("Sealed"), QVariant(static_cast<int>(ETemplateZoneType::SEALED)));
+	for (int i = 0; i < ui->comboBoxZoneType->count(); ++i)
+    	if (ui->comboBoxZoneType->itemData(i).toInt() == static_cast<int>(zone->getType()))
+        	ui->comboBoxZoneType->setCurrentIndex(i);
+
+	ui->comboBoxZoneOwner->clear();
+	auto type = static_cast<ETemplateZoneType>(ui->comboBoxZoneType->currentData().toInt());
+	if((type == ETemplateZoneType::PLAYER_START || type == ETemplateZoneType::CPU_START))
+	{
+		ui->comboBoxZoneOwner->setEnabled(true);
+		for(auto color = PlayerColor(0); color < PlayerColor::PLAYER_LIMIT; ++color)
+		{
+			MetaString str;
+			str.appendName(color);
+			ui->comboBoxZoneOwner->addItem(QString::fromStdString(str.toString()), QVariant(static_cast<int>(color)));
+		}
+		for (int i = 0; i < ui->comboBoxZoneOwner->count(); ++i)
+			if (ui->comboBoxZoneOwner->itemData(i).toInt() == static_cast<int>(*zone->getOwner()))
+				ui->comboBoxZoneOwner->setCurrentIndex(i);
+	}
+	else
+	{
+		ui->comboBoxZoneOwner->addItem(tr("None"));
+		ui->comboBoxZoneOwner->setEnabled(false);
+	}
+
+	ui->comboBoxMonsterStrength->clear();
+	ui->comboBoxMonsterStrength->addItem(tr("None"), QVariant(static_cast<int>(EMonsterStrength::EMonsterStrength::ZONE_NONE)));
+	ui->comboBoxMonsterStrength->addItem(tr("Random"), QVariant(static_cast<int>(EMonsterStrength::EMonsterStrength::RANDOM)));
+	ui->comboBoxMonsterStrength->addItem(tr("Weak"), QVariant(static_cast<int>(EMonsterStrength::EMonsterStrength::ZONE_WEAK)));
+	ui->comboBoxMonsterStrength->addItem(tr("Normal"), QVariant(static_cast<int>(EMonsterStrength::EMonsterStrength::ZONE_NORMAL)));
+	ui->comboBoxMonsterStrength->addItem(tr("Strong"), QVariant(static_cast<int>(EMonsterStrength::EMonsterStrength::ZONE_STRONG)));
+	for (int i = 0; i < ui->comboBoxMonsterStrength->count(); ++i)
+    	if (ui->comboBoxMonsterStrength->itemData(i).toInt() == static_cast<int>(zone->monsterStrength))
+        	ui->comboBoxMonsterStrength->setCurrentIndex(i);
+}
+
+void TemplateEditor::loadZoneConnectionMenuContent()
+{
+	auto widget = ui->tableWidgetConnections;
+	auto & connections = templates[selectedTemplate]->connections;
+
+	widget->clear();
+	widget->clearContents();
+	widget->setRowCount(0);
+	widget->setColumnCount(6);
+	widget->setHorizontalHeaderLabels({ tr("Zone A"), tr("Zone B"), tr("Guard"), tr("Type"), tr("Road"), "" });
+	for (int i = 0; i < connections.size(); i++)
+	{
+		int row = widget->rowCount();
+		widget->insertRow(row);
+		QSpinBox* zoneA = new QSpinBox();
+		QSpinBox* zoneB = new QSpinBox();
+		QSpinBox* guardStrength = new QSpinBox();
+		QComboBox* connectionType = new QComboBox();
+		QComboBox* hasRoad = new QComboBox();
+		QPushButton* delButton = new QPushButton();
+		zoneA->setRange(0, 999);
+		zoneB->setRange(0, 999);
+		guardStrength->setRange(0, 99999);
+		connectionType->addItem(tr("Guarded"), QVariant(static_cast<int>(rmg::EConnectionType::GUARDED)));
+		connectionType->addItem(tr("Fictive"), QVariant(static_cast<int>(rmg::EConnectionType::FICTIVE)));
+		connectionType->addItem(tr("Repulsive"), QVariant(static_cast<int>(rmg::EConnectionType::REPULSIVE)));
+		connectionType->addItem(tr("Wide"), QVariant(static_cast<int>(rmg::EConnectionType::WIDE)));
+		connectionType->addItem(tr("Force portal"), QVariant(static_cast<int>(rmg::EConnectionType::FORCE_PORTAL)));
+		hasRoad->addItem(tr("Random"), QVariant(static_cast<int>(rmg::ERoadOption::ROAD_RANDOM)));
+		hasRoad->addItem(tr("Yes"), QVariant(static_cast<int>(rmg::ERoadOption::ROAD_TRUE)));
+		hasRoad->addItem(tr("No"), QVariant(static_cast<int>(rmg::ERoadOption::ROAD_FALSE)));
+		zoneA->setValue(connections.at(i).getZoneA());
+		zoneB->setValue(connections.at(i).getZoneB());
+		guardStrength->setValue(connections.at(i).getGuardStrength());
+		for (int j = 0; j < connectionType->count(); ++j)
+			if (connectionType->itemData(j).toInt() == static_cast<int>(connections[i].getConnectionType()))
+				connectionType->setCurrentIndex(j);
+		for (int j = 0; j < hasRoad->count(); ++j)
+			if (hasRoad->itemData(j).toInt() == static_cast<int>(connections[i].hasRoad))
+				hasRoad->setCurrentIndex(j);
+		delButton->setText(tr("Del"));
+		delButton->setToolTip(tr("Delete"));
+		connect(zoneA, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [this, i, &connections](int val){
+			connections.at(i).zoneA = val;
+			updateConnectionLines(true);
+			changed();
+		});
+		connect(zoneB, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [this, i, &connections](int val){
+			connections.at(i).zoneB = val;
+			updateConnectionLines(true);
+			changed();
+		});
+		connect(guardStrength, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [this, i, &connections](int val){
+			connections.at(i).guardStrength = val;
+			updateConnectionLines();
+			changed();
+		});
+		connect(connectionType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this, i, &connections, connectionType](int val){
+			connections.at(i).connectionType = static_cast<rmg::EConnectionType>(connectionType->itemData(val).toInt());
+			updateConnectionLines();
+			changed();
+		});
+		connect(hasRoad, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this, i, &connections, hasRoad](int val){
+			connections.at(i).hasRoad = static_cast<rmg::ERoadOption>(hasRoad->itemData(val).toInt());
+			updateConnectionLines();
+			changed();
+		});
+		connect(delButton, &QPushButton::pressed, this, [this, i, &connections](){
+			connections.erase(connections.begin() + i);
+			updateConnectionLines(true);
+			loadZoneConnectionMenuContent();
+			changed();
+		});
+		widget->setCellWidget(i, 0, zoneA);
+		widget->setCellWidget(i, 1, zoneB);
+		widget->setCellWidget(i, 2, guardStrength);
+		widget->setCellWidget(i, 3, connectionType);
+		widget->setCellWidget(i, 4, hasRoad);
+		widget->setCellWidget(i, 5, delButton);
+	};
+	widget->resizeColumnsToContents();
+}
+
+void TemplateEditor::saveZoneMenuContent()
+{
+	if(selectedZone < 0 || selectedTemplate.empty())
+		return;
+
+	auto zone = templates[selectedTemplate]->getZones().at(selectedZone);
+	auto type = static_cast<ETemplateZoneType>(ui->comboBoxZoneType->currentData().toInt());
+
+	zone->setVisPosition(Point(ui->spinBoxZoneVisPosX->value(), ui->spinBoxZoneVisPosY->value()));
+	zone->setVisSize(ui->doubleSpinBoxZoneVisSize->value());
+	zone->setType(type);
+	zone->setSize(ui->spinBoxZoneSize->value());
+	zone->playerTowns.townCount = ui->spinBoxTownCountPlayer->value();
+	zone->playerTowns.castleCount = ui->spinBoxCastleCountPlayer->value();
+	zone->playerTowns.townDensity = ui->spinBoxTownDensityPlayer->value();
+	zone->playerTowns.castleDensity = ui->spinBoxCastleDensityPlayer->value();
+	zone->neutralTowns.townCount = ui->spinBoxTownCountNeutral->value();
+	zone->neutralTowns.castleCount = ui->spinBoxCastleCountNeutral->value();
+	zone->neutralTowns.townDensity = ui->spinBoxTownDensityNeutral->value();
+	zone->neutralTowns.castleDensity = ui->spinBoxCastleDensityNeutral->value();
+	zone->matchTerrainToTown = ui->checkBoxMatchTerrainToTown->isChecked();
+	zone->townsAreSameType = ui->checkBoxTownsAreSameType->isChecked();
+	zone->monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(ui->comboBoxMonsterStrength->currentData().toInt());
+	zone->id = ui->spinBoxZoneId->value();
+	zone->townsLikeZone = ui->checkBoxZoneLinkTowns->isChecked() ? ui->spinBoxZoneLinkTowns->value() : rmg::ZoneOptions::NO_ZONE;
+	zone->minesLikeZone = ui->checkBoxZoneLinkMines->isChecked() ? ui->spinBoxZoneLinkMines->value() : rmg::ZoneOptions::NO_ZONE;
+	zone->terrainTypeLikeZone = ui->checkBoxZoneLinkTerrain->isChecked() ? ui->spinBoxZoneLinkTerrain->value() : rmg::ZoneOptions::NO_ZONE;
+	zone->treasureLikeZone = ui->checkBoxZoneLinkTreasure->isChecked() ? ui->spinBoxZoneLinkTreasure->value() : rmg::ZoneOptions::NO_ZONE;
+	zone->customObjectsLikeZone = ui->checkBoxZoneLinkCustomObjects->isChecked() ? ui->spinBoxZoneLinkCustomObjects->value() : rmg::ZoneOptions::NO_ZONE;
+
+	if((type == ETemplateZoneType::PLAYER_START || type == ETemplateZoneType::CPU_START))
+		zone->owner = std::optional<int>(static_cast<PlayerColor>(ui->comboBoxZoneOwner->currentData().toInt()));
+	else
+		zone->owner = std::nullopt;
+
+	updateZonePositions();
+	updateZoneCards(selectedZone);
+
+	changed();
+}
+
+void TemplateEditor::updateConnectionLines(bool recreate)
+{
+	if(recreate)
+	{
+		for(auto & line : lines)
+			templateScene->removeItem(line);
+		lines.clear();
+
+		for(int i = 0; i < templates[selectedTemplate]->getConnectedZoneIds().size(); i++)
+		{
+			auto & connection = templates[selectedTemplate]->getConnectedZoneIds()[i];
+			auto line = new LineItem();
+			line->setId(i);
+			line->setLineToolTip(tr("Zone A: %1\nZone B: %2\nGuard: %3").arg(QString::number(connection.zoneA)).arg(QString::number(connection.zoneB)).arg(QString::number(connection.guardStrength)));
+			line->setClickCallback([this, line](){
+				ui->toolBox->setCurrentIndex(2);
+				ui->tableWidgetConnections->selectRow(line->getId());
+			});
+			lines.push_back(line);
+			templateScene->addItem(line);
+		}
+	}
+
+	const auto& connections = templates[selectedTemplate]->getConnectedZoneIds();
+	for (size_t i = 0; i < connections.size(); ++i)
+	{
+		auto& connection = connections[i];
+
+		if(!cards.count(connection.getZoneA()) || !cards.count(connection.getZoneB()) || i >= lines.size())
+			continue;
+
+		auto getCenter = [](auto & i){
+			return i->pos() + QPointF(i->boundingRect().width() / 2, i->boundingRect().height() / 2) * i->scale();
+		};
+		auto posA = getCenter(cards[connection.getZoneA()]);
+		auto posB = getCenter(cards[connection.getZoneB()]);
+
+		lines[i]->setLine(QLineF(posA.x(), posA.y(), posB.x(), posB.y()));
+		lines[i]->setText(QString::number(connection.getGuardStrength()));
+
+		std::map<rmg::EConnectionType, QPen> pens = {
+			{rmg::EConnectionType::GUARDED, QPen(Qt::black, 5, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)},
+			{rmg::EConnectionType::FICTIVE, QPen(Qt::black, 5, Qt::DashLine, Qt::SquareCap, Qt::BevelJoin)},
+			{rmg::EConnectionType::REPULSIVE, QPen(Qt::black, 5, Qt::DashDotLine, Qt::SquareCap, Qt::BevelJoin)},
+			{rmg::EConnectionType::WIDE, QPen(Qt::black, 5, Qt::DotLine, Qt::SquareCap, Qt::BevelJoin)},
+			{rmg::EConnectionType::FORCE_PORTAL, QPen(Qt::black, 5, Qt::DashDotDotLine, Qt::SquareCap, Qt::BevelJoin)}
+		};
+		lines[i]->setPen(pens[connection.connectionType]);
+	}
+}
+
+void TemplateEditor::saveContent()
+{
+	templates[selectedTemplate]->name = ui->lineEditName->text().toStdString();
+	templates[selectedTemplate]->description = ui->lineEditDescription->text().toStdString();
+	templates[selectedTemplate]->minSize = int3(ui->spinBoxMinSizeX->value(), ui->spinBoxMinSizeY->value(), ui->spinBoxMinSizeZ->value());
+	templates[selectedTemplate]->maxSize = int3(ui->spinBoxMaxSizeX->value(), ui->spinBoxMaxSizeY->value(), ui->spinBoxMaxSizeZ->value());
+
+	templates[selectedTemplate]->allowedWaterContent.clear();
+	if(ui->checkBoxAllowedWaterContentNone->isChecked())
+		templates[selectedTemplate]->allowedWaterContent.insert(EWaterContent::EWaterContent::NONE);
+	if(ui->checkBoxAllowedWaterContentNormal->isChecked())
+		templates[selectedTemplate]->allowedWaterContent.insert(EWaterContent::EWaterContent::NORMAL);
+	if(ui->checkBoxAllowedWaterContentIslands->isChecked())
+		templates[selectedTemplate]->allowedWaterContent.insert(EWaterContent::EWaterContent::ISLANDS);
+
+	changed();
+}
+
+bool TemplateEditor::getAnswerAboutUnsavedChanges()
+{
+	if(unsaved)
+	{
+		auto sure = QMessageBox::question(this, tr("Confirmation"), tr("Unsaved changes will be lost, are you sure?"));
+		if(sure == QMessageBox::No)
+		{
+			return false;
+		}
+	}
+	return true;
+}
+
+void TemplateEditor::setTitle()
+{
+	QFileInfo fileInfo(filename);
+	QString title = QString("%1%2 - %3 (%4)").arg(fileInfo.fileName(), unsaved ? "*" : "", tr("VCMI Template Editor"), GameConstants::VCMI_VERSION.c_str());
+	setWindowTitle(title);
+}
+
+void TemplateEditor::changed()
+{
+	unsaved = true;
+	setTitle();
+}
+
+void TemplateEditor::saveTemplate()
+{
+	saveContent();
+
+	Helper::saveTemplate(templates, filename);
+	unsaved = false;
+}
+
+void TemplateEditor::showTemplateEditor()
+{
+	auto * dialog = new TemplateEditor();
+
+	dialog->setAttribute(Qt::WA_DeleteOnClose);
+}
+
+void TemplateEditor::on_actionOpen_triggered()
+{
+	if(!getAnswerAboutUnsavedChanges())
+		return;
+	
+	auto filenameSelect = QFileDialog::getOpenFileName(this, tr("Open template"),
+		QString::fromStdString(VCMIDirs::get().userDataPath().make_preferred().string()),
+		tr("VCMI templates(*.json)"));
+	if(filenameSelect.isEmpty())
+		return;
+
+	templates = Helper::openTemplateInternal(filenameSelect);
+
+	initContent();
+	loadContent();
+	ui->templateView->autoFit();
+}
+
+void TemplateEditor::on_actionSave_as_triggered()
+{
+	auto filenameSelect = QFileDialog::getSaveFileName(this, tr("Save template"), "", tr("VCMI templates (*.json)"));
+
+	if(filenameSelect.isNull())
+		return;
+
+	QFileInfo fileInfo(filenameSelect);
+
+	if(fileInfo.suffix().toLower() != "json")
+		filenameSelect += ".json";
+
+	filename = filenameSelect;
+	saveTemplate();
+	setTitle();
+}
+
+void TemplateEditor::on_actionNew_triggered()
+{
+	if(!getAnswerAboutUnsavedChanges())
+		return;
+
+	templates = std::map<std::string, std::shared_ptr<CRmgTemplate>>();
+	templates["TemplateEditor"] = std::make_shared<CRmgTemplate>();
+	
+	changed();
+	initContent();
+	loadContent();
+	ui->templateView->autoFit();
+}
+
+void TemplateEditor::on_actionSave_triggered()
+{
+	if(filename.isNull())
+		on_actionSave_as_triggered();
+	else 
+		saveTemplate();
+	setTitle();
+}
+
+void TemplateEditor::on_actionAutoPosition_triggered()
+{
+	if(!templates.size())
+		return;
+
+	saveContent();
+	loadContent(true);
+	ui->templateView->autoFit();
+}
+
+void TemplateEditor::on_actionZoom_in_triggered()
+{
+	ui->templateView->changeZoomLevel(true);
+}
+
+void TemplateEditor::on_actionZoom_out_triggered()
+{
+	ui->templateView->changeZoomLevel(false);
+}
+
+void TemplateEditor::on_actionZoom_auto_triggered()
+{
+	ui->templateView->autoFit();
+}
+
+void TemplateEditor::on_actionZoom_reset_triggered()
+{
+	ui->templateView->setZoomLevel(0);
+}
+
+void TemplateEditor::on_actionAddZone_triggered()
+{
+	if(!templates.size())
+		return;
+
+	for(int i = 1; i < 999; i++)
+	{
+		if(!templates[selectedTemplate]->zones.count(i))
+		{
+			templates[selectedTemplate]->zones[i] = std::make_shared<rmg::ZoneOptions>();
+			break;
+		}
+	}
+	loadContent();
+}
+
+void TemplateEditor::on_actionRemoveZone_triggered()
+{
+	templates[selectedTemplate]->zones.erase(selectedZone);
+	selectedZone = -1;
+	loadContent();
+}
+
+void TemplateEditor::on_comboBoxTemplateSelection_activated(int index)
+{
+	auto value = ui->comboBoxTemplateSelection->currentText().toStdString();
+	if(value.empty())
+		return;
+
+	saveContent();
+	selectedTemplate = value;
+	loadContent();
+}
+
+void TemplateEditor::closeEvent(QCloseEvent *event)
+{
+	if(getAnswerAboutUnsavedChanges())
+		QWidget::closeEvent(event);
+	else
+		event->ignore();
+}
+
+void TemplateEditor::on_pushButtonAddSubTemplate_clicked()
+{
+	bool ok;
+	QString text = QInputDialog::getText(this, tr("Enter Name"), tr("Name:"), QLineEdit::Normal, "", &ok);
+
+	if (!ok || text.isEmpty())
+		return;
+
+	if(templates.count(text.toStdString()))
+	{
+		QMessageBox::critical(this, tr("Already existing!"), tr("At template with this name is already existing."));
+		return;
+	}
+
+	selectedTemplate = text.toStdString();
+	templates[selectedTemplate] = std::make_shared<CRmgTemplate>();
+	ui->comboBoxTemplateSelection->addItem(text);
+	ui->comboBoxTemplateSelection->setCurrentIndex(ui->comboBoxTemplateSelection->count() - 1);
+
+	loadContent();
+}
+
+void TemplateEditor::on_pushButtonRemoveSubTemplate_clicked()
+{
+	if(templates.size() < 2)
+	{
+		QMessageBox::critical(this, tr("To few templates!"), tr("At least one template should remain after removing."));
+		return;
+	}
+
+	templates.erase(selectedTemplate);
+	ui->comboBoxTemplateSelection->removeItem(ui->comboBoxTemplateSelection->currentIndex());
+	selectedTemplate = ui->comboBoxTemplateSelection->currentText().toStdString();
+
+	loadContent();
+}
+
+void TemplateEditor::on_pushButtonRenameSubTemplate_clicked()
+{
+	if(ui->comboBoxTemplateSelection->currentText().isEmpty() || !templates.size())
+		return;
+
+	bool ok;
+	QString text = QInputDialog::getText(this, tr("Enter Name"), tr("Name:"), QLineEdit::Normal, ui->comboBoxTemplateSelection->currentText(), &ok);
+
+	if (!ok || text.isEmpty())
+		return;
+
+	ui->comboBoxTemplateSelection->setItemText(ui->comboBoxTemplateSelection->currentIndex(), text);
+
+	templates[text.toStdString()] = templates[selectedTemplate];
+	templates.erase(selectedTemplate);
+	selectedTemplate = text.toStdString();
+}
+
+void TemplateEditor::on_spinBoxZoneVisPosX_valueChanged()
+{
+	if(ui->spinBoxZoneVisPosX->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxZoneVisPosY_valueChanged()
+{
+	if(ui->spinBoxZoneVisPosY->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_doubleSpinBoxZoneVisSize_valueChanged()
+{
+	if(ui->doubleSpinBoxZoneVisSize->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_comboBoxZoneType_currentTextChanged(const QString &text)
+{
+	if(!ui->comboBoxZoneType->hasFocus())
+		return;
+	ui->comboBoxZoneType->clearFocus(); 
+
+	saveZoneMenuContent();
+	loadZoneMenuContent();
+}
+
+void TemplateEditor::on_comboBoxZoneOwner_currentTextChanged(const QString &text)
+{
+	if(ui->comboBoxZoneOwner->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxZoneSize_valueChanged()
+{
+	if(ui->spinBoxZoneSize->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxTownCountPlayer_valueChanged()
+{
+	if(ui->spinBoxTownCountPlayer->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxCastleCountPlayer_valueChanged()
+{
+	if(ui->spinBoxCastleCountPlayer->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxTownDensityPlayer_valueChanged()
+{
+	if(ui->spinBoxTownDensityPlayer->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxCastleDensityPlayer_valueChanged()
+{
+	if(ui->spinBoxCastleDensityPlayer->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxTownCountNeutral_valueChanged()
+{
+	if(ui->spinBoxTownCountNeutral->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxCastleCountNeutral_valueChanged()
+{
+	if(ui->spinBoxCastleCountNeutral->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxTownDensityNeutral_valueChanged()
+{
+	if(ui->spinBoxTownDensityNeutral->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxCastleDensityNeutral_valueChanged()
+{
+	if(ui->spinBoxCastleDensityNeutral->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxMatchTerrainToTown_stateChanged(int state)
+{
+	if(ui->checkBoxMatchTerrainToTown->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxTownsAreSameType_stateChanged(int state)
+{
+	if(ui->checkBoxTownsAreSameType->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_comboBoxMonsterStrength_currentTextChanged(const QString &text)
+{
+	if(ui->comboBoxMonsterStrength->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxZoneId_valueChanged()
+{
+	if(ui->spinBoxZoneId->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxZoneLinkTowns_valueChanged()
+{
+	if(ui->spinBoxZoneLinkTowns->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxZoneLinkMines_valueChanged()
+{
+	if(ui->spinBoxZoneLinkMines->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxZoneLinkTerrain_valueChanged()
+{
+	if(ui->spinBoxZoneLinkTerrain->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxZoneLinkTreasure_valueChanged()
+{
+	if(ui->spinBoxZoneLinkTreasure->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_spinBoxZoneLinkCustomObjects_valueChanged()
+{
+	if(ui->spinBoxZoneLinkCustomObjects->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxZoneLinkTowns_stateChanged(int state)
+{
+	if(!ui->checkBoxZoneLinkTowns->hasFocus())
+		return;
+	ui->checkBoxZoneLinkTowns->clearFocus();
+
+	saveZoneMenuContent();
+	loadZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxZoneLinkMines_stateChanged(int state)
+{
+	if(!ui->checkBoxZoneLinkMines->hasFocus())
+		return;
+	ui->checkBoxZoneLinkMines->clearFocus();
+
+	saveZoneMenuContent();
+	loadZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxZoneLinkTerrain_stateChanged(int state)
+{
+	if(!ui->checkBoxZoneLinkTerrain->hasFocus())
+		return;
+	ui->checkBoxZoneLinkTerrain->clearFocus();
+
+	saveZoneMenuContent();
+	loadZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxZoneLinkTreasure_stateChanged(int state)
+{
+	if(!ui->checkBoxZoneLinkTreasure->hasFocus())
+		return;
+	ui->checkBoxZoneLinkTreasure->clearFocus();
+
+	saveZoneMenuContent();
+	loadZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxZoneLinkCustomObjects_stateChanged(int state)
+{
+	if(!ui->checkBoxZoneLinkCustomObjects->hasFocus())
+		return;
+	ui->checkBoxZoneLinkCustomObjects->clearFocus();
+
+	saveZoneMenuContent();
+	loadZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxAllowedWaterContentNone_stateChanged(int state)
+{
+	if(ui->checkBoxAllowedWaterContentNone->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxAllowedWaterContentNormal_stateChanged(int state)
+{
+	if(ui->checkBoxAllowedWaterContentNormal->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_checkBoxAllowedWaterContentIslands_stateChanged(int state)
+{
+	if(ui->checkBoxAllowedWaterContentIslands->hasFocus())
+		saveZoneMenuContent();
+}
+
+void TemplateEditor::on_pushButtonConnectionAdd_clicked()
+{
+	auto & connections = templates[selectedTemplate]->connections;
+	connections.push_back(rmg::ZoneConnection());
+	loadZoneConnectionMenuContent();
+}
+
+void TemplateEditor::on_pushButtonOpenTerrainTypes_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonOpenBannedTerrainTypes_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonAllowedTowns_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonBannedTowns_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonTownHints_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonAllowedMonsters_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonBannedMonsters_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonTreasure_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonMines_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}
+
+void TemplateEditor::on_pushButtonCustomObjects_clicked()
+{
+	//TODO: Implement dialog
+	QMessageBox::critical(this, tr("Error"), tr("Not implemented yet!"));
+}

+ 131 - 0
mapeditor/templateeditor/templateeditor.h

@@ -0,0 +1,131 @@
+/*
+ * templateeditor.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
+#include <QWidget>
+
+#include "templateview.h"
+
+#include "../StdInc.h"
+#include "../../lib/constants/EntityIdentifiers.h"
+#include "../../lib/GameConstants.h"
+
+class CRmgTemplate;
+class CardItem;
+class LineItem;
+class ZoneOptions;
+namespace rmg {
+class ZoneOptions;
+}
+
+namespace Ui {
+class TemplateEditor;
+}
+
+class TemplateEditor : public QWidget
+{
+	Q_OBJECT
+
+public:
+	explicit TemplateEditor();
+	~TemplateEditor();
+
+	static void showTemplateEditor();
+
+private slots:
+	void on_actionOpen_triggered();
+	void on_actionSave_as_triggered();
+	void on_actionNew_triggered();
+	void on_actionSave_triggered();
+	void on_actionAutoPosition_triggered();
+	void on_actionZoom_in_triggered();
+	void on_actionZoom_out_triggered();
+	void on_actionZoom_auto_triggered();
+	void on_actionZoom_reset_triggered();
+	void on_actionAddZone_triggered();
+	void on_actionRemoveZone_triggered();
+	void on_comboBoxTemplateSelection_activated(int index);
+	void on_pushButtonAddSubTemplate_clicked();
+	void on_pushButtonRemoveSubTemplate_clicked();
+	void on_pushButtonRenameSubTemplate_clicked();
+	void on_spinBoxZoneVisPosX_valueChanged();
+	void on_spinBoxZoneVisPosY_valueChanged();
+	void on_doubleSpinBoxZoneVisSize_valueChanged();
+	void on_comboBoxZoneType_currentTextChanged(const QString &text);
+	void on_comboBoxZoneOwner_currentTextChanged(const QString &text);
+	void on_spinBoxZoneSize_valueChanged();
+	void on_spinBoxTownCountPlayer_valueChanged();
+	void on_spinBoxCastleCountPlayer_valueChanged();
+	void on_spinBoxTownDensityPlayer_valueChanged();
+	void on_spinBoxCastleDensityPlayer_valueChanged();
+	void on_spinBoxTownCountNeutral_valueChanged();
+	void on_spinBoxCastleCountNeutral_valueChanged();
+	void on_spinBoxTownDensityNeutral_valueChanged();
+	void on_spinBoxCastleDensityNeutral_valueChanged();
+	void on_checkBoxMatchTerrainToTown_stateChanged(int state);
+	void on_checkBoxTownsAreSameType_stateChanged(int state);
+	void on_comboBoxMonsterStrength_currentTextChanged(const QString &text);
+	void on_spinBoxZoneId_valueChanged();
+	void on_spinBoxZoneLinkTowns_valueChanged();
+	void on_spinBoxZoneLinkMines_valueChanged();
+	void on_spinBoxZoneLinkTerrain_valueChanged();
+	void on_spinBoxZoneLinkTreasure_valueChanged();
+	void on_spinBoxZoneLinkCustomObjects_valueChanged();
+	void on_checkBoxZoneLinkTowns_stateChanged(int state);
+	void on_checkBoxZoneLinkMines_stateChanged(int state);
+	void on_checkBoxZoneLinkTerrain_stateChanged(int state);
+	void on_checkBoxZoneLinkTreasure_stateChanged(int state);
+	void on_checkBoxZoneLinkCustomObjects_stateChanged(int state);
+	void on_checkBoxAllowedWaterContentNone_stateChanged(int state);
+	void on_checkBoxAllowedWaterContentNormal_stateChanged(int state);
+	void on_checkBoxAllowedWaterContentIslands_stateChanged(int state);
+	void on_pushButtonConnectionAdd_clicked();
+	void on_pushButtonOpenTerrainTypes_clicked();
+	void on_pushButtonOpenBannedTerrainTypes_clicked();
+	void on_pushButtonAllowedTowns_clicked();
+	void on_pushButtonBannedTowns_clicked();
+	void on_pushButtonTownHints_clicked();
+	void on_pushButtonAllowedMonsters_clicked();
+	void on_pushButtonBannedMonsters_clicked();
+	void on_pushButtonTreasure_clicked();
+	void on_pushButtonMines_clicked();
+	void on_pushButtonCustomObjects_clicked();
+	
+private:
+	bool getAnswerAboutUnsavedChanges();
+	void setTitle();
+	void changed();
+	void saveTemplate();
+	void initContent();
+	void loadContent(bool autoPosition = false);
+	void saveContent();
+	void loadZoneMenuContent(bool onlyPosition = false);
+	void saveZoneMenuContent();
+	void loadZoneConnectionMenuContent();
+	void updateConnectionLines(bool recreate = false);
+	void autoPositionZones();
+	void updateZonePositions();
+	QString getZoneToolTip(std::shared_ptr<rmg::ZoneOptions> zone);
+	void updateZoneCards(TRmgTemplateZoneId id = -1);
+
+	void closeEvent(QCloseEvent *event) override;
+
+	Ui::TemplateEditor *ui;
+
+	std::unique_ptr<TemplateScene> templateScene;
+
+	QString filename;
+	bool unsaved = false;
+	std::map<std::string, std::shared_ptr<CRmgTemplate>> templates;
+	std::string selectedTemplate;
+	int selectedZone;
+
+	std::map<TRmgTemplateZoneId, CardItem *> cards;
+	std::vector<LineItem *> lines;
+};

+ 1393 - 0
mapeditor/templateeditor/templateeditor.ui

@@ -0,0 +1,1393 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TemplateEditor</class>
+ <widget class="QWidget" name="TemplateEditor">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1024</width>
+    <height>720</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>VCMI Template Editor</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QMenuBar" name="menubar">
+     <widget class="QMenu" name="menuFile">
+      <property name="title">
+       <string>File</string>
+      </property>
+      <addaction name="actionNew"/>
+      <addaction name="actionOpen"/>
+      <addaction name="actionSave"/>
+      <addaction name="actionSave_as"/>
+     </widget>
+     <widget class="QMenu" name="menuEdit">
+      <property name="title">
+       <string>Edit</string>
+      </property>
+      <addaction name="actionAddZone"/>
+      <addaction name="actionRemoveZone"/>
+      <addaction name="actionAutoPosition"/>
+     </widget>
+     <widget class="QMenu" name="menuView">
+      <property name="title">
+       <string>View</string>
+      </property>
+      <addaction name="actionZoom_in"/>
+      <addaction name="actionZoom_out"/>
+      <addaction name="actionZoom_auto"/>
+      <addaction name="actionZoom_reset"/>
+     </widget>
+     <addaction name="menuFile"/>
+     <addaction name="menuEdit"/>
+     <addaction name="menuView"/>
+    </widget>
+   </item>
+   <item>
+    <widget class="QToolBar" name="toolBar">
+     <property name="windowTitle">
+      <string>Toolbar</string>
+     </property>
+     <property name="bottomMargin" stdset="0">
+      <number>0</number>
+     </property>
+     <property name="topMargin" stdset="0">
+      <number>0</number>
+     </property>
+     <addaction name="actionNew"/>
+     <addaction name="actionOpen"/>
+     <addaction name="actionSave"/>
+     <addaction name="separator"/>
+     <addaction name="actionAddZone"/>
+     <addaction name="actionRemoveZone"/>
+     <addaction name="actionAutoPosition"/>
+     <addaction name="separator"/>
+     <addaction name="actionZoom_in"/>
+     <addaction name="actionZoom_out"/>
+     <addaction name="actionZoom_auto"/>
+     <addaction name="actionZoom_reset"/>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <spacer name="horizontalSpacer_8">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Minimum</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>10</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QLabel" name="labelTemplateSelection">
+       <property name="text">
+        <string>Selected Template:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QComboBox" name="comboBoxTemplateSelection">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>200</width>
+         <height>0</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pushButtonAddSubTemplate">
+       <property name="text">
+        <string>Add</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pushButtonRemoveSubTemplate">
+       <property name="text">
+        <string>Remove</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pushButtonRenameSubTemplate">
+       <property name="text">
+        <string>Rename</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_7">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="TemplateView" name="templateView">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+         <horstretch>12</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="mouseTracking">
+        <bool>true</bool>
+       </property>
+       <property name="sizeAdjustPolicy">
+        <enum>QAbstractScrollArea::AdjustToContents</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolBox" name="toolBox">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+         <horstretch>10</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>600</width>
+         <height>16777215</height>
+        </size>
+       </property>
+       <property name="currentIndex">
+        <number>1</number>
+       </property>
+       <widget class="QWidget" name="pageGeneral">
+        <property name="geometry">
+         <rect>
+          <x>0</x>
+          <y>-148</y>
+          <width>449</width>
+          <height>662</height>
+         </rect>
+        </property>
+        <attribute name="label">
+         <string>General</string>
+        </attribute>
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <item>
+          <widget class="QGroupBox" name="groupBoxName">
+           <property name="title">
+            <string>Name</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_5">
+            <item>
+             <widget class="QLineEdit" name="lineEditName"/>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxDescription">
+           <property name="title">
+            <string>Description</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_6">
+            <item>
+             <widget class="QLineEdit" name="lineEditDescription"/>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxMinSize">
+           <property name="title">
+            <string>Min Size</string>
+           </property>
+           <layout class="QHBoxLayout" name="horizontalLayout_9">
+            <item>
+             <spacer name="horizontalSpacer">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelMinSizeX">
+              <property name="text">
+               <string>X</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="spinBoxMinSizeX">
+              <property name="minimum">
+               <number>1</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_2">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelMinSizeY">
+              <property name="text">
+               <string>Y</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="spinBoxMinSizeY">
+              <property name="minimum">
+               <number>1</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_3">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelMinSizeZ">
+              <property name="text">
+               <string>Z</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="spinBoxMinSizeZ">
+              <property name="minimum">
+               <number>1</number>
+              </property>
+              <property name="maximum">
+               <number>2</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxMaxSize">
+           <property name="title">
+            <string>Max Size</string>
+           </property>
+           <layout class="QHBoxLayout" name="horizontalLayout_10">
+            <item>
+             <spacer name="horizontalSpacer_4">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelMaxSizeX">
+              <property name="text">
+               <string>X</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="spinBoxMaxSizeX">
+              <property name="minimum">
+               <number>1</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_5">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelMaxSizeY">
+              <property name="text">
+               <string>Y</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="spinBoxMaxSizeY">
+              <property name="minimum">
+               <number>1</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_6">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelMaxSizeZ">
+              <property name="text">
+               <string>Z</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="spinBoxMaxSizeZ">
+              <property name="minimum">
+               <number>1</number>
+              </property>
+              <property name="maximum">
+               <number>2</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxPlayers">
+           <property name="title">
+            <string>Players</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_20">
+            <item>
+             <widget class="QLabel" name="labelPlayers">
+              <property name="text">
+               <string>Players</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QTableWidget" name="tableWidgetPlayersPlayer"/>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelPlayersHuman">
+              <property name="text">
+               <string>Human</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QTableWidget" name="tableWidgetPlayersHuman"/>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxAllowedWaterContent">
+           <property name="title">
+            <string>Allowed water content</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_19">
+            <item>
+             <widget class="QCheckBox" name="checkBoxAllowedWaterContentNone">
+              <property name="text">
+               <string>None</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QCheckBox" name="checkBoxAllowedWaterContentNormal">
+              <property name="text">
+               <string>Normal</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QCheckBox" name="checkBoxAllowedWaterContentIslands">
+              <property name="text">
+               <string>Islands</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <spacer name="verticalSpacer">
+           <property name="orientation">
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>20</width>
+             <height>40</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </widget>
+       <widget class="QWidget" name="pageZone">
+        <property name="geometry">
+         <rect>
+          <x>0</x>
+          <y>-980</y>
+          <width>449</width>
+          <height>1494</height>
+         </rect>
+        </property>
+        <attribute name="label">
+         <string>Zone</string>
+        </attribute>
+        <layout class="QVBoxLayout" name="verticalLayout_3">
+         <item>
+          <widget class="QGroupBox" name="groupBoxVisualisation">
+           <property name="title">
+            <string>Visualisation</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_7">
+            <item>
+             <widget class="QLabel" name="labelZoneVisPos">
+              <property name="text">
+               <string>Position</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_4">
+              <property name="topMargin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="labelZoneVisPosX">
+                <property name="text">
+                 <string>X</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxZoneVisPosX">
+                <property name="minimum">
+                 <number>-9999</number>
+                </property>
+                <property name="maximum">
+                 <number>9999</number>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_13">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item>
+               <widget class="QLabel" name="labelZoneVisPosY">
+                <property name="text">
+                 <string>Y</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxZoneVisPosY">
+                <property name="minimum">
+                 <number>-9999</number>
+                </property>
+                <property name="maximum">
+                 <number>9999</number>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_14">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item>
+               <widget class="QLabel" name="labelZonePosVisSize">
+                <property name="text">
+                 <string>Size</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QDoubleSpinBox" name="doubleSpinBoxZoneVisSize">
+                <property name="decimals">
+                 <number>1</number>
+                </property>
+                <property name="minimum">
+                 <double>0.100000000000000</double>
+                </property>
+                <property name="maximum">
+                 <double>9.900000000000000</double>
+                </property>
+                <property name="singleStep">
+                 <double>0.100000000000000</double>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxId">
+           <property name="title">
+            <string>ID</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_8">
+            <item>
+             <widget class="QSpinBox" name="spinBoxZoneId">
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxType">
+           <property name="title">
+            <string>Type</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_9">
+            <item>
+             <widget class="QComboBox" name="comboBoxZoneType"/>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxSize">
+           <property name="title">
+            <string>Size</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_10">
+            <item>
+             <widget class="QSpinBox" name="spinBoxZoneSize">
+              <property name="maximum">
+               <number>99999</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxOwner">
+           <property name="title">
+            <string>Owner</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_11">
+            <item>
+             <widget class="QComboBox" name="comboBoxZoneOwner"/>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxZoneLink">
+           <property name="title">
+            <string>Zone link</string>
+           </property>
+           <layout class="QGridLayout" name="gridLayout">
+            <item row="3" column="0">
+             <widget class="QCheckBox" name="checkBoxZoneLinkMines">
+              <property name="text">
+               <string>Mines</string>
+              </property>
+             </widget>
+            </item>
+            <item row="6" column="0">
+             <widget class="QCheckBox" name="checkBoxZoneLinkCustomObjects">
+              <property name="text">
+               <string>Custom objects</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0">
+             <widget class="QCheckBox" name="checkBoxZoneLinkTowns">
+              <property name="text">
+               <string>Towns</string>
+              </property>
+             </widget>
+            </item>
+            <item row="4" column="0">
+             <widget class="QCheckBox" name="checkBoxZoneLinkTerrain">
+              <property name="text">
+               <string>Terrain</string>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="1">
+             <widget class="QSpinBox" name="spinBoxZoneLinkMines">
+              <property name="minimum">
+               <number>0</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item row="5" column="0">
+             <widget class="QCheckBox" name="checkBoxZoneLinkTreasure">
+              <property name="text">
+               <string>Treasure</string>
+              </property>
+             </widget>
+            </item>
+            <item row="4" column="1">
+             <widget class="QSpinBox" name="spinBoxZoneLinkTerrain">
+              <property name="minimum">
+               <number>0</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item row="5" column="1">
+             <widget class="QSpinBox" name="spinBoxZoneLinkTreasure">
+              <property name="minimum">
+               <number>0</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QSpinBox" name="spinBoxZoneLinkTowns">
+              <property name="minimum">
+               <number>0</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item row="6" column="1">
+             <widget class="QSpinBox" name="spinBoxZoneLinkCustomObjects">
+              <property name="minimum">
+               <number>0</number>
+              </property>
+              <property name="maximum">
+               <number>999</number>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="2">
+             <spacer name="horizontalSpacer_19">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxTownInfo">
+           <property name="title">
+            <string>Town info</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_12">
+            <item>
+             <widget class="QLabel" name="labelTownCount">
+              <property name="text">
+               <string>Town count</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_5">
+              <property name="topMargin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="labelTownCountPlayer">
+                <property name="text">
+                 <string>Player</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxTownCountPlayer"/>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_9">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>20</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item>
+               <widget class="QLabel" name="labelTownCountNeutral">
+                <property name="text">
+                 <string>Neutral</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxTownCountNeutral"/>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_15">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelCastleCount">
+              <property name="text">
+               <string>Castle count</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_6">
+              <property name="topMargin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="labelCastleCountPlayer">
+                <property name="text">
+                 <string>Player</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxCastleCountPlayer"/>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_10">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>20</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item>
+               <widget class="QLabel" name="labelCastleCountNeutral">
+                <property name="text">
+                 <string>Neutral</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxCastleCountNeutral"/>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_16">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelTownDensity">
+              <property name="text">
+               <string>Town density</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_7">
+              <property name="topMargin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="labelTownDensityPlayer">
+                <property name="text">
+                 <string>Player</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxTownDensityPlayer"/>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_11">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>20</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item>
+               <widget class="QLabel" name="labelTownDensityNeutral">
+                <property name="text">
+                 <string>Neutral</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxTownDensityNeutral"/>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_17">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelCastleDensity">
+              <property name="text">
+               <string>Castle density</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_8">
+              <property name="topMargin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="labelCastleDensityPlayer">
+                <property name="text">
+                 <string>Player</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxCastleDensityPlayer"/>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_12">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeType">
+                 <enum>QSizePolicy::Fixed</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>20</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item>
+               <widget class="QLabel" name="labelCastleDensityNeutral">
+                <property name="text">
+                 <string>Neutral</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QSpinBox" name="spinBoxCastleDensityNeutral"/>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_18">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxTerrain">
+           <property name="title">
+            <string>Terrain</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_13">
+            <item>
+             <widget class="QCheckBox" name="checkBoxMatchTerrainToTown">
+              <property name="text">
+               <string>Match terrain to town</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonOpenTerrainTypes">
+              <property name="text">
+               <string>Terrain types</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonOpenBannedTerrainTypes">
+              <property name="text">
+               <string>Banned terrain types</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxTowns">
+           <property name="title">
+            <string>Towns</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_14">
+            <item>
+             <widget class="QCheckBox" name="checkBoxTownsAreSameType">
+              <property name="text">
+               <string>Towns are same type</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonAllowedTowns">
+              <property name="text">
+               <string>Allowed towns</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonBannedTowns">
+              <property name="text">
+               <string>Banned towns</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonTownHints">
+              <property name="text">
+               <string>Town hints</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxMonsters">
+           <property name="title">
+            <string>Monsters</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_15">
+            <item>
+             <widget class="QPushButton" name="pushButtonAllowedMonsters">
+              <property name="text">
+               <string>Allowed monsters</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonBannedMonsters">
+              <property name="text">
+               <string>Banned monsters</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_11">
+              <property name="topMargin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="labelMonsterStrength">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+                <property name="text">
+                 <string>Strength</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="comboBoxMonsterStrength">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxTreasure">
+           <property name="title">
+            <string>Treasure</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_16">
+            <item>
+             <widget class="QPushButton" name="pushButtonTreasure">
+              <property name="text">
+               <string>Treasure</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxMines">
+           <property name="title">
+            <string>Mines</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_17">
+            <item>
+             <widget class="QPushButton" name="pushButtonMines">
+              <property name="text">
+               <string>Mines</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBoxObjects">
+           <property name="title">
+            <string>Objects</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_18">
+            <item>
+             <widget class="QPushButton" name="pushButtonCustomObjects">
+              <property name="text">
+               <string>Custom objects</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <spacer name="verticalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>20</width>
+             <height>526</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </widget>
+       <widget class="QWidget" name="pageConnections">
+        <property name="geometry">
+         <rect>
+          <x>0</x>
+          <y>0</y>
+          <width>462</width>
+          <height>514</height>
+         </rect>
+        </property>
+        <attribute name="label">
+         <string>Connections</string>
+        </attribute>
+        <layout class="QVBoxLayout" name="verticalLayout_4">
+         <item>
+          <widget class="QTableWidget" name="tableWidgetConnections"/>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" name="horizontalLayout_3">
+           <property name="topMargin">
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QPushButton" name="pushButtonConnectionAdd">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>1</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="text">
+              <string>Add</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </widget>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QStatusBar" name="statusbar"/>
+   </item>
+  </layout>
+  <action name="actionOpen">
+   <property name="text">
+    <string>Open</string>
+   </property>
+   <property name="shortcut">
+    <string notr="true">Ctrl+O</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>Save</string>
+   </property>
+   <property name="shortcut">
+    <string notr="true">Ctrl+S</string>
+   </property>
+  </action>
+  <action name="actionNew">
+   <property name="text">
+    <string>New</string>
+   </property>
+   <property name="shortcut">
+    <string notr="true">Ctrl+N</string>
+   </property>
+  </action>
+  <action name="actionSave_as">
+   <property name="text">
+    <string>Save as...</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+S</string>
+   </property>
+  </action>
+  <action name="actionAddZone">
+   <property name="text">
+    <string>Add zone</string>
+   </property>
+   <property name="shortcut">
+    <string>Z</string>
+   </property>
+  </action>
+  <action name="actionRemoveZone">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Remove zone</string>
+   </property>
+   <property name="shortcut">
+    <string>Del</string>
+   </property>
+  </action>
+  <action name="actionAutoPosition">
+   <property name="text">
+    <string>Auto position</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+P</string>
+   </property>
+  </action>
+  <action name="actionZoom_in">
+   <property name="text">
+    <string>Zoom in</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl++</string>
+   </property>
+  </action>
+  <action name="actionZoom_out">
+   <property name="text">
+    <string>Zoom out</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+-</string>
+   </property>
+  </action>
+  <action name="actionZoom_auto">
+   <property name="text">
+    <string>Zoom auto</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+:</string>
+   </property>
+  </action>
+  <action name="actionZoom_reset">
+   <property name="text">
+    <string>Zoom reset</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+=</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>TemplateView</class>
+   <extends>QGraphicsView</extends>
+   <header>templateeditor/templateview.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 60 - 0
mapeditor/templateeditor/templateview.cpp

@@ -0,0 +1,60 @@
+/*
+ * templateview.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 "templateview.h"
+
+TemplateScene::TemplateScene():
+	QGraphicsScene(nullptr)
+{
+}
+
+TemplateView::TemplateView(QWidget * parent):
+	QGraphicsView(parent)
+{
+}
+
+void TemplateView::setZoomLevel(int level)
+{
+	zoomlevel = level;
+
+	setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+	float scale = pow(1.1, zoomlevel);
+	QTransform matrix;
+	matrix.scale(scale, scale);
+	setTransform(matrix);
+}
+
+void TemplateView::changeZoomLevel(bool increase)
+{
+	if(increase)
+		zoomlevel++;
+	else
+		zoomlevel--;
+	
+	setZoomLevel(zoomlevel);
+}
+
+void TemplateView::autoFit()
+{
+	fitInView(scene()->itemsBoundingRect(), Qt::KeepAspectRatio);
+	
+	zoomlevel = log(transform().m11()) / log(1.1f);
+}
+
+void TemplateView::wheelEvent(QWheelEvent *e)
+{
+	if (e->angleDelta().y() > 0)
+		changeZoomLevel(true);
+	else
+		changeZoomLevel(false);
+
+	e->accept();
+}

+ 37 - 0
mapeditor/templateeditor/templateview.h

@@ -0,0 +1,37 @@
+/*
+ * templateview.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
+
+#include <QGraphicsView>
+#include <QGraphicsPixmapItem>
+
+class TemplateScene : public QGraphicsScene
+{
+	Q_OBJECT;
+public:
+	TemplateScene();
+};
+
+class TemplateView : public QGraphicsView
+{
+	Q_OBJECT
+
+	int zoomlevel = 0;
+
+public:
+	TemplateView(QWidget * parent);
+
+	void setZoomLevel(int level);
+	void changeZoomLevel(bool increase);
+	void autoFit();
+
+	void wheelEvent(QWheelEvent * e) override;
+};