From d3b2893cdca8c61d5c2eb1757e1418ceacba9042 Mon Sep 17 00:00:00 2001
From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com>
Date: Thu, 24 Nov 2022 10:45:42 +0100
Subject: [PATCH] Change ImGui config file path and use engine's FileSystem API

'ImGuiConfig::Load()' was loading from the new path, however 'ImGuiConfig::Save()' was not. Defined path as constant expression to avoid this problem in the future. Also loading the files through the engine's API from now on.
---
 r5dev/launcher/IApplication.cpp               |  1 +
 .../thirdparty/imgui/include/imgui_utility.h  |  3 +
 r5dev/thirdparty/imgui/src/imgui_utility.cpp  | 67 ++++++++++++-------
 r5dev/windows/id3dx.cpp                       |  1 -
 4 files changed, 46 insertions(+), 26 deletions(-)

diff --git a/r5dev/launcher/IApplication.cpp b/r5dev/launcher/IApplication.cpp
index ad731665..fa4f0e37 100644
--- a/r5dev/launcher/IApplication.cpp
+++ b/r5dev/launcher/IApplication.cpp
@@ -77,6 +77,7 @@ bool CModAppSystemGroup::Create(CModAppSystemGroup* pModAppSystemGroup)
 	g_pClientEntityList = g_pFactory->GetFactoryPtr("VClientEntityList003", false).RCast<IClientEntityList*>();
 	g_pEngineTrace = g_pFactory->GetFactoryPtr("EngineTraceClient004", false).RCast<CEngineTrace*>();
 
