Browse Source

working at mario level

meemknight 2 years ago
parent
commit
31064e5dff

+ 1 - 1
Pika/core/pikaEditor/editor/editor.cpp

@@ -12,7 +12,7 @@
 #include "IconsForkAwesome.h"
 #include "shortcutApi/shortcutApi.h"
 #include <editShortcuts/editShortcuts.h>
-#include <safeSave.h>
+#include <safeSave/safeSave.h>
 
 
 

+ 1 - 1
Pika/core/pikaRuntime/containerManager/containerManager.cpp

@@ -228,7 +228,7 @@ pika::containerId_t pika::ContainerManager::createContainer
 	container.requestedContainerInfo.consoleWindow = consoleWindow;
 #pragma endregion
 
-	pika::StaticString<256> cmdArgs;
+	pika::StaticString<256> cmdArgs = {};
 	
 	if (cmd.size() > cmdArgs.MAX_SIZE)
 	{

+ 0 - 2
Pika/core/pikaRuntime/pikaMain.cpp

@@ -184,8 +184,6 @@ int main()
 	(loadedDll.containerInfo[0], loadedDll, logs, imguiIdsManager, nullptr, std::string());
 #endif
 
-	
-
 	while (!shouldClose)
 	{
 		if (window.shouldClose())

+ 1 - 1
Pika/core/sharedRuntime/windowSystemm/window.cpp

@@ -10,7 +10,7 @@
 
 #include <pikaSizes.h>
 
-#include <safeSave.h>
+#include <safeSave/safeSave.h>
 
 struct WindowRect
 {

BIN
Pika/engineResources/engineSaves/options1.bin


BIN
Pika/engineResources/engineSaves/options2.bin


BIN
Pika/engineResources/engineSaves/window1.bin


BIN
Pika/engineResources/engineSaves/window2.bin


BIN
Pika/engineResources/test.snapshot


+ 5 - 2
Pika/gameplay/containers.h

@@ -15,6 +15,8 @@ Container *getContainer(const char* name, pika::memory::MemoryArena *memoryArena
 
 #include "containers/pikaGameplay.h"
 #include "containers/threedtest.h"
+#include "containers/mario/mario.h"
+#include "containers/mario/marioEditor.h"
 #include "pluggins/immageviewer.h"
 #include "pluggins/threeDEditor.h"
 #include "pluggins/pikatextEditor.h"
@@ -24,5 +26,6 @@ Container *getContainer(const char* name, pika::memory::MemoryArena *memoryArena
 	PIKA_DECLARE_CONTAINER(ImmageViewer) \
 	PIKA_DECLARE_CONTAINER(ThreeDTest) \
 	PIKA_DECLARE_CONTAINER(ThreeDEditor) \
-	PIKA_DECLARE_CONTAINER(PikaTextEditor)
-
+	PIKA_DECLARE_CONTAINER(PikaTextEditor) \
+	PIKA_DECLARE_CONTAINER(Mario) \
+	PIKA_DECLARE_CONTAINER(MarioEditor)

+ 126 - 0
Pika/gameplay/containers/mario/mario.h

@@ -0,0 +1,126 @@
+#pragma once
+
+#include <gl2d/gl2d.h>
+#include <imgui.h>
+#include <baseContainer.h>
+#include <shortcutApi/shortcutApi.h>
+#include <pikaSizes.h>
+#include "marioCommon.h"
+
+struct Mario: public Container
+{
+
+	gl2d::Renderer2D renderer;
+	gl2d::Texture tiles;
+	gl2d::TextureAtlasPadding atlas;
+	
+
+	//todo user can request imgui ids; shortcut manager context; allocators
+	static ContainerStaticInfo containerInfo()
+	{
+		ContainerStaticInfo info = {};
+		info.defaultHeapMemorySize = pika::MB(10);
+
+		info.requestImguiFbo = true; //todo this should not affect the compatibility of input recording
+
+
+
+		return info;
+	}
+
+
+	bool create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
+	{
+		renderer.create();
+		//gl2d::setErrorFuncCallback() //tood
+		//pika::initShortcutApi();
+
+		size_t s = 0;
+		if (requestedInfo.getFileSizeBinary(PIKA_RESOURCES_PATH "/mario/1985_tiles.png", s))
+		{
+			void *data = new unsigned char[s];
+			if (requestedInfo.readEntireFileBinary(PIKA_RESOURCES_PATH "/mario/1985_tiles.png", data, s))
+			{
+				tiles.createFromFileDataWithPixelPadding((unsigned char*)data, s, 8, true, false);
+
+			}
+			else { return 0; }
+
+			delete[] data;
+		}
+		else { return 0; }
+
+
+		atlas = gl2d::TextureAtlasPadding(8, 10, 8*8, 8*10);
+
+
+		return true;
+	}
+
+	bool update(pika::Input input, pika::WindowState windowState,
+		RequestedContainerInfo &requestedInfo)
+	{
+		//todo keep window on top stuff
+
+		glClear(GL_COLOR_BUFFER_BIT);
+		gl2d::enableNecessaryGLFeatures();
+
+
+		renderer.updateWindowMetrics(windowState.w, windowState.h);
+
+
+		renderer.renderRectangle({10, 10, 100, 100}, {}, {}, tiles, atlas.get(3, 5));
+
+
+		int size = 20;
+		renderer.renderRectangle({input.mouseX - size / 2, input.mouseY - size / 2, size, size},
+			Colors_Turqoise, {}, 0.f);
+
+
+
+		//requestedInfo.consoleWrite((std::string("Mouse: ") + std::to_string(input.mouseX) + " " +
+		//	std::to_string(input.mouseY) + "\n").c_str());
+
+
+		//if (input.lMouse.pressed())
+		//{
+		//	std::cout << "pressed\n";
+		//}
+		//if (input.lMouse.released())
+		//{
+		//	std::cout << "released\n";
+		//}
+
+		//if (input.lMouse.typed())
+		//{
+		//	std::cout << "typed\n";
+		//}
+
+		//if (input.buttons[pika::Button::E].typed())
+		//{
+		//	std::cout << "e";
+		//}
+
+		//std::cout << state.deltaTime << "\n";
+
+		renderer.flush();
+
+		//ImGui::SetAllocatorFunctions(userMalloc, userFree);
+
+		//ImGui::Begin("window from gameplay");
+		//ImGui::Spinner("spinner", 10, 2);
+		//ImGui::ProgressBar(0.4);
+		//ImGui::BufferingBar("buffering bar", 0.4, {100, 5});
+		//ImGui::LoadingIndicatorCircle("circle", 20, 8, 8);
+		//ImGui::End();
+
+		//ImGui::ShowDemoWindow();
+
+		return true;
+	}
+
+};
+
+//todo flag to clear screen from engine
+//todo error popup
+//todo error popup disable in release

+ 15 - 0
Pika/gameplay/containers/mario/marioCommon.cpp

@@ -0,0 +1,15 @@
+#include "marioCommon.h"
+
+
+
+bool isSolid(int id)
+{
+	return(collisionMap[id] == 'X');
+}
+
+glm::vec4 getTileUV(gl2d::TextureAtlasPadding atlas, int id, int flip)
+{
+	int x = id % 8;
+	int y = id / 8;
+	return atlas.get(x, y, flip);
+}

+ 21 - 0
Pika/gameplay/containers/mario/marioCommon.h

@@ -0,0 +1,21 @@
+#pragma once
+#include <gl2d/gl2d.h>
+
+
+
+constexpr const char *collisionMap =
+"XX-X-XXX"
+"XX-XXXXX"
+"--------"
+"-XX--X--"
+"-XX-----"
+"-XX-XXXX"
+"--X-XXX-"
+"XX------"
+"XX--XX--"
+"XXXXXX--"
+;
+
+bool isSolid(int id);
+
+glm::vec4 getTileUV(gl2d::TextureAtlasPadding atlas, int id, int flip = 0);

+ 386 - 0
Pika/gameplay/containers/mario/marioEditor.h

@@ -0,0 +1,386 @@
+#pragma once
+
+#include <gl2d/gl2d.h>
+#include <imgui.h>
+#include <baseContainer.h>
+#include <shortcutApi/shortcutApi.h>
+#include <pikaSizes.h>
+#include "marioCommon.h"
+#include <safeSave/safeSave.h>
+
+struct MarioEditor: public Container
+{
+
+	gl2d::Renderer2D renderer;
+	gl2d::Texture tiles;
+	gl2d::TextureAtlasPadding atlas;
+	glm::ivec2 mapSize = {100, 100};
+
+	char path[257] = {};
+
+	glm::vec2 pos = {};
+
+	int currentBlock = 0;
+	bool flip = 0;
+
+	struct Block
+	{
+		unsigned char type : 7;
+		unsigned char flipped : 1;
+	};
+
+	Block *map;
+
+	Block &getMapBlockUnsafe(int x, int y)
+	{
+		return map[x + y * mapSize.x];
+	}
+
+	//todo user can request imgui ids; shortcut manager context; allocators
+	static ContainerStaticInfo containerInfo()
+	{
+		ContainerStaticInfo info = {};
+		info.defaultHeapMemorySize = pika::MB(10);
+
+		info.requestImguiFbo = true;
+		info.requestImguiIds = 1;
+
+		info.extensionsSuported = {".mario"};
+
+		return info;
+	}
+
+
+	bool create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
+	{
+
+		renderer.create();
+		//gl2d::setErrorFuncCallback() //tood
+		//pika::initShortcutApi();
+
+		size_t s = 0;
+		if (requestedInfo.getFileSizeBinary(PIKA_RESOURCES_PATH "/mario/1985_tiles.png", s))
+		{
+			void *data = new unsigned char[s];
+			if (requestedInfo.readEntireFileBinary(PIKA_RESOURCES_PATH "/mario/1985_tiles.png", data, s))
+			{
+				tiles.createFromFileDataWithPixelPadding((unsigned char*)data, s, 8, true, false);
+
+			}
+			else { return 0; }
+
+			delete[] data;
+		}
+		else { return 0; }
+
+
+		atlas = gl2d::TextureAtlasPadding(8, 10, 8*8, 8*10);
+
+
+		map = new Block[mapSize.x * mapSize.y];
+		Block d{27,0};
+		memset(map, *(int *)(&d), mapSize.x * mapSize.y);
+
+		if (commandLineArgument.size() != 0)
+		{
+			memcpy(path, commandLineArgument.data(), commandLineArgument.size());
+
+			size_t s = 0;
+			if (requestedInfo.getFileSizeBinary(commandLineArgument.to_string().c_str(), s))
+			{
+				if (s == mapSize.x * mapSize.y)
+				{
+					requestedInfo.readEntireFileBinary(commandLineArgument.to_string().c_str(), map, mapSize.x * mapSize.y);
+				}
+			}
+
+		}
+
+		return true;
+	}
+
+	bool update(pika::Input input, pika::WindowState windowState,
+		RequestedContainerInfo &requestedInfo)
+	{
+		{
+			glClear(GL_COLOR_BUFFER_BIT);
+			gl2d::enableNecessaryGLFeatures();
+			renderer.updateWindowMetrics(windowState.w, windowState.h);
+		}
+		
+		{
+			float wheel = ImGui::GetIO().MouseWheel;
+
+			//todo standard out
+
+			if ((ImGui::GetIO().KeysData[ImGuiKey_LeftCtrl].Down || ImGui::GetIO().KeysData[ImGuiKey_RightCtrl].Down) && input.hasFocus)
+			{
+				renderer.currentCamera.zoom += wheel * 3;
+			}
+
+			renderer.currentCamera.zoom = std::min(renderer.currentCamera.zoom, 200.f);
+			renderer.currentCamera.zoom = std::max(renderer.currentCamera.zoom, 10.f);
+
+			glm::vec2 delta = {};
+
+			if (input.hasFocus)
+			{
+				if (input.buttons[pika::Button::A].held())
+				{
+					delta.x -= 1;
+				}
+				if (input.buttons[pika::Button::D].held())
+				{
+					delta.x += 1;
+				}
+				if (input.buttons[pika::Button::W].held())
+				{
+					delta.y -= 1;
+				}
+				if (input.buttons[pika::Button::S].held())
+				{
+					delta.y += 1;
+				}
+			}
+
+			float speed = 10;
+
+			delta *= input.deltaTime * speed;
+
+			pos += delta;
+
+			//todo update gl2d this function
+
+			renderer.currentCamera.follow(pos, input.deltaTime * speed * 0.9f, 0.0001, 0.2, windowState.w, windowState.h);
+
+		}
+		auto viewRect = renderer.getViewRect();
+
+		glm::ivec2 minV;
+		glm::ivec2 maxV;
+		//render
+		{
+
+			minV = {viewRect.x-1, viewRect.y-1};
+			maxV = minV + glm::ivec2{viewRect.z+2, viewRect.w+2};
+			minV = glm::max(minV, {0,0});
+			maxV = glm::min(maxV, mapSize);
+		
+		
+			for (int j = minV.y; j < maxV.y; j++)
+				for (int i = minV.x; i < maxV.x; i++)
+				{
+					auto b = getMapBlockUnsafe(i, j);
+					auto uv = getTileUV(atlas, b.type, b.flipped);
+
+					renderer.renderRectangle({i, j, 1, 1}, {}, {}, tiles, uv);
+
+				}
+		}
+
+		//mouse pos
+		glm::ivec2 blockPosition;
+		{
+			glm::ivec2 mousePos(input.mouseX, input.mouseY);
+
+			auto lerp = [](auto a, auto b, auto c)
+			{
+				return a * (1.f - c) + b * c;
+			};
+
+			blockPosition = lerp(glm::vec2(viewRect.x, viewRect.y),
+				glm::vec2(viewRect.x + viewRect.z, viewRect.y + viewRect.w), glm::vec2(mousePos) / glm::vec2(windowState.w, windowState.h));
+
+			if (blockPosition.x >= maxV.x || blockPosition.y >= maxV.y || blockPosition.x < minV.x || blockPosition.y < minV.y)
+			{
+				blockPosition = {-1,-1};
+			}
+			else
+			{
+			renderer.renderRectangle({blockPosition, 1, 1}, {0.9,0.9,0.9,0.9}, {}, {}, tiles, 
+				getTileUV(atlas, currentBlock, flip));
+			}
+
+		}
+
+
+		ImGui::Begin("Block picker");
+		{
+			bool collidable = true;
+			bool nonCollidable = true;
+
+			ImGui::Checkbox("Show Collidable Blocks", &collidable);
+			ImGui::Checkbox("Show Non-Collidable Blocks", &nonCollidable);
+			ImGui::Checkbox("Flip", &flip);
+			ImGui::Text("MousePos: %d, %d", blockPosition.x, blockPosition.y);
+
+			ImGui::InputText("Save file", path, sizeof(path));
+			
+			if (ImGui::Button("save"))
+			{
+				pika::memory::setGlobalAllocatorToStandard();
+				sfs::writeEntireFile((void*)map, mapSize.x * mapSize.y, path);
+				pika::memory::setGlobalAllocator(requestedInfo.mainAllocator);
+			}
+
+			ImGui::Separator();
+
+			unsigned short mCount = 0;
+			ImGui::BeginChild("Block Selector");
+			bool inImgui = ImGui::IsWindowHovered();
+
+			if (collidable && nonCollidable)
+			{
+				unsigned short localCount = 0;
+				while (mCount < 8*10)
+				{
+					auto uv = getTileUV(atlas, mCount);
+
+					ImGui::PushID(mCount);
+					if (ImGui::ImageButton((void *)(intptr_t)tiles.id,
+						{35,35}, {uv.x, uv.y}, {uv.z, uv.w}))
+					{
+						currentBlock = mCount;
+					}
+
+					ImGui::PopID();
+
+					if (localCount % 10 != 0)
+					{
+						ImGui::SameLine();
+					}
+					localCount++;
+
+					mCount++;
+				}
+			}
+			else
+			{
+				if (collidable && !nonCollidable)
+				{
+					unsigned short localCount = 0;
+					while (mCount < 8 * 10)
+					{
+						if (isSolid(mCount))
+						{
+							auto uv = getTileUV(atlas, mCount);
+
+							ImGui::PushID(mCount);
+							if (ImGui::ImageButton((void *)(intptr_t)tiles.id,
+								{35,35}, {uv.x, uv.y}, {uv.z, uv.w}));
+							{
+								currentBlock = mCount;
+							}
+							ImGui::PopID();
+
+							if (localCount % 10 != 0)
+							{
+								ImGui::SameLine();
+							}
+							localCount++;
+
+						}
+						mCount++;
+					}
+				}
+				else if (!collidable && nonCollidable)
+				{
+					unsigned short localCount = 0;
+					while (mCount < 8*10)
+					{
+						if (!isSolid(mCount))
+						{
+							auto uv = getTileUV(atlas, mCount);
+
+							ImGui::PushID(mCount);
+							if (ImGui::ImageButton((void *)(intptr_t)tiles.id,
+								{35,35}, {uv.x, uv.y}, {uv.z, uv.w}));
+							{
+								currentBlock = mCount;
+							}
+							ImGui::PopID();
+
+							if (localCount % 10 != 0)
+							{
+								ImGui::SameLine();
+							}
+							localCount++;
+
+						}
+						mCount++;
+					}
+				}
+			}
+			ImGui::EndChild();
+
+
+
+		}
+		ImGui::End();
+
+	
+
+		if (input.hasFocus && input.lMouse.held() && blockPosition.x >= 0)
+		{
+			if (input.buttons[pika::Button::LeftCtrl].held())
+			{
+
+				currentBlock = getMapBlockUnsafe(blockPosition.x, blockPosition.y).type;
+				flip = getMapBlockUnsafe(blockPosition.x, blockPosition.y).flipped;
+
+			}
+			else
+			{
+				getMapBlockUnsafe(blockPosition.x, blockPosition.y).type = currentBlock;
+				getMapBlockUnsafe(blockPosition.x, blockPosition.y).flipped = flip;
+
+			}
+
+		}
+
+		//requestedInfo.consoleWrite((std::string("Mouse: ") + std::to_string(input.mouseX) + " " +
+		//	std::to_string(input.mouseY) + "\n").c_str());
+
+
+		//if (input.lMouse.pressed())
+		//{
+		//	std::cout << "pressed\n";
+		//}
+		//if (input.lMouse.released())
+		//{
+		//	std::cout << "released\n";
+		//}
+
+		//if (input.lMouse.typed())
+		//{
+		//	std::cout << "typed\n";
+		//}
+
+		//if (input.buttons[pika::Button::E].typed())
+		//{
+		//	std::cout << "e";
+		//}
+
+		//std::cout << state.deltaTime << "\n";
+
+		renderer.flush();
+
+		//ImGui::SetAllocatorFunctions(userMalloc, userFree);
+
+		//ImGui::Begin("window from gameplay");
+		//ImGui::Spinner("spinner", 10, 2);
+		//ImGui::ProgressBar(0.4);
+		//ImGui::BufferingBar("buffering bar", 0.4, {100, 5});
+		//ImGui::LoadingIndicatorCircle("circle", 20, 8, 8);
+		//ImGui::End();
+
+		//ImGui::ShowDemoWindow();
+
+		return true;
+	}
+
+};
+
+//todo flag to clear screen from engine
+//todo error popup
+//todo error popup disable in release

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

@@ -64,18 +64,21 @@ struct Gameplay : public Container
 
 		glClear(GL_COLOR_BUFFER_BIT);
 
-		//if (pika::shortcut(input, "Ctrl + S"))
-		if (input.buttons[pika::Button::S].released())
+		if (pika::shortcut(input, "Ctrl + S"))
 		{
 			requestedInfo.consoleWrite("save\n");
 		}
+		
+		//if (input.buttons[pika::Button::S].released())
+		//{
+		//	requestedInfo.consoleWrite("save\n");
+		//}
 
 		//if (input.buttons[pika::Button::G].released())
 		//{
 		//	return 0;
 		//}
 
-
 		requestedInfo.consoleWrite(input.typedInput);
 
 

+ 3 - 3
Pika/pluggins/pluggins/immageViewer.h

@@ -27,6 +27,7 @@ struct ImmageViewer: public Container
 
 		info.requestImguiIds = 1;
 
+
 		return info;
 	}
 
@@ -43,7 +44,6 @@ struct ImmageViewer: public Container
 		//}
 		//pika::memory::setGlobalAllocator(requestedInfo.mainAllocator);
 
-
 		size_t size = 0;
 		if (!requestedInfo.getFileSizeBinary(file.c_str(), size))
 		{
@@ -71,7 +71,6 @@ struct ImmageViewer: public Container
 	bool update(pika::Input input, pika::WindowState windowState,
 		RequestedContainerInfo &requestedInfo) override
 	{
-
 		//todo deffer
 		ImGui::PushID(requestedInfo.requestedImguiIds);
 
@@ -109,8 +108,9 @@ struct ImmageViewer: public Container
 		float wheel = ImGui::GetIO().MouseWheel;
 
 		//todo standard out
+		//todo small libraries for functionality like this
 
-		if (ImGui::GetIO().KeysData[ImGuiKey_LeftCtrl].Down || ImGui::GetIO().KeysData[ImGuiKey_RightCtrl].Down)
+		if ((ImGui::GetIO().KeysData[ImGuiKey_LeftCtrl].Down || ImGui::GetIO().KeysData[ImGuiKey_RightCtrl].Down) && input.hasFocus)
 		{
 			zoom += wheel * 0.2;
 		}

+ 8 - 6
Pika/resources/logs.txt

@@ -1,6 +1,8 @@
-#2023-01-26 15:42:05: Created container: Gameplay
-#2023-01-26 15:42:07: Created container: PikaTextEditor
-#2023-01-26 15:42:18: Created container: PikaTextEditor
-#2023-01-26 15:42:20: Destroyed continer: Gameplay #1
-#2023-01-26 15:42:20: Destroyed continer: PikaTextEditor #2
-#2023-01-26 15:42:20: Destroyed continer: PikaTextEditor #3
+#2023-01-27 13:53:38: Created container: Gameplay
+#2023-01-27 13:53:43: Destroyed continer: Gameplay #1
+#2023-01-27 13:53:47: Created container: MarioEditor
+#2023-01-27 13:53:49: Created container: ImmageViewer
+#2023-01-27 13:57:04: Destroyed continer: MarioEditor #2
+#2023-01-27 13:57:14: Created container: MarioEditor
+#2023-01-27 14:03:07: Destroyed continer: ImmageViewer #3
+#2023-01-27 14:03:07: Destroyed continer: MarioEditor #4

BIN
Pika/resources/mario/1985_reference.png


BIN
Pika/resources/mario/1985_tiles.png


BIN
Pika/resources/mario/map1.mario


+ 2 - 2
Pika/thirdparty/gl2d/include/gl2d/gl2d.h

@@ -50,7 +50,7 @@
 #define GL2D_OPNEGL_SHADER_PRECISION "precision highp float;"
 
 //this is the default capacity of the renderer
-#define GL2D_Renderer2D_Max_Triangle_Capacity 4200
+#define GL2D_Renderer2D_Max_Triangle_Capacity 42000
 #define GL2D_DefaultTextureCoords (glm::vec4{ 0, 1, 1, 0 })
 
 #include <glad/glad.h>
@@ -254,7 +254,7 @@ namespace gl2d
 		void setDefault() { *this = Camera{}; }
 		glm::mat3 getMatrix();
 
-		void follow(glm::vec2 pos, float speed, float max, float w, float h);
+		void follow(glm::vec2 pos, float speed, float min, float max, float w, float h);
 
 		glm::vec2 convertPoint(const glm::vec2 &p, float windowW, float windowH); //todo move to internal
 	};

+ 18 - 4
Pika/thirdparty/gl2d/src/gl2d.cpp

@@ -1748,26 +1748,30 @@ namespace gl2d
 		return m; //todo not tested, add rotation
 	}
 
-	void Camera::follow(glm::vec2 pos, float speed, float max, float w, float h)
+	void Camera::follow(glm::vec2 pos, float speed, float min, float max, float w, float h)
 	{
 		pos.x -= w / 2.f;
 		pos.y -= h / 2.f;
 
 		glm::vec2 delta = pos - position;
+		bool signX = delta.x >= 0;
+		bool signY = delta.y >= 0;
+
 		float len = glm::length(delta);
 
 		delta = glm::normalize(delta);
 
-		if (len < 4.f)
+		if (len < min * 2)
 		{
 			speed /= 4.f;
 		}
-		else if (len < 8.f)
+		else if (len < min * 4)
 		{
 			speed /= 2.f;
 		}
 
-		if (len > 2.f)
+		if (len > min)
+		{
 			if (len > max)
 			{
 				len = max;
@@ -1777,8 +1781,18 @@ namespace gl2d
 			else
 			{
 				position += delta * speed;
+
+
 			}
 
+			glm::vec2 delta2 = pos - position;
+			bool signX2 = delta.x >= 0;
+			bool signY2 = delta.y >= 0;
+			if (signX2 != signX || signY2 != signY || glm::length(delta2) > len)
+			{
+				position = pos;
+			}
+		}
 	}
 
 	glm::vec2 Camera::convertPoint(const glm::vec2 &p, float windowW, float windowH)

+ 0 - 0
Pika/thirdparty/safeSafe/include/safeSave.h → Pika/thirdparty/safeSafe/include/safeSave/safeSave.h


+ 1 - 1
Pika/thirdparty/safeSafe/src/safeSave.cpp

@@ -6,7 +6,7 @@
 // 
 ///////////////////////////////////////////
 
-#include <safeSave.h>
+#include <safeSave/safeSave.h>
 
 #if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__
 #define NOMINMAX