Selaa lähdekoodia

small changes

meemknight 2 vuotta sitten
vanhempi
sitoutus
a0acedb959
44 muutettua tiedostoa jossa 1736 lisäystä ja 769 poistoa
  1. 6 3
      Pika/core/pikaRuntime/containerManager/containerManager.cpp
  2. 33 0
      Pika/core/pikaSTD/engineLibraresSupport/engineSafeSaveSupport.cpp
  3. 14 0
      Pika/core/pikaSTD/engineLibraresSupport/engineSafeSaveSupport.h
  4. 1 2
      Pika/core/sharedRuntime/baseContainer.h
  5. 224 36
      Pika/gameplay/containers/hollowknight/hollowknight.h
  6. 1 7
      Pika/gameplay/containers/mario/mario.h
  7. 1 6
      Pika/gameplay/containers/mario/marioEditor.h
  8. 1 1
      Pika/gameplay/containers/mario/marioNeuralTrainer.h
  9. 1 6
      Pika/gameplay/containers/mario/marioNeuralVizualizer.h
  10. 1 1
      Pika/gameplay/containers/minecraftDungeons/mcDungeonsEditor.h
  11. 1 2
      Pika/gameplay/containers/minecraftDungeons/mcDungeonsMenu.h
  12. 1 5
      Pika/gameplay/containers/minecraftDungeons/mcDungeonsgameplay.h
  13. 5 6
      Pika/gameplay/containers/pikaGameplay.h
  14. 2 2
      Pika/gameplay/dll/dllMain.cpp
  15. 38 25
      Pika/pluggins/pluggins/immageViewer.h
  16. BIN
      Pika/resources/hollowknight/Untitled_Artwork.jpg
  17. BIN
      Pika/resources/hollowknight/background.jpg
  18. BIN
      Pika/resources/hollowknight/block1.png
  19. BIN
      Pika/resources/hollowknight/block2.png
  20. BIN
      Pika/resources/hollowknight/block3.png
  21. BIN
      Pika/resources/hollowknight/block4.png
  22. BIN
      Pika/resources/hollowknight/bush.png
  23. BIN
      Pika/resources/hollowknight/grass.png
  24. BIN
      Pika/resources/hollowknight/grass2.png
  25. BIN
      Pika/resources/hollowknight/grass3.png
  26. BIN
      Pika/resources/hollowknight/inputMetrics.bin
  27. BIN
      Pika/resources/hollowknight/map1.bin
  28. BIN
      Pika/resources/hollowknight/map2.bin
  29. BIN
      Pika/resources/hollowknight/mushroom1.png
  30. BIN
      Pika/resources/hollowknight/mushroom2.png
  31. BIN
      Pika/resources/hollowknight/mushroom3.png
  32. BIN
      Pika/resources/hollowknight/mushroom4.png
  33. BIN
      Pika/resources/hollowknight/mushroom5.png
  34. BIN
      Pika/resources/hollowknight/mushroom6.png
  35. BIN
      Pika/resources/hollowknight/mushrooms.png
  36. BIN
      Pika/resources/hollowknight/vines1.png
  37. BIN
      Pika/resources/hollowknight/vines2.png
  38. BIN
      Pika/resources/hollowknight/vines3.png
  39. 2 2
      Pika/resources/logs.txt
  40. 1 0
      Pika/thirdparty/imgui-docking/CMakeLists.txt
  41. 668 0
      Pika/thirdparty/imgui-docking/imgui/imguiComboSearch.cpp
  42. 4 661
      Pika/thirdparty/imgui-docking/imgui/imguiComboSearch.h
  43. 116 2
      Pika/thirdparty/safeSafe/include/safeSave/safeSave.h
  44. 615 2
      Pika/thirdparty/safeSafe/src/safeSave.cpp

+ 6 - 3
Pika/core/pikaRuntime/containerManager/containerManager.cpp

@@ -466,7 +466,6 @@ void pika::ContainerManager::update(pika::LoadedDll &loadedDll, pika::PikaWindow
 					ImGui::PopID();
 					ImGui::PopID();
 				}
 				}
 
 
-
 				auto milliseconds = (std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1)).count()/1000.f;
 				auto milliseconds = (std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1)).count()/1000.f;
 
 
 				c.second.frameTimer += milliseconds;
 				c.second.frameTimer += milliseconds;
@@ -777,7 +776,7 @@ bool pika::ContainerManager::reloadDll(pika::LoadedDll &loadedDll, pika::PikaWin
 	return 1;
 	return 1;
 }
 }
 
 
-//not verbose flag
+//todo not verbose flag
 bool pika::ContainerManager::destroyContainer(containerId_t id, pika::LoadedDll &loadedDll,
 bool pika::ContainerManager::destroyContainer(containerId_t id, pika::LoadedDll &loadedDll,
 	pika::LogManager &logManager)
 	pika::LogManager &logManager)
 {
 {
@@ -794,7 +793,11 @@ bool pika::ContainerManager::destroyContainer(containerId_t id, pika::LoadedDll
 	auto name = c->second.baseContainerName;
 	auto name = c->second.baseContainerName;
 
 
 	loadedDll.bindAllocatorDllRealm(&c->second.allocator);
 	loadedDll.bindAllocatorDllRealm(&c->second.allocator);
-	c->second.pointer->destruct();
+
+	c->second.requestedContainerInfo.mainAllocator = &c->second.allocator; //reset this
+	c->second.requestedContainerInfo.bonusAllocators = &c->second.bonusAllocators;
+	c->second.pointer->destruct(c->second.requestedContainerInfo);
+
 	loadedDll.destructContainer_(&(c->second.pointer), &c->second.arena);
 	loadedDll.destructContainer_(&(c->second.pointer), &c->second.arena);
 	loadedDll.resetAllocatorDllRealm();
 	loadedDll.resetAllocatorDllRealm();
 
 

+ 33 - 0
Pika/core/pikaSTD/engineLibraresSupport/engineSafeSaveSupport.cpp

@@ -0,0 +1,33 @@
+#include "engineSafeSaveSupport.h"
+#include <globalAllocator/globalAllocator.h>
+
+namespace pika
+{
+	namespace sfs
+	{
+
+		::sfs::Errors safeLoad(::sfs::SafeSafeKeyValueData &data,
+			const char *nameWithoutExtension, bool reportLoadingBackupAsAnError)
+		{
+			data = {};
+
+			std::vector<char> readData;
+			readData.reserve(4000);
+
+			pika::memory::pushCustomAllocatorsToStandard();
+			auto errCode = ::sfs::safeLoad(readData, nameWithoutExtension, reportLoadingBackupAsAnError);
+			pika::memory::popCustomAllocatorsToStandard();
+
+			if (errCode == ::sfs::noError || errCode == ::sfs::readBackup)
+			{
+				return data.loadFromFileData(readData.data(), readData.size());
+			}
+			else
+			{
+				return errCode;
+			}
+
+		}
+
+	}
+}

+ 14 - 0
Pika/core/pikaSTD/engineLibraresSupport/engineSafeSaveSupport.h

@@ -0,0 +1,14 @@
+#pragma once
+
+#include <safeSave/safeSave.h>
+
+namespace pika
+{
+	namespace sfs
+	{
+		
+		::sfs::Errors safeLoad(::sfs::SafeSafeKeyValueData &data, 
+			const char *nameWithoutExtension, bool reportLoadingBackupAsAnError);
+
+	}
+}

+ 1 - 2
Pika/core/sharedRuntime/baseContainer.h

@@ -281,7 +281,6 @@ struct RequestedContainerInfo
 		bool success = true;
 		bool success = true;
 		size = 0;
 		size = 0;
 
 
-		//todo push pop allocator or use that pointer thing (and don't forget to only use explicit allocators calls or sthing)
 		pika::memory::pushCustomAllocatorsToStandard();
 		pika::memory::pushCustomAllocatorsToStandard();
 		{
 		{
 			std::ifstream f(name, std::ifstream::ate | std::ifstream::binary);
 			std::ifstream f(name, std::ifstream::ate | std::ifstream::binary);
@@ -397,7 +396,7 @@ struct Container
 		pika::WindowState windowState,
 		pika::WindowState windowState,
 		RequestedContainerInfo &requestedInfo) = 0;
 		RequestedContainerInfo &requestedInfo) = 0;
 
 
-	virtual void destruct() {};
+	virtual void destruct(RequestedContainerInfo &requestedInfo) {};
 
 
 	virtual ~Container() {};
 	virtual ~Container() {};
 
 

+ 224 - 36
Pika/gameplay/containers/hollowknight/hollowknight.h

@@ -9,6 +9,9 @@
 #include <box2d/box2d.h>
 #include <box2d/box2d.h>
 #include <engineLibraresSupport/engineGL2DSupport.h>
 #include <engineLibraresSupport/engineGL2DSupport.h>
 #include <pikaImgui/pikaImgui.h>
 #include <pikaImgui/pikaImgui.h>
+#include <safeSave/safeSave.h>
+#include <engineLibraresSupport/engineSafeSaveSupport.h>
+#include "imguiComboSearch.h"
 
 
 struct Holloknight: public Container
 struct Holloknight: public Container
 {
 {
@@ -19,10 +22,36 @@ struct Holloknight: public Container
 
 
 	b2World world{{0, 10}};
 	b2World world{{0, 10}};
 
 
+	constexpr static int ASSETS_COUNT = 18;
+
+	std::vector<const char*> assetsNames=
+	{
+		"bush.png",
+		"grass.png",
+		"mushroom1.png",
+		"mushroom2.png",
+		"mushroom3.png",
+		"mushroom4.png",
+		"mushroom5.png",
+		"mushroom6.png",
+		"vines1.png",
+		"vines2.png",
+		"vines3.png",
+		"background.jpg",
+		"grass2.png",
+		"grass3.png",
+		"block1.png",
+		"block2.png",
+		"block3.png",
+		"block4.png",
+	};
+
+	gl2d::Texture assets[ASSETS_COUNT];
+
 	static ContainerStaticInfo containerInfo()
 	static ContainerStaticInfo containerInfo()
 	{
 	{
 		ContainerStaticInfo info = {};
 		ContainerStaticInfo info = {};
-		info.defaultHeapMemorySize = pika::MB(10);
+		info.defaultHeapMemorySize = pika::MB(100);
 
 
 		info.requestImguiFbo = true; 
 		info.requestImguiFbo = true; 
 		info.pushAnImguiIdForMe = true;
 		info.pushAnImguiIdForMe = true;
@@ -86,17 +115,16 @@ struct Holloknight: public Container
 			return dynamicBody->GetAngle();
 			return dynamicBody->GetAngle();
 		}
 		}
 
 
-		void create(b2World &world, glm::vec4 dimensions, bool dynamic)
+		void create(b2World &world, glm::vec4 dimensions, float rotation, int type)
 		{
 		{
 			b2BodyDef myBodyDef;
 			b2BodyDef myBodyDef;
-			if (dynamic)
-				myBodyDef.type = b2_dynamicBody; //this will be a dynamic body
+			myBodyDef.type = (b2BodyType)type; //this will be a dynamic body
 
 
 			dimensions.x += dimensions.z / 2.f;
 			dimensions.x += dimensions.z / 2.f;
-			dimensions.y += dimensions.y / 2.f;
+			dimensions.y += dimensions.w / 2.f;
 
 
 			myBodyDef.position.Set(dimensions.x, dimensions.y); //set the starting position
 			myBodyDef.position.Set(dimensions.x, dimensions.y); //set the starting position
-			myBodyDef.angle = 0; //set the starting angle
+			myBodyDef.angle = rotation; //set the starting angle
 
 
 			dynamicBody = world.CreateBody(&myBodyDef);
 			dynamicBody = world.CreateBody(&myBodyDef);
 
 
@@ -147,6 +175,13 @@ struct Holloknight: public Container
 		}
 		}
 	};
 	};
 
 
+	struct SavedBlock
+	{
+		glm::vec4 dimensions = {};
+		float rotation = 0;
+		int type = 0;
+	};
+
 	struct Entity
 	struct Entity
 	{
 	{
 		Block physicalBody;
 		Block physicalBody;
@@ -165,9 +200,9 @@ struct Holloknight: public Container
 		}
 		}
 	};
 	};
 
 
-	Block floor;
 	Block blocks[10];
 	Block blocks[10];
 	b2Body *currentBodySelected = 0;
 	b2Body *currentBodySelected = 0;
+	int currentSelectedSprite = 0;
 
 
 	Entity character;
 	Entity character;
 	b2Fixture *characterJumpSensor;
 	b2Fixture *characterJumpSensor;
@@ -175,19 +210,34 @@ struct Holloknight: public Container
 	glm::vec2 draggedStart = {};
 	glm::vec2 draggedStart = {};
 
 
 	bool followPlayer = true;
 	bool followPlayer = true;
+	bool dragGeometry = false;
+	bool renderGeometry = true;
+	int selectType = 0;
 
 
 	struct InputMetrict
 	struct InputMetrict
 	{
 	{
 		float speed = 20;
 		float speed = 20;
-		float jump = 7;
+		float jump = 8;
 		float stopSpeed = 7;
 		float stopSpeed = 7;
-		float jumpTimer = 1.5;
-		float initialJumpImpulse = 1;
+		float jumpTimer = 1;
+		float initialJumpImpulse = 4;
 	} inputMetrics = {};
 	} inputMetrics = {};
 
 
-	bool create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
+	struct GameSprite
 	{
 	{
+		glm::vec2 pos = {};
+		float scale = 1;
+		int type = 0;
+		float rotation = 0;
+		bool flip = 0;
+		int layer = 0; //0 is background than 1 is objects than 2 is decoration than player than 3
+	};
 
 
+	std::vector<GameSprite> gameSprites;
+
+	bool create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
+	{
+		
 		renderer.create(requestedInfo.requestedFBO.fbo);
 		renderer.create(requestedInfo.requestedFBO.fbo);
 		renderer.currentCamera.zoom = 80.f;
 		renderer.currentCamera.zoom = 80.f;
 		renderer.currentCamera.position.x = -440;
 		renderer.currentCamera.position.x = -440;
@@ -199,20 +249,63 @@ struct Holloknight: public Container
 			inputMetrics = {};
 			inputMetrics = {};
 		}
 		}
 
 
+		for (int i = 0; i < ASSETS_COUNT; i++)
+		{
+			assets[i]
+				= pika::gl2d::loadTexture
+				((std::string(PIKA_RESOURCES_PATH "hollowknight/") + std::string(assetsNames[i])).c_str()
+				, requestedInfo);
+		}
+
+
+
 		sprites = pika::gl2d::loadTextureWithPixelPadding(PIKA_RESOURCES_PATH "hollowknight/sprites.png", requestedInfo, 80);
 		sprites = pika::gl2d::loadTextureWithPixelPadding(PIKA_RESOURCES_PATH "hollowknight/sprites.png", requestedInfo, 80);
 		atlas = gl2d::TextureAtlasPadding(12, 12, sprites.GetSize().x, sprites.GetSize().y);
 		atlas = gl2d::TextureAtlasPadding(12, 12, sprites.GetSize().x, sprites.GetSize().y);
 
 
 		world.SetAllowSleeping(true);
 		world.SetAllowSleeping(true);
 		world.SetContinuousPhysics(true);
 		world.SetContinuousPhysics(true);
 
 
-		floor.create(world, {-50, 10, 100, 1}, false);
-		
-		for (int i = 0; i < 10; i++) 
 		{
 		{
-			blocks[i].create(world, {1+ sin(i)*5, -1.5*i, 1,1}, true);
+			sfs::SafeSafeKeyValueData data;
+
+			pika::sfs::safeLoad(data, PIKA_RESOURCES_PATH "hollowknight/map", false);
+
+			void *geometry = 0;
+			size_t s = 0;
+			if (data.getRawDataPointer("geometry", geometry, s) == sfs::noError)
+			{
+				SavedBlock *b = (SavedBlock*)geometry;
+
+				for (int i = 0; i < s / sizeof(SavedBlock); i++)
+				{
+					blocks[i].create(world, b[i].dimensions, b[i].rotation, b[i].type);
+				}
+			}
+			else
+			{
+				requestedInfo.log("Error reading map file", pika::logError);
+			}
+
+			void *loadedSprites = 0;
+			s = 0;
+			if (data.getRawDataPointer("sprites", loadedSprites, s) == sfs::noError)
+			{
+				GameSprite *loagedGameSprites = (GameSprite *)loadedSprites;
+
+				for (int i = 0; i < s / sizeof(SavedBlock); i++)
+				{
+					gameSprites.push_back(loagedGameSprites[i]);
+				}
+			}
+
 		}
 		}
 
 
-		character.physicalBody.create(world, {10, 2, 0.6f,1}, true);
+		//for (int i = 0; i < 10; i++)
+		//{
+		//	blocks[i].create(world, {1 + sin(i) * 5, -1.5 * i, 1,1}, 0, b2BodyType::b2_dynamicBody);
+		//}
+
+		character.physicalBody.create(world, {10, 2, 0.6f,1}, 0, b2BodyType::b2_dynamicBody);
 		character.spriteDimensions = glm::vec4{0,0,1,1};
 		character.spriteDimensions = glm::vec4{0,0,1,1};
 		character.physicalBody.dynamicBody->SetFixedRotation(true);
 		character.physicalBody.dynamicBody->SetFixedRotation(true);
 		characterJumpSensor = character.physicalBody.addSensor({0, 0.5, 0.55f, 0.1f});
 		characterJumpSensor = character.physicalBody.addSensor({0, 0.5, 0.55f, 0.1f});
@@ -220,6 +313,8 @@ struct Holloknight: public Container
 		return true;
 		return true;
 	}
 	}
 
 
