From 6fb20ab703ad3bf43016031366ad0125bff20e7b Mon Sep 17 00:00:00 2001 From: Henrique Gemignani Passos Lima Date: Thu, 27 May 2021 23:55:30 +0300 Subject: [PATCH] Add imgui layer editor --- Runtime/ImGuiConsole.cpp | 43 ++++++++++++++++++++++++++++++++++++++++ Runtime/ImGuiConsole.hpp | 2 ++ Runtime/World/CWorld.cpp | 10 +++++++--- Runtime/World/CWorld.hpp | 25 +++++++++++++---------- 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/Runtime/ImGuiConsole.cpp b/Runtime/ImGuiConsole.cpp index ec525c4c6..c16510a93 100644 --- a/Runtime/ImGuiConsole.cpp +++ b/Runtime/ImGuiConsole.cpp @@ -575,6 +575,7 @@ void ImGuiConsole::ShowAppMainMenuBar(bool canInspect) { if (ImGui::BeginMenu("Tools")) { ImGui::MenuItem("Inspect", nullptr, &m_showInspectWindow, canInspect); ImGui::MenuItem("Items", nullptr, &m_showItemsWindow, canInspect); + ImGui::MenuItem("Layers", nullptr, &m_showLayersWindow, canInspect); ImGui::Separator(); ImGui::MenuItem("Demo", nullptr, &m_showDemoWindow); ImGui::EndMenu(); @@ -642,6 +643,9 @@ void ImGuiConsole::PreUpdate() { if (canInspect && m_showItemsWindow) { ShowItemsWindow(); } + if (canInspect && m_showLayersWindow) { + ShowLayersWindow(); + } if (m_showAboutWindow) { ShowAboutWindow(); } @@ -778,4 +782,43 @@ void ImGuiConsole::ShowItemsWindow() { } ImGui::End(); } + +void ImGuiConsole::ShowLayersWindow() { + if (ImGui::Begin("Layers", &m_showLayersWindow)) { + for (const auto& world : ListWorlds()) { + const auto& layers = dummyWorlds[world.second]->GetWorldLayers(); + if (!layers) { + continue; + } + + if (ImGui::TreeNode(world.first.c_str())) { + auto worldLayerState = g_GameState->StateForWorld(world.second).GetLayerState(); + u32 startNameIdx = 0; + + for (const auto& area : ListAreas(world.second)) { + u32 layerCount = worldLayerState->GetAreaLayerCount(area.second); + if (layerCount == 0) { + continue; + } + if (ImGui::TreeNode(area.first.c_str())) { + // TODO: m_startNameIdx have incorrect values in the data due to a Metaforce bug + // u32 startNameIdx = layers->m_areas[area.second].m_startNameIdx; + + for (u32 layer = 0; layer < layerCount; ++layer) { + bool active = worldLayerState->IsLayerActive(area.second, layer); + if (ImGui::Checkbox(layers->m_names[startNameIdx + layer].c_str(), &active)) { + worldLayerState->SetLayerActive(area.second, layer, active); + } + } + ImGui::TreePop(); + } + startNameIdx += layerCount; + } + ImGui::TreePop(); + } + } + } + ImGui::End(); +} + } // namespace metaforce diff --git a/Runtime/ImGuiConsole.hpp b/Runtime/ImGuiConsole.hpp index bb504243a..193473afb 100644 --- a/Runtime/ImGuiConsole.hpp +++ b/Runtime/ImGuiConsole.hpp @@ -51,6 +51,7 @@ private: bool m_showDemoWindow = false; bool m_showAboutWindow = false; bool m_showItemsWindow = false; + bool m_showLayersWindow = false; bool m_paused = false; bool m_stepFrame = false; @@ -83,5 +84,6 @@ private: void ShowAboutWindow(); void ShowDebugOverlay(); void ShowItemsWindow(); + void ShowLayersWindow(); }; } // namespace metaforce diff --git a/Runtime/World/CWorld.cpp b/Runtime/World/CWorld.cpp index 07f2ae239..03f1c47f2 100644 --- a/Runtime/World/CWorld.cpp +++ b/Runtime/World/CWorld.cpp @@ -76,9 +76,9 @@ std::vector CWorld::CRelay::ReadMemoryRelays(athena::io::MemoryR return ret; } -void CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r, int version, CAssetId mlvlId) { +std::optional CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r, int version, CAssetId mlvlId) { if (version <= 14) { - return; + return std::nullopt; } CWorldLayers ret; @@ -104,6 +104,8 @@ void CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r, int version, CAs CWorldState& wldState = g_GameState->StateForWorld(mlvlId); wldState.GetLayerState()->InitializeWorldLayers(ret.m_areas); + + return ret; } bool CDummyWorld::ICheckWorldComplete() { @@ -148,7 +150,7 @@ bool CDummyWorld::ICheckWorldComplete() { if (version > 12) r.readString(); - CWorldLayers::ReadWorldLayers(r, version, xc_mlvlId); + worldLayers = CWorldLayers::ReadWorldLayers(r, version, xc_mlvlId); x30_loadToken.reset(); x34_loadBuf.reset(); @@ -188,6 +190,8 @@ std::string CDummyWorld::IGetDefaultAudioTrack() const { return {}; } int CDummyWorld::IGetAreaCount() const { return x18_areas.size(); } +const std::optional& CDummyWorld::GetWorldLayers() const { return worldLayers; } + CWorld::CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId) : x8_mlvlId(mlvlId) , x60_objectStore(objStore) diff --git a/Runtime/World/CWorld.hpp b/Runtime/World/CWorld.hpp index ae6951c79..bc12e1b81 100644 --- a/Runtime/World/CWorld.hpp +++ b/Runtime/World/CWorld.hpp @@ -37,6 +37,17 @@ public: virtual int IGetAreaCount() const = 0; }; +struct CWorldLayers { + struct Area { + u32 m_startNameIdx; + u32 m_layerCount; + u64 m_layerBits; + }; + std::vector m_areas; + std::vector m_names; + static std::optional ReadWorldLayers(athena::io::MemoryReader& r, int version, CAssetId mlvlId); +}; + class CDummyWorld : public IWorld { enum class Phase { Loading, @@ -58,6 +69,8 @@ class CDummyWorld : public IWorld { u32 x38_bufSz; TAreaId x3c_curAreaId = kInvalidAreaId; + std::optional worldLayers; + public: CDummyWorld(CAssetId mlvlId, bool loadMap); ~CDummyWorld() override; @@ -72,6 +85,7 @@ public: bool ICheckWorldComplete() override; std::string IGetDefaultAudioTrack() const override; int IGetAreaCount() const override; + const std::optional& GetWorldLayers() const; }; class CWorld : public IWorld { @@ -214,15 +228,4 @@ public: TAreaId GetAreaIdForSaveId(s32 saveId) const; }; -struct CWorldLayers { - struct Area { - u32 m_startNameIdx; - u32 m_layerCount; - u64 m_layerBits; - }; - std::vector m_areas; - std::vector m_names; - static void ReadWorldLayers(athena::io::MemoryReader& r, int version, CAssetId mlvlId); -}; - } // namespace metaforce