Save editor flag improvements (#7198)

1. clicking on flag name toggles checkbox
2. hovering over player state shows flag name
3. add search box for player state, adjust names to what headers call them
This commit is contained in:
Philip Dubé
2026-09-15 00:59:12 +00:00
committed by GitHub
parent 034bf5f3c7
commit 4c04c7615f
2 changed files with 85 additions and 34 deletions
@@ -112,6 +112,7 @@ ButtonOptions buttonOptionsBase;
CheckboxOptions checkboxOptionsBase;
ComboboxOptions comboboxOptionsBase;
static std::map<std::string, ImGuiTextFilter> flagTableFilters;
static ImGuiTextFilter playerStateFilter;
// Modification of gAmmoItems that replaces ITEM_NONE with the item in inventory slot it represents
u8 gAllAmmoItems[] = {
@@ -1350,6 +1351,35 @@ void DrawFlagArrayWithTooltips(const std::string& name, T& flags, Colors color,
ImGui::PopID();
}
// List state flags matching the search, returns whether any matched
template <typename T>
bool DrawStateSearchResults(const char* label, T& flags, const std::vector<std::string>& names,
ImGuiTextFilter& filter) {
bool hasMatches = false;
ImGui::PushID(label);
for (size_t flagIndex = 0; flagIndex < names.size() && flagIndex < sizeof(T) * 8; flagIndex++) {
std::string text = spdlog::fmt_lib::format("{} Bit {}: {}", label, flagIndex, names[flagIndex]);
if (!filter.PassFilter(text.c_str())) {
continue;
}
hasMatches = true;
ImGui::PushID(static_cast<int>(flagIndex));
uint32_t bitMask = 1u << flagIndex;
bool flag = (flags & bitMask) != 0;
PushStyleCheckbox(THEME_COLOR);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 3.0f));
if (ImGui::Checkbox(text.c_str(), &flag)) {
flags ^= bitMask;
}
ImGui::PopStyleVar();
PopStyleCheckbox();
ImGui::PopID();
}
ImGui::PopID();
return hasMatches;
}
static const char* GetFlagDescription(const FlagTable& flagTable, uint16_t index) {
if (flagTable.flagTableType == RANDOMIZER_INF) {
std::string_view name = EnumToString(static_cast<RandomizerInf>(index));
@@ -1431,7 +1461,7 @@ void DrawActiveStates(const std::string& label, uint32_t states, const std::vect
if (!hasAny)
active += "None";
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6f, 0.6f, 0.6f, 1.0f));
ImGui::Text("%s", active.c_str());
ImGui::TextWrapped("%s", active.c_str());
ImGui::PopStyleColor();
}
@@ -1499,12 +1529,18 @@ static void DrawFlagTableSearchResults(const FlagTable& flagTable, ImGuiTextFilt
}
ImGui::SameLine();
ImVec2 labelPos = ImGui::GetCursorScreenPos();
if (hasDescription) {
ImGui::TextWrapped("0x%02X: %s", index, desc);
} else {
ImGui::Text("0x%02X", index);
}
ImGui::SetCursorScreenPos(labelPos);
if (ImGui::InvisibleButton("##label", ImGui::GetItemRectSize())) {
flags ^= bitMask;
}
ImGui::PopID();
}
}
@@ -2603,31 +2639,46 @@ void DrawPlayerTab() {
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Player State");
ImGui::Spacing();
// State Flags 1
ImGui::Text("State 1");
DrawFlagArrayWithTooltips("State1", player->stateFlags1, THEME_COLOR, state1);
// Show active State 1 flags
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 16);
PushStyleInput(THEME_COLOR);
playerStateFilter.Draw();
PopStyleInput();
ImGui::Spacing();
DrawActiveStates("State1", player->stateFlags1, state1);
ImGui::Spacing();
// State Flags 2
ImGui::Text("State 2");
DrawFlagArrayWithTooltips("State2", player->stateFlags2, THEME_COLOR, state2);
if (playerStateFilter.IsActive()) {
bool hasMatches = DrawStateSearchResults("State 1", player->stateFlags1, state1, playerStateFilter);
hasMatches |= DrawStateSearchResults("State 2", player->stateFlags2, state2, playerStateFilter);
hasMatches |= DrawStateSearchResults("State 3", player->stateFlags3, state3, playerStateFilter);
if (!hasMatches) {
ImGui::Text("No flags match the current search.");
}
} else {
// State Flags 1
ImGui::Text("State 1");
DrawFlagArrayWithTooltips("State1", player->stateFlags1, THEME_COLOR, state1);
// Show active State 2 flags
ImGui::Spacing();
DrawActiveStates("State2", player->stateFlags2, state2);
// Show active State 1 flags
ImGui::Spacing();
DrawActiveStates("State1", player->stateFlags1, state1);
ImGui::Spacing();
// State Flags 3
ImGui::Text("State 3");
DrawFlagArrayWithTooltips("State3", player->stateFlags3, THEME_COLOR, state3);
ImGui::Spacing();
// State Flags 2
ImGui::Text("State 2");
DrawFlagArrayWithTooltips("State2", player->stateFlags2, THEME_COLOR, state2);
// Show active State 3 flags
ImGui::Spacing();
DrawActiveStates("State3", player->stateFlags3, state3);
// Show active State 2 flags
ImGui::Spacing();
DrawActiveStates("State2", player->stateFlags2, state2);
ImGui::Spacing();
// State Flags 3
ImGui::Text("State 3");
DrawFlagArrayWithTooltips("State3", player->stateFlags3, THEME_COLOR, state3);
// Show active State 3 flags
ImGui::Spacing();
DrawActiveStates("State3", player->stateFlags3, state3);
}
ImGui::Spacing();
// Rotation Flags (unk_6AE_rotFlags)
+13 -13
View File
@@ -368,33 +368,33 @@ const std::vector<std::string> state1 = {
"Swinging Bottle",
"Falling from Hookshot",
"Hookshot/Bow in Hand",
"Targeting Enemy",
"Hostile Lock-On",
"Input Disabled",
"Text on Screen",
"Talking",
"Death",
"Starting to put away",
"Ready to Fire",
"Get Item",
"Item over Head",
"Carrying Actor",
"Charging Spin Attack",
"Hanging off Ledge",
"Climbing Ledge",
"Targeting",
"Target Locked",
"Targeting Nothing",
"Z-Targeting",
"Friendly Actor Focus",
"Parallel Targeting",
"Jumping Forward",
"In Freefall",
"In First-Person View",
"Climbing Ladder",
"Shielding",
"On Horse",
"Boomerang in Hand",
"Using Boomerang",
"Boomerang Thrown",
"Damaged",
"In Water",
"In Item Cutscene",
"In Cutscene",
"30", // Unknown
"Lock-On Forced to Release",
"Floor collision disabled",
};
@@ -408,18 +408,18 @@ const std::vector<std::string> state2 = {
"Disabled Rotation",
"Grabbed by Enemy",
"Grabbing Dynapoly",
"Spawning Dust",
"Force Sand Floor Sound",
"Underwater",
"Diving",
"Stationary on Ladder",
"Switch Targeting",
"Lock-On with Switch Targeting",
"Frozen",
"Pause Most Updating",
"Enter",
"Spin Attack w/o Magic",
"Crawling",
"Hopping",
"Navi Out",
"Navi Active",
"Navi Alert",
"Down",
"Near Ocarina Actor",
@@ -427,10 +427,10 @@ const std::vector<std::string> state2 = {
"Playing for Oca. Actor",
"Reflection",
"Ocarina Playing",
"Idling",
"Idle Fidget",
"Disabled draw func",
"Sword Lunge",
"Void out",
"Forced Void Out",
};
const std::vector<std::string> state3 = {