+	bool movingLeft = 0;
+
 	bool update(pika::Input input, pika::WindowState windowState,
 	bool update(pika::Input input, pika::WindowState windowState,
 		RequestedContainerInfo &requestedInfo)
 		RequestedContainerInfo &requestedInfo)
 	{
 	{
@@ -233,16 +328,17 @@ struct Holloknight: public Container
 		::pika::gl2d::cameraController(renderer.currentCamera, input, 60 * (!followPlayer), 4);
 		::pika::gl2d::cameraController(renderer.currentCamera, input, 60 * (!followPlayer), 4);
 
 
 		int direction = 0;
 		int direction = 0;
+		
 
 
 		if (input.buttons[pika::Button::Left].held() 
 		if (input.buttons[pika::Button::Left].held() 
 			|| input.anyController.buttons[pika::Controller::Left].held() 
 			|| input.anyController.buttons[pika::Controller::Left].held() 
 			|| input.anyController.LStick.left()
 			|| input.anyController.LStick.left()
-			) { direction--; }
+			) { direction--; movingLeft = true; }
 
 
 		if (input.buttons[pika::Button::Right].held() 
 		if (input.buttons[pika::Button::Right].held() 
 			|| input.anyController.buttons[pika::Controller::Right].held()
 			|| input.anyController.buttons[pika::Controller::Right].held()
 			|| input.anyController.LStick.right()
 			|| input.anyController.LStick.right()
-			) { direction++; }
+			) { direction++; movingLeft = false; }
 
 
 		{
 		{
 			b2Vec2 vel = character.physicalBody.dynamicBody->GetLinearVelocity();
 			b2Vec2 vel = character.physicalBody.dynamicBody->GetLinearVelocity();
@@ -340,26 +436,42 @@ struct Holloknight: public Container
 		}
 		}
 	#pragma endregion
 	#pragma endregion
 
 
+	#pragma region render
 
 
-		floor.render(renderer, Colors_White);
-
-		for (int i = 0; i < 10; i++)
+		for (int i = 0; i < 4; i++)
 		{
 		{
-			if (blocks[i].dynamicBody->GetType() == b2_dynamicBody)
+			//player
+			if (i == 3)
 			{
 			{
-				blocks[i].render(renderer, Colors_Orange);
+				renderer.renderRectangle(character.getRenderPos(), sprites, Colors_White, {}, 0, 
+					atlas.get(0, 0, movingLeft));
 			}
 			}
-			else if (blocks[i].dynamicBody->GetType() == b2_kinematicBody)
-			{
-				blocks[i].render(renderer, {0.5,0.7,0.1,1});
-			}
-			else
+
+			int index = 0;
+			for (auto &s : gameSprites)
 			{
 			{
-				blocks[i].render(renderer, Colors_White);
+				if (s.layer == i)
+				{
+
+					if (currentSelectedSprite == index && selectType == 2)
+					{
+						renderer.renderRectangle({s.pos, glm::vec2(assets[s.type].GetSize()) * s.scale * (1.f / 400.f)},
+							assets[s.type], {1,0.5,0.5,1.0}, {}, s.rotation, s.flip ? glm::vec4(1, 1, 0, 0) : glm::vec4(0, 1, 1, 0));
+					}
+					else
+					{
+						renderer.renderRectangle({s.pos, glm::vec2(assets[s.type].GetSize()) * s.scale * (1.f / 400.f)},
+							assets[s.type], Colors_White, {}, s.rotation, s.flip ? glm::vec4(1, 1, 0, 0) : glm::vec4(0, 1, 1, 0));
+					}
+				}
+
+				index++;
 			}
 			}
 		}
 		}
 
 
-		renderer.renderRectangle(character.getRenderPos(), sprites, Colors_White, {}, 0, atlas.get(0, 0));
+
+	#pragma endregion
+
 
 
 		glm::vec2 mouseWorldpos(input.mouseX, input.mouseY);
 		glm::vec2 mouseWorldpos(input.mouseX, input.mouseY);
 		{
 		{
@@ -372,13 +484,14 @@ struct Holloknight: public Container
 
 
 	#pragma region body render
 	#pragma region body render
 
 
+		if(renderGeometry)
 		for (b2Body *b = world.GetBodyList(); b; b = b->GetNext())
 		for (b2Body *b = world.GetBodyList(); b; b = b->GetNext())
 		{
 		{
 
 
 			glm::vec4 color = Colors_Red;
 			glm::vec4 color = Colors_Red;
 			float thickness = 0.01;
 			float thickness = 0.01;
 
 
-			if (currentBodySelected == b) 
+			if (currentBodySelected == b && selectType == 1)
 			{
 			{
 				color = Colors_Blue;
 				color = Colors_Blue;
 				thickness = 0.02;
 				thickness = 0.02;
@@ -395,7 +508,9 @@ struct Holloknight: public Container
 			{
 			{
 				auto shape = f->GetShape();
 				auto shape = f->GetShape();
 
 
-				if (shape->TestPoint(shapePos, {mouseWorldpos.x,mouseWorldpos.y}) && input.lMouse.held())
+				if (shape->TestPoint(shapePos, {mouseWorldpos.x,mouseWorldpos.y}) && input.lMouse.held()
+					&& selectType == 1
+					)
 				{
 				{
 					currentBodySelected = b;
 					currentBodySelected = b;
 				}
 				}
@@ -442,6 +557,7 @@ struct Holloknight: public Container
 
 
 	#pragma region drag
 	#pragma region drag
 
 
+		if(dragGeometry)
 		{
 		{
 
 
 			if (input.rMouse.pressed())
 			if (input.rMouse.pressed())
@@ -465,7 +581,6 @@ struct Holloknight: public Container
 			
 			
 		}
 		}
 
 
-
 	#pragma endregion
 	#pragma endregion
 
 
 
 
@@ -479,6 +594,10 @@ struct Holloknight: public Container
 			ImGui::DragFloat("Camera zoom", &renderer.currentCamera.zoom, 0.5, 10, 1000);
 			ImGui::DragFloat("Camera zoom", &renderer.currentCamera.zoom, 0.5, 10, 1000);
 		
 		
 			ImGui::Checkbox("Follow player", &followPlayer);
 			ImGui::Checkbox("Follow player", &followPlayer);
+			ImGui::Checkbox("Drag geometry", &dragGeometry);
+			ImGui::Checkbox("Render geometry", &renderGeometry);
+
+			ImGui::Combo("Editor type: ", &selectType, "none\0geometry\0sprites\0");
 
 
 			ImGui::Separator();
 			ImGui::Separator();
 
 
@@ -503,12 +622,12 @@ struct Holloknight: public Container
 
 
 			ImGui::PopStyleColor();
 			ImGui::PopStyleColor();
 
 
-
+			if(selectType == 1)
 			if (currentBodySelected)
 			if (currentBodySelected)
 			{
 			{
 				ImGui::NewLine();
 				ImGui::NewLine();
 				ImGui::Separator();
 				ImGui::Separator();
-				ImGui::Text("World editor");
+				ImGui::Text("Geometry editor");
 				ImGui::NewLine();
 				ImGui::NewLine();
 
 
 
 
@@ -582,6 +701,75 @@ struct Holloknight: public Container
 
 
 			}
 			}
 
 
+			if (selectType == 2)
+			{
+				ImGui::NewLine();
+				ImGui::Separator();
+				ImGui::Text("Sprites editor");
+				ImGui::NewLine();
+
+				if (ImGui::Button("Add sprite"))
+				{
+					gameSprites.push_back({});
+					currentSelectedSprite = gameSprites.size() - 1;
+				}
+				
+				ImGui::InputInt("Sprite", &currentSelectedSprite);
+
+				currentSelectedSprite = glm::clamp(currentSelectedSprite, 0, (int)gameSprites.size() - 1);
+
+				if (gameSprites.size())
+				{
+
+					auto &s = gameSprites[currentSelectedSprite];
+
+					ImGui::ComboWithFilter("Type", &s.type, assetsNames);
+					s.type = glm::clamp(s.type, 0, ASSETS_COUNT);
+
+					ImGui::Combo("Layer: ", &s.layer, "background\0geometry\0geometry2\0on top of player\0");
+
+					ImGui::DragFloat2("Pos", &s.pos[0], 0.01);
+
+					ImGui::Checkbox("Flip", &s.flip);
+
+					ImGui::SliderAngle("Angle", &s.rotation);
+
+					ImGui::DragFloat("Scale", &s.scale, 0.01, 0.001, 100);
+
+
+				}
+
+			}
+
+
+			ImGui::NewLine();
+			ImGui::Separator();
+
+			if (ImGui::Button("Save map"))
+			{
+				SavedBlock b[10];
+
+				for (int i = 0; i < 10; i++)
+				{
+					b[i].dimensions = glm::vec4(blocks[i].getPosTopLeft(), blocks[i].getSize());
+					b[i].rotation = blocks[i].getRotation();
+					b[i].type = blocks[i].dynamicBody->GetType();
+				}
+
+				sfs::SafeSafeKeyValueData data;
+
+				data.setRawData("geometry", b, sizeof(b));
+
+				data.setRawData("sprites", gameSprites.data(), sizeof(GameSprite) *gameSprites.size());
+
+
+				pika::memory::pushCustomAllocatorsToStandard();
+				sfs::safeSave(data, PIKA_RESOURCES_PATH "hollowknight/map", false);
+				pika::memory::popCustomAllocatorsToStandard();
+
+			}
+
+
 			ImGui::End();
 			ImGui::End();
 		}
 		}
 
 
@@ -596,7 +784,7 @@ struct Holloknight: public Container
 	}
 	}
 
 
 	//optional
 	//optional
-	void destruct()
+	void destruct(RequestedContainerInfo &requestedInfo)
 	{
 	{
 	}
 	}
 
 

+ 1 - 7
Pika/gameplay/containers/mario/mario.h

@@ -24,8 +24,6 @@ struct Mario: public Container
 	pika::FileChanged vertexChanged;
 	pika::FileChanged vertexChanged;
 	pika::FileChanged fragmentChanged;
 	pika::FileChanged fragmentChanged;
 
 
-
-	//todo user can request imgui ids; shortcut manager context; allocators
 	static ContainerStaticInfo containerInfo()
 	static ContainerStaticInfo containerInfo()
 	{
 	{
 		ContainerStaticInfo info = {};
 		ContainerStaticInfo info = {};
@@ -148,7 +146,7 @@ struct Mario: public Container
 		return true;
 		return true;
 	}
 	}
 
 
-	void destruct() override
+	void destruct(RequestedContainerInfo &requestedInfo) override
 	{
 	{
 		renderer.cleanup();
 		renderer.cleanup();
 		simulator.cleanup();
 		simulator.cleanup();
@@ -157,7 +155,3 @@ struct Mario: public Container
 	}
 	}
 
 
 };
 };
-
-//todo flag to clear screen from engine
-//todo error popup
-//todo error popup disable in release

+ 1 - 6
Pika/gameplay/containers/mario/marioEditor.h

@@ -34,7 +34,6 @@ struct MarioEditor: public Container
 		return map[x + y * mapSize.x];
 		return map[x + y * mapSize.x];
 	}
 	}
 
 
-	//todo user can request imgui ids; shortcut manager context; allocators
 	static ContainerStaticInfo containerInfo()
 	static ContainerStaticInfo containerInfo()
 	{
 	{
 		ContainerStaticInfo info = {};
 		ContainerStaticInfo info = {};
@@ -345,7 +344,7 @@ struct MarioEditor: public Container
 		return true;
 		return true;
 	}
 	}
 
 
-	void destruct() override
+	void destruct(RequestedContainerInfo &requestedInfo) override
 	{
 	{
 		tiles.cleanup();
 		tiles.cleanup();
 		renderer.cleanup();
 		renderer.cleanup();
@@ -353,7 +352,3 @@ struct MarioEditor: public Container
 	}
 	}
 
 
 };
 };
-
-//todo flag to clear screen from engine
-//todo error popup
-//todo error popup disable in release

+ 1 - 1
Pika/gameplay/containers/mario/marioNeuralTrainer.h

@@ -269,7 +269,7 @@ struct MarioNeuralTrainer: public Container
 		return true;
 		return true;
 	}
 	}
 
 
