refactor: Enhance Map Properties System with Callback Mechanism and UI Improvements

- Introduced callback mechanisms in MapPropertiesSystem for refreshing map properties, overworld map, and palette, improving modularity and flexibility.
- Updated UI elements in map properties to include icons and tooltips for better user experience and accessibility.
- Refactored drawing methods to utilize a more organized layout, enhancing readability and maintainability of the code.
- Adjusted table structures in the UI to improve visual density and usability, ensuring a more compact and efficient interface.
- Removed unused includes and cleaned up code for better performance and clarity.
This commit is contained in:
scawful
2025-10-05 17:53:55 -04:00
parent b21aeeb663
commit 4451d9132f
4 changed files with 3734 additions and 3870 deletions

View File

@@ -3,7 +3,6 @@
#include "app/gfx/performance_profiler.h" #include "app/gfx/performance_profiler.h"
#include "app/editor/overworld/overworld_editor.h" #include "app/editor/overworld/overworld_editor.h"
#include "app/editor/overworld/ui_constants.h" #include "app/editor/overworld/ui_constants.h"
#include "app/gfx/atlas_renderer.h"
#include "app/gui/canvas.h" #include "app/gui/canvas.h"
#include "app/gui/color.h" #include "app/gui/color.h"
#include "app/gui/icons.h" #include "app/gui/icons.h"
@@ -27,6 +26,8 @@ void MapPropertiesSystem::DrawSimplifiedMapSettings(
bool& show_map_properties_panel, bool& show_custom_bg_color_editor, bool& show_map_properties_panel, bool& show_custom_bg_color_editor,
bool& show_overlay_editor, bool& show_overlay_preview, int& game_state, bool& show_overlay_editor, bool& show_overlay_preview, int& game_state,
int& current_mode) { int& current_mode) {
(void)show_overlay_editor; // Reserved for future use
(void)current_mode; // Reserved for future use
// Enhanced settings table with popup buttons for quick access and integrated toolset // Enhanced settings table with popup buttons for quick access and integrated toolset
if (BeginTable("SimplifiedMapSettings", 9, if (BeginTable("SimplifiedMapSettings", 9,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit,
@@ -124,6 +125,7 @@ void MapPropertiesSystem::DrawSimplifiedMapSettings(
void MapPropertiesSystem::DrawMapPropertiesPanel( void MapPropertiesSystem::DrawMapPropertiesPanel(
int current_map, bool& show_map_properties_panel) { int current_map, bool& show_map_properties_panel) {
(void)show_map_properties_panel; // Used by caller for window state
if (!overworld_->is_loaded()) { if (!overworld_->is_loaded()) {
Text("No overworld loaded"); Text("No overworld loaded");
return; return;
@@ -178,6 +180,7 @@ void MapPropertiesSystem::DrawMapPropertiesPanel(
void MapPropertiesSystem::DrawCustomBackgroundColorEditor( void MapPropertiesSystem::DrawCustomBackgroundColorEditor(
int current_map, bool& show_custom_bg_color_editor) { int current_map, bool& show_custom_bg_color_editor) {
(void)show_custom_bg_color_editor; // Used by caller for window state
if (!overworld_->is_loaded()) { if (!overworld_->is_loaded()) {
Text("No overworld loaded"); Text("No overworld loaded");
return; return;
@@ -232,6 +235,7 @@ void MapPropertiesSystem::DrawCustomBackgroundColorEditor(
void MapPropertiesSystem::DrawOverlayEditor(int current_map, void MapPropertiesSystem::DrawOverlayEditor(int current_map,
bool& show_overlay_editor) { bool& show_overlay_editor) {
(void)show_overlay_editor; // Used by caller for window state
if (!overworld_->is_loaded()) { if (!overworld_->is_loaded()) {
Text("No overworld loaded"); Text("No overworld loaded");
return; return;
@@ -281,6 +285,7 @@ void MapPropertiesSystem::SetupCanvasContextMenu(
gui::Canvas& canvas, int current_map, bool current_map_lock, gui::Canvas& canvas, int current_map, bool current_map_lock,
bool& show_map_properties_panel, bool& show_custom_bg_color_editor, bool& show_map_properties_panel, bool& show_custom_bg_color_editor,
bool& show_overlay_editor) { bool& show_overlay_editor) {
(void)current_map; // Used for future context-sensitive menu items
// Clear any existing context menu items // Clear any existing context menu items
canvas.ClearContextMenuItems(); canvas.ClearContextMenuItems();
@@ -349,16 +354,19 @@ void MapPropertiesSystem::DrawGraphicsPopup(int current_map, int game_state) {
ImGui::Text("Graphics Settings"); ImGui::Text("Graphics Settings");
ImGui::Separator(); ImGui::Separator();
if (gui::InputHexByteCustom("Area Graphics", // Area Graphics
if (gui::InputHexByteCustom(ICON_MD_IMAGE " Area Graphics",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->mutable_area_graphics(), ->mutable_area_graphics(),
kHexByteInputWidth)) { kHexByteInputWidth)) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Main tileset graphics for this map area");
// Sprite Graphics
if (gui::InputHexByteCustom( if (gui::InputHexByteCustom(
absl::StrFormat("Sprite GFX (%s)", kGameStateNames[game_state]) absl::StrFormat(ICON_MD_PETS " Sprite GFX (%s)", kGameStateNames[game_state])
.c_str(), .c_str(),
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->mutable_sprite_graphics(game_state), ->mutable_sprite_graphics(game_state),
@@ -366,32 +374,43 @@ void MapPropertiesSystem::DrawGraphicsPopup(int current_map, int game_state) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Sprite graphics sheet for current game state");
static uint8_t asm_version = static uint8_t asm_version =
(*rom_)[zelda3::OverworldCustomASMHasBeenApplied]; (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
if (asm_version >= 3) { if (asm_version >= 3) {
if (gui::InputHexByte("Animated GFX", if (gui::InputHexByteCustom(ICON_MD_ANIMATION " Animated GFX",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->mutable_animated_gfx(), ->mutable_animated_gfx(),
kInputFieldSize)) { kHexByteInputWidth)) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Animated tile graphics (water, lava, etc.)");
} }
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Custom Tile Graphics (8 sheets):"); ImGui::Text(ICON_MD_GRID_VIEW " Custom Tile Graphics");
ImGui::Separator();
// Show the 8 custom graphics IDs in a more accessible way // Show the 8 custom graphics IDs in a 2-column layout for density
if (BeginTable("CustomTileGraphics", 2,
ImGuiTableFlags_SizingFixedFit)) {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
std::string label = absl::StrFormat("Sheet %d", i); TableNextColumn();
if (gui::InputHexByte(label.c_str(), std::string label = absl::StrFormat(ICON_MD_LAYERS " Sheet %d", i);
if (gui::InputHexByteCustom(label.c_str(),
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->mutable_custom_tileset(i), ->mutable_custom_tileset(i),
80.f)) { 90.f)) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Custom graphics sheet %d (0x00-0xFF)", i);
}
}
ImGui::EndTable();
} }
ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
@@ -410,7 +429,8 @@ void MapPropertiesSystem::DrawPalettesPopup(int current_map, int game_state,
ImGui::Text("Palette Settings"); ImGui::Text("Palette Settings");
ImGui::Separator(); ImGui::Separator();
if (gui::InputHexByteCustom("Area Palette", // Area Palette
if (gui::InputHexByteCustom(ICON_MD_PALETTE " Area Palette",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->mutable_area_palette(), ->mutable_area_palette(),
kHexByteInputWidth)) { kHexByteInputWidth)) {
@@ -418,11 +438,12 @@ void MapPropertiesSystem::DrawPalettesPopup(int current_map, int game_state,
auto status = RefreshMapPalette(); auto status = RefreshMapPalette();
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Main color palette for background tiles");
static uint8_t asm_version = static uint8_t asm_version =
(*rom_)[zelda3::OverworldCustomASMHasBeenApplied]; (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
if (asm_version >= 2) { if (asm_version >= 2) {
if (gui::InputHexByteCustom("Main Palette", if (gui::InputHexByteCustom(ICON_MD_COLOR_LENS " Main Palette",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->mutable_main_palette(), ->mutable_main_palette(),
kHexByteInputWidth)) { kHexByteInputWidth)) {
@@ -430,10 +451,12 @@ void MapPropertiesSystem::DrawPalettesPopup(int current_map, int game_state,
auto status = RefreshMapPalette(); auto status = RefreshMapPalette();
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Extended main palette (ZSCustomOverworld v2+)");
} }
// Sprite Palette
if (gui::InputHexByteCustom( if (gui::InputHexByteCustom(
absl::StrFormat("Sprite Palette (%s)", kGameStateNames[game_state]) absl::StrFormat(ICON_MD_COLORIZE " Sprite Pal (%s)", kGameStateNames[game_state])
.c_str(), .c_str(),
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->mutable_sprite_palette(game_state), ->mutable_sprite_palette(game_state),
@@ -441,11 +464,14 @@ void MapPropertiesSystem::DrawPalettesPopup(int current_map, int game_state,
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Color palette for sprites in current game state");
ImGui::Separator(); ImGui::Separator();
if (ImGui::Button("Background Color")) { if (ImGui::Button(ICON_MD_FORMAT_COLOR_FILL " Custom Background Color",
ImVec2(-1, 0))) {
show_custom_bg_color_editor = !show_custom_bg_color_editor; show_custom_bg_color_editor = !show_custom_bg_color_editor;
} }
HOVER_HINT("Open custom background color editor (v2+)");
ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
ImGui::EndPopup(); ImGui::EndPopup();
@@ -462,30 +488,45 @@ void MapPropertiesSystem::DrawPropertiesPopup(int current_map,
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,
ImVec2(kCompactItemSpacing, kCompactFramePadding)); ImVec2(kCompactItemSpacing, kCompactFramePadding));
ImGui::Text("Map Properties"); ImGui::Text(ICON_MD_SETTINGS " Map Properties");
ImGui::Separator(); ImGui::Separator();
// Basic Map Properties Section // Basic Properties in 2-column layout for density
ImGui::Text("Basic Properties"); if (BeginTable("BasicProps", 2, ImGuiTableFlags_SizingFixedFit)) {
ImGui::Separator(); // Message ID
TableNextColumn();
if (gui::InputHexWordCustom("Message ID", ImGui::Text(ICON_MD_MESSAGE " Message");
TableNextColumn();
if (gui::InputHexWordCustom("##MsgId",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->mutable_message_id(), ->mutable_message_id(),
kHexWordInputWidth)) { kHexWordInputWidth)) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Message ID shown when entering this area");
}
// Game State
TableNextColumn();
ImGui::Text(ICON_MD_GAMEPAD " Game State");
TableNextColumn();
ImGui::SetNextItemWidth(kComboGameStateWidth); ImGui::SetNextItemWidth(kComboGameStateWidth);
if (ImGui::Combo("Game State", &game_state, kGameStateNames, 3)) { if (ImGui::Combo("##GameState", &game_state, kGameStateNames, 3)) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Affects sprite graphics/palettes based on story progress");
}
ImGui::EndTable();
}
// Area Configuration Section // Area Configuration Section
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Area Configuration"); ImGui::Text(ICON_MD_ASPECT_RATIO " Area Configuration");
ImGui::Separator(); ImGui::Separator();
static uint8_t asm_version = static uint8_t asm_version =
@@ -494,16 +535,17 @@ void MapPropertiesSystem::DrawPropertiesPopup(int current_map,
int current_area_size = int current_area_size =
static_cast<int>(overworld_->overworld_map(current_map)->area_size()); static_cast<int>(overworld_->overworld_map(current_map)->area_size());
ImGui::SetNextItemWidth(kComboAreaSizeWidth); ImGui::SetNextItemWidth(kComboAreaSizeWidth);
if (ImGui::Combo("Area Size", &current_area_size, kAreaSizeNames, 4)) { if (ImGui::Combo(ICON_MD_PHOTO_SIZE_SELECT_LARGE " Size", &current_area_size, kAreaSizeNames, 4)) {
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size)); ->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Map area size (1x1, 2x2, 2x1, 1x2 screens)");
} else { } else {
// Vanilla ROM - show small/large map controls // Vanilla ROM - show small/large map controls
auto* map = overworld_->mutable_overworld_map(current_map); auto* map = overworld_->mutable_overworld_map(current_map);
bool is_small = !map->is_large_map(); bool is_small = !map->is_large_map();
if (ImGui::Checkbox("Small Map", &is_small)) { if (ImGui::Checkbox(ICON_MD_CROP_SQUARE " Small Map", &is_small)) {
if (is_small) { if (is_small) {
map->SetAsSmallMap(); map->SetAsSmallMap();
} else { } else {
@@ -512,11 +554,12 @@ void MapPropertiesSystem::DrawPropertiesPopup(int current_map,
} }
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Small (1x1) vs Large (2x2) map size");
} }
// Visual Effects Section // Visual Effects Section
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Visual Effects"); ImGui::Text(ICON_MD_AUTO_FIX_HIGH " Visual Effects");
ImGui::Separator(); ImGui::Separator();
DrawMosaicControls(current_map); DrawMosaicControls(current_map);
@@ -524,15 +567,12 @@ void MapPropertiesSystem::DrawPropertiesPopup(int current_map,
// Advanced Options Section // Advanced Options Section
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Advanced Options"); if (ImGui::Button(ICON_MD_OPEN_IN_NEW " Full Properties Panel",
ImGui::Separator(); ImVec2(-1, 0))) {
if (ImGui::Button("Full Properties Panel",
ImVec2(kLargeButtonWidth + 50, 0))) {
show_map_properties_panel = true; show_map_properties_panel = true;
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
HOVER_HINT("Open comprehensive properties editor"); HOVER_HINT("Open comprehensive properties editor with all tabs");
ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
ImGui::EndPopup(); ImGui::EndPopup();
@@ -542,11 +582,11 @@ void MapPropertiesSystem::DrawPropertiesPopup(int current_map,
void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) { void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
if (BeginTable("BasicProperties", 2, if (BeginTable("BasicProperties", 2,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) { ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150); ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 180);
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
TableNextColumn(); TableNextColumn();
ImGui::Text("Area Graphics"); ImGui::Text(ICON_MD_IMAGE " Area Graphics");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##AreaGfx", if (gui::InputHexByte("##AreaGfx",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -555,9 +595,12 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Main tileset graphics for this map area");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Area Palette"); ImGui::Text(ICON_MD_PALETTE " Area Palette");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##AreaPal", if (gui::InputHexByte("##AreaPal",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -567,9 +610,12 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
auto status = RefreshMapPalette(); auto status = RefreshMapPalette();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Color palette for background tiles");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Message ID"); ImGui::Text(ICON_MD_MESSAGE " Message ID");
TableNextColumn(); TableNextColumn();
if (gui::InputHexWord("##MsgId", if (gui::InputHexWord("##MsgId",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -578,9 +624,12 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Message displayed when entering this area");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Mosaic Effect"); ImGui::Text(ICON_MD_BLUR_ON " Mosaic Effect");
TableNextColumn(); TableNextColumn();
if (ImGui::Checkbox( if (ImGui::Checkbox(
"##mosaic", "##mosaic",
@@ -588,11 +637,13 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
HOVER_HINT("Enable Mosaic effect for the current map"); if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Enable pixelated mosaic transition effect");
}
// Add music editing controls // Add music editing controls with icons
TableNextColumn(); TableNextColumn();
ImGui::Text("Music (Beginning)"); ImGui::Text(ICON_MD_MUSIC_NOTE " Music (Beginning)");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##Music0", if (gui::InputHexByte("##Music0",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -600,10 +651,12 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
kInputFieldSize)) { kInputFieldSize)) {
RefreshMapProperties(); RefreshMapProperties();
} }
HOVER_HINT("Music track for game beginning state"); if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Music track before rescuing Zelda");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Music (Zelda)"); ImGui::Text(ICON_MD_MUSIC_NOTE " Music (Zelda)");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##Music1", if (gui::InputHexByte("##Music1",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -611,10 +664,12 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
kInputFieldSize)) { kInputFieldSize)) {
RefreshMapProperties(); RefreshMapProperties();
} }
HOVER_HINT("Music track for Zelda rescued state"); if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Music track after rescuing Zelda");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Music (Master Sword)"); ImGui::Text(ICON_MD_MUSIC_NOTE " Music (Master Sword)");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##Music2", if (gui::InputHexByte("##Music2",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -622,10 +677,12 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
kInputFieldSize)) { kInputFieldSize)) {
RefreshMapProperties(); RefreshMapProperties();
} }
HOVER_HINT("Music track for Master Sword obtained state"); if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Music track after obtaining Master Sword");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Music (Agahnim)"); ImGui::Text(ICON_MD_MUSIC_NOTE " Music (Agahnim)");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##Music3", if (gui::InputHexByte("##Music3",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -633,7 +690,9 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
kInputFieldSize)) { kInputFieldSize)) {
RefreshMapProperties(); RefreshMapProperties();
} }
HOVER_HINT("Music track for Agahnim defeated state"); if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Music track after defeating Agahnim (Dark World)");
}
ImGui::EndTable(); ImGui::EndTable();
} }
@@ -642,21 +701,24 @@ void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
void MapPropertiesSystem::DrawSpritePropertiesTab(int current_map) { void MapPropertiesSystem::DrawSpritePropertiesTab(int current_map) {
if (BeginTable("SpriteProperties", 2, if (BeginTable("SpriteProperties", 2,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) { ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150); ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 180);
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
TableNextColumn(); TableNextColumn();
ImGui::Text("Game State"); ImGui::Text(ICON_MD_GAMEPAD " Game State");
TableNextColumn(); TableNextColumn();
static int game_state = 0; static int game_state = 0;
ImGui::SetNextItemWidth(100.f); ImGui::SetNextItemWidth(120.f);
if (ImGui::Combo("##GameState", &game_state, kGameStateNames, 3)) { if (ImGui::Combo("##GameState", &game_state, kGameStateNames, 3)) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Affects which sprite graphics/palettes are used");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Sprite Graphics 1"); ImGui::Text(ICON_MD_PETS " Sprite Graphics 1");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##SprGfx1", if (gui::InputHexByte("##SprGfx1",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -665,9 +727,12 @@ void MapPropertiesSystem::DrawSpritePropertiesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("First sprite graphics sheet for Zelda rescued state");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Sprite Graphics 2"); ImGui::Text(ICON_MD_PETS " Sprite Graphics 2");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##SprGfx2", if (gui::InputHexByte("##SprGfx2",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -676,9 +741,12 @@ void MapPropertiesSystem::DrawSpritePropertiesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Second sprite graphics sheet for Master Sword obtained state");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Sprite Palette 1"); ImGui::Text(ICON_MD_COLORIZE " Sprite Palette 1");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##SprPal1", if (gui::InputHexByte("##SprPal1",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -687,9 +755,12 @@ void MapPropertiesSystem::DrawSpritePropertiesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Color palette for sprites - Zelda rescued state");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Sprite Palette 2"); ImGui::Text(ICON_MD_COLORIZE " Sprite Palette 2");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##SprPal2", if (gui::InputHexByte("##SprPal2",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -698,6 +769,9 @@ void MapPropertiesSystem::DrawSpritePropertiesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Color palette for sprites - Master Sword obtained state");
}
ImGui::EndTable(); ImGui::EndTable();
} }
@@ -706,28 +780,31 @@ void MapPropertiesSystem::DrawSpritePropertiesTab(int current_map) {
void MapPropertiesSystem::DrawCustomFeaturesTab(int current_map) { void MapPropertiesSystem::DrawCustomFeaturesTab(int current_map) {
if (BeginTable("CustomFeatures", 2, if (BeginTable("CustomFeatures", 2,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) { ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150); ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 180);
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
TableNextColumn(); TableNextColumn();
ImGui::Text("Area Size"); ImGui::Text(ICON_MD_PHOTO_SIZE_SELECT_LARGE " Area Size");
TableNextColumn(); TableNextColumn();
static const char* area_size_names[] = {"Small (1x1)", "Large (2x2)", static const char* area_size_names[] = {"Small (1x1)", "Large (2x2)",
"Wide (2x1)", "Tall (1x2)"}; "Wide (2x1)", "Tall (1x2)"};
int current_area_size = int current_area_size =
static_cast<int>(overworld_->overworld_map(current_map)->area_size()); static_cast<int>(overworld_->overworld_map(current_map)->area_size());
ImGui::SetNextItemWidth(120.f); ImGui::SetNextItemWidth(130.f);
if (ImGui::Combo("##AreaSize", &current_area_size, area_size_names, 4)) { if (ImGui::Combo("##AreaSize", &current_area_size, area_size_names, 4)) {
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size)); ->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Map size in screens (ZSCustomOverworld feature)");
}
static uint8_t asm_version = static uint8_t asm_version =
(*rom_)[zelda3::OverworldCustomASMHasBeenApplied]; (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
if (asm_version >= 2) { if (asm_version >= 2) {
TableNextColumn(); TableNextColumn();
ImGui::Text("Main Palette"); ImGui::Text(ICON_MD_COLOR_LENS " Main Palette");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##MainPal", if (gui::InputHexByte("##MainPal",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -737,11 +814,14 @@ void MapPropertiesSystem::DrawCustomFeaturesTab(int current_map) {
auto status = RefreshMapPalette(); auto status = RefreshMapPalette();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Extended main palette (ZSCustomOverworld v2+)");
}
} }
if (asm_version >= 3) { if (asm_version >= 3) {
TableNextColumn(); TableNextColumn();
ImGui::Text("Animated GFX"); ImGui::Text(ICON_MD_ANIMATION " Animated GFX");
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte("##AnimGfx", if (gui::InputHexByte("##AnimGfx",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -750,9 +830,12 @@ void MapPropertiesSystem::DrawCustomFeaturesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Animated tile graphics ID (water, lava, etc.)");
}
TableNextColumn(); TableNextColumn();
ImGui::Text("Subscreen Overlay"); ImGui::Text(ICON_MD_LAYERS " Subscreen Overlay");
TableNextColumn(); TableNextColumn();
if (gui::InputHexWord("##SubOverlay", if (gui::InputHexWord("##SubOverlay",
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -761,6 +844,9 @@ void MapPropertiesSystem::DrawCustomFeaturesTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Visual effects overlay ID (fog, rain, backgrounds)");
}
} }
ImGui::EndTable(); ImGui::EndTable();
@@ -768,19 +854,17 @@ void MapPropertiesSystem::DrawCustomFeaturesTab(int current_map) {
} }
void MapPropertiesSystem::DrawTileGraphicsTab(int current_map) { void MapPropertiesSystem::DrawTileGraphicsTab(int current_map) {
ImGui::Text("Custom Tile Graphics (8 sheets per map):"); ImGui::Text(ICON_MD_GRID_VIEW " Custom Tile Graphics (8 sheets)");
Separator(); Separator();
if (BeginTable("TileGraphics", 4, if (BeginTable("TileGraphics", 2,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) { ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 60); ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 180);
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed, 80); ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 60);
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed, 80);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 8; i++) {
TableNextColumn(); TableNextColumn();
ImGui::Text("Sheet %d", i); ImGui::Text(ICON_MD_LAYERS " Sheet %d", i);
TableNextColumn(); TableNextColumn();
if (gui::InputHexByte(absl::StrFormat("##TileGfx%d", i).c_str(), if (gui::InputHexByte(absl::StrFormat("##TileGfx%d", i).c_str(),
overworld_->mutable_overworld_map(current_map) overworld_->mutable_overworld_map(current_map)
@@ -789,43 +873,41 @@ void MapPropertiesSystem::DrawTileGraphicsTab(int current_map) {
RefreshMapProperties(); RefreshMapProperties();
RefreshOverworldMap(); RefreshOverworldMap();
} }
if (ImGui::IsItemHovered()) {
TableNextColumn(); ImGui::SetTooltip("Custom graphics sheet %d (0x00-0xFF)", i);
ImGui::Text("Sheet %d", i + 4);
TableNextColumn();
if (gui::InputHexByte(absl::StrFormat("##TileGfx%d", i + 4).c_str(),
overworld_->mutable_overworld_map(current_map)
->mutable_custom_tileset(i + 4),
kInputFieldSize)) {
RefreshMapProperties();
RefreshOverworldMap();
} }
} }
ImGui::EndTable(); ImGui::EndTable();
} }
Separator();
ImGui::TextWrapped("These 8 sheets allow custom tile graphics per map. "
"Each sheet references a graphics ID loaded into VRAM.");
} }
void MapPropertiesSystem::DrawMusicTab(int current_map) { void MapPropertiesSystem::DrawMusicTab(int current_map) {
ImGui::Text("Music Settings for Different Game States:"); ImGui::Text(ICON_MD_MUSIC_NOTE " Music Settings for Game States");
Separator(); Separator();
if (BeginTable("MusicSettings", 2, if (BeginTable("MusicSettings", 2,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) { ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
ImGui::TableSetupColumn("Game State", ImGuiTableColumnFlags_WidthFixed, ImGui::TableSetupColumn("Game State", ImGuiTableColumnFlags_WidthFixed,
150); 220);
ImGui::TableSetupColumn("Music Track ID", ImGui::TableSetupColumn("Music Track ID",
ImGuiTableColumnFlags_WidthStretch); ImGuiTableColumnFlags_WidthStretch);
const char* music_state_names[] = {"Beginning (Pre-Zelda)", "Zelda Rescued", const char* music_state_names[] = {
"Master Sword Obtained", ICON_MD_PLAY_ARROW " Beginning (Pre-Zelda)",
"Agahnim Defeated"}; ICON_MD_FAVORITE " Zelda Rescued",
ICON_MD_OFFLINE_BOLT " Master Sword Obtained",
ICON_MD_CASTLE " Agahnim Defeated"};
const char* music_descriptions[] = { const char* music_descriptions[] = {
"Music before rescuing Zelda", "Music before rescuing Zelda from the castle",
"Music after rescuing Zelda from Hyrule Castle", "Music after rescuing Zelda from Hyrule Castle",
"Music after obtaining the Master Sword", "Music after obtaining the Master Sword from the Lost Woods",
"Music after defeating Agahnim (Dark World)"}; "Music after defeating Agahnim (Dark World music)"};
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
TableNextColumn(); TableNextColumn();
@@ -870,30 +952,40 @@ void MapPropertiesSystem::DrawMusicTab(int current_map) {
} }
Separator(); Separator();
ImGui::Text("Music tracks control the background music for different"); ImGui::TextWrapped("Music tracks control the background music for different "
ImGui::Text("game progression states on this overworld map."); "game progression states on this overworld map.");
// Show common music track IDs for reference // Show common music track IDs for reference in a collapsing section
Separator(); Separator();
ImGui::Text("Common Music Track IDs:"); if (ImGui::CollapsingHeader(ICON_MD_HELP_OUTLINE " Common Music Track IDs",
ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::Indent();
ImGui::BulletText("0x02 - Overworld Theme"); ImGui::BulletText("0x02 - Overworld Theme");
ImGui::BulletText("0x05 - Kakariko Village"); ImGui::BulletText("0x05 - Kakariko Village");
ImGui::BulletText("0x07 - Lost Woods"); ImGui::BulletText("0x07 - Lost Woods");
ImGui::BulletText("0x09 - Dark World Theme"); ImGui::BulletText("0x09 - Dark World Theme");
ImGui::BulletText("0x0F - Ganon's Tower"); ImGui::BulletText("0x0F - Ganon's Tower");
ImGui::BulletText("0x11 - Death Mountain"); ImGui::BulletText("0x11 - Death Mountain");
ImGui::Unindent();
}
} }
void MapPropertiesSystem::RefreshMapProperties() { void MapPropertiesSystem::RefreshMapProperties() {
// Implementation would refresh map properties if (refresh_map_properties_) {
refresh_map_properties_();
}
} }
void MapPropertiesSystem::RefreshOverworldMap() { void MapPropertiesSystem::RefreshOverworldMap() {
// Implementation would refresh the overworld map display if (refresh_overworld_map_) {
refresh_overworld_map_();
}
} }
absl::Status MapPropertiesSystem::RefreshMapPalette() { absl::Status MapPropertiesSystem::RefreshMapPalette() {
// Implementation would refresh the map palette if (refresh_map_palette_) {
return refresh_map_palette_();
}
return absl::OkStatus(); return absl::OkStatus();
} }

View File

@@ -1,6 +1,8 @@
#ifndef YAZE_APP_EDITOR_OVERWORLD_MAP_PROPERTIES_H #ifndef YAZE_APP_EDITOR_OVERWORLD_MAP_PROPERTIES_H
#define YAZE_APP_EDITOR_OVERWORLD_MAP_PROPERTIES_H #define YAZE_APP_EDITOR_OVERWORLD_MAP_PROPERTIES_H
#include <functional>
#include "app/zelda3/overworld/overworld.h" #include "app/zelda3/overworld/overworld.h"
#include "app/rom.h" #include "app/rom.h"
#include "app/gui/canvas.h" #include "app/gui/canvas.h"
@@ -17,11 +19,24 @@ namespace editor {
class MapPropertiesSystem { class MapPropertiesSystem {
public: public:
// Callback types for refresh operations
using RefreshCallback = std::function<void()>;
using RefreshPaletteCallback = std::function<absl::Status()>;
explicit MapPropertiesSystem(zelda3::Overworld* overworld, Rom* rom, explicit MapPropertiesSystem(zelda3::Overworld* overworld, Rom* rom,
std::array<gfx::Bitmap, zelda3::kNumOverworldMaps>* maps_bmp = nullptr, std::array<gfx::Bitmap, zelda3::kNumOverworldMaps>* maps_bmp = nullptr,
gui::Canvas* canvas = nullptr) gui::Canvas* canvas = nullptr)
: overworld_(overworld), rom_(rom), maps_bmp_(maps_bmp), canvas_(canvas) {} : overworld_(overworld), rom_(rom), maps_bmp_(maps_bmp), canvas_(canvas) {}
// Set callbacks for refresh operations
void SetRefreshCallbacks(RefreshCallback refresh_map_properties,
RefreshCallback refresh_overworld_map,
RefreshPaletteCallback refresh_map_palette) {
refresh_map_properties_ = std::move(refresh_map_properties);
refresh_overworld_map_ = std::move(refresh_overworld_map);
refresh_map_palette_ = std::move(refresh_map_palette);
}
// Main interface methods // Main interface methods
void DrawSimplifiedMapSettings(int& current_world, int& current_map, void DrawSimplifiedMapSettings(int& current_world, int& current_map,
bool& current_map_lock, bool& show_map_properties_panel, bool& current_map_lock, bool& show_map_properties_panel,
@@ -66,7 +81,7 @@ class MapPropertiesSystem {
void DrawTileGraphicsTab(int current_map); void DrawTileGraphicsTab(int current_map);
void DrawMusicTab(int current_map); void DrawMusicTab(int current_map);
// Utility methods // Utility methods - now call the callbacks
void RefreshMapProperties(); void RefreshMapProperties();
void RefreshOverworldMap(); void RefreshOverworldMap();
absl::Status RefreshMapPalette(); absl::Status RefreshMapPalette();
@@ -76,6 +91,11 @@ class MapPropertiesSystem {
std::array<gfx::Bitmap, zelda3::kNumOverworldMaps>* maps_bmp_; std::array<gfx::Bitmap, zelda3::kNumOverworldMaps>* maps_bmp_;
gui::Canvas* canvas_; gui::Canvas* canvas_;
// Callbacks for refresh operations
RefreshCallback refresh_map_properties_;
RefreshCallback refresh_overworld_map_;
RefreshPaletteCallback refresh_map_palette_;
// Using centralized UI constants from ui_constants.h // Using centralized UI constants from ui_constants.h
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,6 @@
#include "app/editor/overworld/overworld_editor_manager.h" #include "app/editor/overworld/overworld_editor_manager.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include <mutex> #include <mutex>
#include <chrono>
namespace yaze { namespace yaze {
namespace editor { namespace editor {
@@ -129,8 +128,6 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
private: private:
void DrawFullscreenCanvas(); void DrawFullscreenCanvas();
void DrawToolset(); void DrawToolset();
void DrawOverworldMapSettings();
void DrawCustomOverworldMapSettings();
void RefreshChildMap(int map_index); void RefreshChildMap(int map_index);
void RefreshOverworldMap(); void RefreshOverworldMap();
@@ -141,8 +138,7 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
void RefreshMapProperties(); void RefreshMapProperties();
absl::Status RefreshTile16Blockset(); absl::Status RefreshTile16Blockset();
void DrawOverworldEntrances(ImVec2 canvas_p, ImVec2 scrolling, void DrawOverworldEntrances(ImVec2 canvas_p, ImVec2 scrolling);
bool holes = false);
void DrawOverworldExits(ImVec2 zero, ImVec2 scrolling); void DrawOverworldExits(ImVec2 zero, ImVec2 scrolling);
void DrawOverworldItems(); void DrawOverworldItems();
void DrawOverworldSprites(); void DrawOverworldSprites();
@@ -292,6 +288,15 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
bool show_map_properties_panel_ = false; bool show_map_properties_panel_ = false;
bool show_overlay_preview_ = false; bool show_overlay_preview_ = false;
// Card visibility states
bool show_tile16_selector_ = true;
bool show_tile8_selector_ = false;
bool show_area_gfx_ = false;
bool show_scratch_ = false;
bool show_gfx_groups_ = false;
bool show_usage_stats_ = false;
bool show_v3_settings_ = false;
// Map properties system for UI organization // Map properties system for UI organization
std::unique_ptr<MapPropertiesSystem> map_properties_system_; std::unique_ptr<MapPropertiesSystem> map_properties_system_;
std::unique_ptr<OverworldEditorManager> overworld_manager_; std::unique_ptr<OverworldEditorManager> overworld_manager_;