From e5bc5188e78695017f476c1682353007c6a9f97c Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 23 Jan 2023 15:39:05 -0600 Subject: [PATCH] Actor view values now using pointers rather than copies, add playerState flags to save editor (#2388) --- soh/soh/Enhancements/debugger/actorViewer.cpp | 60 +++++--- .../Enhancements/debugger/debugSaveEditor.cpp | 145 +++++++++++++----- soh/soh/UIWidgets.cpp | 63 ++++++++ soh/soh/UIWidgets.hpp | 3 + 4 files changed, 207 insertions(+), 64 deletions(-) diff --git a/soh/soh/Enhancements/debugger/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp index 31ce27236..b0c870383 100644 --- a/soh/soh/Enhancements/debugger/actorViewer.cpp +++ b/soh/soh/Enhancements/debugger/actorViewer.cpp @@ -541,8 +541,8 @@ void DrawActorViewer(bool& open) { return; } - static Actor display; - static const Actor empty{}; + static Actor* display; + static Actor empty{}; static Actor* fetch = NULL; static ActorInfo newActor = {0,0, {0, 0, 0}, {0, 0, 0}}; static ActorOverlay* dispOverlay; @@ -558,7 +558,7 @@ void DrawActorViewer(bool& open) { if (gPlayState != nullptr) { needs_reset = lastSceneId != gPlayState->sceneNum; if (needs_reset) { - display = empty; + display = ∅ fetch = nullptr; dispOverlay = nullptr; actor = category = 0; @@ -591,7 +591,7 @@ void DrawActorViewer(bool& open) { if (ImGui::Selectable(label.c_str())) { rm = LIST; - display = *list[i]; + display = list[i]; actor = i; filler = label; break; @@ -601,50 +601,62 @@ void DrawActorViewer(bool& open) { } if (ImGui::TreeNode("Selected Actor")) { - dispOverlay = display.overlayEntry; + dispOverlay = display->overlayEntry; DrawGroupWithBorder([&]() { ImGui::Text("Name: %s", dispOverlay != nullptr ? dispOverlay->name : "???"); - ImGui::Text("Description: %s", dispOverlay != nullptr ? GetActorDescription(display.id).c_str() : "???"); - ImGui::Text("Category: %s", dispOverlay != nullptr ? acMapping[display.category] : "???"); - ImGui::Text("ID: %d", display.id); - ImGui::Text("Parameters: %d", display.params); + ImGui::Text("Description: %s", dispOverlay != nullptr ? GetActorDescription(display->id).c_str() : "???"); + ImGui::Text("Category: %s", dispOverlay != nullptr ? acMapping[display->category] : "???"); + ImGui::Text("ID: %d", display->id); + ImGui::Text("Parameters: %d", display->params); }); ImGui::PushItemWidth(ImGui::GetFontSize() * 6); DrawGroupWithBorder([&]() { ImGui::Text("Actor Position"); - ImGui::InputScalar("x pos", ImGuiDataType_Float, &display.world.pos.x); + ImGui::InputScalar("x pos", ImGuiDataType_Float, &display->world.pos.x); ImGui::SameLine(); - ImGui::InputScalar("y pos", ImGuiDataType_Float, &display.world.pos.y); + ImGui::InputScalar("y pos", ImGuiDataType_Float, &display->world.pos.y); ImGui::SameLine(); - ImGui::InputScalar("z pos", ImGuiDataType_Float, &display.world.pos.z); + ImGui::InputScalar("z pos", ImGuiDataType_Float, &display->world.pos.z); }); DrawGroupWithBorder([&]() { ImGui::Text("Actor Rotation"); - ImGui::InputScalar("x rot", ImGuiDataType_S16, &display.world.rot.x); + ImGui::InputScalar("x rot", ImGuiDataType_S16, &display->world.rot.x); ImGui::SameLine(); - ImGui::InputScalar("y rot", ImGuiDataType_S16, &display.world.rot.y); + ImGui::InputScalar("y rot", ImGuiDataType_S16, &display->world.rot.y); ImGui::SameLine(); - ImGui::InputScalar("z rot", ImGuiDataType_S16, &display.world.rot.z); + ImGui::InputScalar("z rot", ImGuiDataType_S16, &display->world.rot.z); }); - if (display.category == ACTORCAT_BOSS || display.category == ACTORCAT_ENEMY) { - ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display.colChkInfo.health); + if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) { + ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display->colChkInfo.health); UIWidgets::InsertHelpHoverText("Some actors might not use this!"); } + DrawGroupWithBorder([&]() { + ImGui::Text("flags"); + UIWidgets::DrawFlagArray32("flags", display->flags); + }); + + ImGui::SameLine(); + + DrawGroupWithBorder([&]() { + ImGui::Text("bgCheckFlags"); + UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags); + }); + if (ImGui::Button("Refresh")) { PopulateActorDropdown(category, list); switch (rm) { case INTERACT: case HELD: case TARGET: - display = *fetch; + display = fetch; break; case LIST: - display = *list[actor]; + display = list[actor]; break; default: break; @@ -653,7 +665,7 @@ void DrawActorViewer(bool& open) { if (ImGui::Button("Go to Actor")) { Player* player = GET_PLAYER(gPlayState); - Math_Vec3f_Copy(&player->actor.world.pos, &display.world.pos); + Math_Vec3f_Copy(&player->actor.world.pos, &display->world.pos); Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos); } @@ -661,7 +673,7 @@ void DrawActorViewer(bool& open) { Player* player = GET_PLAYER(gPlayState); fetch = player->targetActor; if (fetch != NULL) { - display = *fetch; + display = fetch; category = fetch->category; PopulateActorDropdown(category, list); rm = TARGET; @@ -672,7 +684,7 @@ void DrawActorViewer(bool& open) { Player* player = GET_PLAYER(gPlayState); fetch = player->heldActor; if (fetch != NULL) { - display = *fetch; + display = fetch; category = fetch->category; PopulateActorDropdown(category, list); rm = HELD; @@ -683,7 +695,7 @@ void DrawActorViewer(bool& open) { Player* player = GET_PLAYER(gPlayState); fetch = player->interactRangeActor; if (fetch != NULL) { - display = *fetch; + display = fetch; category = fetch->category; PopulateActorDropdown(category, list); rm = INTERACT; @@ -739,7 +751,7 @@ void DrawActorViewer(bool& open) { } if (ImGui::Button("Spawn as Child")) { - Actor* parent = &display; + Actor* parent = display; if (parent != NULL) { if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX && gActorOverlayTable[newActor.id].initInfo != NULL) { diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 7814a5c9f..86af3c9c6 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -749,28 +749,7 @@ void DrawInventoryTab() { } // Draw a flag bitfield as an grid of checkboxes -void DrawFlagArray32(const std::string& name, uint32_t& flags) { - ImGui::PushID(name.c_str()); - for (int32_t flagIndex = 0; flagIndex < 32; flagIndex++) { - if ((flagIndex % 8) != 0) { - ImGui::SameLine(); - } - ImGui::PushID(flagIndex); - uint32_t bitMask = 1 << flagIndex; - bool flag = (flags & bitMask) != 0; - if (ImGui::Checkbox("##check", &flag)) { - if (flag) { - flags |= bitMask; - } else { - flags &= ~bitMask; - } - } - ImGui::PopID(); - } - ImGui::PopID(); -} - -void DrawFlagArray16(const FlagTable& flagTable, uint16_t row, uint16_t& flags) { +void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& flags) { ImGui::PushID((std::to_string(row) + flagTable.name).c_str()); for (int32_t flagIndex = 15; flagIndex >= 0; flagIndex--) { ImGui::SameLine(); @@ -798,6 +777,36 @@ void DrawFlagArray16(const FlagTable& flagTable, uint16_t row, uint16_t& flags) } void DrawFlagsTab() { + if (ImGui::TreeNode("Player State")) { + if (gPlayState != nullptr) { + Player* player = GET_PLAYER(gPlayState); + + DrawGroupWithBorder([&]() { + ImGui::Text("stateFlags1"); + UIWidgets::DrawFlagArray32("stateFlags1", player->stateFlags1); + }); + + ImGui::SameLine(); + + DrawGroupWithBorder([&]() { + ImGui::Text("stateFlags2"); + UIWidgets::DrawFlagArray32("stateFlags2", player->stateFlags2); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("stateFlags3"); + UIWidgets::DrawFlagArray8("stateFlags3", player->stateFlags3); + }); + + ImGui::SameLine(); + + DrawGroupWithBorder([&]() { + ImGui::Text("unk_6AE"); + UIWidgets::DrawFlagArray16("unk_6AE", player->unk_6AE); + }); + } + ImGui::TreePop(); + } if (ImGui::TreeNode("Current Scene")) { if (gPlayState != nullptr) { ActorContext* act = &gPlayState->actorCtx; @@ -805,7 +814,15 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Switch"); UIWidgets::InsertHelpHoverText("Permanently-saved switch flags"); - DrawFlagArray32("Switch", act->flags.swch); + ImGui::SameLine(); + if (ImGui::Button("Set All##Switch")) { + act->flags.swch = UINT32_MAX; + } + ImGui::SameLine(); + if (ImGui::Button("Clear All##Switch")) { + act->flags.swch = 0; + } + UIWidgets::DrawFlagArray32("Switch", act->flags.swch); }); ImGui::SameLine(); @@ -813,13 +830,29 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Switch"); UIWidgets::InsertHelpHoverText("Temporary switch flags. Unset on scene transitions"); - DrawFlagArray32("Temp Switch", act->flags.tempSwch); + ImGui::SameLine(); + if (ImGui::Button("Set All##Temp Switch")) { + act->flags.tempSwch = UINT32_MAX; + } + ImGui::SameLine(); + if (ImGui::Button("Clear All##Temp Switch")) { + act->flags.tempSwch = 0; + } + UIWidgets::DrawFlagArray32("Temp Switch", act->flags.tempSwch); }); DrawGroupWithBorder([&]() { ImGui::Text("Clear"); UIWidgets::InsertHelpHoverText("Permanently-saved room-clear flags"); - DrawFlagArray32("Clear", act->flags.clear); + ImGui::SameLine(); + if (ImGui::Button("Set All##Clear")) { + act->flags.clear = UINT32_MAX; + } + ImGui::SameLine(); + if (ImGui::Button("Clear All##Clear")) { + act->flags.clear = 0; + } + UIWidgets::DrawFlagArray32("Clear", act->flags.clear); }); ImGui::SameLine(); @@ -827,13 +860,29 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Clear"); UIWidgets::InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions"); - DrawFlagArray32("Temp Clear", act->flags.tempClear); + ImGui::SameLine(); + if (ImGui::Button("Set All##Temp Clear")) { + act->flags.tempClear = UINT32_MAX; + } + ImGui::SameLine(); + if (ImGui::Button("Clear All##Temp Clear")) { + act->flags.tempClear = 0; + } + UIWidgets::DrawFlagArray32("Temp Clear", act->flags.tempClear); }); DrawGroupWithBorder([&]() { ImGui::Text("Collect"); UIWidgets::InsertHelpHoverText("Permanently-saved collect flags"); - DrawFlagArray32("Collect", act->flags.collect); + ImGui::SameLine(); + if (ImGui::Button("Set All##Collect")) { + act->flags.collect = UINT32_MAX; + } + ImGui::SameLine(); + if (ImGui::Button("Clear All##Collect")) { + act->flags.collect = 0; + } + UIWidgets::DrawFlagArray32("Collect", act->flags.collect); }); ImGui::SameLine(); @@ -841,13 +890,29 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Collect"); UIWidgets::InsertHelpHoverText("Temporary collect flags. Unset on scene transitions"); - DrawFlagArray32("Temp Collect", act->flags.tempCollect); + ImGui::SameLine(); + if (ImGui::Button("Set All##Temp Collect")) { + act->flags.tempCollect = UINT32_MAX; + } + ImGui::SameLine(); + if (ImGui::Button("Clear All##Temp Collect")) { + act->flags.tempCollect = 0; + } + UIWidgets::DrawFlagArray32("Temp Collect", act->flags.tempCollect); }); DrawGroupWithBorder([&]() { ImGui::Text("Chest"); UIWidgets::InsertHelpHoverText("Permanently-saved chest flags"); - DrawFlagArray32("Chest", act->flags.chest); + ImGui::SameLine(); + if (ImGui::Button("Set All##Chest")) { + act->flags.chest = UINT32_MAX; + } + ImGui::SameLine(); + if (ImGui::Button("Clear All##Chest")) { + act->flags.chest = 0; + } + UIWidgets::DrawFlagArray32("Chest", act->flags.chest); }); ImGui::SameLine(); @@ -913,7 +978,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Switch"); UIWidgets::InsertHelpHoverText("Switch flags"); - DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch); + UIWidgets::DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch); }); ImGui::SameLine(); @@ -921,13 +986,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Clear"); UIWidgets::InsertHelpHoverText("Room-clear flags"); - DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear); + UIWidgets::DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear); }); DrawGroupWithBorder([&]() { ImGui::Text("Collect"); UIWidgets::InsertHelpHoverText("Collect flags"); - DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect); + UIWidgets::DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect); }); ImGui::SameLine(); @@ -935,13 +1000,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Chest"); UIWidgets::InsertHelpHoverText("Chest flags"); - DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest); + UIWidgets::DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest); }); DrawGroupWithBorder([&]() { ImGui::Text("Rooms"); UIWidgets::InsertHelpHoverText("Flags for visted rooms"); - DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms); + UIWidgets::DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms); }); ImGui::SameLine(); @@ -949,7 +1014,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Floors"); UIWidgets::InsertHelpHoverText("Flags for visted floors"); - DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors); + UIWidgets::DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors); }); ImGui::TreePop(); @@ -1027,19 +1092,19 @@ void DrawFlagsTab() { ImGui::Text(fmt::format("{:<2x}", j).c_str()); switch (flagTable.flagTableType) { case EVENT_CHECK_INF: - DrawFlagArray16(flagTable, j, gSaveContext.eventChkInf[j]); + DrawFlagTableArray16(flagTable, j, gSaveContext.eventChkInf[j]); break; case ITEM_GET_INF: - DrawFlagArray16(flagTable, j, gSaveContext.itemGetInf[j]); + DrawFlagTableArray16(flagTable, j, gSaveContext.itemGetInf[j]); break; case INF_TABLE: - DrawFlagArray16(flagTable, j, gSaveContext.infTable[j]); + DrawFlagTableArray16(flagTable, j, gSaveContext.infTable[j]); break; case EVENT_INF: - DrawFlagArray16(flagTable, j, gSaveContext.eventInf[j]); + DrawFlagTableArray16(flagTable, j, gSaveContext.eventInf[j]); break; case RANDOMIZER_INF: - DrawFlagArray16(flagTable, j, gSaveContext.randomizerInf[j]); + DrawFlagTableArray16(flagTable, j, gSaveContext.randomizerInf[j]); break; } }); diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 4c1fcd0a0..1feefd2e8 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -663,4 +663,67 @@ namespace UIWidgets { return changed; } + + void DrawFlagArray32(const std::string& name, uint32_t& flags) { + ImGui::PushID(name.c_str()); + for (int32_t flagIndex = 0; flagIndex < 32; flagIndex++) { + if ((flagIndex % 8) != 0) { + ImGui::SameLine(); + } + ImGui::PushID(flagIndex); + uint32_t bitMask = 1 << flagIndex; + bool flag = (flags & bitMask) != 0; + if (ImGui::Checkbox("##check", &flag)) { + if (flag) { + flags |= bitMask; + } else { + flags &= ~bitMask; + } + } + ImGui::PopID(); + } + ImGui::PopID(); + } + + void DrawFlagArray16(const std::string& name, uint16_t& flags) { + ImGui::PushID(name.c_str()); + for (int16_t flagIndex = 0; flagIndex < 16; flagIndex++) { + if ((flagIndex % 8) != 0) { + ImGui::SameLine(); + } + ImGui::PushID(flagIndex); + uint16_t bitMask = 1 << flagIndex; + bool flag = (flags & bitMask) != 0; + if (ImGui::Checkbox("##check", &flag)) { + if (flag) { + flags |= bitMask; + } else { + flags &= ~bitMask; + } + } + ImGui::PopID(); + } + ImGui::PopID(); + } + + void DrawFlagArray8(const std::string& name, uint8_t& flags) { + ImGui::PushID(name.c_str()); + for (int8_t flagIndex = 0; flagIndex < 8; flagIndex++) { + if ((flagIndex % 8) != 0) { + ImGui::SameLine(); + } + ImGui::PushID(flagIndex); + uint8_t bitMask = 1 << flagIndex; + bool flag = (flags & bitMask) != 0; + if (ImGui::Checkbox("##check", &flag)) { + if (flag) { + flags |= bitMask; + } else { + flags &= ~bitMask; + } + } + ImGui::PopID(); + } + ImGui::PopID(); + } } diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index 31ba7fd83..40d80c716 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -47,6 +47,9 @@ namespace UIWidgets { void EnhancementRadioButton(const char* text, const char* cvarName, int id); bool EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); + void DrawFlagArray32(const std::string& name, uint32_t& flags); + void DrawFlagArray16(const std::string& name, uint16_t& flags); + void DrawFlagArray8(const std::string& name, uint8_t& flags); } #endif /* UIWidgets_hpp */