-	void destruct() override
+	void destruct(RequestedContainerInfo &requestedInfo) override
 	{
 	{
 		renderer.cleanup();
 		renderer.cleanup();
 		simulator.cleanup();
 		simulator.cleanup();

+ 1 - 6
Pika/gameplay/containers/mario/marioNeuralVizualizer.h

@@ -21,7 +21,6 @@ struct MarioNeuralVizualizer: public Container
 
 
 	bool fixedFramerate = 0;
 	bool fixedFramerate = 0;
 
 
-	//todo user can request imgui ids; shortcut manager context; allocators
 	static ContainerStaticInfo containerInfo()
 	static ContainerStaticInfo containerInfo()
 	{
 	{
 		ContainerStaticInfo info = {};
 		ContainerStaticInfo info = {};
@@ -121,13 +120,9 @@ struct MarioNeuralVizualizer: public Container
 		return true;
 		return true;
 	}
 	}
 
 
-	void destruct() override
+	void destruct(RequestedContainerInfo &requestedInfo) override
 	{
 	{
 		renderer.cleanup();
 		renderer.cleanup();
 		simulator.cleanup();
 		simulator.cleanup();
 	}
 	}
 };
 };
-
-//todo flag to clear screen from engine
-//todo error popup
-//todo error popup disable in release

+ 1 - 1
Pika/gameplay/containers/minecraftDungeons/mcDungeonsEditor.h

@@ -673,7 +673,7 @@ struct McDungeonsEditor: public Container
 		return true;
 		return true;
 	}
 	}
 
 
-	void destruct()
+	void destruct(RequestedContainerInfo &requestedInfo)
 	{
 	{
 
 
 		this->renderer.skyBox.clearTextures();
 		this->renderer.skyBox.clearTextures();

+ 1 - 2
Pika/gameplay/containers/minecraftDungeons/mcDungeonsMenu.h

@@ -18,7 +18,6 @@ struct McDungeonsMenu : public Container
 	gl2d::Texture button;
 	gl2d::Texture button;
 	glui::RendererUi ui;
 	glui::RendererUi ui;
 
 
-	//todo user can request imgui ids; shortcut manager context; allocators
 	static ContainerStaticInfo containerInfo()
 	static ContainerStaticInfo containerInfo()
 	{
 	{
 		ContainerStaticInfo info = {};
 		ContainerStaticInfo info = {};
@@ -92,7 +91,7 @@ struct McDungeonsMenu : public Container
 		return true;
 		return true;
 	}
 	}
 
 
-	void destruct()
+	void destruct(RequestedContainerInfo &requestedInfo)
 	{
 	{
 
 
 		renderer.cleanup();
 		renderer.cleanup();

+ 1 - 5
Pika/gameplay/containers/minecraftDungeons/mcDungeonsgameplay.h

@@ -1072,7 +1072,7 @@ struct McDungeonsGameplay: public Container
 		return true;
 		return true;
 	}
 	}
 
 
-	void destruct()
+	void destruct(RequestedContainerInfo &requestedInfo)
 	{
 	{
 
 
 		this->renderer.skyBox.clearTextures();
 		this->renderer.skyBox.clearTextures();
@@ -1084,7 +1084,3 @@ struct McDungeonsGameplay: public Container
 
 
 
 
 };
 };
-
-//todo flag to clear screen from engine
-//todo error popup
-//todo error popup disable in release

+ 5 - 6
Pika/gameplay/containers/pikaGameplay.h

@@ -64,10 +64,10 @@ struct Gameplay : public Container
 
 
 		glClear(GL_COLOR_BUFFER_BIT);
 		glClear(GL_COLOR_BUFFER_BIT);
 
 
-		//if (pika::shortcut(input, "Ctrl + S"))
-		//{
-		//	requestedInfo.consoleWrite("save\n");
-		//}
+		if (pika::shortcut(input, "Ctrl + S"))
+		{
+			requestedInfo.consoleWrite("save\n");
+		}
 		
 		
 		//if (input.buttons[pika::Button::S].released())
 		//if (input.buttons[pika::Button::S].released())
 		//{
 		//{
@@ -82,7 +82,6 @@ struct Gameplay : public Container
 		requestedInfo.consoleWrite(input.typedInput);
 		requestedInfo.consoleWrite(input.typedInput);
 
 
 
 
-
 		if (input.buttons[pika::Button::P].held())
 		if (input.buttons[pika::Button::P].held())
 		{
 		{
 			requestedInfo.consoleWrite(std::to_string(input.deltaTime).c_str());
 			requestedInfo.consoleWrite(std::to_string(input.deltaTime).c_str());
@@ -149,7 +148,7 @@ struct Gameplay : public Container
 	}
 	}
 
 
 	//optional
 	//optional
-	void destruct()
+	void destruct(RequestedContainerInfo &requestedInfo)
 	{
 	{
 
 
 	}
 	}

+ 2 - 2
Pika/gameplay/dll/dllMain.cpp

@@ -74,7 +74,7 @@ void gl2dErrorFunc(const char *msg, void* userData) //todo
 PIKA_API void gameplayStart(pika::PikaContext &pikaContext, pika::LogManager &logs)
 PIKA_API void gameplayStart(pika::PikaContext &pikaContext, pika::LogManager &logs)
 {
 {
 	pika::pikaImgui::setImguiAllocator(pikaContext.imguiAllocator);
 	pika::pikaImgui::setImguiAllocator(pikaContext.imguiAllocator);
-	//pika::initShortcutApi(); //todo
+	pika::initShortcutApi(); //todo
 
 
 	//todo user should have functions to specify this
 	//todo user should have functions to specify this
 #pragma region init stuff
 #pragma region init stuff
@@ -97,7 +97,7 @@ PIKA_API void gameplayReload(pika::PikaContext &pikaContext, pika::LogManager &l
 #ifdef PIKA_DEVELOPMENT	
 #ifdef PIKA_DEVELOPMENT	
 
 
 	pika::pikaImgui::setImguiAllocator(pikaContext.imguiAllocator); //todo check if really needed
 	pika::pikaImgui::setImguiAllocator(pikaContext.imguiAllocator); //todo check if really needed
-	//pika::initShortcutApi();
+	pika::initShortcutApi();
 
 
 
 
 	PIKA_PERMA_ASSERT(gladLoadGL(), "Problem initializing glad from dll");
 	PIKA_PERMA_ASSERT(gladLoadGL(), "Problem initializing glad from dll");

+ 38 - 25
Pika/pluggins/pluggins/immageViewer.h

@@ -16,18 +16,19 @@ struct ImmageViewer: public Container
 	gl2d::Texture texture;
 	gl2d::Texture texture;
 	float zoom = 1.f;
 	float zoom = 1.f;
 	glm::ivec2 immageSize;
 	glm::ivec2 immageSize;
+	bool uvEditor = 0;
+	glm::vec4 uv = {0,1,1,0};
 
 
 	static ContainerStaticInfo containerInfo()
 	static ContainerStaticInfo containerInfo()
 	{
 	{
 		ContainerStaticInfo info = {};
 		ContainerStaticInfo info = {};
-		info.defaultHeapMemorySize = pika::MB(30);
+		info.defaultHeapMemorySize = pika::MB(10);
 
 
 		//todo to lower
 		//todo to lower
 		info.extensionsSuported = {".png", ".bmp", ".psd", ".tga", ".gif", ".hdr", ".pic", ".ppm", ".pgm", ".jpg", ".jpeg"};
 		info.extensionsSuported = {".png", ".bmp", ".psd", ".tga", ".gif", ".hdr", ".pic", ".ppm", ".pgm", ".jpg", ".jpeg"};
 
 
 		info.requestImguiIds = 1;
 		info.requestImguiIds = 1;
 
 
-
 		return info;
 		return info;
 	}
 	}
 
 
@@ -47,26 +48,10 @@ struct ImmageViewer: public Container
 		}
 		}
 		pika::memory::setGlobalAllocator(requestedInfo.mainAllocator);
 		pika::memory::setGlobalAllocator(requestedInfo.mainAllocator);
 
 
-		//size_t size = 0;
-		//if (!requestedInfo.getFileSizeBinary(file.c_str(), size))
-		//{
-		//	return 0; //todo
-		//}
-		//
-		//unsigned char *buffer = new unsigned char[size];
-		//
-		//if (!requestedInfo.readEntireFileBinary(file.c_str(), buffer, size))
-		//{
-		//	delete[] buffer;
-		//	return 0; //todo
-		//}
-		
-		//texture.createFromFileData(buffer, size, true, true);
 		
 		
 		immageSize = texture.GetSize();
 		immageSize = texture.GetSize();
 		if (immageSize == glm::ivec2{0, 0}) { return 0; }
 		if (immageSize == glm::ivec2{0, 0}) { return 0; }
 
 
-		//delete[] buffer;
 
 
 		return true;
 		return true;
 	}
 	}
@@ -103,6 +88,8 @@ struct ImmageViewer: public Container
 
 
 
 
 		ImGui::Text("%s; %d, %d",file.c_str(), immageSize.x, immageSize.y);
 		ImGui::Text("%s; %d, %d",file.c_str(), immageSize.x, immageSize.y);
+		ImGui::Checkbox("UV editor", &uvEditor);
+
 
 
 		auto s = ImGui::GetContentRegionMax();
 		auto s = ImGui::GetContentRegionMax();
 		
 		
@@ -121,26 +108,52 @@ struct ImmageViewer: public Container
 		zoom = std::min(zoom, 10.f);
 		zoom = std::min(zoom, 10.f);
 		zoom = std::max(zoom, 0.2f);
 		zoom = std::max(zoom, 0.2f);
 
 
-		if (ImGui::BeginChild(6996, {}, false, ImGuiWindowFlags_HorizontalScrollbar))
+		if (uvEditor)
 		{
 		{
+			
+			ImGui::Separator();
+
+			if (ImGui::BeginChild(6996, {}, false, ImGuiWindowFlags_HorizontalScrollbar))
+			{
+
+				float xsize = std::max((int)(s.x * zoom) - 10, (int)(100 * zoom));
+				float aspect = 1.f; //todo
 
 
-			float xsize = std::max((int)(s.x*zoom) - 10, (int)(100*zoom));
-			float aspect = 1.f; //todo
+				ImGui::DragFloat4("UV", &uv[0], 0.01, 0.f, 1.f);
 
 
-			ImGui::Image((void *)texture.id, {xsize,xsize / aspect},
-				{0, 1}, {1, 0});
+				ImGui::Image((void *)texture.id, {xsize,xsize / aspect},
+					{uv.x, uv.y}, {uv.z, uv.w}, {1,1,1,1}, {0.2,0.2,0.2,0.9});
+
+				ImGui::EndChild();
+			}
 
 
-			ImGui::EndChild();
 		}
 		}
+		else
+		{
+			ImGui::Separator();
+
+			if (ImGui::BeginChild(6996, {}, false, ImGuiWindowFlags_HorizontalScrollbar))
+			{
+
+				float xsize = std::max((int)(s.x * zoom) - 10, (int)(100 * zoom));
+				float aspect = 1.f; //todo
 
 
+				ImGui::Image((void *)texture.id, {xsize,xsize / aspect},
+					{0, 1}, {1, 0}, {1,1,1,1}, {0.2,0.2,0.2,0.9});
+
+				ImGui::EndChild();
+			}
+		}
+		
 
 
+	
 		ImGui::End();
 		ImGui::End();
 		ImGui::PopID();
 		ImGui::PopID();
 
 
 		return true;
 		return true;
 	}
 	}
 
 
-	void destruct() override
+	void destruct(RequestedContainerInfo &requestedInfo) override
 	{
 	{
 		texture.cleanup();
 		texture.cleanup();
 	}
 	}

BIN
Pika/resources/hollowknight/Untitled_Artwork.jpg


BIN
Pika/resources/hollowknight/background.jpg


BIN
Pika/resources/hollowknight/block1.png


BIN
Pika/resources/hollowknight/block2.png


BIN
Pika/resources/hollowknight/block3.png


BIN
Pika/resources/hollowknight/block4.png


BIN
Pika/resources/hollowknight/bush.png


BIN
Pika/resources/hollowknight/grass.png


BIN
Pika/resources/hollowknight/grass2.png


BIN
Pika/resources/hollowknight/grass3.png


BIN
Pika/resources/hollowknight/inputMetrics.bin


BIN
Pika/resources/hollowknight/map1.bin


BIN
Pika/resources/hollowknight/map2.bin


BIN
Pika/resources/hollowknight/mushroom1.png


BIN
Pika/resources/hollowknight/mushroom2.png


BIN
Pika/resources/hollowknight/mushroom3.png


BIN
Pika/resources/hollowknight/mushroom4.png


BIN
Pika/resources/hollowknight/mushroom5.png


BIN
Pika/resources/hollowknight/mushroom6.png


BIN
Pika/resources/hollowknight/mushrooms.png


BIN
Pika/resources/hollowknight/vines1.png


BIN
Pika/resources/hollowknight/vines2.png


BIN
Pika/resources/hollowknight/vines3.png


+ 2 - 2
Pika/resources/logs.txt

@@ -1,2 +1,2 @@
-#2023-07-14 18:32:01: Created container: Holloknight
-#2023-07-14 18:41:00: Destroyed continer: Holloknight #1
+#2023-07-21 11:48:34: Created container: Gameplay
+#2023-07-21 11:48:39: Destroyed continer: Gameplay #1

+ 1 - 0
Pika/thirdparty/imgui-docking/CMakeLists.txt

