Browse Source

some refactorings and save editor stuff

vlod 3 years ago
parent
commit
7faf397534
37 changed files with 1223 additions and 97 deletions
  1. 4 3
      Pika/CMakeLists.txt
  2. 4 2
      Pika/core/coreConfig/pikaConfig.h
  3. 113 27
      Pika/core/pikaEditor/containersWindow/containersWindow.cpp
  4. 4 1
      Pika/core/pikaEditor/containersWindow/containersWindow.h
  5. 1 0
      Pika/core/pikaEditor/editShortcuts/editShortcuts.cpp
  6. 26 2
      Pika/core/pikaEditor/editor/editor.cpp
  7. 5 2
      Pika/core/pikaEditor/editor/editor.h
  8. 279 9
      Pika/core/pikaRuntime/containerManager/containerManager.cpp
  9. 16 2
      Pika/core/pikaRuntime/containerManager/containerManager.h
  10. 43 13
      Pika/core/pikaRuntime/pikaMain.cpp
  11. 24 8
      Pika/core/pikaRuntime/runtimeContainer/runtimeContainer.h
  12. 1 0
      Pika/core/pikaSTD/pikaAllocator/freeListAllocator.cpp
  13. 2 1
      Pika/core/pikaSTD/pikaAllocator/freeListAllocator.h
  14. 70 0
      Pika/core/pikaSTD/pikaGL/frameBuffer.cpp
  15. 32 0
      Pika/core/pikaSTD/pikaGL/frameBuffer.h
  16. 1 0
      Pika/core/pikaSTD/pikaSizes.h
  17. 11 2
      Pika/core/sharedRuntime/baseContainer.h
  18. 13 3
      Pika/core/sharedRuntime/pushNotification/pushNotification.cpp
  19. 1 0
      Pika/core/sharedRuntime/windowSystemm/callbacks.cpp
  20. 4 1
      Pika/core/sharedRuntime/windowSystemm/input.h
  21. 40 4
      Pika/core/sharedRuntime/windowSystemm/window.cpp
  22. 2 2
      Pika/core/sharedRuntime/windowSystemm/window.h
  23. BIN
      Pika/engineResources/engineSaves/options1.bin
  24. BIN
      Pika/engineResources/engineSaves/options2.bin
  25. BIN
      Pika/engineResources/engineSaves/window1.bin
  26. BIN
      Pika/engineResources/engineSaves/window2.bin
  27. BIN
      Pika/engineResources/engineSaves/windowPos1.bin
  28. BIN
      Pika/engineResources/engineSaves/windowPos2.bin
  29. BIN
      Pika/engineResources/test1.snapshot
  30. BIN
      Pika/engineResources/testWithoutImguiStuff.snapshot
  31. BIN
      Pika/engineResources/testwithimgui.snapshot
  32. 17 12
      Pika/gameplay/containers/pikaGameplay.h
  33. 1 1
      Pika/pluggins/pluggins/immageViewer.h
  34. 2 2
      Pika/resources/logs.txt
  35. 7 0
      Pika/thirdparty/safeSafe/CMakeLists.txt
  36. 93 0
      Pika/thirdparty/safeSafe/include/safeSave.h
  37. 407 0
      Pika/thirdparty/safeSafe/src/safeSave.cpp

+ 4 - 3
Pika/CMakeLists.txt

@@ -29,6 +29,7 @@ add_subdirectory(thirdparty/glm)
 add_subdirectory(thirdparty/stb_image)
 add_subdirectory(thirdparty/stb_truetype)
 add_subdirectory(thirdparty/imgui-docking)
+add_subdirectory(thirdparty/safeSafe)
 
 
 #Define some macros for the project sources