+	g_pImGuiConfig->Load(); // Load ImGui configs.
 	for (auto& map : g_pCVar->DumpToMap())
 	{
 		g_pConsole->m_vsvCommandBases.push_back(
diff --git a/r5dev/thirdparty/imgui/include/imgui_utility.h b/r5dev/thirdparty/imgui/include/imgui_utility.h
index 5f6f9aa7..be1bf978 100644
--- a/r5dev/thirdparty/imgui/include/imgui_utility.h
+++ b/r5dev/thirdparty/imgui/include/imgui_utility.h
@@ -1,5 +1,8 @@
 #pragma once
 
+constexpr char IMGUI_BIND_PATH[] = "cfg/imgui/";
+constexpr char IMGUI_BIND_FILE[] = "bind.json";
+
 /////////////////////////////////////////////////////////////////////////////
 // Internals
 int   Stricmp(const char* s1, const char* s2);
diff --git a/r5dev/thirdparty/imgui/src/imgui_utility.cpp b/r5dev/thirdparty/imgui/src/imgui_utility.cpp
index 77eb4c23..76365ee2 100644
--- a/r5dev/thirdparty/imgui/src/imgui_utility.cpp
+++ b/r5dev/thirdparty/imgui/src/imgui_utility.cpp
@@ -4,6 +4,8 @@
 
 #include "core/stdafx.h"
 #include "tier0/commandline.h"
+#include "tier0/memstd.h"
+#include "filesystem/filesystem.h"
 #include "thirdparty/imgui/include/imgui_utility.h"
 
 int Stricmp(const char* s1, const char* s2)
@@ -45,44 +47,62 @@ void Strtrim(char* s)
 
 void ImGuiConfig::Load()
 {
-    static const fs::path fsPath = "platform\\cfg\\imgui\\bind.json";
-    DevMsg(eDLL_T::MS, "Loading ImGui config file '%s'\n", fsPath.relative_path().u8string().c_str());
+    const string svPath = fmt::format("{:s}{:s}", IMGUI_BIND_PATH, IMGUI_BIND_FILE);
+    DevMsg(eDLL_T::MS, "Loading ImGui config file '%s'\n", svPath.c_str());
 
-    if (!fs::exists(fsPath))
+    FileSystem()->CreateDirHierarchy(IMGUI_BIND_PATH, "PLATFORM"); // Create directory, so ImGui can load/save 'layout.ini'.
+    FileHandle_t hFile = FileSystem()->Open(svPath.c_str(), "rt", "PLATFORM");
+
+    if (!hFile)
     {
         return;
     }
 
+    uint32_t nLen = FileSystem()->Size(hFile);
+    uint8_t* pBuf = MemAllocSingleton()->Alloc<uint8_t>(nLen);
+
+    int nRead = FileSystem()->Read(pBuf, nLen, hFile);
+    FileSystem()->Close(hFile);
+
+    pBuf[nRead] = '\0';
+
     try
     {
-        nlohmann::json jsIn;
-        std::ifstream configFile(fsPath, std::ios::binary); // Parse config file.
+        nlohmann::json jsIn = nlohmann::json::parse(pBuf);
 
-        configFile >> jsIn;
-        configFile.close();
-
-        if (jsIn.is_null() || jsIn["config"].is_null())
+        if (!jsIn.is_null() || !jsIn["config"].is_null())
         {
-            return; // Invalid or no config.
+            // IConsole
+            m_ConsoleConfig.m_nBind0 = jsIn["config"]["GameConsole"]["bind0"].get<int>();
+            m_ConsoleConfig.m_nBind1 = jsIn["config"]["GameConsole"]["bind1"].get<int>();
+
+            // IBrowser
+            m_BrowserConfig.m_nBind0 = jsIn["config"]["GameBrowser"]["bind0"].get<int>();
+            m_BrowserConfig.m_nBind1 = jsIn["config"]["GameBrowser"]["bind1"].get<int>();
         }
-
-        // IConsole
-        m_ConsoleConfig.m_nBind0 = jsIn["config"]["GameConsole"]["bind0"].get<int>();
-        m_ConsoleConfig.m_nBind1 = jsIn["config"]["GameConsole"]["bind1"].get<int>();
-
-        // IBrowser
-        m_BrowserConfig.m_nBind0 = jsIn["config"]["GameBrowser"]["bind0"].get<int>();
-        m_BrowserConfig.m_nBind1 = jsIn["config"]["GameBrowser"]["bind1"].get<int>();
     }
     catch (const std::exception& ex)
     {
         Warning(eDLL_T::MS, "Exception while parsing ImGui config file:\n%s\n", ex.what());
-        return;
     }
+
+    MemAllocSingleton()->Free(pBuf);
 }
 
 void ImGuiConfig::Save()
 {
+    const string svPath = fmt::format("{:s}{:s}", IMGUI_BIND_PATH, IMGUI_BIND_FILE);
+    DevMsg(eDLL_T::MS, "Saving ImGui config file '%s'\n", svPath.c_str());
+
+    FileSystem()->CreateDirHierarchy(IMGUI_BIND_PATH, "PLATFORM");
+    FileHandle_t hFile = FileSystem()->Open(svPath.c_str(), "wt", "PLATFORM");
+
+    if (!hFile)
+    {
+        Error(eDLL_T::MS, NO_ERROR, "%s - Unable to write to '%s' (read-only?)\n", __FUNCTION__, svPath.c_str());
+        return;
+    }
+
     nlohmann::json jsOut;
 
     // IConsole
@@ -93,13 +113,10 @@ void ImGuiConfig::Save()
     jsOut["config"]["GameBrowser"]["bind0"] = m_BrowserConfig.m_nBind0;
     jsOut["config"]["GameBrowser"]["bind1"] = m_BrowserConfig.m_nBind1;
 
-    fs::path fsPath = "platform\\imgui.json";
+    const string svOutFile = jsOut.dump(4);
 
-    DevMsg(eDLL_T::MS, "Saving ImGui config file '%s'\n", fsPath.relative_path().u8string().c_str());
-    std::ofstream outFile(fsPath, std::ios::out | std::ios::trunc); // Write config file.
-
-    outFile << jsOut.dump(4); // Dump it into config file.
-    outFile.close();          // Close the file handle.
+    FileSystem()->Write(svOutFile.data(), svOutFile.size(), hFile);
+    FileSystem()->Close(hFile);
 }
 
 ImGuiStyle_t ImGuiConfig::InitStyle() const
diff --git a/r5dev/windows/id3dx.cpp b/r5dev/windows/id3dx.cpp
index 4c48af10..30fc05fd 100644
--- a/r5dev/windows/id3dx.cpp
+++ b/r5dev/windows/id3dx.cpp
@@ -521,7 +521,6 @@ void VDXGI::GetAdr(void) const
 
 DWORD __stdcall DXSwapChainWorker(LPVOID)
 {
-	g_pImGuiConfig->Load(); // Load ImGui configs.
 	GetPresent();
 	InstallDXHooks();