@@ -8,6 +8,7 @@ target_sources(imgui PRIVATE
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_draw.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_draw.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_tables.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_tables.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_widgets.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_widgets.cpp"
+"${CMAKE_CURRENT_SOURCE_DIR}/imgui/imguiComboSearch.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/TextEditor.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/TextEditor.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_glfw.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_glfw.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_opengl3.cpp"
 "${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_opengl3.cpp"

+ 668 - 0
Pika/thirdparty/imgui-docking/imgui/imguiComboSearch.cpp

@@ -0,0 +1,668 @@
+#include "imgui_internal.h"
+#include "imguiComboSearch.h"
+
+
+namespace ImGui
+{
+
+    // https://github.com/forrestthewoods/lib_fts
+
+// Forward declarations for "private" implementation
+    namespace fuzzy_internal
+    {
+        static bool fuzzy_match_recursive(const char *pattern, const char *str, int &outScore, const char *strBegin,
+            uint8_t const *srcMatches, uint8_t *newMatches, int maxMatches, int nextMatch,
+            int &recursionCount, int recursionLimit);
+    }
+    // Private implementation
+    static bool fuzzy_internal::fuzzy_match_recursive(const char *pattern, const char *str, int &outScore,
+        const char *strBegin, uint8_t const *srcMatches, uint8_t *matches, int maxMatches,
+        int nextMatch, int &recursionCount, int recursionLimit)
+    {
+        // Count recursions
+        ++recursionCount;
+        if (recursionCount >= recursionLimit)
+            return false;
+
+        // Detect end of strings
+        if (*pattern == '\0' || *str == '\0')
+            return false;
+
+        // Recursion params
+        bool recursiveMatch = false;
+        uint8_t bestRecursiveMatches[256];
+        int bestRecursiveScore = 0;
+
+        // Loop through pattern and str looking for a match
+        bool first_match = true;
+        while (*pattern != '\0' && *str != '\0')
+        {
+
+            // Found match
+            if (tolower(*pattern) == tolower(*str))
+            {
+
+                // Supplied matches buffer was too short
+                if (nextMatch >= maxMatches)
+                    return false;
+
+                // "Copy-on-Write" srcMatches into matches
+                if (first_match && srcMatches)
+                {
+                    memcpy(matches, srcMatches, nextMatch);
+                    first_match = false;
+                }
+
+                // Recursive call that "skips" this match
+                uint8_t recursiveMatches[256];
+                int recursiveScore;
+                if (fuzzy_match_recursive(pattern, str + 1, recursiveScore, strBegin, matches, recursiveMatches, sizeof(recursiveMatches), nextMatch, recursionCount, recursionLimit))
+                {
+
+                    // Pick best recursive score
+                    if (!recursiveMatch || recursiveScore > bestRecursiveScore)
+                    {
+                        memcpy(bestRecursiveMatches, recursiveMatches, 256);
+                        bestRecursiveScore = recursiveScore;
+                    }
+                    recursiveMatch = true;
+                }
+
+                // Advance
+                matches[nextMatch++] = (uint8_t)(str - strBegin);
+                ++pattern;
+            }
+            ++str;
+        }
+
+        // Determine if full pattern was matched
+        bool matched = *pattern == '\0' ? true : false;
+
+        // Calculate score
+        if (matched)
+        {
+            const int sequential_bonus = 15;            // bonus for adjacent matches
+            const int separator_bonus = 30;             // bonus if match occurs after a separator
+            const int camel_bonus = 30;                 // bonus if match is uppercase and prev is lower
+            const int first_letter_bonus = 15;          // bonus if the first letter is matched
+
+            const int leading_letter_penalty = -5;      // penalty applied for every letter in str before the first match
+            const int max_leading_letter_penalty = -15; // maximum penalty for leading letters
+            const int unmatched_letter_penalty = -1;    // penalty for every letter that doesn't matter
+
+            // Iterate str to end
+            while (*str != '\0')
+                ++str;
+
+            // Initialize score
+            outScore = 100;
+
+            // Apply leading letter penalty
+            int penalty = leading_letter_penalty * matches[0];
+            if (penalty < max_leading_letter_penalty)
+                penalty = max_leading_letter_penalty;
+            outScore += penalty;
+
+            // Apply unmatched penalty
+            int unmatched = (int)(str - strBegin) - nextMatch;
+            outScore += unmatched_letter_penalty * unmatched;
+
+            // Apply ordering bonuses
+            for (int i = 0; i < nextMatch; ++i)
+            {
+                uint8_t currIdx = matches[i];
+
+                if (i > 0)
+                {
+                    uint8_t prevIdx = matches[i - 1];
+
+                    // Sequential
+                    if (currIdx == (prevIdx + 1))
+                        outScore += sequential_bonus;
+                }
+
+                // Check for bonuses based on neighbor character value
+                if (currIdx > 0)
+                {
+                    // Camel case
+                    char neighbor = strBegin[currIdx - 1];
+                    char curr = strBegin[currIdx];
+                    if (::islower(neighbor) && ::isupper(curr))
+                        outScore += camel_bonus;
+
+                    // Separator
+                    bool neighborSeparator = neighbor == '_' || neighbor == ' ';
+                    if (neighborSeparator)
+                        outScore += separator_bonus;
+                }
+                else
+                {
+                    // First letter
+                    outScore += first_letter_bonus;
+                }
+            }
+        }
+
+        // Return best result
+        if (recursiveMatch && (!matched || bestRecursiveScore > outScore))
+        {
+            // Recursive score is better than "this"
+            memcpy(matches, bestRecursiveMatches, maxMatches);
+            outScore = bestRecursiveScore;
+            return true;
+        }
+        else if (matched)
+        {
+            // "this" score is better than recursive
+            return true;
+        }
+        else
+        {
+            // no match
+            return false;
+        }
+    }
+
+    static bool fuzzy_match(char const *pattern, char const *str, int &outScore, uint8_t *matches, int maxMatches)
+    {
+        int recursionCount = 0;
+        int recursionLimit = 10;
+
+        return fuzzy_internal::fuzzy_match_recursive(pattern, str, outScore, str, nullptr, matches, maxMatches, 0, recursionCount, recursionLimit);
+    }
+
+    // Public interface
+    bool fuzzy_match_simple(char const *pattern, char const *str)
+    {
+        while (*pattern != '\0' && *str != '\0')
+        {
+            if (tolower(*pattern) == tolower(*str))
+                ++pattern;
+            ++str;
+        }
+
+        return *pattern == '\0' ? true : false;
+    }
+
+    bool fuzzy_match(char const *pattern, char const *str, int &outScore)
+    {
+
+        uint8_t matches[256];
+        return fuzzy_match(pattern, str, outScore, matches, sizeof(matches));
+    }
+
+    static bool sortbysec_desc(const std::pair<int, int> &a, const std::pair<int, int> &b)
+    {
+        return (b.second < a.second);
+    }
+
+    bool ComboWithFilter(const char *label, int *current_item, std::vector<const char *> &items)
+    {
+        ImGuiContext &g = *GImGui;
+
+        ImGuiWindow *window = GetCurrentWindow();
+        if (window->SkipItems)
+            return false;
+
+        const ImGuiStyle &style = g.Style;
+        int items_count = items.size();
+
+        // Call the getter to obtain the preview string which is a parameter to BeginCombo()
+        const char *preview_value = NULL;
+        if (*current_item >= 0 && *current_item < items_count)
+            preview_value = items[*current_item];
+
+        static char pattern_buffer[256] = {0};
+        bool isNeedFilter = false;
+
+        char comboButtonName[512] = {0};
+        ImFormatString(comboButtonName, IM_ARRAYSIZE(comboButtonName), "%s##name_ComboWithFilter_button_%s", preview_value ? preview_value : "", label);
+
+        char name_popup[256 + 10];
+        ImFormatString(name_popup, IM_ARRAYSIZE(name_popup), "##name_popup_%s", label);
+
+        // Display items
+        // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
+        bool value_changed = false;
+
+        const float expected_w = CalcItemWidth();
+        ImVec2 item_min = GetItemRectMin();
+        bool isNewOpen = false;
+        float sz = GetFrameHeight();
+        ImVec2 size(sz, sz);
+        ImVec2 CursorPos = window->DC.CursorPos;
+        ImVec2 pos = ImVec2{CursorPos.x + expected_w - sz, CursorPos.y};
+        const ImRect bb(pos, ImVec2{pos.x + size.x , pos.y + size.y});
+
+        float ButtonTextAlignX = g.Style.ButtonTextAlign.x;
+        g.Style.ButtonTextAlign.x = 0;
+        if (ImGui::Button(comboButtonName, ImVec2(expected_w, 0)))
+        {
+            ImGui::OpenPopup(name_popup);
+            isNewOpen = true;
+        }
+        g.Style.ButtonTextAlign.x = ButtonTextAlignX;
+        bool hovered = IsItemHovered();
+        bool active = IsItemActivated();
+        bool pressed = IsItemClicked();
+
+        // Render
+        //const ImU32 bg_col = GetColorU32((active && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+        //RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
+        const ImU32 text_col = GetColorU32(ImGuiCol_Text);
+        RenderArrow(window->DrawList, ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f) + bb.Min.x,
+            ImMax(0.0f, (size.y - g.FontSize) * 0.5f) + bb.Min.y), text_col, ImGuiDir_Down);
+
+        if (isNewOpen)
+        {
+            memset(pattern_buffer, 0, IM_ARRAYSIZE(pattern_buffer));
+        }
+        ImVec2 item_max = GetItemRectMax();
+        SetNextWindowPos({CursorPos.x, item_max.y});
+        ImGui::SetNextWindowSize({ImGui::GetItemRectSize().x, 0});
+        if (ImGui::BeginPopup(name_popup))
+        {
+            ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor(240, 240, 240, 255));
+            ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(0, 0, 0, 255));
+            ImGui::PushItemWidth(-FLT_MIN);
+            // Filter input
+            if (isNewOpen)
+                ImGui::SetKeyboardFocusHere();
+            InputText("##ComboWithFilter_inputText", pattern_buffer, 256);
+
+            // Search Icon, you can use it if you load IconsFontAwesome5 https://github.com/juliettef/IconFontCppHeaders
+            //const ImVec2 label_size = CalcTextSize(ICON_FA_SEARCH, NULL, true);
+            //const ImVec2 search_icon_pos(ImGui::GetItemRectMax().x - label_size.x - style.ItemInnerSpacing.x * 2, window->DC.CursorPos.y + style.FramePadding.y + g.FontSize * 0.1f);
+            //RenderText(search_icon_pos, ICON_FA_SEARCH);
+
+            ImGui::PopStyleColor(2);
+            if (pattern_buffer[0] != '\0')
+            {
+                isNeedFilter = true;
+            }
+
+            std::vector<std::pair<int, int> > itemScoreVector;
+            if (isNeedFilter)
+            {
+                for (int i = 0; i < items_count; i++)
+                {
+                    int score = 0;
+                    bool matched = fuzzy_match(pattern_buffer, items[i], score);
+                    if (matched)
+                        itemScoreVector.push_back(std::make_pair(i, score));
+                }
+                std::sort(itemScoreVector.begin(), itemScoreVector.end(), sortbysec_desc);
+            }
+
+            int show_count = isNeedFilter ? itemScoreVector.size() : items_count;
+            if (ImGui::ListBoxHeader("##ComboWithFilter_itemList", show_count))
+            {
+                for (int i = 0; i < show_count; i++)
+                {
+                    int idx = isNeedFilter ? itemScoreVector[i].first : i;
+                    PushID((void *)(intptr_t)idx);
+                    const bool item_selected = (idx == *current_item);
+                    const char *item_text = items[idx];
+                    if (Selectable(item_text, item_selected))
+                    {
+                        value_changed = true;
+                        *current_item = idx;
+                        CloseCurrentPopup();
+                    }
+                    if (item_selected)
+                        SetItemDefaultFocus();
+                    PopID();
+                }
+                ImGui::ListBoxFooter();
+            }
+            ImGui::PopItemWidth();
+            ImGui::EndPopup();
+        }
+
+
+        if (value_changed)
+        {
+            MarkItemEdited(g.LastItemData.ID);
+        }
+
+        return value_changed;
+    }
+
+    bool ComboWithFilter(const char *label, int *current_item, const std::vector<char *> &items)
+    {
+        ImGuiContext &g = *GImGui;
+
+        ImGuiWindow *window = GetCurrentWindow();
+        if (window->SkipItems)
+            return false;
+
+        const ImGuiStyle &style = g.Style;
+        int items_count = items.size();
+
+        // Call the getter to obtain the preview string which is a parameter to BeginCombo()
+        const char *preview_value = NULL;
+        if (*current_item >= 0 && *current_item < items_count)
+            preview_value = items[*current_item];
+
+        static char pattern_buffer[256] = {0};
+        bool isNeedFilter = false;
+
+        char comboButtonName[512] = {0};
+        ImFormatString(comboButtonName, IM_ARRAYSIZE(comboButtonName), "%s##name_ComboWithFilter_button_%s", preview_value ? preview_value : "", label);
+
+        char name_popup[256 + 10];
+        ImFormatString(name_popup, IM_ARRAYSIZE(name_popup), "##name_popup_%s", label);
+
+        // Display items
+        // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
+        bool value_changed = false;
+
+        const float expected_w = CalcItemWidth();
+        ImVec2 item_min = GetItemRectMin();
+        bool isNewOpen = false;
+        float sz = GetFrameHeight();
+        ImVec2 size(sz, sz);
+        ImVec2 CursorPos = window->DC.CursorPos;
+        ImVec2 pos = ImVec2{CursorPos.x + expected_w - sz, CursorPos.y};
+        const ImRect bb(pos, ImVec2{pos.x + size.x , pos.y + size.y});
+
+        float ButtonTextAlignX = g.Style.ButtonTextAlign.x;
+        g.Style.ButtonTextAlign.x = 0;
+        if (ImGui::Button(comboButtonName, ImVec2(expected_w, 0)))
+        {
+            ImGui::OpenPopup(name_popup);
+            isNewOpen = true;
+        }
+        g.Style.ButtonTextAlign.x = ButtonTextAlignX;
+        bool hovered = IsItemHovered();
+        bool active = IsItemActivated();
+        bool pressed = IsItemClicked();
+
+        // Render
+        //const ImU32 bg_col = GetColorU32((active && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+        //RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
+        const ImU32 text_col = GetColorU32(ImGuiCol_Text);
+        RenderArrow(window->DrawList, ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f) + bb.Min.x,
+            ImMax(0.0f, (size.y - g.FontSize) * 0.5f) + bb.Min.y), text_col, ImGuiDir_Down);
+
+        if (isNewOpen)
+        {
+            memset(pattern_buffer, 0, IM_ARRAYSIZE(pattern_buffer));
+        }
+        ImVec2 item_max = GetItemRectMax();
+        SetNextWindowPos({CursorPos.x, item_max.y});
+        ImGui::SetNextWindowSize({ImGui::GetItemRectSize().x, 0});
+        if (ImGui::BeginPopup(name_popup))
+        {
+            ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor(240, 240, 240, 255));
+            ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(0, 0, 0, 255));
+            ImGui::PushItemWidth(-FLT_MIN);
+            // Filter input
+            if (isNewOpen)
+                ImGui::SetKeyboardFocusHere();
+            InputText("##ComboWithFilter_inputText", pattern_buffer, 256);
+
+            // Search Icon, you can use it if you load IconsFontAwesome5 https://github.com/juliettef/IconFontCppHeaders
+            //const ImVec2 label_size = CalcTextSize(ICON_FA_SEARCH, NULL, true);
+            //const ImVec2 search_icon_pos(ImGui::GetItemRectMax().x - label_size.x - style.ItemInnerSpacing.x * 2, window->DC.CursorPos.y + style.FramePadding.y + g.FontSize * 0.1f);
+            //RenderText(search_icon_pos, ICON_FA_SEARCH);
+
+            ImGui::PopStyleColor(2);
+            if (pattern_buffer[0] != '\0')
+            {
+                isNeedFilter = true;
+            }
+
+            std::vector<std::pair<int, int> > itemScoreVector;
+            if (isNeedFilter)
+            {
+                for (int i = 0; i < items_count; i++)
+                {
+                    int score = 0;
+                    bool matched = fuzzy_match(pattern_buffer, items[i], score);
+                    if (matched)
+                        itemScoreVector.push_back(std::make_pair(i, score));
+                }
+                std::sort(itemScoreVector.begin(), itemScoreVector.end(), sortbysec_desc);
+            }
+
+            int show_count = isNeedFilter ? itemScoreVector.size() : items_count;
+            if (ImGui::ListBoxHeader("##ComboWithFilter_itemList", show_count))
+            {
+                for (int i = 0; i < show_count; i++)
+                {
+                    int idx = isNeedFilter ? itemScoreVector[i].first : i;
+                    PushID((void *)(intptr_t)idx);
+                    const bool item_selected = (idx == *current_item);
+                    const char *item_text = items[idx];
+                    if (Selectable(item_text, item_selected))
+                    {
+                        value_changed = true;
+                        *current_item = idx;
+                        CloseCurrentPopup();
+                    }
+                    if (item_selected)
+                        SetItemDefaultFocus();
+                    PopID();
+                }
+                ImGui::ListBoxFooter();
+            }
+            ImGui::PopItemWidth();
+            ImGui::EndPopup();
+        }
+
+
+        if (value_changed)
+        {
+            MarkItemEdited(g.LastItemData.ID);
+        }
+
+        return value_changed;
+    }
+
+    bool ComboWithFilter(const char *label, int *current_item, const std::vector<std::string> &items)
+    {
+        ImGuiContext &g = *GImGui;
+
+        ImGuiWindow *window = GetCurrentWindow();
+        if (window->SkipItems)
+            return false;
+
+        const ImGuiStyle &style = g.Style;
+        int items_count = items.size();
+
+        // Call the getter to obtain the preview string which is a parameter to BeginCombo()
+        const char *preview_value = NULL;
+        if (*current_item >= 0 && *current_item < items_count)
+            preview_value = items[*current_item].c_str();
+
+        static char pattern_buffer[256] = {0};
+        bool isNeedFilter = false;
+
+        char comboButtonName[512] = {0};
+        ImFormatString(comboButtonName, IM_ARRAYSIZE(comboButtonName), "%s##name_ComboWithFilter_button_%s", preview_value ? preview_value : "", label);
+
+        char name_popup[256 + 10];
+        ImFormatString(name_popup, IM_ARRAYSIZE(name_popup), "##name_popup_%s", label);
+
+        // Display items
+        // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
+        bool value_changed = false;
+
+        const float expected_w = CalcItemWidth();
+        ImVec2 item_min = GetItemRectMin();
+        bool isNewOpen = false;
+        float sz = GetFrameHeight();
+        ImVec2 size(sz, sz);
+        ImVec2 CursorPos = window->DC.CursorPos;
+        ImVec2 pos = ImVec2{CursorPos.x + expected_w - sz, CursorPos.y};
+        const ImRect bb(pos, ImVec2{pos.x + size.x , pos.y + size.y});
+
+        float ButtonTextAlignX = g.Style.ButtonTextAlign.x;
+        g.Style.ButtonTextAlign.x = 0;
+        if (ImGui::Button(comboButtonName, ImVec2(expected_w, 0)))
+        {
+            ImGui::OpenPopup(name_popup);
+            isNewOpen = true;
+        }
+        g.Style.ButtonTextAlign.x = ButtonTextAlignX;
+        bool hovered = IsItemHovered();
+        bool active = IsItemActivated();
+        bool pressed = IsItemClicked();
+
+        // Render
+        //const ImU32 bg_col = GetColorU32((active && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+        //RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
+        const ImU32 text_col = GetColorU32(ImGuiCol_Text);
+        RenderArrow(window->DrawList, ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f) + bb.Min.x,
+            ImMax(0.0f, (size.y - g.FontSize) * 0.5f) + bb.Min.y), text_col, ImGuiDir_Down);
+
+        if (isNewOpen)
+        {
+            memset(pattern_buffer, 0, IM_ARRAYSIZE(pattern_buffer));
+        }
+        ImVec2 item_max = GetItemRectMax();
+        SetNextWindowPos({CursorPos.x, item_max.y});
+        ImGui::SetNextWindowSize({ImGui::GetItemRectSize().x, 0});
+        if (ImGui::BeginPopup(name_popup))
+        {
+            ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor(240, 240, 240, 255));
+            ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(0, 0, 0, 255));
+            ImGui::PushItemWidth(-FLT_MIN);
+            // Filter input
+            if (isNewOpen)
+                ImGui::SetKeyboardFocusHere();
+            InputText("##ComboWithFilter_inputText", pattern_buffer, 256);
+
+            // Search Icon, you can use it if you load IconsFontAwesome5 https://github.com/juliettef/IconFontCppHeaders
+            //const ImVec2 label_size = CalcTextSize(ICON_FA_SEARCH, NULL, true);
+            //const ImVec2 search_icon_pos(ImGui::GetItemRectMax().x - label_size.x - style.ItemInnerSpacing.x * 2, window->DC.CursorPos.y + style.FramePadding.y + g.FontSize * 0.1f);
+            //RenderText(search_icon_pos, ICON_FA_SEARCH);
+
+            ImGui::PopStyleColor(2);
+            if (pattern_buffer[0] != '\0')
+            {
+                isNeedFilter = true;
+            }
+
+            std::vector<std::pair<int, int> > itemScoreVector;
+            if (isNeedFilter)
+            {
+                for (int i = 0; i < items_count; i++)
+                {
+                    int score = 0;
+                    bool matched = fuzzy_match(pattern_buffer, items[i].c_str(), score);
+                    if (matched)
+                        itemScoreVector.push_back(std::make_pair(i, score));
+                }
+                std::sort(itemScoreVector.begin(), itemScoreVector.end(), sortbysec_desc);
+            }
+
+            int show_count = isNeedFilter ? itemScoreVector.size() : items_count;
+            if (ImGui::ListBoxHeader("##ComboWithFilter_itemList", show_count))
+            {
+                for (int i = 0; i < show_count; i++)
+                {
+                    int idx = isNeedFilter ? itemScoreVector[i].first : i;
+                    PushID((void *)(intptr_t)idx);
+                    const bool item_selected = (idx == *current_item);
+                    const char *item_text = items[idx].c_str();
+                    if (Selectable(item_text, item_selected))
+                    {
+                        value_changed = true;
+                        *current_item = idx;
+                        CloseCurrentPopup();
+                    }
+                    if (item_selected)
+                        SetItemDefaultFocus();
+                    PopID();
+                }
+                ImGui::ListBoxFooter();
+            }
+            ImGui::PopItemWidth();
+            ImGui::EndPopup();
+        }
+
+
+        if (value_changed)
+        {
+            MarkItemEdited(g.LastItemData.ID);
+        }
+
+        return value_changed;
+    }
+
+    void ListWithFilter(const char *label, int *current_item,
+        char *filter, size_t filterSize,
+        std::vector<std::string> &items, ImVec2 size)
+    {
+
+        if (size.x > 0)
+        {
+            ImGui::SetNextItemWidth(size.x);
+        }
+
+        std::string textLabel = std::string(label) + "##Filter1";
+
+        ImGui::InputText(textLabel.c_str(), filter, filterSize);
+
+
+    #pragma region filter
+        bool isNeedFilter = false;
+
+        if (filter[0] != '\0')
+        {
+            isNeedFilter = true;
+        }
+
+        std::vector<std::pair<int, int> > itemScoreVector;
+        if (isNeedFilter)
+        {
+            for (int i = 0; i < items.size(); i++)
+            {
+                int score = 0;
+                bool matched = fuzzy_match(filter, items[i].c_str(), score);
+                if (matched)
+                    itemScoreVector.push_back(std::make_pair(i, score));
+            }
+            std::sort(itemScoreVector.begin(), itemScoreVector.end(), sortbysec_desc);
+        }
+
+    #pragma endregion
+
+        textLabel = "##list box" + textLabel;
+
+        if (ImGui::BeginListBox(textLabel.c_str(), size))
+        {
+            if (isNeedFilter)
+            {
+                for (int n = 0; n < itemScoreVector.size(); n++)
+                {
+                    bool isSelected = (*current_item == itemScoreVector[n].first);
+                    if (ImGui::Selectable(items[itemScoreVector[n].first].c_str(), isSelected))
+                        *current_item = itemScoreVector[n].first;
+
+                    if (isSelected)
+                        ImGui::SetItemDefaultFocus();
+                }
+
+            }
+            else
+            {
+                for (int n = 0; n < items.size(); n++)
+                {
+                    bool isSelected = (*current_item == n);
+                    if (ImGui::Selectable(items[n].c_str(), isSelected))
+                        *current_item = n;
+
+                    if (isSelected)
+                        ImGui::SetItemDefaultFocus();
+                }
+            }
+
+            ImGui::EndListBox();
+        }
+
+
+    }
+}