@@ -71,7 +72,7 @@ target_include_directories(pikaCore PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/pik
 target_include_directories(pikaCore PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/pikaRuntime/")
 target_include_directories(pikaCore PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/pikaSTD/")
 target_include_directories(pikaCore PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/sharedRuntime/")
-target_link_libraries(pikaCore PRIVATE glad glfw gl2d glm stb_image stb_truetype imgui)
+target_link_libraries(pikaCore PRIVATE glad glfw gl2d glm stb_image stb_truetype imgui safeSave)
 #################^^^^^^^^#############################
 
 
@@ -87,7 +88,7 @@ target_include_directories(pikaGameplay PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core
 target_include_directories(pikaGameplay PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/gameplay/")
 target_include_directories(pikaGameplay PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/sharedRuntime/")
 target_include_directories(pikaGameplay PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/pluggins/")
-target_link_libraries(pikaGameplay PRIVATE glad glfw gl2d glm stb_image stb_truetype imgui)
+target_link_libraries(pikaGameplay PRIVATE glad glfw gl2d glm stb_image stb_truetype imgui safeSave)
 #################^^^^^^^^^^^^^^############################
 
 
@@ -109,7 +110,7 @@ target_include_directories(pikaProduction PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/ga
 target_include_directories(pikaProduction PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/core/sharedRuntime/")
 target_include_directories(pikaProduction PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/pluggins/")
 
-target_link_libraries(pikaProduction PRIVATE glad glfw gl2d glm stb_image stb_truetype imgui)
+target_link_libraries(pikaProduction PRIVATE glad glfw gl2d glm stb_image stb_truetype imgui safeSave)
 
 
 

+ 4 - 2
Pika/core/coreConfig/pikaConfig.h

@@ -49,8 +49,8 @@
 #define PIKA_ENABLE_CONSOLE 1
 
 
-#define PIKA_CLEAR_SCREEN_BY_ENGINE 1
-#define PIKA_CLEAR_DEPTH_BY_ENGINE 0
+#define PIKA_CLEAR_SCREEN_BY_ENGINE_IN_PRODUCTION 0
+#define PIKA_CLEAR_DEPTH_BY_ENGINE_IN_PRODUCTION 0
 
 //todo ? not implemented
 //makes the main window a docking space or not in production build
@@ -60,6 +60,8 @@
 #define PIKA_REMOVE_IMGUI_IN_PRODUCTION 0
 
 
+ #define PIKA_ENGINE_SAVES_PATH PIKA_ENGINE_RESOURCES_PATH "/engineSaves/"
+
 
 #include <pikaConfigInternal.h>
 

+ 113 - 27
Pika/core/pikaEditor/containersWindow/containersWindow.cpp

@@ -9,7 +9,7 @@ void pika::ContainersWindow::init()
 }
 
 void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pika::LoadedDll &loadedDll,
-	pika::ContainerManager &containerManager)
+	pika::ContainerManager &containerManager, pika::pikaImgui::ImGuiIdsManager &imguiIdsManager)
 {
 	//todo imgui firsttime stuff for all windows
 	ImGui::PushID(pikaImgui::EditorImguiIds::containersWindow);
@@ -145,21 +145,79 @@ void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pi
 							{
 								ImGui::NewLine();
 
+
 								if (!selectedContainerToLaunch.empty()
 									&& ImGui::Button(ICON_FK_PLAY " Launch a default configuration"))
 								{
-									containerManager.createContainer(selectedContainerToLaunch, loadedDll, logManager);
+									if (createAtSpecificMemoryRegion)
+									{
+										containerManager.createContainer(selectedContainerToLaunch, loadedDll,
+											logManager, imguiIdsManager, pika::TB(1));
+									}
+									else
+									{
+										containerManager.createContainer(selectedContainerToLaunch, loadedDll, logManager,
+											imguiIdsManager);
+									}
 								}
 
-								ImGui::NewLine();
+								ImGui::Checkbox("allocate at specific memory region", &createAtSpecificMemoryRegion);
 
 
-								if (!selectedContainerToLaunch.empty()
-									&& ImGui::Button(ICON_FK_PICTURE_O " Launch a snapshot"))
+								//ImGui::NewLine();
+
 								{
-									//containerManager.createContainer(selectedContainerToLaunch, loadedDll, logManager);
+									static int currentSelectedSnapshot = 0;
+									auto snapshots = pika::getAvailableSnapshotsAnyMemoryPosition(c);
+
+									if (!selectedContainerToLaunch.empty()
+										&& ImGui::Button(ICON_FK_PICTURE_O " Launch a snapshot"))
+									{
+										auto s = snapshots[currentSelectedSnapshot];
+
+										auto memPos = getSnapshotMemoryPosition(s.c_str());
+
+										if (memPos == nullptr)
+										{
+											logManager.log("Failes to get snapshot info", pika::logError);
+										}
+										else
+										{
+
+											auto c = containerManager.createContainer(
+												selectedContainerToLaunch, loadedDll, logManager,
+												imguiIdsManager, (size_t)memPos);
+
+											//no need to log error since create container does that
+											if (c != 0)
+											{
+												if (!containerManager.setSnapshotToContainer(c,
+													s.c_str(), logManager))
+												{
+													containerManager.destroyContainer(c, loadedDll, logManager);
+												}
+											}
+
+
+										}
+
+										
+									
+									
+									}
+
+
+									auto contentSize = ImGui::GetItemRectSize();
+									contentSize.y -= ImGui::GetFrameHeightWithSpacing();
+									//contentSize.x /= 2;
+
+									ImGui::ListWithFilter("##list box snapshots", &currentSelectedSnapshot,
+										filterSnapshots, sizeof(filterSnapshots),
+										snapshots, contentSize);
 								}
 
+								
+
 								ImGui::EndTabItem();
 							}
 
@@ -260,11 +318,11 @@ void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pi
 							pika::pikaImgui::alignForWidth(width);
 						}
 
-						if (c.flags.running)
+						if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_RUNNING)
 						{
 							if (ImGui::Button(ICON_FK_PAUSE))
 							{
-								c.flags.running = 0;
+								c.flags.status = pika::RuntimeContainer::FLAGS::STATUS_PAUSE;
 							}
 
 							if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
@@ -272,11 +330,11 @@ void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pi
 								ImGui::SetTooltip("Pause container.");
 							}
 						}
-						else
+						else if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_PAUSE)
 						{
 							if (ImGui::Button(ICON_FK_PLAY))
 							{
-								c.flags.running = 1;
+								c.flags.status = pika::RuntimeContainer::FLAGS::STATUS_RUNNING;
 							}
 
 							if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
@@ -284,6 +342,20 @@ void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pi
 								ImGui::SetTooltip("Resume container.");
 							}
 						}
+						else
+						{
+							ImGui::BeginDisabled();
+							if (ImGui::Button(ICON_FK_PAUSE))
+							{
+							}
+							ImGui::EndDisabled();
+
+							if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
+							{
+								ImGui::SetTooltip("Can't pause container while it is recorded."); //todo implement
+							}
+						}
+
 
 						ImGui::SameLine();
 
@@ -324,34 +396,48 @@ void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pi
 							ImGui::Separator();
 
 
-
-							if (ImGui::Button(ICON_FK_CAMERA))
 							{
-								if (pika::isFileNameValid(snapshotName, sizeof(snapshotName)))
+								if (ImGui::Button(ICON_FK_CAMERA))
 								{
-									if (!containerManager.makeSnapshot(containerIds[itemCurrentCreatedContainers], logManager, snapshotName))
+									if (pika::isFileNameValid(snapshotName, sizeof(snapshotName)))
 									{
-										logManager.log("Coultn't make snapshot", pika::logError);
-									}else
+										if (!containerManager.makeSnapshot(containerIds[itemCurrentCreatedContainers], logManager, snapshotName))
+										{
+											logManager.log("Coultn't make snapshot", pika::logError);
+										}
+										else
+										{
+											logManager.log("Successfully created snapshot.");
+										}
+									}
+									else
 									{
-										logManager.log("Successfully created snapshot.");
+										logManager.log("File name invalid", pika::logError);
 									}
+
 								}
-								else
+								if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
 								{
-									logManager.log("File name invalid", pika::logError);
+									ImGui::SetTooltip("Make snapshot");
 								}
 
-							}
-							if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
-							{
-								ImGui::SetTooltip("Make snapshot");
+								ImGui::SameLine();
+								ImGui::InputText("snapshot name", snapshotName, sizeof(snapshotName));
 							}
 
-							ImGui::SameLine();
-
+							//recording
+							{
+								if (ImGui::Button(ICON_FK_VIDEO_CAMERA))
+								{
 
-							ImGui::InputText("snapshot name", snapshotName, sizeof(snapshotName));
+								}
+								if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
+								{
+									ImGui::SetTooltip("start recording");
+								}
+								ImGui::SameLine();
+								ImGui::InputText("recording name", recordingName, sizeof(recordingName));
+							}
 
 
 							ImGui::NewLine();
@@ -359,7 +445,7 @@ void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pi
 
 						#pragma region snapshots
 							{
-								static int currentSelectedSnapshot = 0;
+								static int currentSelectedSnapshot = 0; //todo move
 
 								auto snapshots = pika::getAvailableSnapshots(
 									containerManager.runningContainers[containerIds[itemCurrentCreatedContainers]]);

+ 4 - 1
Pika/core/pikaEditor/containersWindow/containersWindow.h

@@ -14,7 +14,7 @@ namespace pika
 		void init();
 
 		void update(pika::LogManager &logManager, bool &open, pika::LoadedDll &loadedDll,
-			pika::ContainerManager &containerManager);
+			pika::ContainerManager &containerManager, pika::pikaImgui::ImGuiIdsManager &imguiIdsManager);
 
 		static constexpr char *ICON = ICON_FK_MICROCHIP;
 		static constexpr char *NAME = "Containers manager";
@@ -23,10 +23,13 @@ namespace pika
 		char filterContainerInfo[50] = {};
 		char filterSnapshots[50] = {};
 		char snapshotName[50] = {};
+		char recordingName[50] = {};
 
 		int itemCurrentAvailableCOntainers = 0;
 		int itemCurrentCreatedContainers = 0;
 
+		bool createAtSpecificMemoryRegion = 0;
+
 	};
 
 

+ 1 - 0
Pika/core/pikaEditor/editShortcuts/editShortcuts.cpp

@@ -5,6 +5,7 @@
 void pika::EditShortcutsWindow::init(pika::pikaImgui::ImGuiIdsManager &imguiIdManager)
 {
 	imguiId = imguiIdManager.getImguiIds();
+	//todo save shortcuts
 }
 
 void pika::EditShortcutsWindow::update(pika::ShortcutManager &shortcutManager, bool &open)

+ 26 - 2
Pika/core/pikaEditor/editor/editor.cpp

@@ -9,6 +9,7 @@
 #include "IconsForkAwesome.h"
 #include "shortcutApi/shortcutApi.h"
 #include <editShortcuts/editShortcuts.h>
+#include <safeSave.h>
 
 #define DOCK_MAIN_WINDOW_SHORTCUT ICON_FK_EYE_SLASH " Hide main window"
 #define LOGS_SHORTCUT ICON_FK_COMMENT_O " Logs window"
@@ -31,6 +32,19 @@ void pika::Editor::init(pika::ShortcutManager &shortcutManager, pika::pikaImgui:
 	logWindow.init();
 	editShortcutsWindow.init(imguiIDManager);
 	containersWindow.init();
+
+	
+	if (sfs::safeLoad(&optionsFlags, sizeof(optionsFlags), PIKA_ENGINE_SAVES_PATH "options", false) != sfs::noError)
+	{
+		optionsFlags = {};
+	}
+
+	if (sfs::safeLoad(&windowFlags, sizeof(windowFlags), PIKA_ENGINE_SAVES_PATH "window", false) != sfs::noError)
+	{
+		windowFlags = {};
+	}
+	
+
 }
 
 
@@ -38,7 +52,7 @@ void pika::Editor::init(pika::ShortcutManager &shortcutManager, pika::pikaImgui:
 void pika::Editor::update(const pika::Input &input,
 	pika::ShortcutManager &shortcutManager, pika::LogManager &logs, 
 	pika::PushNotificationManager &pushNotificationManager, pika::LoadedDll &loadedDll
-	,pika::ContainerManager &containerManager)
+	,pika::ContainerManager &containerManager, pika::pikaImgui::ImGuiIdsManager &imguiIDsManager)
 {
 
 #pragma region push notification if hide window
@@ -198,11 +212,21 @@ void pika::Editor::update(const pika::Input &input,
 #pragma region containers window
 	if (windowFlags.containerManager)
 	{
-		containersWindow.update(logs, windowFlags.containerManager, loadedDll, containerManager);
+		containersWindow.update(logs, windowFlags.containerManager, 
+			loadedDll, containerManager, imguiIDsManager);
 	}
 #pragma endregion
 
 
 
 
+}
+
+void pika::Editor::saveFlagsData()
+{
+
+	sfs::safeSave(&optionsFlags, sizeof(optionsFlags), PIKA_ENGINE_SAVES_PATH "options", false);
+	sfs::safeSave(&windowFlags, sizeof(windowFlags), PIKA_ENGINE_SAVES_PATH "window", false);
+
+
 }

+ 5 - 2
Pika/core/pikaEditor/editor/editor.h

@@ -23,7 +23,10 @@ namespace pika
 
 		void update(const pika::Input &input, pika::ShortcutManager &shortcutManager
 			,pika::LogManager &logs, pika::PushNotificationManager &pushNotificationManager,
-			pika::LoadedDll &loadedDll, pika::ContainerManager &containerManager);
+			pika::LoadedDll &loadedDll, pika::ContainerManager &containerManager,
+			pika::pikaImgui::ImGuiIdsManager &imguiIDsManager);
+
+		void saveFlagsData();
 
 		struct
 		{
@@ -35,7 +38,7 @@ namespace pika
 			bool logsWindow = 0;
 			bool editShortcutsWindow = 0;
 			bool containerManager = 0;
-			bool transparentWindow = 1;
+			bool transparentWindow = 0;
 		}windowFlags;
 
 		pika::LogWindow logWindow;

+ 279 - 9
Pika/core/pikaRuntime/containerManager/containerManager.cpp

@@ -9,9 +9,11 @@
 #include <fileManipulation/fileManipulation.h>
 #include <stringManipulation/stringManipulation.h>
 #include <filesystem>
+#include <imgui.h>
 
 pika::containerId_t pika::ContainerManager::createContainer(std::string containerName, 
-	pika::LoadedDll &loadedDll, pika::LogManager &logManager)
+	pika::LoadedDll &loadedDll, pika::LogManager &logManager, 
+	pika::pikaImgui::ImGuiIdsManager &imguiIDsManager, size_t memoryPos)
 {
 	
 	for(auto &i : loadedDll.containerInfo)
@@ -19,7 +21,7 @@ pika::containerId_t pika::ContainerManager::createContainer(std::string containe
 		
 		if (i.containerName == containerName)
 		{
-			return createContainer(i, loadedDll, logManager);
+			return createContainer(i, loadedDll, logManager, imguiIDsManager, memoryPos);
 		}
 
 	}
@@ -133,7 +135,8 @@ void pika::ContainerManager::freeContainerStuff(pika::RuntimeContainer &containe
 
 pika::containerId_t pika::ContainerManager::createContainer
 (pika::ContainerInformation containerInformation,
-	pika::LoadedDll &loadedDll, pika::LogManager &logManager)
+	pika::LoadedDll &loadedDll, pika::LogManager &logManager, pika::pikaImgui::ImGuiIdsManager &imguiIDsManager,
+	size_t memoryPos)
 {	
 	containerId_t id = ++idCounter;
 	
@@ -150,13 +153,20 @@ pika::containerId_t pika::ContainerManager::createContainer
 	pika::strlcpy(container.baseContainerName, containerInformation.containerName,
 		sizeof(container.baseContainerName));
 	
-	if (!allocateContainerMemory(container, containerInformation))
+	if (!allocateContainerMemory(container, containerInformation, (void*)memoryPos))
 	{
 		logManager.log((std::string("Couldn't allocate memory for constructing container: #") 
 			+ std::to_string(id)).c_str(), pika::logError);
 		return 0;
 	}
 
+	if (containerInformation.containerStaticInfo.requestImguiFbo)
+	{
+		container.requestedContainerInfo.requestedFBO.createFramebuffer(400, 400); //todo resize small or sthing
+		container.imguiWindowId = imguiIDsManager.getImguiIds();
+	}
+
+
 	loadedDll.bindAllocatorDllRealm(&container.allocator);
 	
 	//this calls the constructors (from the dll realm)
@@ -168,6 +178,8 @@ pika::containerId_t pika::ContainerManager::createContainer
 
 		freeContainerStuff(container);
 
+		container.requestedContainerInfo.requestedFBO.deleteFramebuffer();
+
 		return 0;
 	}
 
@@ -211,7 +223,10 @@ void pika::ContainerManager::update(pika::LoadedDll &loadedDll, pika::PikaWindow
 	{
 		reloadDll(loadedDll, window, logs); //todo return 0 on fail
 
-		//todo
+		//todo mark shouldCallReaload
+		
+
+
 		//for (auto &c : runningContainers)
 		//{
 		//	if (c.second.flags.running)
@@ -282,11 +297,66 @@ void pika::ContainerManager::update(pika::LoadedDll &loadedDll, pika::PikaWindow
 	for (auto &c : runningContainers)
 	{
 
-		if (c.second.flags.running)
+		if (c.second.flags.status == pika::RuntimeContainer::FLAGS::STATUS_RUNNING
+			||
+			c.second.flags.status == pika::RuntimeContainer::FLAGS::STATUS_BEING_RECORDED
+			)
 		{
-			loadedDll.bindAllocatorDllRealm(&c.second.allocator);
-			c.second.pointer->update(window.input, window.deltaTime, window.windowState, c.second.requestedContainerInfo);
-			loadedDll.resetAllocatorDllRealm();
+			
+			PIKA_DEVELOPMENT_ONLY_ASSERT(
+				(c.second.requestedContainerInfo.requestedFBO.fbo == 0 &&
+				c.second.imguiWindowId == 0) ||
+				(
+				c.second.requestedContainerInfo.requestedFBO.fbo != 0 &&
+				c.second.imguiWindowId != 0), "we have a fbo but no imguiwindow id"
+			);
+
+			if (c.second.imguiWindowId)
+			{
+				//todo remove in production
+
+				ImGui::PushID(c.second.imguiWindowId);
+				
+				ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.f, 0.f, 0.f, 1.0f));
+				ImGui::SetNextWindowSize({200,200}, ImGuiCond_Once);
+				ImGui::Begin( (std::string("gameplay window id: ") + std::to_string(c.first)).c_str(),
+					0, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
+				
+				auto s = ImGui::GetContentRegionMax();
+
+				ImGui::Image((void *)c.second.requestedContainerInfo.requestedFBO.texture, s, {0, 1}, {1, 0},
+					{1,1,1,1}, {0,0,0,1});
+
+				ImGui::End();
+
+				ImGui::PopStyleColor();
+
+				ImGui::PopID();
+
+				auto state = window.windowState;
+				state.w = s.x;
+				state.h = s.y;
+
+				c.second.requestedContainerInfo.requestedFBO.resizeFramebuffer(state.w, state.h);
+
+				glBindFramebuffer(GL_FRAMEBUFFER, c.second.requestedContainerInfo.requestedFBO.fbo);
+
+				loadedDll.bindAllocatorDllRealm(&c.second.allocator);
+				c.second.pointer->update(window.input, state, c.second.requestedContainerInfo);
+				loadedDll.resetAllocatorDllRealm();
+
+				glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+
+			}
+			else
+			{
+				loadedDll.bindAllocatorDllRealm(&c.second.allocator);
+				c.second.pointer->update(window.input, window.windowState, c.second.requestedContainerInfo);
+				loadedDll.resetAllocatorDllRealm();
+			}
+
+
 		}
 
 	}
@@ -418,6 +488,8 @@ bool pika::ContainerManager::destroyContainer(containerId_t id, pika::LoadedDll
 
 	freeContainerStuff(c->second);
 
+	c->second.requestedContainerInfo.requestedFBO.deleteFramebuffer();
+
 	runningContainers.erase(c);
 
 	logManager.log((std::string("Destroyed continer: ") + name + " #" + std::to_string(id)).c_str());
@@ -515,6 +587,8 @@ bool pika::ContainerManager::forceTerminateContainer(containerId_t id, pika::Loa
 
 	logManager.log((std::string("Force terminated continer: ") + name + " #" + std::to_string(id)).c_str());
 
+	c->second.requestedContainerInfo.requestedFBO.deleteFramebuffer();
+
 	return true;
 }
 
@@ -590,6 +664,52 @@ std::vector<std::string> pika::getAvailableSnapshots(pika::RuntimeContainer &inf
 	return files;
 }
 
+std::vector<std::string> pika::getAvailableSnapshotsAnyMemoryPosition(pika::RuntimeContainer &info)
+{
+	std::vector<std::string> files;
+
+	auto curDir = std::filesystem::directory_iterator(PIKA_ENGINE_RESOURCES_PATH);
+
+	for (const auto &iter : curDir)
+	{
+		if (std::filesystem::is_regular_file(iter)
+			&& iter.path().extension() == ".snapshot"
+			)
+		{
+			if (pika::checkIfSnapshotIsCompatibleAnyMemoryPosition(info, iter.path().stem().string().c_str()))
+			{
+				files.push_back(iter.path().stem().string());
+			}
+
+		}
+	}
+
+	return files;
+}
+
+std::vector<std::string> pika::getAvailableSnapshotsAnyMemoryPosition(pika::ContainerInformation &info)
+{
+	std::vector<std::string> files;
+
+	auto curDir = std::filesystem::directory_iterator(PIKA_ENGINE_RESOURCES_PATH);
+
+	for (const auto &iter : curDir)
+	{
+		if (std::filesystem::is_regular_file(iter)
+			&& iter.path().extension() == ".snapshot"
+			)
+		{
+			if (pika::checkIfSnapshotIsCompatibleAnyMemoryPosition(info, iter.path().stem().string().c_str()))
+			{
+				files.push_back(iter.path().stem().string());
+			}
+
+		}
+	}
+
+	return files;
+}
+
 bool pika::checkIfSnapshotIsCompatible(pika::RuntimeContainer &info, const char *snapshotName)
 {
 
@@ -632,6 +752,22 @@ bool pika::checkIfSnapshotIsCompatible(pika::RuntimeContainer &info, const char
 		return false;
 	}
 
+	//check if user requested an imgui window
+	if (
+		!(
+			(info.imguiWindowId == 0&&
+			loadedInfo.imguiWindowId == 0
+			)||
+			(
+			info.imguiWindowId != 0 &&
+			loadedInfo.imguiWindowId != 0
+			)
+		)
+		)
+	{
+		return false;
+	}
+
 	if (loadedInfo.totalSize != info.totalSize)
 	{
 		return false;
@@ -639,3 +775,137 @@ bool pika::checkIfSnapshotIsCompatible(pika::RuntimeContainer &info, const char
 		
 	return true;
 }
+
+bool pika::checkIfSnapshotIsCompatibleAnyMemoryPosition(pika::RuntimeContainer &info, const char *snapshotName)
+{
+	std::string file = PIKA_ENGINE_RESOURCES_PATH;
+	file += snapshotName;
+	file += ".snapshot";
+
+	pika::RuntimeContainer loadedInfo = {};
+
+	auto s = pika::readEntireFile(file.c_str(), &loadedInfo, sizeof(loadedInfo));
+
+	if (s != sizeof(loadedInfo))
+	{
+		return 0;
+	}
+
+	if (loadedInfo.arena.containerStructMemory.size != info.arena.containerStructMemory.size)
+	{
+		return false;
+	}
+
+	if (std::strcmp(loadedInfo.baseContainerName, info.baseContainerName) != 0)
+	{
+		return false;
+	}
+
+	if (loadedInfo.requestedContainerInfo.bonusAllocators != info.requestedContainerInfo.bonusAllocators)
+	{
+		return false;
+	}
+
+	//check if user requested an imgui window
+	if (
+		!(
+		(info.imguiWindowId == 0 &&
+		loadedInfo.imguiWindowId == 0
+		) ||
+		(
+		info.imguiWindowId != 0 &&
+		loadedInfo.imguiWindowId != 0
+		)
+		)
+		)
+	{
+		return false;
+	}
+
+	if (loadedInfo.totalSize != info.totalSize)
+	{
+		return false;
+	}
+
+	return true;
+}
+
+bool pika::checkIfSnapshotIsCompatibleAnyMemoryPosition(pika::ContainerInformation &info, const char *snapshotName)
+{
+	std::string file = PIKA_ENGINE_RESOURCES_PATH;
+	file += snapshotName;
+	file += ".snapshot";
+
+	pika::RuntimeContainer loadedInfo = {};
+
+	auto s = pika::readEntireFile(file.c_str(), &loadedInfo, sizeof(loadedInfo));
+
+	if (s != sizeof(loadedInfo))
+	{
+		return 0;
+	}
+
+	if (loadedInfo.arena.containerStructMemory.size != info.containerStructBaseSize)
+	{
+		return false;
+	}
+
+	if (std::strcmp(loadedInfo.baseContainerName, info.containerName.c_str()) != 0)
+	{
+		return false;
+	}
+
+	if (loadedInfo.bonusAllocators.size() != info.containerStaticInfo.bonusAllocators.size())
+	{
+		return false;
+	}
+
+	for (int i = 0; i < loadedInfo.bonusAllocators.size(); i++)
+	{
+		if (loadedInfo.bonusAllocators[i].heapSize != info.containerStaticInfo.bonusAllocators[i]) //todo this doesn't seem to work
+		{
+			return false;
+		}
+	}
+
+	//check if user requested an imgui window
+	if (
+		!(
+		(info.containerStaticInfo.requestImguiFbo == false &&
+		loadedInfo.imguiWindowId == 0
+		) ||
+		(
+		info.containerStaticInfo.requestImguiFbo == true &&
+		loadedInfo.imguiWindowId != 0
+		)
+		)
+		)
+	{
+		return false;
+	}
+
+	if (loadedInfo.allocator.heapSize != info.containerStaticInfo.defaultHeapMemorySize)
+	{
+		return false;
+	}
+
+	return true;
+}
+
+void *pika::getSnapshotMemoryPosition(const char *snapshotName)
+{
+	std::string file = PIKA_ENGINE_RESOURCES_PATH;
+	file += snapshotName;
+	file += ".snapshot";
+
+	pika::RuntimeContainer loadedInfo = {};
+
+	auto s = pika::readEntireFile(file.c_str(), &loadedInfo, sizeof(loadedInfo));
+
+	if (s != sizeof(loadedInfo))
+	{
+		return nullptr;
+	}
+
+	return loadedInfo.getBaseAdress();
+}

+ 16 - 2
Pika/core/pikaRuntime/containerManager/containerManager.h

@@ -10,6 +10,8 @@
 #include <windowSystemm/input.h>
 #include <windowSystemm/window.h>
 
+#include <pikaImgui/pikaImgui.h>
+
 namespace pika
 {
 	using containerId_t = unsigned int;
@@ -22,11 +24,13 @@ namespace pika
 
 		containerId_t createContainer(
 			pika::ContainerInformation containerInformation,
-			pika::LoadedDll &loadedDll, pika::LogManager &logManager);
+			pika::LoadedDll &loadedDll, pika::LogManager &logManager, 
+			pika::pikaImgui::ImGuiIdsManager &imguiIDsManager, size_t memoryPos = 0);
 
 		containerId_t createContainer(
 			std::string containerName,
-			pika::LoadedDll &loadedDll, pika::LogManager &logManager);
+			pika::LoadedDll &loadedDll, pika::LogManager &logManager,
+			pika::pikaImgui::ImGuiIdsManager &imguiIDsManager, size_t memoryPos = 0);
 
 		bool setSnapshotToContainer(pika::containerId_t containerId, const char* snapshotName,
 			pika::LogManager &logManager);
@@ -75,6 +79,16 @@ namespace pika
 
 	std::vector<std::string> getAvailableSnapshots(pika::RuntimeContainer &info);
 
+	std::vector<std::string> getAvailableSnapshotsAnyMemoryPosition(pika::RuntimeContainer &info);
+	
+	std::vector<std::string> getAvailableSnapshotsAnyMemoryPosition(pika::ContainerInformation &info);
+
 	bool checkIfSnapshotIsCompatible(pika::RuntimeContainer &info, const char *snapshotName);
 
+	bool checkIfSnapshotIsCompatibleAnyMemoryPosition(pika::RuntimeContainer &info, const char *snapshotName);
+
+	bool checkIfSnapshotIsCompatibleAnyMemoryPosition(pika::ContainerInformation &info, const char *snapshotName);
+
+	void *getSnapshotMemoryPosition(const char *snapshotName);
+
 }

+ 43 - 13
Pika/core/pikaRuntime/pikaMain.cpp

@@ -146,7 +146,7 @@ int main()
 
 	
 	auto container = containerManager.createContainer
-		(loadedDll.containerInfo[0], loadedDll, logs);
+		(loadedDll.containerInfo[0], loadedDll, logs, imguiIdsManager);
 
 	while (!shouldClose)
 	{
@@ -162,28 +162,34 @@ int main()
 	#pragma endregion
 
 	#pragma region clear screen
-	#if PIKA_CLEAR_SCREEN_BY_ENGINE && PIKA_CLEAR_DEPTH_BY_ENGINE 
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-	#elif PIKA_CLEAR_SCREEN_BY_ENGINE
+
+	#if PIKA_PRODUCTION
+		#if PIKA_CLEAR_SCREEN_BY_ENGINE_IN_PRODUCTION && PIKA_CLEAR_DEPTH_BY_ENGINE _IN_PRODUCTION
+			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		#elif PIKA_CLEAR_SCREEN_BY_ENGINE_IN_PRODUCTION
+			glClear(GL_COLOR_BUFFER_BIT);
+		#elif PIKA_CLEAR_DEPTH_BY_ENGINE_IN_PRODUCTION
+			glClear(GL_DEPTH_BUFFER_BIT);
+		#endif
+
+	#else
+
 		glClear(GL_COLOR_BUFFER_BIT);
-	#elif PIKA_CLEAR_DEPTH_BY_ENGINE
-		glClear(GL_DEPTH_BUFFER_BIT);
+
 	#endif
+
+
+
 	#pragma endregion
 
 	#pragma region editor stuff
 	#if !PIKA_SHOULD_REMOVE_EDITOR
 		editor.update(window.input, shortcutManager, logs, 
-			pushNotificationManager, loadedDll, containerManager);
+			pushNotificationManager, loadedDll, containerManager, imguiIdsManager);
 	#endif
 	#pragma endregion
 
-	#pragma region push notification
-	#if !(PIKA_SHOULD_REMOVE_PUSH_NOTIFICATIONS)
-		static bool pushNoticicationOpen = true;
-		pushNotificationManager.update(pushNoticicationOpen);
-	#endif
-	#pragma endregion
+
 
 	#pragma region container manager
 
@@ -199,6 +205,13 @@ int main()
 
 	#pragma endregion
 
+	#pragma region push notification
+	#if !(PIKA_SHOULD_REMOVE_PUSH_NOTIFICATIONS)
+		static bool pushNoticicationOpen = true;
+		pushNotificationManager.update(pushNoticicationOpen);
+	#endif
+	#pragma endregion
+
 	#pragma region end imgui frame
 		pika::pikaImgui::imguiEndFrame(window.context);
 	#pragma endregion
@@ -207,14 +220,31 @@ int main()
 		window.update();
 	#pragma endregion
 
+
 	#pragma region shortcut manager update
 		shortcutManager.update(window.input);
 	#pragma endregion
 	
+	#if !PIKA_SHOULD_REMOVE_EDITOR
+		editor.saveFlagsData();
+	#endif
+
+	window.saveWindowPositions();
+
 	}
 
+	#if !PIKA_SHOULD_REMOVE_EDITOR
+		editor.saveFlagsData();
+	#endif
+
+	//todo flag?
+	window.saveWindowPositions();
+
+
 	containerManager.destroyAllContainers(loadedDll, logs);
 
+	
+	
 
 	//terminate();
 

+ 24 - 8
Pika/core/pikaRuntime/runtimeContainer/runtimeContainer.h

@@ -31,22 +31,31 @@ struct RuntimeContainer
 	//bonus allocators
 	pika::StaticVector<pika::memory::FreeListAllocator, MaxAllocatorsCount> bonusAllocators = {};
 
-
 	RequestedContainerInfo requestedContainerInfo = {};
+	
+	int imguiWindowId = 0;
 
-	struct
+	struct FLAGS
 	{
-		bool running = 1;
+		enum
+		{
+			STATUS_PAUSE = 0,
+			STATUS_RUNNING = 1,
+			STATUS_BEING_RECORDED = 1,
+		};
+
+		int status = STATUS_RUNNING;
+
 		bool shouldCallReaload = 0; //if the container happens to be on pause when the dll reloads we mark this to true
 
 		const char *getStatusName()
 		{
 
-			if (running)
+			if (status == STATUS_RUNNING)
 			{
 				return "running.";
 			}
-			else
+			else if(status == STATUS_PAUSE)
 			{
 				if (shouldCallReaload)
 				{
@@ -56,20 +65,27 @@ struct RuntimeContainer
 				{
 					return "paused.";
 				}
-
+			}
+			else if (status == STATUS_BEING_RECORDED)
+			{
+				return "on recording";
 			}
 		}
 		
 		const char *getStatusIcon()
 		{
-			if (running)
+			if (status == STATUS_RUNNING)
 			{
 				return ICON_FK_BOLT;
 			}
-			else
+			else if (status == STATUS_PAUSE)
 			{
 				return ICON_FK_PAUSE_CIRCLE_O;
 			}
+			else if (status == STATUS_BEING_RECORDED)
+			{
+				return ICON_FK_VIDEO_CAMERA;
+			}
 		}
 
 	}flags;

+ 1 - 0
Pika/core/pikaSTD/pikaAllocator/freeListAllocator.cpp

@@ -41,6 +41,7 @@ namespace memory
 
 	void FreeListAllocator::init(void *baseMemory, size_t memorySize)
 		{
+			heapSize = memorySize; 
 			originalBaseMemory = baseMemory;
 			end = (void *)((size_t)baseMemory + memorySize);
 

+ 2 - 1
Pika/core/pikaSTD/pikaAllocator/freeListAllocator.h

@@ -49,7 +49,8 @@ namespace memory
 	{
 		char* baseMemory = 0;
 		void* originalBaseMemory = 0;
-	
+		size_t heapSize = 0;
+
 		FreeListAllocator() = default;
 		FreeListAllocator(void* baseMemory, size_t memorySize)
 		{

+ 70 - 0
Pika/core/pikaSTD/pikaGL/frameBuffer.cpp

@@ -0,0 +1,70 @@
+#include "frameBuffer.h"
+
+namespace pika
+{
+	namespace GL
+	{
+
+		void PikaFramebuffer::createFramebuffer(unsigned int w, unsigned int h)
+		{
+			glGenFramebuffers(1, &fbo);
+			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+			glGenTextures(1, &texture);
+			glBindTexture(GL_TEXTURE_2D, texture);
+
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+			//glDrawBuffer(GL_COLOR_ATTACHMENT0); //todo look into this function
+
+			//glGenTextures(1, &depthtTexture); //todo add depth stuff
+			//glBindTexture(GL_TEXTURE_2D, depthtTexture);
+
+			//glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, w, h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+
+			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+			//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthtTexture, 0);
+
+			glBindTexture(GL_TEXTURE_2D, 0);
+			glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+		}
+
+		void PikaFramebuffer::deleteFramebuffer()
+		{
+			if (fbo)
+			{
+				glDeleteFramebuffers(1, &fbo);
+				fbo = 0;
+			}
+
+			if (texture)
+			{
+				glDeleteTextures(1, &texture);
+				texture = 0;
+			}
+		}
+
+		void PikaFramebuffer::resizeFramebuffer(unsigned int w, unsigned int h)
+		{
+			glBindTexture(GL_TEXTURE_2D, texture);
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+			//glBindTexture(GL_TEXTURE_2D, depthtTexture);
+			//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+			
+			glBindTexture(GL_TEXTURE_2D, 0);
+		}
+
+	}
+
+
+}
+
+

+ 32 - 0
Pika/core/pikaSTD/pikaGL/frameBuffer.h

@@ -0,0 +1,32 @@
+#pragma once
+#include <glad/glad.h>
+
+namespace pika
+{
+
+	namespace GL
+	{
+
+		struct PikaFramebuffer
+		{
+			GLuint fbo = 0;
+			GLuint texture = 0; 
+
+			void createFramebuffer(unsigned int w, unsigned int h);
+
+			void deleteFramebuffer();
+
+			void resizeFramebuffer(unsigned int w, unsigned int h);
+		
+		};
+
+
+		
+
+
+
+	}
+
+
+
+}

+ 1 - 0
Pika/core/pikaSTD/pikaSizes.h

@@ -10,6 +10,7 @@ namespace pika
 	inline size_t KB(size_t x) { return x * 1024ull; }
 	inline size_t MB(size_t x) { return KB(x) * 1024ull; }
 	inline size_t GB(size_t x) { return MB(x) * 1024ull; }
+	inline size_t TB(size_t x) { return GB(x) * 1024ull; }
 
 	inline float BYTES_TO_KB(size_t x) { return x / 1024.f; }
 	inline float BYTES_TO_MB(size_t x) { return BYTES_TO_KB(x) / 1024.f; }

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

@@ -5,6 +5,7 @@
 #include <string>
 #include <pikaAllocator/freeListAllocator.h>
 #include <staticVector.h>
+#include <pikaGL/frameBuffer.h>
 
 #define READENTIREFILE(x) bool x(const char* name, void* buffer, size_t size)
 typedef READENTIREFILE(readEntireFile_t);
@@ -27,6 +28,9 @@ struct RequestedContainerInfo
 	//readEntireFile_t *readEntireFilePointer = {};
 	//getFileSize_t *getFileSizePointer = {};
 
+	pika::GL::PikaFramebuffer requestedFBO = {};
+
+	//todo implement
 	bool readEntireFile(const char *name, void *buffer, size_t size)
 	{
 		//PIKA_DEVELOPMENT_ONLY_ASSERT(readEntireFilePointer, "read entire file pointer not assigned");
@@ -56,6 +60,10 @@ struct ContainerStaticInfo
 	
 	pika::StaticVector<size_t, MaxAllocatorsCount> bonusAllocators = {};
 
+	//the engine will create a new window for your container and give you the fbo to bind to
+	//in release that fbo will just be the default framebuffer
+	bool requestImguiFbo = 0;
+
 	bool _internalNotImplemented = 0;
 
 	bool operator==(const ContainerStaticInfo &other)
@@ -65,7 +73,9 @@ struct ContainerStaticInfo
 		return
 			this->defaultHeapMemorySize == other.defaultHeapMemorySize &&
 			this->bonusAllocators == other.bonusAllocators &&
-			this->_internalNotImplemented == other._internalNotImplemented;
+			this->_internalNotImplemented == other._internalNotImplemented &&
+			this->requestImguiFbo == other.requestImguiFbo;
+			;
 	}
 
 	bool operator!=(const ContainerStaticInfo &other)
@@ -91,7 +101,6 @@ struct Container
 
 	virtual void update(
 		pika::Input input, 
-		float deltaTime, 
 		pika::WindowState windowState,
 		RequestedContainerInfo &requestedInfo) = 0;
 

+ 13 - 3
Pika/core/sharedRuntime/pushNotification/pushNotification.cpp

@@ -45,7 +45,7 @@ void pika::PushNotificationManager::update(bool &open)
 	//set popup pos
 	{
 		const float PADX = 10.0f;
-		const float PADY = 20.0f;
+		const float PADY = 40.0f;
 		const ImGuiViewport *viewport = ImGui::GetMainViewport();
 		ImVec2 work_pos = viewport->WorkPos;
 		ImVec2 work_size = viewport->WorkSize;
@@ -59,7 +59,16 @@ void pika::PushNotificationManager::update(bool &open)
 		window_flags |= ImGuiWindowFlags_NoMove;
 	}
 
-	ImGui::SetNextWindowBgAlpha(0.30f);
+	static int lastSize = 0; //todo move
+
+	if (lastSize < notificationQue.size())
+	{
+		ImGui::SetNextWindowFocus();
+	}
+
+	lastSize = notificationQue.size();
+
+	ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.1f, 0.1f, 0.15f, 1.0f));
 	if (ImGui::Begin("Notification content", &open, window_flags))
 	{
 
@@ -95,11 +104,12 @@ void pika::PushNotificationManager::update(bool &open)
 			if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
 			if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
 			if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
-			if (ImGui::MenuItem("Close")) open = false;
+			if (ImGui::MenuItem("Close")) notificationQue.clear();
 			ImGui::EndPopup();
 		}
 	}
 	ImGui::End();
+	ImGui::PopStyleColor();
 
 
 	while (!notificationQue.empty() && notificationQue.front().startTime +

+ 1 - 0
Pika/core/sharedRuntime/windowSystemm/callbacks.cpp

@@ -22,6 +22,7 @@ static void processAButton(pika::Button &b, int action)
 	if (action == GLFW_PRESS)
 	{
 		b.setHeld(true);
+
 	}
 	else if (action == GLFW_RELEASE)
 	{

+ 4 - 1
Pika/core/sharedRuntime/windowSystemm/input.h

@@ -34,6 +34,7 @@ namespace pika
 		//true in the first frame is pressed then after a pause true every few milliseconds
 		PIKA_ADD_FLAG(typed, setTyped, 3);
 
+		//todo implement
 		//true if the key is double pressed (true only for one frame, 3 presses would yield only one frame of this being true)
 		PIKA_ADD_FLAG(doublePressed, setDoublePressed, 4);
 
@@ -55,6 +56,7 @@ namespace pika
 
 	struct Input
 	{
+		//typed input doesn't work with mouse buttons
 		Button lMouse = {};
 		Button rMouse = {};
 
@@ -63,7 +65,8 @@ namespace pika
 		int mouseY = 0;
 
 		Button buttons[Button::BUTTONS_COUNT] = {};
-
+		
+		float deltaTime = 0;
 	};
 
 	

+ 40 - 4
Pika/core/sharedRuntime/windowSystemm/window.cpp

@@ -10,10 +10,28 @@
 
 #include <pikaSizes.h>
 
+#include <safeSave.h>
+
+struct WindowRect
+{
+	int x = 100, y = 100, z = 640, w = 480;
+};
+
 void pika::PikaWindow::create()
 {
-	context.wind = glfwCreateWindow(640, 480, "Pika", NULL, NULL);
-	
+
+	WindowRect wr = {};
+
+#if PIKA_DEVELOPMENT
+	if (sfs::safeLoad(&wr, sizeof(wr), PIKA_ENGINE_SAVES_PATH "windowPos", false) != sfs::noError)
+	{
+		wr = {};
+	}
+#endif
+
+	context.wind = glfwCreateWindow(wr.z, wr.w, "Pika", NULL, NULL);
+	glfwSetWindowPos(context.wind, wr.x, wr.y);
+
 	windowState.hasFocus = true;
 
 	PIKA_PERMA_ASSERT(context.wind, "problem initializing window");
@@ -50,6 +68,23 @@ void pika::PikaWindow::create()
 	timer = std::chrono::high_resolution_clock::now();
 }
 
+void pika::PikaWindow::saveWindowPositions()
+{
+#if PIKA_DEVELOPMENT
+
+	WindowRect wr = {};
+
+	glfwGetWindowPos(context.wind, &wr.x, &wr.y);
+
+	wr.z = windowState.w;
+	wr.w = windowState.h;
+
+	sfs::safeSave(&wr, sizeof(wr), PIKA_ENGINE_SAVES_PATH "windowPos", false);
+
+#endif
+
+}
+
 bool pika::PikaWindow::shouldClose()
 {
 	return glfwWindowShouldClose(context.wind);
@@ -59,10 +94,10 @@ void pika::PikaWindow::update()
 {
 #pragma region deltaTime
 	auto end = std::chrono::high_resolution_clock::now();
-	deltaTime = (std::chrono::duration_cast<std::chrono::microseconds>(end - timer)).count() / 1000000.0f;
+	input.deltaTime = (std::chrono::duration_cast<std::chrono::microseconds>(end - timer)).count() / 1000000.0f;
 	timer = end;
 
-	if (deltaTime > 1.f / 10) { deltaTime = 1.f / 10; }
+	if (input.deltaTime > 1.f / 10) { input.deltaTime = 1.f / 10; }
 #pragma endregion
 
 #pragma region input
@@ -115,6 +150,7 @@ void pika::PikaWindow::update()
 		if (!b.lastState() && b.held())
 		{
 			b.setPressed(true);
+			b.setTyped(true);
 		}
 		else
 		{

+ 2 - 2
Pika/core/sharedRuntime/windowSystemm/window.h

@@ -28,15 +28,15 @@ namespace pika
 		//this is made to be passed to the user code
 		//on live code editing this will be recorded every frame
 		Input input = {};
-		float deltaTime = 0;
 
 
 		WindowState windowState = {};
 
-
 		//this doesn't return error codes because it will do the asserts for you
 		void create();
 
+		void saveWindowPositions();
+
 		bool shouldClose();
 
 		void update();

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/engineSaves/windowPos1.bin


BIN
Pika/engineResources/engineSaves/windowPos2.bin


BIN
Pika/engineResources/test1.snapshot


BIN
Pika/engineResources/current.snapshot → Pika/engineResources/testWithoutImguiStuff.snapshot


BIN
Pika/engineResources/test.snapshot → Pika/engineResources/testwithimgui.snapshot


+ 17 - 12
Pika/gameplay/containers/pikaGameplay.h

@@ -27,6 +27,8 @@ struct Gameplay : public Container
 		ContainerStaticInfo info = {};
 		info.defaultHeapMemorySize = pika::MB(10);
 
+		info.requestImguiFbo = true; //todo this should not affect the compatibility of input recording
+
 		//info.bonusAllocators.push_back(100);
 		//info.bonusAllocators.push_back(200);
 		//info.bonusAllocators.push_back(300);
@@ -55,9 +57,12 @@ struct Gameplay : public Container
 		//void *test = new char[pika::MB(10)]; //todo let the allocator tell the engine somehow that it is out of memory
 	}
 
-	void update(pika::Input input, float deltaTime, pika::WindowState windowState,
+	void update(pika::Input input, pika::WindowState windowState,
 		RequestedContainerInfo &requestedInfo)
 	{
+		//todo keep window on top stuff
+
+		glClear(GL_COLOR_BUFFER_BIT);
 
 		if (pika::shortcut(input, "Ctrl + S"))
 		{
@@ -68,9 +73,9 @@ struct Gameplay : public Container
 		gl2d::enableNecessaryGLFeatures();
 		renderer.updateWindowMetrics(windowState.w, windowState.h);
 
-		*r += deltaTime * 4.f;
+		*r += input.deltaTime * 4.f;
 
-		renderer.renderRectangle({10, 10, 100, 100}, Colors_Blue, {}, *r);
+		renderer.renderRectangle({10, 10, 100, 100}, Colors_Green, {}, *r);
 
 		//if (input.lMouse.pressed())
 		//{
@@ -81,15 +86,15 @@ struct Gameplay : public Container
 		//	std::cout << "released\n";
 		//}
 
-		if (input.lMouse.typed())
-		{
-			std::cout << "typed\n";
-		}
+		//if (input.lMouse.typed())
+		//{
+		//	std::cout << "typed\n";
+		//}
 
-		if (input.buttons[pika::Button::E].doublePressed())
-		{
-			std::cout << "double pressed\n";
-		}
+		//if (input.buttons[pika::Button::E].typed())
+		//{
+		//	std::cout << "e";
+		//}
 
 		//std::cout << state.deltaTime << "\n";
 
@@ -104,7 +109,7 @@ struct Gameplay : public Container
 		//ImGui::LoadingIndicatorCircle("circle", 20, 8, 8);
 		//ImGui::End();
 		
-		ImGui::ShowDemoWindow();
+		//ImGui::ShowDemoWindow();
 
 	}
 

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

@@ -44,7 +44,7 @@ struct ImmageViewer: public Container
 		//new int[100];
 	}
 
-	void update(pika::Input input, float deltaTime, pika::WindowState windowState,
+	void update(pika::Input input, pika::WindowState windowState,
 		RequestedContainerInfo &requestedInfo)
 	{
 

+ 2 - 2
Pika/resources/logs.txt

@@ -1,2 +1,2 @@
-#2022-10-10 13:39:59: Created container: Gameplay
-#2022-10-10 13:40:02: Destroyed continer: Gameplay #1
+#2022-10-12 20:35:18: Created container: Gameplay
+#2022-10-12 20:35:35: Destroyed continer: Gameplay #1

+ 7 - 0
Pika/thirdparty/safeSafe/CMakeLists.txt

@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.13)
+project(safeSave)
+
+
+add_library(safeSave)
+target_include_directories(safeSave PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/")
+target_sources(safeSave PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/safeSave.cpp")

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

@@ -0,0 +1,93 @@
+///////////////////////////////////////////
+//do not remove this notice
+//(c) Luta Vlad
+// 
+// safeSave 1.0.0
+// 
+///////////////////////////////////////////
+
+#pragma once
+#include <fstream>
+#include <vector>
+
+#ifdef _MSC_VER
+#pragma warning( disable : 26812 )
+#endif
+
+namespace sfs
+{
+	enum Errors : int
+	{
+		noError,
+		couldNotOpenFinle,
+		fileSizeDitNotMatch,
+		checkSumFailed,
+		couldNotMakeBackup,
+		readBackup,
+	};
+	
+	const char* getErrorString(Errors e);
+	
+	//can return error: couldNotOpenFinle
+	Errors readEntireFile(std::vector<char>& data, const char* name);
+	
+	//can return error: couldNotOpenFinle
+	Errors readEntireFile(void* data, size_t size, const char* name, bool shouldMatchSize, int *bytesRead = nullptr);
+
+	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed
+	Errors readEntireFileWithCheckSum(void* data, size_t size, const char* name);
+
+	//can return error: couldNotOpenFinle
+	Errors writeEntireFileWithCheckSum(const void* data, size_t size, const char* name);
+
+	//can return error: couldNotOpenFinle
+	Errors writeEntireFile(const std::vector<char>& data, const char* name);
+	
+	//can return error: couldNotOpenFinle
+	Errors writeEntireFile(const void*data, size_t size, const char* name);
+
+	//can return error: couldNotOpenFinle, 
+	//	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);
+
+	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed, 
+	//	readBackup (if reportLoadingBackupAsAnError but data will still be loaded with the backup)
+	Errors safeLoad(void* data, size_t size, const char* nameWithoutExtension, bool reportLoadingBackupAsAnError);
+
+	//same as safeLoad but only loads the backup file.
+	//can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed
+	Errors safeLoadBackup(void* data, size_t size, const char* nameWithoutExtension);
+
+#if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__
+
+	struct FileMapping
+	{
+		void* pointer = {};
+		size_t size = 0;
+		struct
+		{
+			void* fileHandle = 0;
+			void* fileMapping = 0;
+		}internal = {};
+	};
+
+#elif defined __linux__
+
+	struct FileMapping
+	{
+		void* pointer = {};
+		size_t size = 0;
+		struct
+		{
+			int fd = 0;
+		}internal = {};
+	};
+
+#endif
+
+	//can return error: couldNotOpenFinle
+	Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting);
+
+	void closeFileMapping(FileMapping& fileMapping);
+
+};

+ 407 - 0
Pika/thirdparty/safeSafe/src/safeSave.cpp

@@ -0,0 +1,407 @@
+///////////////////////////////////////////
+//do not remove this notice
+//(c) Luta Vlad
+// 
+// safeSave 1.0.0
+// 
+///////////////////////////////////////////
+
+#include <safeSave.h>
+
+#if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__
+#define NOMINMAX 
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+
+#elif defined __linux__
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#endif
+
+
+namespace sfs
+{
+
+	constexpr const char* errorsString[] =
+	{
+		"noError",
+		"couldNotOpenFinle",
+		"fileSizeDitNotMatch",
+		"checkSumFailed",
+		"couldNotMakeBackup",
+		"readBackup",
+	};
+
+	const char* getErrorString(Errors e)
+	{
+		if (e >= 0 && e < sizeof(errorsString) / sizeof(errorsString[0]))
+		{
+			return errorsString[e];
+		}
+		else
+		{
+			return "unknown error";
+		}
+	}
+
+	Errors readEntireFile(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 size = f.tellg();
+			f.seekg(0, std::ios_base::beg);
+
+			data.resize(size);
+
+			f.read(&data[0], size);
+
+			return noError;
+		}else
+		{
+			return couldNotOpenFinle;
+		}
+	}
+
+	Errors readEntireFile(void* data, size_t size, const char* name, bool shouldMatchSize, int* bytesRead)
+	{
+		if (bytesRead)
+		{
+			*bytesRead = 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.seekg(0, std::ios_base::beg);
+
+			if (shouldMatchSize)
+			{
+				if (readSize != size)
+				{
+					return fileSizeDitNotMatch;
+				}
+				else
+				{
+					f.read((char*)data, readSize);
+					if (bytesRead)
+					{
+						*bytesRead = readSize;
+					}
+
+					return noError;
+				}
+			}
+			else
+			{
+				f.read((char*)data, std::min(size, readSize));
+
+				if (bytesRead)
+				{
+					*bytesRead = std::min(size, readSize);
+				}
+
+				return noError;
+			}
+		}
+		else
+		{
+			return couldNotOpenFinle;
+		}
+	}
+	
+	using HashType = unsigned long long;
+	
+	//https://stackoverflow.com/questions/34595/what-is-a-good-hash-function
+	unsigned long long fnv_hash_1a_64(const void* key, int len)
+	{
+		const unsigned char* p = (const unsigned char*)key;
+		unsigned long long h = 0xcbf29ce484222325ULL;
+		for (int i = 0; i < len; i+=4)
+		{
+			h = (h ^ p[i + 0]) * 0x100000001b3ULL;
+			h = (h ^ p[i + 1]) * 0x100000001b3ULL;
+			h = (h ^ p[i + 2]) * 0x100000001b3ULL;
+			h = (h ^ p[i + 3]) * 0x100000001b3ULL;
+		}
+
+		for (int i = len - (len%4); i < len; i++)
+		{
+			h = (h ^ p[i]) * 0x100000001b3ULL;
+		}
+
+		return h;
+	}
+
+	Errors readEntireFileWithCheckSum(void* data, size_t size, const char* name)
+	{
+		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);
+			
+			size_t sizeWithCheckSum = size + sizeof(HashType);
+
+			if (readSize != sizeWithCheckSum)
+			{
+				return fileSizeDitNotMatch;
+			}
+			else
+			{
+				f.read((char*)data, size);
+				HashType checkSum = 0;
+				f.read((char*)&checkSum, sizeof(HashType));
+
+				auto testCheck = fnv_hash_1a_64(data, size);
+
+				if (testCheck != checkSum)
+				{
+					return checkSumFailed;
+				}
+				else
+				{
+					return noError;
+				}
+			}
+			
+		}
+		else
+		{
+			return couldNotOpenFinle;
+		}
+	}
+
+	Errors writeEntireFileWithCheckSum(const void* data, size_t size, const char* name)
+	{
+		std::ofstream f(name, std::ios::binary);
+
+		if (f.is_open())
+		{
+			f.write((char*)data, size);
+			auto testCheck = fnv_hash_1a_64(data, size);
+
+			f.write((char*)&testCheck, sizeof(testCheck));
+
+			return noError;
+		}
+		else
+		{
+			return couldNotOpenFinle;
+		}
+	}
+
+	Errors writeEntireFile(const std::vector<char>& data, const char* name)
+	{
+		return writeEntireFile(data.data(), data.size(), name);
+	}
+
+	Errors writeEntireFile(const void* data, size_t size, const char* name)
+	{
+		std::ofstream f(name, std::ios::binary);
+	
+		if (f.is_open())
+		{
+			f.write((char*)data, size);
+			return noError;
+		}
+		else
+		{
+			return couldNotOpenFinle;
+		}
+	}
+
+	Errors safeSave(const void* data, size_t size, const char* nameWithoutExtension, bool reportnotMakingBackupAsAnError)
+	{
+		std::string file1 = nameWithoutExtension; file1 += "1.bin";
+		std::string file2 = nameWithoutExtension; file2 += "2.bin";
+
+		auto err = writeEntireFileWithCheckSum((char*)data, size, file1.c_str());
+
+		if (err == couldNotOpenFinle)
+		{
+			return couldNotOpenFinle;
+		}
+		else
+		{
+			auto err2 = writeEntireFileWithCheckSum((char*)data, size, file2.c_str());	
+
+			if (err2 == couldNotOpenFinle)
+			{
+				if (reportnotMakingBackupAsAnError)
+				{
+					return couldNotMakeBackup;
+				}
+				else
+				{
+					return noError;
+				}
+			}
+			else
+			{
+				return noError;
+			}
+		}
+	}
+
+	Errors safeLoad(void* data, size_t size, const char* nameWithoutExtension, bool reportLoadingBackupAsAnError)
+	{
+		std::string file1 = nameWithoutExtension; file1 += "1.bin";
+		std::string file2 = nameWithoutExtension; file2 += "2.bin";
+
+		auto err = readEntireFileWithCheckSum((char*)data, size, file1.c_str());
+
+		if (err == noError)
+		{
+			return noError;
+		}
+		else 
+		{
+			//load backup
+			auto err2 = readEntireFileWithCheckSum((char*)data, size, 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)
+	{
+		std::string file2 = nameWithoutExtension; file2 += "2.bin";
+
+		//load backup
+		auto err2 = readEntireFileWithCheckSum((char*)data, size, file2.c_str());
+		return err2;
+	}
+
+#if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__
+
+	Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting)
+	{
+		fileMapping = {};
+
+		DWORD createDisposition = 0;
+
+		if (createIfNotExisting)
+		{
+			createDisposition = OPEN_ALWAYS;
+		}
+		else
+		{
+			createDisposition = OPEN_EXISTING;
+		}
+
+		fileMapping.internal.fileHandle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0,
+			NULL, createDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
+
+		if (fileMapping.internal.fileHandle == INVALID_HANDLE_VALUE)
+		{
+			auto err = GetLastError();
+			return Errors::couldNotOpenFinle;
+		}
+
+		fileMapping.internal.fileMapping = CreateFileMappingA(fileMapping.internal.fileHandle, NULL, PAGE_READWRITE, 0, size, NULL);
+
+		if (fileMapping.internal.fileMapping == NULL)
+		{
+			CloseHandle(fileMapping.internal.fileHandle);
+			return Errors::couldNotOpenFinle;
+		}
+
+
+		fileMapping.pointer = MapViewOfFile(fileMapping.internal.fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
+
+		if (fileMapping.pointer == nullptr)
+		{
+			CloseHandle(fileMapping.internal.fileMapping);
+			CloseHandle(fileMapping.internal.fileHandle);
+			return Errors::couldNotOpenFinle;
+		}
+
+		fileMapping.size = size;
+
+
+		return Errors::noError;
+	}
+
+	void closeFileMapping(FileMapping& fileMapping)
+	{
+		UnmapViewOfFile(fileMapping.pointer);
+		CloseHandle(fileMapping.internal.fileMapping);
+		CloseHandle(fileMapping.internal.fileHandle);
+		fileMapping = {};
+	}
+
+#elif defined __linux__
+
+	Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting)
+	{
+		int createDisposition = 0;
+		if(createIfNotExisting)
+		{
+			createDisposition = O_CREAT;
+		}
+
+		fileMapping.internal.fd = open(name, O_RDWR | createDisposition);
+
+		if(fileMapping.internal.fd == -1)
+		{
+			return Errors::couldNotOpenFinle;
+		}
+
+		if(ftruncate(fileMapping.internal.fd, size) == -1)
+		{
+			close(fileMapping.internal.fd);
+			return Errors::couldNotOpenFinle;
+		}
+		
+		fileMapping.pointer = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED,
+				fileMapping.internal.fd, 0);
+
+		if(fileMapping.pointer == MAP_FAILED)
+		{
+			fileMapping.pointer = 0;
+			close(fileMapping.internal.fd);
+			return Errors::couldNotOpenFinle;
+		}
+
+		fileMapping.size = size;
+		
+
+		return Errors::noError;
+	}
+
+	void closeFileMapping(FileMapping& fileMapping)
+	{
+		fsync(fileMapping.internal.fd);
+		msync(fileMapping.pointer, fileMapping.size, MS_SYNC);
+		munmap(fileMapping.pointer, fileMapping.size);
+		close(fileMapping.internal.fd);
+		
+		fileMapping = {};
+	}
+
+#endif	
+
+}