+ 4 - 661
Pika/thirdparty/imgui-docking/imgui/imguiComboSearch.h

@@ -1,4 +1,3 @@
-#include "imgui_internal.h" //todo move stuff to cpps
 #include <cstdint>
 #include <cstdint>
 #include <cctype>
 #include <cctype>
 #include <utility>
 #include <utility>
@@ -11,673 +10,17 @@
 namespace ImGui
 namespace ImGui
 {
 {
 
 
-    // https://github.com/forrestthewoods/lib_fts
 
 
-    // Forward declarations for "private" implementation
-    namespace fuzzy_internal
-    {
-        static bool fuzzy_match_recursive(const char *pattern, const char *str, int &outScore, const char *strBegin,
-            uint8_t const *srcMatches, uint8_t *newMatches, int maxMatches, int nextMatch,
-            int &recursionCount, int recursionLimit);
-    }
-    // Private implementation
-    static bool fuzzy_internal::fuzzy_match_recursive(const char *pattern, const char *str, int &outScore,
-        const char *strBegin, uint8_t const *srcMatches, uint8_t *matches, int maxMatches,
-        int nextMatch, int &recursionCount, int recursionLimit)
-    {
-        // Count recursions
-        ++recursionCount;
-        if (recursionCount >= recursionLimit)
-            return false;
 
 
-        // Detect end of strings
-        if (*pattern == '\0' || *str == '\0')
-            return false;
+    bool ComboWithFilter(const char *label, int *current_item, const std::vector<std::string> &items);
 
 
-        // Recursion params
-        bool recursiveMatch = false;
-        uint8_t bestRecursiveMatches[256];
-        int bestRecursiveScore = 0;
-
-        // Loop through pattern and str looking for a match
-        bool first_match = true;
-        while (*pattern != '\0' && *str != '\0')
-        {
-
-            // Found match
-            if (tolower(*pattern) == tolower(*str))
-            {
-
-                // Supplied matches buffer was too short
-                if (nextMatch >= maxMatches)
-                    return false;
-
-                // "Copy-on-Write" srcMatches into matches
-                if (first_match && srcMatches)
-                {
-                    memcpy(matches, srcMatches, nextMatch);
-                    first_match = false;
-                }
-
-                // Recursive call that "skips" this match
-                uint8_t recursiveMatches[256];
-                int recursiveScore;
-                if (fuzzy_match_recursive(pattern, str + 1, recursiveScore, strBegin, matches, recursiveMatches, sizeof(recursiveMatches), nextMatch, recursionCount, recursionLimit))
-                {
-
-                    // Pick best recursive score
-                    if (!recursiveMatch || recursiveScore > bestRecursiveScore)
-                    {
-                        memcpy(bestRecursiveMatches, recursiveMatches, 256);
-                        bestRecursiveScore = recursiveScore;
-                    }
-                    recursiveMatch = true;
-                }
-
-                // Advance
-                matches[nextMatch++] = (uint8_t)(str - strBegin);
-                ++pattern;
-            }
-            ++str;
-        }
-
-        // Determine if full pattern was matched
-        bool matched = *pattern == '\0' ? true : false;
-
-        // Calculate score
-        if (matched)
-        {
-            const int sequential_bonus = 15;            // bonus for adjacent matches
-            const int separator_bonus = 30;             // bonus if match occurs after a separator
-            const int camel_bonus = 30;                 // bonus if match is uppercase and prev is lower
-            const int first_letter_bonus = 15;          // bonus if the first letter is matched
-
-            const int leading_letter_penalty = -5;      // penalty applied for every letter in str before the first match
-            const int max_leading_letter_penalty = -15; // maximum penalty for leading letters
-            const int unmatched_letter_penalty = -1;    // penalty for every letter that doesn't matter
-
-            // Iterate str to end
-            while (*str != '\0')
-                ++str;
-
-            // Initialize score
-            outScore = 100;
-
-            // Apply leading letter penalty
-            int penalty = leading_letter_penalty * matches[0];
-            if (penalty < max_leading_letter_penalty)
-                penalty = max_leading_letter_penalty;
-            outScore += penalty;
-
-            // Apply unmatched penalty
-            int unmatched = (int)(str - strBegin) - nextMatch;
-            outScore += unmatched_letter_penalty * unmatched;
-
-            // Apply ordering bonuses
-            for (int i = 0; i < nextMatch; ++i)
-            {
-                uint8_t currIdx = matches[i];
-
-                if (i > 0)
-                {
-                    uint8_t prevIdx = matches[i - 1];
-
-                    // Sequential
-                    if (currIdx == (prevIdx + 1))
-                        outScore += sequential_bonus;
-                }
-
-                // Check for bonuses based on neighbor character value
-                if (currIdx > 0)
-                {
-                    // Camel case
-                    char neighbor = strBegin[currIdx - 1];
-                    char curr = strBegin[currIdx];
-                    if (::islower(neighbor) && ::isupper(curr))
-                        outScore += camel_bonus;
-
-                    // Separator
-                    bool neighborSeparator = neighbor == '_' || neighbor == ' ';
-                    if (neighborSeparator)
-                        outScore += separator_bonus;
-                }
-                else
-                {
-                    // First letter
-                    outScore += first_letter_bonus;
-                }
-            }
-        }
-
-        // Return best result
-        if (recursiveMatch && (!matched || bestRecursiveScore > outScore))
-        {
-            // Recursive score is better than "this"
-            memcpy(matches, bestRecursiveMatches, maxMatches);
-            outScore = bestRecursiveScore;
-            return true;
-        }
-        else if (matched)
-        {
-            // "this" score is better than recursive
-            return true;
-        }
-        else
-        {
-            // no match
-            return false;
-        }
-    }
-
-
-
-    static bool fuzzy_match(char const *pattern, char const *str, int &outScore, uint8_t *matches, int maxMatches)
-    {
-        int recursionCount = 0;
-        int recursionLimit = 10;
-
-        return fuzzy_internal::fuzzy_match_recursive(pattern, str, outScore, str, nullptr, matches, maxMatches, 0, recursionCount, recursionLimit);
-    }
-
-    // Public interface
-    bool fuzzy_match_simple(char const *pattern, char const *str)
-    {
-        while (*pattern != '\0' && *str != '\0')
-        {
-            if (tolower(*pattern) == tolower(*str))
-                ++pattern;
-            ++str;
-        }
-
-        return *pattern == '\0' ? true : false;
-    }
-
-    bool fuzzy_match(char const *pattern, char const *str, int &outScore)
-    {
-
-        uint8_t matches[256];
-        return fuzzy_match(pattern, str, outScore, matches, sizeof(matches));
-    }
-
-    static bool sortbysec_desc(const std::pair<int, int> &a, const std::pair<int, int> &b)
-    {
-        return (b.second < a.second);
-    }
-
-    bool ComboWithFilter(const char *label, int *current_item,const std::vector<std::string> &items)
-    {
-        ImGuiContext &g = *GImGui;
-
-        ImGuiWindow *window = GetCurrentWindow();
-        if (window->SkipItems)
-            return false;
-
-        const ImGuiStyle &style = g.Style;
-        int items_count = items.size();
-
-        // Call the getter to obtain the preview string which is a parameter to BeginCombo()
-        const char *preview_value = NULL;
-        if (*current_item >= 0 && *current_item < items_count)
-            preview_value = items[*current_item].c_str();
-
-        static char pattern_buffer[256] = {0};
-        bool isNeedFilter = false;
-
-        char comboButtonName[512] = {0};
-        ImFormatString(comboButtonName, IM_ARRAYSIZE(comboButtonName), "%s##name_ComboWithFilter_button_%s", preview_value ? preview_value : "", label);
-
-        char name_popup[256 + 10];
-        ImFormatString(name_popup, IM_ARRAYSIZE(name_popup), "##name_popup_%s", label);
-
-        // Display items
-        // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
-        bool value_changed = false;
-
-        const float expected_w = CalcItemWidth();
-        ImVec2 item_min = GetItemRectMin();
-        bool isNewOpen = false;
-        float sz = GetFrameHeight();
-        ImVec2 size(sz, sz);
-        ImVec2 CursorPos = window->DC.CursorPos;
-        ImVec2 pos = ImVec2{CursorPos.x + expected_w - sz, CursorPos.y};
-        const ImRect bb(pos, ImVec2{pos.x + size.x , pos.y + size.y});
-
-        float ButtonTextAlignX = g.Style.ButtonTextAlign.x;
-        g.Style.ButtonTextAlign.x = 0;
-        if (ImGui::Button(comboButtonName, ImVec2(expected_w, 0)))
-        {
-            ImGui::OpenPopup(name_popup);
-            isNewOpen = true;
-        }
-        g.Style.ButtonTextAlign.x = ButtonTextAlignX;
-        bool hovered = IsItemHovered();
-        bool active = IsItemActivated();
-        bool pressed = IsItemClicked();
-
-        // Render
-        //const ImU32 bg_col = GetColorU32((active && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
-        //RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
-        const ImU32 text_col = GetColorU32(ImGuiCol_Text);
-        RenderArrow(window->DrawList, ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f)+ bb.Min.x,
-            ImMax(0.0f, (size.y - g.FontSize) * 0.5f) + bb.Min.y), text_col, ImGuiDir_Down);
-
-        if (isNewOpen)
-        {
-            memset(pattern_buffer, 0, IM_ARRAYSIZE(pattern_buffer));
-        }
-        ImVec2 item_max = GetItemRectMax();
-        SetNextWindowPos({CursorPos.x, item_max.y});
-        ImGui::SetNextWindowSize({ImGui::GetItemRectSize().x, 0});
-        if (ImGui::BeginPopup(name_popup))
-        {
-            ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor(240, 240, 240, 255));
-            ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(0, 0, 0, 255));
-            ImGui::PushItemWidth(-FLT_MIN);
-            // Filter input
-            if (isNewOpen)
-                ImGui::SetKeyboardFocusHere();
-            InputText("##ComboWithFilter_inputText", pattern_buffer, 256);
-
-            // Search Icon, you can use it if you load IconsFontAwesome5 https://github.com/juliettef/IconFontCppHeaders
-            //const ImVec2 label_size = CalcTextSize(ICON_FA_SEARCH, NULL, true);
-            //const ImVec2 search_icon_pos(ImGui::GetItemRectMax().x - label_size.x - style.ItemInnerSpacing.x * 2, window->DC.CursorPos.y + style.FramePadding.y + g.FontSize * 0.1f);
-            //RenderText(search_icon_pos, ICON_FA_SEARCH);
-
-            ImGui::PopStyleColor(2);
-            if (pattern_buffer[0] != '\0')
-            {
-                isNeedFilter = true;
-            }
-
-            std::vector<std::pair<int, int> > itemScoreVector;
-            if (isNeedFilter)
-            {
-                for (int i = 0; i < items_count; i++)
-                {
-                    int score = 0;
-                    bool matched = fuzzy_match(pattern_buffer, items[i].c_str(), score);
-                    if (matched)
-                        itemScoreVector.push_back(std::make_pair(i, score));
-                }
-                std::sort(itemScoreVector.begin(), itemScoreVector.end(), sortbysec_desc);
-            }
-
-            int show_count = isNeedFilter ? itemScoreVector.size() : items_count;
-            if (ImGui::ListBoxHeader("##ComboWithFilter_itemList", show_count))
-            {
-                for (int i = 0; i < show_count; i++)
-                {
-                    int idx = isNeedFilter ? itemScoreVector[i].first : i;
-                    PushID((void *)(intptr_t)idx);
-                    const bool item_selected = (idx == *current_item);
-                    const char *item_text = items[idx].c_str();
-                    if (Selectable(item_text, item_selected))
-                    {
-                        value_changed = true;
-                        *current_item = idx;
-                        CloseCurrentPopup();
-                    }
-                    if (item_selected)
-                        SetItemDefaultFocus();
-                    PopID();
-                }
-                ImGui::ListBoxFooter();
-            }
-            ImGui::PopItemWidth();
-            ImGui::EndPopup();
-        }
-
-
-        if (value_changed)
-        {
-            MarkItemEdited(g.LastItemData.ID);
-        }
-
-        return value_changed;
-    }
-
-    //todo move pattern_buffer
-    bool ComboWithFilter(const char *label, int *current_item, const std::vector<char *> &items)
-    {
-        ImGuiContext &g = *GImGui;
-
-        ImGuiWindow *window = GetCurrentWindow();
-        if (window->SkipItems)
-            return false;
-
-        const ImGuiStyle &style = g.Style;
-        int items_count = items.size();
-
-        // Call the getter to obtain the preview string which is a parameter to BeginCombo()
-        const char *preview_value = NULL;
-        if (*current_item >= 0 && *current_item < items_count)
-            preview_value = items[*current_item];
-
-        static char pattern_buffer[256] = {0};
-        bool isNeedFilter = false;
-
-        char comboButtonName[512] = {0};
-        ImFormatString(comboButtonName, IM_ARRAYSIZE(comboButtonName), "%s##name_ComboWithFilter_button_%s", preview_value ? preview_value : "", label);
-
-        char name_popup[256 + 10];
-        ImFormatString(name_popup, IM_ARRAYSIZE(name_popup), "##name_popup_%s", label);
-
-        // Display items
-        // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
-        bool value_changed = false;
-
-        const float expected_w = CalcItemWidth();
-        ImVec2 item_min = GetItemRectMin();
-        bool isNewOpen = false;
-        float sz = GetFrameHeight();
-        ImVec2 size(sz, sz);
-        ImVec2 CursorPos = window->DC.CursorPos;
-        ImVec2 pos = ImVec2{CursorPos.x + expected_w - sz, CursorPos.y};
-        const ImRect bb(pos, ImVec2{pos.x + size.x , pos.y + size.y});
-
-        float ButtonTextAlignX = g.Style.ButtonTextAlign.x;
-        g.Style.ButtonTextAlign.x = 0;
-        if (ImGui::Button(comboButtonName, ImVec2(expected_w, 0)))
-        {
-            ImGui::OpenPopup(name_popup);
-            isNewOpen = true;
-        }
-        g.Style.ButtonTextAlign.x = ButtonTextAlignX;
-        bool hovered = IsItemHovered();
-        bool active = IsItemActivated();
-        bool pressed = IsItemClicked();
-
-        // Render
-        //const ImU32 bg_col = GetColorU32((active && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
-        //RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
-        const ImU32 text_col = GetColorU32(ImGuiCol_Text);
-        RenderArrow(window->DrawList, ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f) + bb.Min.x,
-            ImMax(0.0f, (size.y - g.FontSize) * 0.5f) + bb.Min.y), text_col, ImGuiDir_Down);
-
-        if (isNewOpen)
-        {
-            memset(pattern_buffer, 0, IM_ARRAYSIZE(pattern_buffer));
-        }
-        ImVec2 item_max = GetItemRectMax();
-        SetNextWindowPos({CursorPos.x, item_max.y});
-        ImGui::SetNextWindowSize({ImGui::GetItemRectSize().x, 0});
-        if (ImGui::BeginPopup(name_popup))
-        {
-            ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor(240, 240, 240, 255));
-            ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(0, 0, 0, 255));
-            ImGui::PushItemWidth(-FLT_MIN);
-            // Filter input
-            if (isNewOpen)
-                ImGui::SetKeyboardFocusHere();
-            InputText("##ComboWithFilter_inputText", pattern_buffer, 256);
-
-            // Search Icon, you can use it if you load IconsFontAwesome5 https://github.com/juliettef/IconFontCppHeaders
-            //const ImVec2 label_size = CalcTextSize(ICON_FA_SEARCH, NULL, true);
-            //const ImVec2 search_icon_pos(ImGui::GetItemRectMax().x - label_size.x - style.ItemInnerSpacing.x * 2, window->DC.CursorPos.y + style.FramePadding.y + g.FontSize * 0.1f);
-            //RenderText(search_icon_pos, ICON_FA_SEARCH);
-
-            ImGui::PopStyleColor(2);
-            if (pattern_buffer[0] != '\0')
-            {
-                isNeedFilter = true;
-            }
-
-            std::vector<std::pair<int, int> > itemScoreVector;
-            if (isNeedFilter)
-            {
-                for (int i = 0; i < items_count; i++)
-                {
-                    int score = 0;
-                    bool matched = fuzzy_match(pattern_buffer, items[i], score);
-                    if (matched)
-                        itemScoreVector.push_back(std::make_pair(i, score));
-                }
-                std::sort(itemScoreVector.begin(), itemScoreVector.end(), sortbysec_desc);
-            }
-
-            int show_count = isNeedFilter ? itemScoreVector.size() : items_count;
-            if (ImGui::ListBoxHeader("##ComboWithFilter_itemList", show_count))
-            {
-                for (int i = 0; i < show_count; i++)
-                {
-                    int idx = isNeedFilter ? itemScoreVector[i].first : i;
-                    PushID((void *)(intptr_t)idx);
-                    const bool item_selected = (idx == *current_item);
-                    const char *item_text = items[idx];
-                    if (Selectable(item_text, item_selected))
-                    {
-                        value_changed = true;
-                        *current_item = idx;
-                        CloseCurrentPopup();
-                    }
-                    if (item_selected)
-                        SetItemDefaultFocus();
-                    PopID();
-                }
-                ImGui::ListBoxFooter();
-            }
-            ImGui::PopItemWidth();
-            ImGui::EndPopup();
-        }
-
-
-        if (value_changed)
-        {
-            MarkItemEdited(g.LastItemData.ID);
-        }
-
-        return value_changed;
-    }
-
-
-    bool ComboWithFilter(const char *label, int *current_item, std::vector<const char *> &items)
-    {
-        ImGuiContext &g = *GImGui;
-
-        ImGuiWindow *window = GetCurrentWindow();
-        if (window->SkipItems)
-            return false;
-
-        const ImGuiStyle &style = g.Style;
-        int items_count = items.size();
-
-        // Call the getter to obtain the preview string which is a parameter to BeginCombo()
-        const char *preview_value = NULL;
-        if (*current_item >= 0 && *current_item < items_count)
-            preview_value = items[*current_item];
-
-        static char pattern_buffer[256] = {0};
-        bool isNeedFilter = false;
-
-        char comboButtonName[512] = {0};
-        ImFormatString(comboButtonName, IM_ARRAYSIZE(comboButtonName), "%s##name_ComboWithFilter_button_%s", preview_value ? preview_value : "", label);
-
-        char name_popup[256 + 10];
-        ImFormatString(name_popup, IM_ARRAYSIZE(name_popup), "##name_popup_%s", label);
-
-        // Display items
-        // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
-        bool value_changed = false;
-
-        const float expected_w = CalcItemWidth();
-        ImVec2 item_min = GetItemRectMin();
-        bool isNewOpen = false;
-        float sz = GetFrameHeight();
-        ImVec2 size(sz, sz);
-        ImVec2 CursorPos = window->DC.CursorPos;
-        ImVec2 pos = ImVec2{CursorPos.x + expected_w - sz, CursorPos.y};
-        const ImRect bb(pos, ImVec2{pos.x + size.x , pos.y + size.y});
-
-        float ButtonTextAlignX = g.Style.ButtonTextAlign.x;
-        g.Style.ButtonTextAlign.x = 0;
-        if (ImGui::Button(comboButtonName, ImVec2(expected_w, 0)))
-        {
-            ImGui::OpenPopup(name_popup);
-            isNewOpen = true;
-        }
-        g.Style.ButtonTextAlign.x = ButtonTextAlignX;
-        bool hovered = IsItemHovered();
-        bool active = IsItemActivated();
-        bool pressed = IsItemClicked();
-
-        // Render
-        //const ImU32 bg_col = GetColorU32((active && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
-        //RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
-        const ImU32 text_col = GetColorU32(ImGuiCol_Text);
-        RenderArrow(window->DrawList, ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f) + bb.Min.x,
-            ImMax(0.0f, (size.y - g.FontSize) * 0.5f) + bb.Min.y), text_col, ImGuiDir_Down);
-
-        if (isNewOpen)
-        {
-            memset(pattern_buffer, 0, IM_ARRAYSIZE(pattern_buffer));
-        }
-        ImVec2 item_max = GetItemRectMax();
-        SetNextWindowPos({CursorPos.x, item_max.y});
-        ImGui::SetNextWindowSize({ImGui::GetItemRectSize().x, 0});
-        if (ImGui::BeginPopup(name_popup))
-        {
-            ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor(240, 240, 240, 255));
-            ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(0, 0, 0, 255));
-            ImGui::PushItemWidth(-FLT_MIN);
-            // Filter input
-            if (isNewOpen)
-                ImGui::SetKeyboardFocusHere();
-            InputText("##ComboWithFilter_inputText", pattern_buffer, 256);
-
-            // Search Icon, you can use it if you load IconsFontAwesome5 https://github.com/juliettef/IconFontCppHeaders
-            //const ImVec2 label_size = CalcTextSize(ICON_FA_SEARCH, NULL, true);
-            //const ImVec2 search_icon_pos(ImGui::GetItemRectMax().x - label_size.x - style.ItemInnerSpacing.x * 2, window->DC.CursorPos.y + style.FramePadding.y + g.FontSize * 0.1f);
-            //RenderText(search_icon_pos, ICON_FA_SEARCH);
-
-            ImGui::PopStyleColor(2);
-            if (pattern_buffer[0] != '\0')
-            {
-                isNeedFilter = true;
-            }
-
-            std::vector<std::pair<int, int> > itemScoreVector;
-            if (isNeedFilter)
-            {
-                for (int i = 0; i < items_count; i++)
-                {
-                    int score = 0;
-                    bool matched = fuzzy_match(pattern_buffer, items[i], score);
-                    if (matched)
-                        itemScoreVector.push_back(std::make_pair(i, score));
-                }
-                std::sort(itemScoreVector.begin(), itemScoreVector.end(), sortbysec_desc);
-            }
-
-            int show_count = isNeedFilter ? itemScoreVector.size() : items_count;
-            if (ImGui::ListBoxHeader("##ComboWithFilter_itemList", show_count))
-            {
-                for (int i = 0; i < show_count; i++)
-                {
-                    int idx = isNeedFilter ? itemScoreVector[i].first : i;
-                    PushID((void *)(intptr_t)idx);
-                    const bool item_selected = (idx == *current_item);
-                    const char *item_text = items[idx];
-                    if (Selectable(item_text, item_selected))
-                    {
-                        value_changed = true;
-                        *current_item = idx;
-                        CloseCurrentPopup();
-                    }
-                    if (item_selected)
-                        SetItemDefaultFocus();
-                    PopID();
-                }
-                ImGui::ListBoxFooter();
-            }
-            ImGui::PopItemWidth();
-            ImGui::EndPopup();
-        }
-
-
-        if (value_changed)
-        {
-            MarkItemEdited(g.LastItemData.ID);
-        }
-
-        return value_changed;
-    }
+    bool ComboWithFilter(const char *label, int *current_item, const std::vector<char *> &items);
 
 
+    bool ComboWithFilter(const char *label, int *current_item, std::vector<const char *> &items);
 
 
     void ListWithFilter(const char *label, int *current_item,
     void ListWithFilter(const char *label, int *current_item,
         char *filter, size_t filterSize,
         char *filter, size_t filterSize,
-        std::vector<std::string> &items, ImVec2 size = {0,0})
-    {
-       
-        if (size.x > 0)
-        {
-            ImGui::SetNextItemWidth(size.x);
-        }
-
-        std::string textLabel = std::string(label) + "##Filter1";
-
-        ImGui::InputText(textLabel.c_str(), filter, filterSize);
-
-
-    #pragma region filter
-        bool isNeedFilter = false;
-
-        if (filter[0] != '\0')
-        {
-            isNeedFilter = true;
-        }
-
-        std::vector<std::pair<int, int> > itemScoreVector;
-        if (isNeedFilter)
-        {
-            for (int i = 0; i < items.size(); i++)
-            {
-                int score = 0;
-                bool matched = fuzzy_match(filter, items[i].c_str(), score);
-                if (matched)
-                    itemScoreVector.push_back(std::make_pair(i, score));
-            }
-            std::sort(itemScoreVector.begin(), itemScoreVector.end(), sortbysec_desc);
-        }
-
-    #pragma endregion
-
-        textLabel = "##list box" + textLabel;
-
-        if (ImGui::BeginListBox(textLabel.c_str(), size))
-        {
-            if (isNeedFilter)
-            {
-                for (int n = 0; n < itemScoreVector.size(); n++)
-                {
-                    bool isSelected = (*current_item == itemScoreVector[n].first);
-                    if (ImGui::Selectable(items[itemScoreVector[n].first].c_str(), isSelected))
-                        *current_item = itemScoreVector[n].first;
-
-                    if (isSelected)
-                        ImGui::SetItemDefaultFocus();
-                }
-
-            }
-            else
-            {
-                for (int n = 0; n < items.size(); n++)
-                {
-                    bool isSelected = (*current_item == n);
-                    if (ImGui::Selectable(items[n].c_str(), isSelected))
-                        *current_item = n;
-
-                    if (isSelected)
-                        ImGui::SetItemDefaultFocus();
-                }
-            }
-
-            ImGui::EndListBox();
-        }
-
-
-    }
-
-
+        std::vector<std::string> &items, ImVec2 size = {0,0});
 
 
 
 
 }
 }

+ 116 - 2
Pika/thirdparty/safeSafe/include/safeSave/safeSave.h

@@ -9,6 +9,7 @@
 #pragma once
 #pragma once
 #include <fstream>
 #include <fstream>
 #include <vector>
 #include <vector>
+#include <unordered_map>
 
 
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 #pragma warning( disable : 26812 )
 #pragma warning( disable : 26812 )
@@ -18,12 +19,17 @@ namespace sfs
 {
 {
 	enum Errors : int
 	enum Errors : int
 	{
 	{
-		noError,
+		noError = 0,
 		couldNotOpenFinle,
 		couldNotOpenFinle,
 		fileSizeDitNotMatch,
 		fileSizeDitNotMatch,
 		checkSumFailed,
 		checkSumFailed,
 		couldNotMakeBackup,
 		couldNotMakeBackup,
 		readBackup,
 		readBackup,
+		warningEntryAlreadyExists,
+		entryNotFound,
+		entryHasDifferentDataType,
+		couldNotParseData,
+		fileSizeNotBigEnough,	//files with checksum have a check sum in them so if the file is smaller than the checksum size it is corupted
 	};
 	};
 	
 	
 	const char* getErrorString(Errors e);
 	const char* getErrorString(Errors e);
@@ -31,33 +37,140 @@ namespace sfs
 	//can return error: couldNotOpenFinle
 	//can return error: couldNotOpenFinle
 	Errors readEntireFile(std::vector<char>& data, const char* name);
 	Errors readEntireFile(std::vector<char>& data, const char* name);
 	
 	
-	//can return error: couldNotOpenFinle
+	//reades the content of a file (size bytes), if shouldMatchSize is false will read the entire fill untill size bytes are read or the entire file was read
+	//can return error: couldNotOpenFinle, fileSizeDitNotMatch
 	Errors readEntireFile(void* data, size_t size, const char* name, bool shouldMatchSize, int *bytesRead = nullptr);
 	Errors readEntireFile(void* data, size_t size, const char* name, bool shouldMatchSize, int *bytesRead = nullptr);
 
 
+	//gets the file size
+	//can return error: couldNotOpenFinle
+	Errors getFileSize(const char *name, size_t &size);
+
+	//reades the entire content of the data to a file and uses checkSum
 	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed
 	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed
 	Errors readEntireFileWithCheckSum(void* data, size_t size, const char* name);
 	Errors readEntireFileWithCheckSum(void* data, size_t size, const char* name);
 
 
+	//reades the entire content of the data to a file and uses checkSum
+	//can return error: couldNotOpenFinle, fileSizeNotBigEnough
+	Errors readEntireFileWithCheckSum(std::vector<char> &data, const char *name);
+
+	//writes the entire content of the data to a file and uses checkSum
 	//can return error: couldNotOpenFinle
 	//can return error: couldNotOpenFinle
 	Errors writeEntireFileWithCheckSum(const void* data, size_t size, const char* name);
 	Errors writeEntireFileWithCheckSum(const void* data, size_t size, const char* name);
 
 
+	//writes the entire content of the data to a file
 	//can return error: couldNotOpenFinle
 	//can return error: couldNotOpenFinle
 	Errors writeEntireFile(const std::vector<char>& data, const char* name);
 	Errors writeEntireFile(const std::vector<char>& data, const char* name);
 	
 	
+	//writes the entire content of the data to a file
 	//can return error: couldNotOpenFinle
 	//can return error: couldNotOpenFinle
 	Errors writeEntireFile(const void*data, size_t size, const char* name);
 	Errors writeEntireFile(const void*data, size_t size, const char* name);
 
 
+	//saved the data with a check sum and a backup
 	//can return error: couldNotOpenFinle, 
 	//can return error: couldNotOpenFinle, 
 	//	couldNotMakeBackup (if reportnotMakingBackupAsAnError is true, but will still save the first file)
 	//	couldNotMakeBackup (if reportnotMakingBackupAsAnError is true, but will still save the first file)
 	Errors safeSave(const void* data, size_t size, const char* nameWithoutExtension, bool reportnotMakingBackupAsAnError);
 	Errors safeSave(const void* data, size_t size, const char* nameWithoutExtension, bool reportnotMakingBackupAsAnError);
 
 
+	//loads the data that was saved using safeSave
 	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed, 
 	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed, 
 	//	readBackup (if reportLoadingBackupAsAnError but data will still be loaded with the backup)
 	//	readBackup (if reportLoadingBackupAsAnError but data will still be loaded with the backup)
 	Errors safeLoad(void* data, size_t size, const char* nameWithoutExtension, bool reportLoadingBackupAsAnError);
 	Errors safeLoad(void* data, size_t size, const char* nameWithoutExtension, bool reportLoadingBackupAsAnError);
 
 
+	//loads the data that was saved using safeSave and stored as a SafeSafeKeyValueData structure
+	//can return error: couldNotOpenFinle, checkSumFailed, fileSizeNotBigEnough
+	//	readBackup (if reportLoadingBackupAsAnError but data will still be loaded with the backup)
+	Errors safeLoad(std::vector<char> &data, const char *nameWithoutExtension, bool reportLoadingBackupAsAnError);
+
 	//same as safeLoad but only loads the backup file.
 	//same as safeLoad but only loads the backup file.
 	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed
 	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed
 	Errors safeLoadBackup(void* data, size_t size, const char* nameWithoutExtension);
 	Errors safeLoadBackup(void* data, size_t size, const char* nameWithoutExtension);
 
 
+
+	//used to save data and read it
+	struct SafeSafeKeyValueData
+	{
+		struct Entry
+		{
+			enum Types
+			{
+				no_type = 0,
+				rawData_type,
+				int_type,
+				float_type,
+				bool_type,
+				string_type,
+			};
+
+			std::vector<char> data;
+			char type = 0;
+			union Primitives
+			{
+				std::int32_t intData;
+				float floatData;
+				bool boolData;
+			}primitives;
+		};
+
+		std::unordered_map<std::string, Entry> entries;
+
+		//returns true if entry exists
+		bool entryExists(std::string at);
+
+		//can return error: entryNotFound
+		Errors getEntryType(std::string at, char &type);
+
+		//can return error: warningEntryAlreadyExists, if so it will overwrite data
+		Errors setRawData(std::string at, void *data, size_t size);
+
+		//it gives you a pointer to the data and the size, so it is like a view
+		//can return error: entryNotFound, entryHasDifferentDataType
+		Errors getRawDataPointer(std::string at, void* &data, size_t &size);
+
+		//won't change i if failed
+		//can return error: entryNotFound, entryHasDifferentDataType
+		Errors getInt(std::string at, int32_t &i);
+
+		//can return error: warningEntryAlreadyExists, if so it will overwrite data
+		Errors setInt(std::string at, int32_t i);
+
+		//won't change f if failed
+		//can return error: entryNotFound, entryHasDifferentDataType
+		Errors getFloat(std::string at, float &f);
+
+		//can return error: warningEntryAlreadyExists, if so it will overwrite data
+		Errors setFloat(std::string at, float f);
+
+		//won't change b if failed
+		//can return error: entryNotFound, entryHasDifferentDataType
+		Errors getBool(std::string at, bool &b);
+
+		//can return error: warningEntryAlreadyExists, if so it will overwrite data
+		Errors setBool(std::string at, bool b);
+
+		//can return error: warningEntryAlreadyExists, if so it will overwrite data
+		Errors setString(std::string at, std::string value);
+
+		//won't change s if failed
+		//can return error: entryNotFound, entryHasDifferentDataType
+		Errors getString(std::string at, std::string &s);
+
+		std::vector<char> formatIntoFileData();
+
+		//can return error: couldNotParseData
+		Errors loadFromFileData(char *data, size_t size);
+	};
+	
+	//saved the data stored as a SafeSafeKeyValueData structure in a binary format with a check sum and a backup
+	//can return error: couldNotOpenFinle, 
+	//	couldNotMakeBackup (if reportnotMakingBackupAsAnError is true, but will still save the first file)
+	Errors safeSave(SafeSafeKeyValueData &data, const char *nameWithoutExtension, bool reportnotMakingBackupAsAnError);
+
+	//loads the data that was saved using safeSave and stored as a SafeSafeKeyValueData structure
+	//can return error: couldNotOpenFinle, fileSizeNotBigEnough, checkSumFailed, couldNotParseData
+	//	readBackup (if reportLoadingBackupAsAnError but data will still be loaded from the backup)
+	Errors safeLoad(SafeSafeKeyValueData &data, const char *nameWithoutExtension, bool reportLoadingBackupAsAnError);
+
+
+
 #if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__
 #if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__
 
 
 	struct FileMapping
 	struct FileMapping
@@ -85,6 +198,7 @@ namespace sfs
 
 
 #endif
 #endif
 
 
+	//a file mapping maps the content of a file to ram
 	//can return error: couldNotOpenFinle
 	//can return error: couldNotOpenFinle
 	Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting);
 	Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting);
 
 

+ 615 - 2
Pika/thirdparty/safeSafe/src/safeSave.cpp

@@ -32,6 +32,11 @@ namespace sfs
 		"checkSumFailed",
 		"checkSumFailed",
 		"couldNotMakeBackup",
 		"couldNotMakeBackup",
 		"readBackup",
 		"readBackup",
+		"warningEntryAlreadyExists",
+		"entryNotFound",
+		"entryHasDifferentDataType",
+		"couldNotParseData",
+		"fileSizeNotBigEnough",
 	};
 	};
 
 
 	const char* getErrorString(Errors e)
 	const char* getErrorString(Errors e)
@@ -116,6 +121,27 @@ namespace sfs
 			return couldNotOpenFinle;
 			return couldNotOpenFinle;
 		}
 		}
 	}
 	}
+
+	Errors getFileSize(const char *name, size_t &size)
+	{
+		size = 0;
+
+		std::ifstream f(name, std::ios::binary);
+
+		if (f.is_open())
+		{
+			f.seekg(0, std::ios_base::end);
+			size_t readSize = f.tellg();
+			f.close();
+			size = readSize;
+
+			return noError;
+		}
+		else
+		{
+			return couldNotOpenFinle;
+		}
+	}
 	
 	
 	using HashType = unsigned long long;
 	using HashType = unsigned long long;
 	
 	
@@ -124,14 +150,21 @@ namespace sfs
 	{
 	{
 		const unsigned char* p = (const unsigned char*)key;
 		const unsigned char* p = (const unsigned char*)key;
 		unsigned long long h = 0xcbf29ce484222325ULL;
 		unsigned long long h = 0xcbf29ce484222325ULL;
-		for (int i = 0; i < len; i+=4)
+
+		//for (int i = 0; i < len; i++)
+		//{
+		//	h = (h ^ p[i]) * 0x100000001b3ULL;
+		//}
+
+		if(len >= 4)
+		for (int i = 0; i < len-3; i+=4)
 		{
 		{
 			h = (h ^ p[i + 0]) * 0x100000001b3ULL;
 			h = (h ^ p[i + 0]) * 0x100000001b3ULL;
 			h = (h ^ p[i + 1]) * 0x100000001b3ULL;
 			h = (h ^ p[i + 1]) * 0x100000001b3ULL;
 			h = (h ^ p[i + 2]) * 0x100000001b3ULL;
 			h = (h ^ p[i + 2]) * 0x100000001b3ULL;
 			h = (h ^ p[i + 3]) * 0x100000001b3ULL;
 			h = (h ^ p[i + 3]) * 0x100000001b3ULL;
 		}
 		}
-
+		
 		for (int i = len - (len%4); i < len; i++)
 		for (int i = len - (len%4); i < len; i++)
 		{
 		{
 			h = (h ^ p[i]) * 0x100000001b3ULL;
 			h = (h ^ p[i]) * 0x100000001b3ULL;
@@ -180,6 +213,48 @@ namespace sfs
 		}
 		}
 	}
 	}
 
 
+	Errors readEntireFileWithCheckSum(std::vector<char> &data, const char *name)
+	{
+		data.clear();
+
+		std::ifstream f(name, std::ios::binary);
+		if (f.is_open())
+		{
+			f.seekg(0, std::ios_base::end);
+			size_t readSize = f.tellg();
+			f.seekg(0, std::ios_base::beg);
+
+			if(readSize > sizeof(HashType))
+			{
+				data.resize(readSize - sizeof(HashType));
+				f.read(&data[0], readSize - sizeof(HashType));
+
+				HashType checkSum = 0;
+				f.read((char *)&checkSum, sizeof(HashType));
+
+				auto testCheck = fnv_hash_1a_64(&data[0], data.size());
+
+				if (testCheck != checkSum)
+				{
+					return checkSumFailed;
+				}
+				else
+				{
+					return noError;
+				}
+			}
+			else
+			{
+				return fileSizeNotBigEnough;
+			}
+
+		}
+		else
+		{
+			return couldNotOpenFinle;
+		}
+	}
+
 	Errors writeEntireFileWithCheckSum(const void* data, size_t size, const char* name)
 	Errors writeEntireFileWithCheckSum(const void* data, size_t size, const char* name)
 	{
 	{
 		std::ofstream f(name, std::ios::binary);
 		std::ofstream f(name, std::ios::binary);
@@ -286,6 +361,42 @@ namespace sfs
 		}
 		}
 	}
 	}
 
 
+	Errors safeLoad(std::vector<char> &data, const char *nameWithoutExtension, bool reportLoadingBackupAsAnError)
+	{
+		data.clear();
+
+		std::string file1 = nameWithoutExtension; file1 += "1.bin";
+		std::string file2 = nameWithoutExtension; file2 += "2.bin";
+
+		auto err = readEntireFileWithCheckSum(data, file1.c_str());
+
+		if (err == noError)
+		{
+			return noError;
+		}
+		else
+		{
+			//load backup
+			auto err2 = readEntireFileWithCheckSum(data, file2.c_str());
+
+			if (err2 == noError)
+			{
+				if (reportLoadingBackupAsAnError)
+				{
+					return readBackup;
+				}
+				else
+				{
+					return noError;
+				}
+			}
+			else
+			{
+				return err2;
+			}
+		}
+	}
+
 	Errors safeLoadBackup(void* data, size_t size, const char* nameWithoutExtension)
 	Errors safeLoadBackup(void* data, size_t size, const char* nameWithoutExtension)
 	{
 	{
 		std::string file2 = nameWithoutExtension; file2 += "2.bin";
 		std::string file2 = nameWithoutExtension; file2 += "2.bin";
@@ -295,6 +406,31 @@ namespace sfs
 		return err2;
 		return err2;
 	}
 	}
 
 
+	Errors safeSave(SafeSafeKeyValueData &data, const char *nameWithoutExtension, bool reportnotMakingBackupAsAnError)
+	{
+		auto rez = data.formatIntoFileData();
+
+		return safeSave(rez.data(), rez.size(), nameWithoutExtension, reportnotMakingBackupAsAnError);
+	}
+
+	Errors safeLoad(SafeSafeKeyValueData &data, const char *nameWithoutExtension, bool reportLoadingBackupAsAnError)
+	{
+		data = {};
+		
+		std::vector<char> readData;
+		auto errCode = safeLoad(readData, nameWithoutExtension, reportLoadingBackupAsAnError);
+
+		if (errCode == noError || errCode == readBackup)
+		{
+			return data.loadFromFileData(readData.data(), readData.size());
+		}
+		else
+		{
+			return errCode;
+		}
+	}
+
+
 #if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__
 #if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__
 
 
 	Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting)
 	Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting)
@@ -404,4 +540,481 @@ namespace sfs
 
 
 #endif	
 #endif	
 
 
+	bool SafeSafeKeyValueData::entryExists(std::string at)
+	{
+		return entries.find(at) != entries.end();
+	}
+
+	Errors SafeSafeKeyValueData::getEntryType(std::string at, char &type)
+	{
+		type = 0;
+
+		auto it = entries.find(at);
+
+		if (it == entries.end()) { return Errors::entryNotFound; }
+
+		type = it->second.type;
+
+		return Errors::noError;
+	}
+
+	Errors SafeSafeKeyValueData::setRawData(std::string at, void *data, size_t size)
+	{
+		auto it = entries.find(at);
+
+		if (it != entries.end())
+		{
+			it->second.type = Entry::Types::rawData_type;
+			it->second.data.clear();
+			it->second.data.resize(size);
+			memcpy(it->second.data.data(), data, size);
+
+			return Errors::warningEntryAlreadyExists;
+		}
+		else
+		{
+			Entry e = {};
+			e.type = Entry::Types::rawData_type;
+			e.data.resize(size);
+			memcpy(e.data.data(), data, size);
+
+			entries.insert({at, std::move(e)});
+
+			return Errors::noError;
+		}
+	}
+
+	Errors SafeSafeKeyValueData::setInt(std::string at, int32_t i)
+	{
+		auto it = entries.find(at);
+
+		if (it != entries.end())
+		{
+			it->second.type = Entry::Types::int_type;
+			it->second.data.clear();
+			it->second.primitives.intData = i;
+
+			return Errors::warningEntryAlreadyExists;
+		}
+		else
+		{
+			Entry e = {};
+
+			e.type = Entry::Types::int_type;
+			e.primitives.intData = i;
+
+			entries.insert({at, std::move(e)});
+
+			return Errors::noError;
+		}
+	}
+
+
+	Errors SafeSafeKeyValueData::getRawDataPointer(std::string at, void *&data, size_t &size)
+	{
+		data = 0;
+		size = 0;
+
+		auto it = entries.find(at);
+
+		if (it == entries.end())
+		{
+			return Errors::entryNotFound;
+		}
+		else
+		{
+			if (it->second.type != Entry::Types::rawData_type)
+			{
+				return Errors::entryHasDifferentDataType;
+			}
+			else
+			{
+				size = it->second.data.size();
+				data = it->second.data.data();
+				return Errors::noError;
+			}
+		}
+	}
+
+	Errors SafeSafeKeyValueData::getInt(std::string at, int32_t &i)
+	{
+		auto it = entries.find(at);
+		
+		if (it == entries.end())
+		{
+			return Errors::entryNotFound;
+		}
+		else
+		{
+			if (it->second.type != Entry::Types::int_type)
+			{
+				return Errors::entryHasDifferentDataType;
+			}
+			else
+			{
+				i = it->second.primitives.intData;
+				return Errors::noError;
+			}
+		}
+	}
+
+	Errors SafeSafeKeyValueData::setFloat(std::string at, float f)
+	{
+		auto it = entries.find(at);
+
+		if (it != entries.end())
+		{
+			it->second.type = Entry::Types::float_type;
+			it->second.data.clear();
+			it->second.primitives.floatData = f;
+
+			return Errors::warningEntryAlreadyExists;
+		}
+		else
+		{
+			Entry e = {};
+
+			e.type = Entry::Types::float_type;
+			e.primitives.floatData = f;
+
+			entries.insert({at, std::move(e)});
+
+			return Errors::noError;
+		}
+	}
+
+
+	Errors SafeSafeKeyValueData::getFloat(std::string at, float &f)
+	{
+		auto it = entries.find(at);
+
+		if (it == entries.end())
+		{
+			return Errors::entryNotFound;
+		}
+		else
+		{
+			if (it->second.type != Entry::Types::float_type)
+			{
+				return Errors::entryHasDifferentDataType;
+			}
+			else
+			{
+				f = it->second.primitives.floatData;
+				return Errors::noError;
+			}
+		}
+	}
+
+	Errors SafeSafeKeyValueData::getBool(std::string at, bool &b)
+	{
+		auto it = entries.find(at);
+
+		if (it == entries.end())
+		{
+			return Errors::entryNotFound;
+		}
+		else
+		{
+			if (it->second.type != Entry::Types::bool_type)
+			{
+				return Errors::entryHasDifferentDataType;
+			}
+			else
+			{
+				b = it->second.primitives.boolData;
+				return Errors::noError;
+			}
+		}
+	}
+
+	Errors SafeSafeKeyValueData::setBool(std::string at, bool b)
+	{
+		auto it = entries.find(at);
+
+		if (it != entries.end())
+		{
+			it->second.type = Entry::Types::bool_type;
+			it->second.data.clear();
+			it->second.data.push_back(b);
+			return Errors::warningEntryAlreadyExists;
+		}
+		else
+		{
+			Entry e = {};
+
+			e.type = Entry::Types::bool_type;
+			e.primitives.boolData = b;
+
+			entries.insert({at, std::move(e)});
+
+			return Errors::noError;
+		}
+	}
+
+	Errors SafeSafeKeyValueData::setString(std::string at, std::string value)
+	{
+		auto it = entries.find(at);
+
+		if (it != entries.end())
+		{
+			it->second.type = Entry::Types::string_type;
+			it->second.data.clear();
+			size_t size = value.length();
+			it->second.data.resize(size);
+			memcpy(it->second.data.data(), value.c_str(), size);
+
+			return Errors::warningEntryAlreadyExists;
+		}
+		else
+		{
+			Entry e = {};
+			e.type = Entry::Types::string_type;
+			size_t size = value.length();
+			e.data.resize(size);
+			memcpy(e.data.data(), value.c_str(), size);
+
+			entries.insert({at, std::move(e)});
+
+			return Errors::noError;
+		}
+	}
+
+	Errors SafeSafeKeyValueData::getString(std::string at, std::string &s)
+	{
+		auto it = entries.find(at);
+
+		if (it == entries.end())
+		{
+			return Errors::entryNotFound;
+		}
+		else
+		{
+			if (it->second.type != Entry::Types::string_type)
+			{
+				return Errors::entryHasDifferentDataType;
+			}
+			else
+			{
+				s.clear();
+				s.resize(it->second.data.size());
+				memcpy(&s[0], it->second.data.data(), it->second.data.size());
+				return Errors::noError;
+			}
+		}
+	}
+
+	std::vector<char> SafeSafeKeyValueData::formatIntoFileData()
+	{
+		std::vector<char> ret;
+		ret.reserve(200);
+
+		size_t size = 0;
+		for (auto &e : entries)
+		{
+			auto &s = e.first;
+			auto &d = e.second;
+
+			size += s.size() + 1;
+			size += d.data.size();
+			size += 1; //type
+			size += 4; //data size
+		}
+
+		ret.reserve(size);
+
+		for (auto &e : entries)
+		{
+			auto &s = e.first;
+			auto &d = e.second;
+			
+			for (auto c : s)
+			{
+				ret.push_back(c);
+			}
+			ret.push_back(0);
+
+			ret.push_back(d.type);
+			
+			if (d.type == Entry::Types::rawData_type || d.type == Entry::Types::string_type)
+			{
+				size_t size = d.data.size();
+				ret.push_back(((char *)(&size))[0]);
+				ret.push_back(((char *)(&size))[1]);
+				ret.push_back(((char *)(&size))[2]);
+				ret.push_back(((char *)(&size))[3]);
+
+				for (auto d : d.data)
+				{
+					ret.push_back(d);
+				}
+			}
+			else if(d.type == Entry::Types::bool_type)
+			{
+				ret.push_back(d.primitives.boolData);
+			}
+			else if (d.type == Entry::Types::int_type)
+			{
+				std::int32_t i = d.primitives.intData;
+				ret.push_back(((char*)(&i))[0]);
+				ret.push_back(((char*)(&i))[1]);
+				ret.push_back(((char*)(&i))[2]);
+				ret.push_back(((char*)(&i))[3]);
+			}
+			else if (d.type == Entry::Types::float_type)
+			{
+				float f = d.primitives.floatData;
+				ret.push_back(((char *)(&f))[0]);
+				ret.push_back(((char *)(&f))[1]);
+				ret.push_back(((char *)(&f))[2]);
+				ret.push_back(((char *)(&f))[3]);
+			}
+
+		}
+
+		return ret;
+	}
+
+	Errors SafeSafeKeyValueData::loadFromFileData(char *data, size_t size)
+	{
+		*this = {};
+
+		std::string currentName = {};
+
+		for (char *c = data; c < data + size; c++)
+		{
+			bool readingName = 1;
+			if (*c == 0)
+			{
+				readingName = 0;
+			}
+			else
+			{
+				currentName.push_back(*c);
+			}
+
+			if (!readingName)
+			{
+				c++; if (c >= data + size) { return Errors::couldNotParseData; }
+
+				char type = *c;
+
+				if (type == Entry::Types::bool_type)
+				{
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					bool b = *c;
+
+					Entry e;
+					e.type = Entry::Types::bool_type;
+					e.primitives.boolData = b;
+
+					entries[currentName] = e;
+				}
+				else if (type == Entry::Types::int_type)
+				{
+					std::int32_t i = 0;
+
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&i))[0] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&i))[1] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&i))[2] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&i))[3] = *c;
+
+					Entry e;
+					e.type = Entry::Types::int_type;
+					e.primitives.intData = i;
+					
+					entries[currentName] = e;
+				}
+				else if (type == Entry::Types::float_type)
+				{
+					float f = 0;
+
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&f))[0] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&f))[1] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&f))[2] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&f))[3] = *c;
+
+					Entry e;
+					e.type = Entry::Types::float_type;
+					e.primitives.floatData = f;
+
+					entries[currentName] = e;
+				}
+				else if (type == Entry::Types::rawData_type)
+				{
+					size_t s = 0;
+
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&s))[0] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&s))[1] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&s))[2] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&s))[3] = *c;
+
+					Entry e;
+					e.type = Entry::Types::rawData_type;
+					e.data.reserve(s);
+
+					for (int i = 0; i < s; i++)
+					{
+						c++; if (c >= data + size) { return Errors::couldNotParseData; }
+						e.data.push_back(*c);
+					}
+					
+					entries[currentName] = std::move(e);
+				}
+				else if (type == Entry::Types::string_type)
+				{
+					size_t s = 0;
+
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&s))[0] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&s))[1] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&s))[2] = *c;
+					c++; if (c >= data + size) { return Errors::couldNotParseData; }
+					((char *)(&s))[3] = *c;
+
+					Entry e;
+					e.type = Entry::Types::string_type;
+					e.data.reserve(s);
+
+					for (int i = 0; i < s; i++)
+					{
+						c++; if (c >= data + size) { return Errors::couldNotParseData; }
+						e.data.push_back(*c);
+					}
+
+					entries[currentName] = std::move(e);
+
+				}
+
+				currentName = {};
+			}
+
+		}
+
+		if (currentName == "")
+		{
+			return Errors::noError;
+		}
+		else
+		{
+			return Errors::couldNotParseData;
+		}
+
+	}
+
+
 }
 }