yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
map_properties.cc
Go to the documentation of this file.
2
12#include "imgui/imgui.h"
13
14namespace yaze {
15namespace editor {
16
17using ImGui::BeginTable;
18// HOVER_HINT is defined in util/macro.h
19using ImGui::Separator;
20using ImGui::TableNextColumn;
21using ImGui::Text;
22
23// Using centralized UI constants
24
26 int& current_world, int& current_map, bool& current_map_lock,
27 bool& show_map_properties_panel, bool& show_custom_bg_color_editor,
28 bool& show_overlay_editor, bool& show_overlay_preview, int& game_state,
29 int& current_mode) {
30 (void)show_overlay_editor; // Reserved for future use
31 (void)current_mode; // Reserved for future use
32 // Enhanced settings table with popup buttons for quick access and integrated toolset
33 if (BeginTable("SimplifiedMapSettings", 9,
34 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit,
35 ImVec2(0, 0), -1)) {
36 ImGui::TableSetupColumn("World", ImGuiTableColumnFlags_WidthFixed,
38 ImGui::TableSetupColumn("Map", ImGuiTableColumnFlags_WidthFixed,
40 ImGui::TableSetupColumn("Area Size", ImGuiTableColumnFlags_WidthFixed,
42 ImGui::TableSetupColumn("Lock", ImGuiTableColumnFlags_WidthFixed,
44 ImGui::TableSetupColumn("Graphics", ImGuiTableColumnFlags_WidthFixed,
46 ImGui::TableSetupColumn("Palettes", ImGuiTableColumnFlags_WidthFixed,
48 ImGui::TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthFixed,
50 ImGui::TableSetupColumn("View", ImGuiTableColumnFlags_WidthFixed,
52 ImGui::TableSetupColumn("Quick", ImGuiTableColumnFlags_WidthFixed,
54
55 TableNextColumn();
56 ImGui::SetNextItemWidth(kComboWorldWidth);
57 ImGui::Combo("##world", &current_world, kWorldNames, 3);
58
59 TableNextColumn();
60 ImGui::Text("%d (0x%02X)", current_map, current_map);
61
62 TableNextColumn();
63 // IMPORTANT: Don't cache - read fresh to reflect ROM upgrades
64 uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
65
66 // ALL ROMs support Small/Large. Only v3+ supports Wide/Tall.
67 int current_area_size =
68 static_cast<int>(overworld_->overworld_map(current_map)->area_size());
69 ImGui::SetNextItemWidth(kComboAreaSizeWidth);
70
71 if (asm_version >= 3 && asm_version != 0xFF) {
72 // v3+ ROM: Show all 4 area size options
73 if (ImGui::Combo("##AreaSize", &current_area_size, kAreaSizeNames, 4)) {
74 auto status = overworld_->ConfigureMultiAreaMap(
75 current_map,
76 static_cast<zelda3::AreaSizeEnum>(current_area_size));
77 if (status.ok()) {
78 RefreshSiblingMapGraphics(current_map, true);
80 }
81 }
82 } else {
83 // Vanilla/v1/v2 ROM: Show only Small/Large (first 2 options)
84 const char* limited_names[] = {"Small (1x1)", "Large (2x2)"};
85 int limited_size = (current_area_size == 0 || current_area_size == 1) ? current_area_size : 0;
86
87 if (ImGui::Combo("##AreaSize", &limited_size, limited_names, 2)) {
88 // limited_size is 0 (Small) or 1 (Large)
89 auto size = (limited_size == 1) ? zelda3::AreaSizeEnum::LargeArea
91 auto status = overworld_->ConfigureMultiAreaMap(current_map, size);
92 if (status.ok()) {
93 RefreshSiblingMapGraphics(current_map, true);
95 }
96 }
97
98 if (asm_version == 0xFF || asm_version < 3) {
99 HOVER_HINT("Small (1x1) and Large (2x2) maps. Wide/Tall require v3+");
100 }
101 }
102
103 TableNextColumn();
104 if (ImGui::Button(current_map_lock ? ICON_MD_LOCK : ICON_MD_LOCK_OPEN,
105 ImVec2(40, 0))) {
106 current_map_lock = !current_map_lock;
107 }
108 HOVER_HINT(current_map_lock ? "Unlock Map" : "Lock Map");
109
110 TableNextColumn();
111 if (ImGui::Button(ICON_MD_IMAGE " GFX", ImVec2(kTableButtonGraphics, 0))) {
112 ImGui::OpenPopup("GraphicsPopup");
113 }
114 if (ImGui::IsItemHovered()) {
115 ImGui::SetTooltip(
116 "Graphics Settings\n\n"
117 "Configure:\n"
118 " • Area graphics (tileset)\n"
119 " • Sprite graphics sheets\n"
120 " • Animated graphics (v3+)\n"
121 " • Custom tile16 sheets (8 slots)");
122 }
123 DrawGraphicsPopup(current_map, game_state);
124
125 TableNextColumn();
126 if (ImGui::Button(ICON_MD_PALETTE " Palettes", ImVec2(kTableButtonPalettes, 0))) {
127 ImGui::OpenPopup("PalettesPopup");
128 }
129 if (ImGui::IsItemHovered()) {
130 ImGui::SetTooltip(
131 "Palette Settings\n\n"
132 "Configure:\n"
133 " • Area palette (background colors)\n"
134 " • Main palette (v2+)\n"
135 " • Sprite palettes\n"
136 " • Custom background colors");
137 }
138 DrawPalettesPopup(current_map, game_state, show_custom_bg_color_editor);
139
140 TableNextColumn();
141 if (ImGui::Button(ICON_MD_TUNE " Config", ImVec2(kTableButtonProperties, 0))) {
142 ImGui::OpenPopup("ConfigPopup");
143 }
144 if (ImGui::IsItemHovered()) {
145 ImGui::SetTooltip(
146 "Area Configuration\n\n"
147 "Quick access to:\n"
148 " • Message ID\n"
149 " • Game state settings\n"
150 " • Area size (v3+)\n"
151 " • Mosaic effects\n"
152 " • Visual effect overlays\n"
153 " • Map overlay info\n\n"
154 "Click 'Full Configuration Panel' for\n"
155 "comprehensive editing with all tabs.");
156 }
157 DrawPropertiesPopup(current_map, show_map_properties_panel,
158 show_overlay_preview, game_state);
159
160 TableNextColumn();
161 // View Controls
162 if (ImGui::Button(ICON_MD_VISIBILITY " View", ImVec2(kTableButtonView, 0))) {
163 ImGui::OpenPopup("ViewPopup");
164 }
165 if (ImGui::IsItemHovered()) {
166 ImGui::SetTooltip(
167 "View Controls\n\n"
168 "Canvas controls:\n"
169 " • Zoom in/out\n"
170 " • Toggle fullscreen\n"
171 " • Reset view");
172 }
174
175 TableNextColumn();
176 // Quick Access Tools
177 if (ImGui::Button(ICON_MD_BOLT " Quick", ImVec2(kTableButtonQuick, 0))) {
178 ImGui::OpenPopup("QuickPopup");
179 }
180 if (ImGui::IsItemHovered()) {
181 ImGui::SetTooltip(
182 "Quick Access Tools\n\n"
183 "Shortcuts to:\n"
184 " • Tile16 editor (Ctrl+T)\n"
185 " • Copy current map\n"
186 " • Lock/unlock map (Ctrl+L)");
187 }
189
190 ImGui::EndTable();
191 }
192}
193
195 int current_map, bool& show_map_properties_panel) {
196 (void)show_map_properties_panel; // Used by caller for window state
197 if (!overworld_->is_loaded()) {
198 Text("No overworld loaded");
199 return;
200 }
201
202 // Header with map info and lock status
203 ImGui::BeginGroup();
204 Text("Current Map: %d (0x%02X)", current_map, current_map);
205 ImGui::EndGroup();
206
207 Separator();
208
209 // Create tabs for different property categories
210 if (ImGui::BeginTabBar("MapPropertiesTabs",
211 ImGuiTabBarFlags_FittingPolicyScroll)) {
212
213 // Basic Properties Tab
214 if (ImGui::BeginTabItem("Basic Properties")) {
215 DrawBasicPropertiesTab(current_map);
216 ImGui::EndTabItem();
217 }
218
219 // Sprite Properties Tab
220 if (ImGui::BeginTabItem("Sprite Properties")) {
221 DrawSpritePropertiesTab(current_map);
222 ImGui::EndTabItem();
223 }
224
225 // Custom Overworld Features Tab
226 uint8_t asm_version =
228 if (asm_version != 0xFF && ImGui::BeginTabItem("Custom Features")) {
229 DrawCustomFeaturesTab(current_map);
230 ImGui::EndTabItem();
231 }
232
233 // Tile Graphics Tab
234 if (ImGui::BeginTabItem("Tile Graphics")) {
235 DrawTileGraphicsTab(current_map);
236 ImGui::EndTabItem();
237 }
238
239 // Music Tab
240 if (ImGui::BeginTabItem("Music")) {
241 DrawMusicTab(current_map);
242 ImGui::EndTabItem();
243 }
244
245 ImGui::EndTabBar();
246 }
247}
248
250 int current_map, bool& show_custom_bg_color_editor) {
251 (void)show_custom_bg_color_editor; // Used by caller for window state
252 if (!overworld_->is_loaded()) {
253 Text("No overworld loaded");
254 return;
255 }
256
257 uint8_t asm_version =
259 if (asm_version < 2) {
260 Text("Custom background colors require ZSCustomOverworld v2+");
261 return;
262 }
263
264 Text("Custom Background Color Editor");
265 Separator();
266
267 // Enable/disable area-specific background color
268 static bool use_area_specific_bg_color = false;
269 if (ImGui::Checkbox("Use Area-Specific Background Color",
270 &use_area_specific_bg_color)) {
271 // Update ROM data
273 use_area_specific_bg_color ? 1 : 0;
274 }
275
276 if (use_area_specific_bg_color) {
277 // Get current color
278 uint16_t current_color =
279 overworld_->overworld_map(current_map)->area_specific_bg_color();
280 gfx::SnesColor snes_color(current_color);
281
282 // Convert to ImVec4 for color picker
283 ImVec4 color_vec = gui::ConvertSnesColorToImVec4(snes_color);
284
285 if (ImGui::ColorPicker4(
286 "Background Color", (float*)&color_vec,
287 ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHex)) {
288 // Convert back to SNES color and update
289 gfx::SnesColor new_snes_color = gui::ConvertImVec4ToSnesColor(color_vec);
291 ->set_area_specific_bg_color(new_snes_color.snes());
292
293 // Update ROM
294 int rom_address =
296 (*rom_)[rom_address] = new_snes_color.snes() & 0xFF;
297 (*rom_)[rom_address + 1] = (new_snes_color.snes() >> 8) & 0xFF;
298 }
299
300 Text("SNES Color: 0x%04X", current_color);
301 }
302}
303
305 bool& show_overlay_editor) {
306 (void)show_overlay_editor; // Used by caller for window state
307 if (!overworld_->is_loaded()) {
308 Text("No overworld loaded");
309 return;
310 }
311
312 uint8_t asm_version =
314
315 ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
316 ICON_MD_LAYERS " Visual Effects Configuration");
317 ImGui::Text("Map: 0x%02X", current_map);
318 Separator();
319
320 if (asm_version < 1) {
321 ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.4f, 1.0f),
322 ICON_MD_WARNING " Subscreen overlays require ZSCustomOverworld v1+");
323 ImGui::Separator();
324 ImGui::TextWrapped(
325 "To use visual effect overlays, you need to upgrade your ROM to "
326 "ZSCustomOverworld. This feature allows you to add atmospheric effects "
327 "like fog, rain, forest canopy, and sky backgrounds to your maps.");
328 return;
329 }
330
331 // Help section
332 if (ImGui::CollapsingHeader(ICON_MD_HELP_OUTLINE " What are Visual Effects?",
333 ImGuiTreeNodeFlags_DefaultOpen)) {
334 ImGui::Indent();
335 ImGui::TextWrapped(
336 "Visual effects (subscreen overlays) are semi-transparent layers drawn "
337 "on top of or behind your map. They reference special area maps (0x80-0x9F) "
338 "for their tile16 graphics data.");
339 ImGui::Spacing();
340 ImGui::Text("Common uses:");
341 ImGui::BulletText("Fog effects (Lost Woods, Skull Woods)");
342 ImGui::BulletText("Rain (Misery Mire)");
343 ImGui::BulletText("Forest canopy (Lost Woods)");
344 ImGui::BulletText("Sky backgrounds (Death Mountain)");
345 ImGui::BulletText("Under bridge views");
346 ImGui::Unindent();
347 ImGui::Separator();
348 }
349
350 // Enable/disable subscreen overlay
351 static bool use_subscreen_overlay = false;
352 if (ImGui::Checkbox(ICON_MD_VISIBILITY " Enable Visual Effect for This Area",
353 &use_subscreen_overlay)) {
354 // Update ROM data
356 use_subscreen_overlay ? 1 : 0;
357 }
358 if (ImGui::IsItemHovered()) {
359 ImGui::SetTooltip("Enable/disable visual effect overlay for this map area");
360 }
361
362 if (use_subscreen_overlay) {
363 ImGui::Spacing();
364 uint16_t current_overlay =
365 overworld_->overworld_map(current_map)->subscreen_overlay();
366 if (gui::InputHexWord(ICON_MD_PHOTO " Visual Effect Map ID", &current_overlay,
367 kInputFieldSize + 30)) {
369 ->set_subscreen_overlay(current_overlay);
370
371 // Update ROM
372 int rom_address =
374 (*rom_)[rom_address] = current_overlay & 0xFF;
375 (*rom_)[rom_address + 1] = (current_overlay >> 8) & 0xFF;
376 }
377 if (ImGui::IsItemHovered()) {
378 ImGui::SetTooltip(
379 "ID of the special area map (0x80-0x9F) to use for\n"
380 "visual effects. That map's tile16 data will be drawn\n"
381 "as a semi-transparent layer on this area.");
382 }
383
384 // Show description
385 std::string overlay_desc = GetOverlayDescription(current_overlay);
386 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
387 ICON_MD_INFO " %s", overlay_desc.c_str());
388
389 ImGui::Separator();
390 if (ImGui::CollapsingHeader(ICON_MD_LIGHTBULB " Common Visual Effect IDs")) {
391 ImGui::Indent();
392 ImGui::BulletText("0x0093 - Triforce Room Curtain");
393 ImGui::BulletText("0x0094 - Under the Bridge");
394 ImGui::BulletText("0x0095 - Sky Background (LW Death Mountain)");
395 ImGui::BulletText("0x0096 - Pyramid Background");
396 ImGui::BulletText("0x0097 - Fog Overlay (Master Sword Area)");
397 ImGui::BulletText("0x009C - Lava Background (DW Death Mountain)");
398 ImGui::BulletText("0x009D - Fog Overlay (Lost/Skull Woods)");
399 ImGui::BulletText("0x009E - Tree Canopy (Forest)");
400 ImGui::BulletText("0x009F - Rain Effect (Misery Mire)");
401 ImGui::BulletText("0x00FF - No Overlay (Disabled)");
402 ImGui::Unindent();
403 }
404 } else {
405 ImGui::Spacing();
406 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
407 ICON_MD_BLOCK " No visual effects enabled for this area");
408 }
409}
410
412 gui::Canvas& canvas, int current_map, bool current_map_lock,
413 bool& show_map_properties_panel, bool& show_custom_bg_color_editor,
414 bool& show_overlay_editor, int current_mode) {
415 (void)current_map; // Used for future context-sensitive menu items
416 // Clear any existing context menu items
417 canvas.ClearContextMenuItems();
418
419 // Add entity insertion submenu (only in MOUSE mode)
420 if (current_mode == 0 && entity_insert_callback_) { // 0 = EditingMode::MOUSE
421 gui::CanvasMenuItem entity_menu;
422 entity_menu.label = ICON_MD_ADD_LOCATION " Insert Entity";
423
424 // Entrance submenu item
425 gui::CanvasMenuItem entrance_item;
426 entrance_item.label = ICON_MD_DOOR_FRONT " Entrance";
427 entrance_item.callback = [this]() {
429 entity_insert_callback_("entrance");
430 }
431 };
432 entity_menu.subitems.push_back(entrance_item);
433
434 // Hole submenu item
435 gui::CanvasMenuItem hole_item;
436 hole_item.label = ICON_MD_CYCLONE " Hole";
437 hole_item.callback = [this]() {
440 }
441 };
442 entity_menu.subitems.push_back(hole_item);
443
444 // Exit submenu item
445 gui::CanvasMenuItem exit_item;
446 exit_item.label = ICON_MD_DOOR_BACK " Exit";
447 exit_item.callback = [this]() {
450 }
451 };
452 entity_menu.subitems.push_back(exit_item);
453
454 // Item submenu item
455 gui::CanvasMenuItem item_item;
456 item_item.label = ICON_MD_GRASS " Item";
457 item_item.callback = [this]() {
460 }
461 };
462 entity_menu.subitems.push_back(item_item);
463
464 // Sprite submenu item
465 gui::CanvasMenuItem sprite_item;
466 sprite_item.label = ICON_MD_PEST_CONTROL_RODENT " Sprite";
467 sprite_item.callback = [this]() {
469 entity_insert_callback_("sprite");
470 }
471 };
472 entity_menu.subitems.push_back(sprite_item);
473
474 canvas.AddContextMenuItem(entity_menu);
475 }
476
477 // Add overworld-specific context menu items
478 gui::CanvasMenuItem lock_item;
479 lock_item.label = current_map_lock ? "Unlock Map" : "Lock to This Map";
480 lock_item.callback = [&current_map_lock]() {
481 current_map_lock = !current_map_lock;
482 };
483 canvas.AddContextMenuItem(lock_item);
484
485 // Area Configuration
486 gui::CanvasMenuItem properties_item;
487 properties_item.label = ICON_MD_TUNE " Area Configuration";
488 properties_item.callback = [&show_map_properties_panel]() {
489 show_map_properties_panel = true;
490 };
491 canvas.AddContextMenuItem(properties_item);
492
493 // Custom overworld features (only show if v3+)
494 uint8_t asm_version =
496 if (asm_version >= 3 && asm_version != 0xFF) {
497 // Custom Background Color
498 gui::CanvasMenuItem bg_color_item;
499 bg_color_item.label = ICON_MD_FORMAT_COLOR_FILL " Custom Background Color";
500 bg_color_item.callback = [&show_custom_bg_color_editor]() {
501 show_custom_bg_color_editor = true;
502 };
503 canvas.AddContextMenuItem(bg_color_item);
504
505 // Visual Effects Editor
506 gui::CanvasMenuItem overlay_item;
507 overlay_item.label = ICON_MD_LAYERS " Visual Effects";
508 overlay_item.callback = [&show_overlay_editor]() {
509 show_overlay_editor = true;
510 };
511 canvas.AddContextMenuItem(overlay_item);
512 }
513
514 // Canvas controls
515 gui::CanvasMenuItem reset_view_item;
516 reset_view_item.label = ICON_MD_RESTORE " Reset View";
517 reset_view_item.callback = [&canvas]() {
518 canvas.set_global_scale(1.0f);
519 canvas.set_scrolling(ImVec2(0, 0));
520 };
521 canvas.AddContextMenuItem(reset_view_item);
522
523 gui::CanvasMenuItem zoom_in_item;
524 zoom_in_item.label = ICON_MD_ZOOM_IN " Zoom In";
525 zoom_in_item.callback = [&canvas]() {
526 float scale = std::min(2.0f, canvas.global_scale() + 0.25f);
527 canvas.set_global_scale(scale);
528 };
529 canvas.AddContextMenuItem(zoom_in_item);
530
531 gui::CanvasMenuItem zoom_out_item;
532 zoom_out_item.label = ICON_MD_ZOOM_OUT " Zoom Out";
533 zoom_out_item.callback = [&canvas]() {
534 float scale = std::max(0.25f, canvas.global_scale() - 0.25f);
535 canvas.set_global_scale(scale);
536 };
537 canvas.AddContextMenuItem(zoom_out_item);
538}
539
540// Private method implementations
541void MapPropertiesSystem::DrawGraphicsPopup(int current_map, int game_state) {
542 if (ImGui::BeginPopup("GraphicsPopup")) {
543 ImGui::PushID("GraphicsPopup"); // Fix ImGui duplicate ID warnings
544
545 // Use theme-aware spacing instead of hardcoded constants
547 float padding = gui::LayoutHelpers::GetButtonPadding();
548 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
549 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
550
551 ImGui::Text("Graphics Settings");
552 ImGui::Separator();
553
554 // Area Graphics
555 if (gui::InputHexByte(ICON_MD_IMAGE " Area Graphics",
557 ->mutable_area_graphics(),
559 // CORRECT ORDER: Properties first, then graphics reload
560
561 // 1. Propagate properties to siblings FIRST (calls LoadAreaGraphics on siblings)
563
564 // 2. Force immediate refresh of current map
565 (*maps_bmp_)[current_map].set_modified(true);
566 overworld_->mutable_overworld_map(current_map)->LoadAreaGraphics();
567
568 // 3. Refresh siblings immediately
569 RefreshSiblingMapGraphics(current_map);
570
571 // 4. Update tile selector
573
574 // 5. Final refresh
576 }
577 HOVER_HINT("Main tileset graphics for this map area");
578
579 // Sprite Graphics
581 absl::StrFormat(ICON_MD_PETS " Sprite GFX (%s)", kGameStateNames[game_state])
582 .c_str(),
584 ->mutable_sprite_graphics(game_state),
586 ForceRefreshGraphics(current_map);
589 }
590 HOVER_HINT("Sprite graphics sheet for current game state");
591
592 uint8_t asm_version =
594 if (asm_version >= 3) {
595 if (gui::InputHexByte(ICON_MD_ANIMATION " Animated GFX",
597 ->mutable_animated_gfx(),
599 ForceRefreshGraphics(current_map);
603 }
604 HOVER_HINT("Animated tile graphics (water, lava, etc.)");
605 }
606
607 // Custom Tile Graphics - Only available for v1+ ROMs
608 if (asm_version >= 1 && asm_version != 0xFF) {
609 ImGui::Separator();
610 ImGui::Text(ICON_MD_GRID_VIEW " Custom Tile Graphics");
611 ImGui::Separator();
612
613 // Show the 8 custom graphics IDs in a 2-column layout for density
614 if (BeginTable("CustomTileGraphics", 2,
615 ImGuiTableFlags_SizingFixedFit)) {
616 for (int i = 0; i < 8; i++) {
617 TableNextColumn();
618 std::string label = absl::StrFormat(ICON_MD_LAYERS " Sheet %d", i);
619 if (gui::InputHexByte(label.c_str(),
621 ->mutable_custom_tileset(i),
622 90.f)) {
623 ForceRefreshGraphics(current_map);
627 }
628 if (ImGui::IsItemHovered()) {
629 ImGui::SetTooltip("Custom graphics sheet %d (0x00-0xFF)", i);
630 }
631 }
632 ImGui::EndTable();
633 }
634 } else if (asm_version == 0xFF) {
635 ImGui::Separator();
636 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
637 ICON_MD_INFO " Custom Tile Graphics");
638 ImGui::TextWrapped(
639 "Custom tile graphics require ZSCustomOverworld v1+.\n"
640 "Upgrade your ROM to access 8 customizable graphics sheets.");
641 }
642
643 ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
644 ImGui::PopID(); // Pop GraphicsPopup ID scope
645 ImGui::EndPopup();
646 }
647}
648
649void MapPropertiesSystem::DrawPalettesPopup(int current_map, int game_state,
650 bool& show_custom_bg_color_editor) {
651 if (ImGui::BeginPopup("PalettesPopup")) {
652 ImGui::PushID("PalettesPopup"); // Fix ImGui duplicate ID warnings
653
654 // Use theme-aware spacing instead of hardcoded constants
656 float padding = gui::LayoutHelpers::GetButtonPadding();
657 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
658 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
659
660 ImGui::Text("Palette Settings");
661 ImGui::Separator();
662
663 // Area Palette
664 if (gui::InputHexByte(ICON_MD_PALETTE " Area Palette",
666 ->mutable_area_palette(),
669 auto status = RefreshMapPalette();
671 }
672 HOVER_HINT("Main color palette for background tiles");
673
674 // Read fresh to reflect ROM upgrades
675 uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
676 if (asm_version >= 2) {
677 if (gui::InputHexByte(ICON_MD_COLOR_LENS " Main Palette",
679 ->mutable_main_palette(),
682 auto status = RefreshMapPalette();
684 }
685 HOVER_HINT("Extended main palette (ZSCustomOverworld v2+)");
686 }
687
688 // Sprite Palette
690 absl::StrFormat(ICON_MD_COLORIZE " Sprite Pal (%s)", kGameStateNames[game_state])
691 .c_str(),
693 ->mutable_sprite_palette(game_state),
697 }
698 HOVER_HINT("Color palette for sprites in current game state");
699
700 ImGui::Separator();
701 if (ImGui::Button(ICON_MD_FORMAT_COLOR_FILL " Custom Background Color",
702 ImVec2(-1, 0))) {
703 show_custom_bg_color_editor = !show_custom_bg_color_editor;
704 }
705 HOVER_HINT("Open custom background color editor (v2+)");
706
707 ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
708 ImGui::PopID(); // Pop PalettesPopup ID scope
709 ImGui::EndPopup();
710 }
711}
712
714 bool& show_map_properties_panel,
715 bool& show_overlay_preview,
716 int& game_state) {
717 if (ImGui::BeginPopup("ConfigPopup")) {
718 ImGui::PushID("ConfigPopup"); // Fix ImGui duplicate ID warnings
719
720 // Use theme-aware spacing instead of hardcoded constants
722 float padding = gui::LayoutHelpers::GetButtonPadding();
723 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
724 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
725
726 ImGui::Text(ICON_MD_TUNE " Area Configuration");
727 ImGui::Separator();
728
729 // Basic Properties in 2-column layout for density
730 if (BeginTable("BasicProps", 2, ImGuiTableFlags_SizingFixedFit)) {
731 // Message ID
732 TableNextColumn();
733 ImGui::Text(ICON_MD_MESSAGE " Message");
734 TableNextColumn();
735 if (gui::InputHexWordCustom("##MsgId",
737 ->mutable_message_id(),
741 }
742 if (ImGui::IsItemHovered()) {
743 ImGui::SetTooltip("Message ID shown when entering this area");
744 }
745
746 // Game State
747 TableNextColumn();
748 ImGui::Text(ICON_MD_GAMEPAD " Game State");
749 TableNextColumn();
750 ImGui::SetNextItemWidth(kComboGameStateWidth);
751 if (ImGui::Combo("##GameState", &game_state, kGameStateNames, 3)) {
754 }
755 if (ImGui::IsItemHovered()) {
756 ImGui::SetTooltip("Affects sprite graphics/palettes based on story progress");
757 }
758
759 ImGui::EndTable();
760 }
761
762 // Area Configuration Section
763 ImGui::Separator();
764 ImGui::Text(ICON_MD_ASPECT_RATIO " Area Configuration");
765 ImGui::Separator();
766
767 // ALL ROMs support Small/Large. Only v3+ supports Wide/Tall.
768 uint8_t asm_version =
770
771 int current_area_size =
772 static_cast<int>(overworld_->overworld_map(current_map)->area_size());
773 ImGui::SetNextItemWidth(kComboAreaSizeWidth);
774
775 if (asm_version >= 3 && asm_version != 0xFF) {
776 // v3+ ROM: Show all 4 area size options
777 if (ImGui::Combo(ICON_MD_PHOTO_SIZE_SELECT_LARGE " Size", &current_area_size, kAreaSizeNames, 4)) {
778 auto status = overworld_->ConfigureMultiAreaMap(
779 current_map,
780 static_cast<zelda3::AreaSizeEnum>(current_area_size));
781 if (status.ok()) {
782 RefreshSiblingMapGraphics(current_map, true);
784 }
785 }
786 HOVER_HINT("Map area size (1x1, 2x2, 2x1, 1x2 screens)");
787 } else {
788 // Vanilla/v1/v2 ROM: Show only Small/Large
789 const char* limited_names[] = {"Small (1x1)", "Large (2x2)"};
790 int limited_size = (current_area_size == 0 || current_area_size == 1) ? current_area_size : 0;
791
792 if (ImGui::Combo(ICON_MD_PHOTO_SIZE_SELECT_LARGE " Size", &limited_size, limited_names, 2)) {
793 auto size = (limited_size == 1) ? zelda3::AreaSizeEnum::LargeArea
795 auto status = overworld_->ConfigureMultiAreaMap(current_map, size);
796 if (status.ok()) {
797 RefreshSiblingMapGraphics(current_map, true);
799 }
800 }
801 HOVER_HINT("Small (1x1) and Large (2x2) maps. Wide/Tall require v3+");
802 }
803
804 // Visual Effects Section
805 ImGui::Separator();
806 ImGui::Text(ICON_MD_AUTO_FIX_HIGH " Visual Effects");
807 ImGui::Separator();
808
809 DrawMosaicControls(current_map);
810 DrawOverlayControls(current_map, show_overlay_preview);
811
812 // Advanced Options Section
813 ImGui::Separator();
814 if (ImGui::Button(ICON_MD_OPEN_IN_NEW " Full Configuration Panel",
815 ImVec2(-1, 0))) {
816 show_map_properties_panel = true;
817 ImGui::CloseCurrentPopup();
818 }
819 HOVER_HINT("Open detailed area configuration with all settings tabs");
820
821 ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
822 ImGui::PopID(); // Pop ConfigPopup ID scope
823 ImGui::EndPopup();
824 }
825}
826
828 if (BeginTable("BasicProperties", 2,
829 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
830 ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 180);
831 ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
832
833 TableNextColumn();
834 ImGui::Text(ICON_MD_IMAGE " Area Graphics");
835 TableNextColumn();
836 if (gui::InputHexByte("##AreaGfx",
838 ->mutable_area_graphics(),
840 // CORRECT ORDER: Properties first, then graphics reload
842 (*maps_bmp_)[current_map].set_modified(true);
843 overworld_->mutable_overworld_map(current_map)->LoadAreaGraphics();
844 RefreshSiblingMapGraphics(current_map);
847 }
848 if (ImGui::IsItemHovered()) {
849 ImGui::SetTooltip("Main tileset graphics for this map area");
850 }
851
852 TableNextColumn();
853 ImGui::Text(ICON_MD_PALETTE " Area Palette");
854 TableNextColumn();
855 if (gui::InputHexByte("##AreaPal",
857 ->mutable_area_palette(),
860 auto status = RefreshMapPalette();
862 }
863 if (ImGui::IsItemHovered()) {
864 ImGui::SetTooltip("Color palette for background tiles");
865 }
866
867 TableNextColumn();
868 ImGui::Text(ICON_MD_MESSAGE " Message ID");
869 TableNextColumn();
870 if (gui::InputHexWord("##MsgId",
872 ->mutable_message_id(),
873 kInputFieldSize + 20)) {
876 }
877 if (ImGui::IsItemHovered()) {
878 ImGui::SetTooltip("Message displayed when entering this area");
879 }
880
881 TableNextColumn();
882 ImGui::Text(ICON_MD_BLUR_ON " Mosaic Effect");
883 TableNextColumn();
884 if (ImGui::Checkbox(
885 "##mosaic",
886 overworld_->mutable_overworld_map(current_map)->mutable_mosaic())) {
889 }
890 if (ImGui::IsItemHovered()) {
891 ImGui::SetTooltip("Enable pixelated mosaic transition effect");
892 }
893
894 // Add music editing controls with icons
895 TableNextColumn();
896 ImGui::Text(ICON_MD_MUSIC_NOTE " Music (Beginning)");
897 TableNextColumn();
898 if (gui::InputHexByte("##Music0",
900 ->mutable_area_music(0),
903 }
904 if (ImGui::IsItemHovered()) {
905 ImGui::SetTooltip("Music track before rescuing Zelda");
906 }
907
908 TableNextColumn();
909 ImGui::Text(ICON_MD_MUSIC_NOTE " Music (Zelda)");
910 TableNextColumn();
911 if (gui::InputHexByte("##Music1",
913 ->mutable_area_music(1),
916 }
917 if (ImGui::IsItemHovered()) {
918 ImGui::SetTooltip("Music track after rescuing Zelda");
919 }
920
921 TableNextColumn();
922 ImGui::Text(ICON_MD_MUSIC_NOTE " Music (Master Sword)");
923 TableNextColumn();
924 if (gui::InputHexByte("##Music2",
926 ->mutable_area_music(2),
929 }
930 if (ImGui::IsItemHovered()) {
931 ImGui::SetTooltip("Music track after obtaining Master Sword");
932 }
933
934 TableNextColumn();
935 ImGui::Text(ICON_MD_MUSIC_NOTE " Music (Agahnim)");
936 TableNextColumn();
937 if (gui::InputHexByte("##Music3",
939 ->mutable_area_music(3),
942 }
943 if (ImGui::IsItemHovered()) {
944 ImGui::SetTooltip("Music track after defeating Agahnim (Dark World)");
945 }
946
947 ImGui::EndTable();
948 }
949}
950
952 if (BeginTable("SpriteProperties", 2,
953 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
954 ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 180);
955 ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
956
957 TableNextColumn();
958 ImGui::Text(ICON_MD_GAMEPAD " Game State");
959 TableNextColumn();
960 static int game_state = 0;
961 ImGui::SetNextItemWidth(120.f);
962 if (ImGui::Combo("##GameState", &game_state, kGameStateNames, 3)) {
965 }
966 if (ImGui::IsItemHovered()) {
967 ImGui::SetTooltip("Affects which sprite graphics/palettes are used");
968 }
969
970 TableNextColumn();
971 ImGui::Text(ICON_MD_PETS " Sprite Graphics 1");
972 TableNextColumn();
973 if (gui::InputHexByte("##SprGfx1",
975 ->mutable_sprite_graphics(1),
979 }
980 if (ImGui::IsItemHovered()) {
981 ImGui::SetTooltip("First sprite graphics sheet for Zelda rescued state");
982 }
983
984 TableNextColumn();
985 ImGui::Text(ICON_MD_PETS " Sprite Graphics 2");
986 TableNextColumn();
987 if (gui::InputHexByte("##SprGfx2",
989 ->mutable_sprite_graphics(2),
993 }
994 if (ImGui::IsItemHovered()) {
995 ImGui::SetTooltip("Second sprite graphics sheet for Master Sword obtained state");
996 }
997
998 TableNextColumn();
999 ImGui::Text(ICON_MD_COLORIZE " Sprite Palette 1");
1000 TableNextColumn();
1001 if (gui::InputHexByte("##SprPal1",
1002 overworld_->mutable_overworld_map(current_map)
1003 ->mutable_sprite_palette(1),
1004 kInputFieldSize)) {
1007 }
1008 if (ImGui::IsItemHovered()) {
1009 ImGui::SetTooltip("Color palette for sprites - Zelda rescued state");
1010 }
1011
1012 TableNextColumn();
1013 ImGui::Text(ICON_MD_COLORIZE " Sprite Palette 2");
1014 TableNextColumn();
1015 if (gui::InputHexByte("##SprPal2",
1016 overworld_->mutable_overworld_map(current_map)
1017 ->mutable_sprite_palette(2),
1018 kInputFieldSize)) {
1021 }
1022 if (ImGui::IsItemHovered()) {
1023 ImGui::SetTooltip("Color palette for sprites - Master Sword obtained state");
1024 }
1025
1026 ImGui::EndTable();
1027 }
1028}
1029
1031 if (BeginTable("CustomFeatures", 2,
1032 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
1033 ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 180);
1034 ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
1035
1036 TableNextColumn();
1037 ImGui::Text(ICON_MD_PHOTO_SIZE_SELECT_LARGE " Area Size");
1038 TableNextColumn();
1039 // ALL ROMs support Small/Large. Only v3+ supports Wide/Tall.
1040 uint8_t asm_version =
1042
1043 int current_area_size =
1044 static_cast<int>(overworld_->overworld_map(current_map)->area_size());
1045 ImGui::SetNextItemWidth(130.f);
1046
1047 if (asm_version >= 3 && asm_version != 0xFF) {
1048 // v3+ ROM: Show all 4 area size options
1049 static const char* all_sizes[] = {"Small (1x1)", "Large (2x2)",
1050 "Wide (2x1)", "Tall (1x2)"};
1051 if (ImGui::Combo("##AreaSize", &current_area_size, all_sizes, 4)) {
1052 auto status = overworld_->ConfigureMultiAreaMap(
1053 current_map,
1054 static_cast<zelda3::AreaSizeEnum>(current_area_size));
1055 if (status.ok()) {
1056 RefreshSiblingMapGraphics(current_map, true);
1058 }
1059 }
1060 if (ImGui::IsItemHovered()) {
1061 ImGui::SetTooltip("Map size: Small (1x1), Large (2x2), Wide (2x1), Tall (1x2)");
1062 }
1063 } else {
1064 // Vanilla/v1/v2 ROM: Show only Small/Large
1065 static const char* limited_sizes[] = {"Small (1x1)", "Large (2x2)"};
1066 int limited_size = (current_area_size == 0 || current_area_size == 1) ? current_area_size : 0;
1067
1068 if (ImGui::Combo("##AreaSize", &limited_size, limited_sizes, 2)) {
1069 auto size = (limited_size == 1) ? zelda3::AreaSizeEnum::LargeArea
1071 auto status = overworld_->ConfigureMultiAreaMap(current_map, size);
1072 if (status.ok()) {
1073 RefreshSiblingMapGraphics(current_map, true);
1075 }
1076 }
1077 if (ImGui::IsItemHovered()) {
1078 ImGui::SetTooltip("Map size: Small (1x1), Large (2x2). Wide/Tall require v3+");
1079 }
1080 }
1081
1082 if (asm_version >= 2) {
1083 TableNextColumn();
1084 ImGui::Text(ICON_MD_COLOR_LENS " Main Palette");
1085 TableNextColumn();
1086 if (gui::InputHexByte("##MainPal",
1087 overworld_->mutable_overworld_map(current_map)
1088 ->mutable_main_palette(),
1089 kInputFieldSize)) {
1091 auto status = RefreshMapPalette();
1093 }
1094 if (ImGui::IsItemHovered()) {
1095 ImGui::SetTooltip("Extended main palette (ZSCustomOverworld v2+)");
1096 }
1097 }
1098
1099 if (asm_version >= 3) {
1100 TableNextColumn();
1101 ImGui::Text(ICON_MD_ANIMATION " Animated GFX");
1102 TableNextColumn();
1103 if (gui::InputHexByte("##AnimGfx",
1104 overworld_->mutable_overworld_map(current_map)
1105 ->mutable_animated_gfx(),
1106 kInputFieldSize)) {
1109 }
1110 if (ImGui::IsItemHovered()) {
1111 ImGui::SetTooltip("Animated tile graphics ID (water, lava, etc.)");
1112 }
1113
1114 TableNextColumn();
1115 ImGui::Text(ICON_MD_LAYERS " Subscreen Overlay");
1116 TableNextColumn();
1117 if (gui::InputHexWord("##SubOverlay",
1118 overworld_->mutable_overworld_map(current_map)
1119 ->mutable_subscreen_overlay(),
1120 kInputFieldSize + 20)) {
1123 }
1124 if (ImGui::IsItemHovered()) {
1125 ImGui::SetTooltip("Visual effects overlay ID (fog, rain, backgrounds)");
1126 }
1127 }
1128
1129 ImGui::EndTable();
1130 }
1131}
1132
1134 uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
1135
1136 // Only show custom tile graphics for v1+ ROMs
1137 if (asm_version >= 1 && asm_version != 0xFF) {
1138 ImGui::Text(ICON_MD_GRID_VIEW " Custom Tile Graphics (8 sheets)");
1139 Separator();
1140
1141 if (BeginTable("TileGraphics", 2,
1142 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
1143 ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 180);
1144 ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
1145
1146 for (int i = 0; i < 8; i++) {
1147 TableNextColumn();
1148 ImGui::Text(ICON_MD_LAYERS " Sheet %d", i);
1149 TableNextColumn();
1150 if (gui::InputHexByte(absl::StrFormat("##TileGfx%d", i).c_str(),
1151 overworld_->mutable_overworld_map(current_map)
1152 ->mutable_custom_tileset(i),
1153 kInputFieldSize)) {
1154 overworld_->mutable_overworld_map(current_map)->LoadAreaGraphics();
1155 ForceRefreshGraphics(current_map);
1156 RefreshSiblingMapGraphics(current_map);
1160 }
1161 if (ImGui::IsItemHovered()) {
1162 ImGui::SetTooltip("Custom graphics sheet %d (0x00-0xFF)", i);
1163 }
1164 }
1165
1166 ImGui::EndTable();
1167 }
1168
1169 Separator();
1170 ImGui::TextWrapped("These 8 sheets allow custom tile graphics per map. "
1171 "Each sheet references a graphics ID loaded into VRAM.");
1172 } else {
1173 // Vanilla ROM - show info message
1174 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
1175 ICON_MD_INFO " Custom Tile Graphics");
1176 ImGui::Separator();
1177 ImGui::TextWrapped(
1178 "Custom tile graphics are not available in vanilla ROMs.\n\n"
1179 "To enable this feature, upgrade your ROM to ZSCustomOverworld v1+, "
1180 "which provides 8 customizable graphics sheets per map for advanced "
1181 "tileset customization.");
1182 }
1183}
1184
1186 ImGui::Text(ICON_MD_MUSIC_NOTE " Music Settings for Game States");
1187 Separator();
1188
1189 if (BeginTable("MusicSettings", 2,
1190 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
1191 ImGui::TableSetupColumn("Game State", ImGuiTableColumnFlags_WidthFixed,
1192 220);
1193 ImGui::TableSetupColumn("Music Track ID",
1194 ImGuiTableColumnFlags_WidthStretch);
1195
1196 const char* music_state_names[] = {
1197 ICON_MD_PLAY_ARROW " Beginning (Pre-Zelda)",
1198 ICON_MD_FAVORITE " Zelda Rescued",
1199 ICON_MD_OFFLINE_BOLT " Master Sword Obtained",
1200 ICON_MD_CASTLE " Agahnim Defeated"};
1201
1202 const char* music_descriptions[] = {
1203 "Music before rescuing Zelda from the castle",
1204 "Music after rescuing Zelda from Hyrule Castle",
1205 "Music after obtaining the Master Sword from the Lost Woods",
1206 "Music after defeating Agahnim (Dark World music)"};
1207
1208 for (int i = 0; i < 4; i++) {
1209 TableNextColumn();
1210 ImGui::Text("%s", music_state_names[i]);
1211
1212 TableNextColumn();
1213 if (gui::InputHexByte(absl::StrFormat("##Music%d", i).c_str(),
1214 overworld_->mutable_overworld_map(current_map)
1215 ->mutable_area_music(i),
1216 kInputFieldSize)) {
1218
1219 // Update the ROM directly since music is not automatically saved
1220 int music_address = 0;
1221 switch (i) {
1222 case 0:
1223 music_address = zelda3::kOverworldMusicBeginning + current_map;
1224 break;
1225 case 1:
1226 music_address = zelda3::kOverworldMusicZelda + current_map;
1227 break;
1228 case 2:
1229 music_address = zelda3::kOverworldMusicMasterSword + current_map;
1230 break;
1231 case 3:
1232 music_address = zelda3::kOverworldMusicAgahnim + current_map;
1233 break;
1234 }
1235
1236 if (music_address > 0) {
1237 (*rom_)[music_address] =
1238 *overworld_->mutable_overworld_map(current_map)
1239 ->mutable_area_music(i);
1240 }
1241 }
1242 if (ImGui::IsItemHovered()) {
1243 ImGui::SetTooltip("%s", music_descriptions[i]);
1244 }
1245 }
1246
1247 ImGui::EndTable();
1248 }
1249
1250 Separator();
1251 ImGui::TextWrapped("Music tracks control the background music for different "
1252 "game progression states on this overworld map.");
1253
1254 // Show common music track IDs for reference in a collapsing section
1255 Separator();
1256 if (ImGui::CollapsingHeader(ICON_MD_HELP_OUTLINE " Common Music Track IDs",
1257 ImGuiTreeNodeFlags_DefaultOpen)) {
1258 ImGui::Indent();
1259 ImGui::BulletText("0x02 - Overworld Theme");
1260 ImGui::BulletText("0x05 - Kakariko Village");
1261 ImGui::BulletText("0x07 - Lost Woods");
1262 ImGui::BulletText("0x09 - Dark World Theme");
1263 ImGui::BulletText("0x0F - Ganon's Tower");
1264 ImGui::BulletText("0x11 - Death Mountain");
1265 ImGui::Unindent();
1266 }
1267}
1268
1274
1280
1283 return refresh_map_palette_();
1284 }
1285 return absl::OkStatus();
1286}
1287
1290 return refresh_tile16_blockset_();
1291 }
1292 return absl::OkStatus();
1293}
1294
1297 force_refresh_graphics_(map_index);
1298 }
1299}
1300
1301void MapPropertiesSystem::RefreshSiblingMapGraphics(int map_index, bool include_self) {
1302 if (!overworld_ || !maps_bmp_ || map_index < 0 || map_index >= zelda3::kNumOverworldMaps) {
1303 return;
1304 }
1305
1306 auto* map = overworld_->mutable_overworld_map(map_index);
1307 if (map->area_size() == zelda3::AreaSizeEnum::SmallArea) {
1308 return; // No siblings for small areas
1309 }
1310
1311 int parent_id = map->parent();
1312 std::vector<int> siblings;
1313
1314 switch (map->area_size()) {
1316 siblings = {parent_id, parent_id + 1, parent_id + 8, parent_id + 9};
1317 break;
1319 siblings = {parent_id, parent_id + 1};
1320 break;
1322 siblings = {parent_id, parent_id + 8};
1323 break;
1324 default:
1325 return;
1326 }
1327
1328 for (int sibling : siblings) {
1329 if (sibling >= 0 && sibling < zelda3::kNumOverworldMaps) {
1330 // Skip self unless include_self is true
1331 if (sibling == map_index && !include_self) {
1332 continue;
1333 }
1334
1335 // Mark as modified FIRST
1336 (*maps_bmp_)[sibling].set_modified(true);
1337
1338 // Load graphics from ROM
1339 overworld_->mutable_overworld_map(sibling)->LoadAreaGraphics();
1340
1341 // CRITICAL FIX: Force immediate refresh on the sibling
1342 // This will trigger the callback to OverworldEditor's RefreshChildMapOnDemand
1343 ForceRefreshGraphics(sibling);
1344 }
1345 }
1346
1347 // After marking all siblings, trigger a refresh
1348 // This ensures all marked maps get processed
1350}
1351
1353 uint8_t asm_version =
1355 if (asm_version >= 2) {
1356 ImGui::Separator();
1357 ImGui::Text("Mosaic Effects (per direction):");
1358
1359 auto* current_map_ptr = overworld_->mutable_overworld_map(current_map);
1360 std::array<bool, 4> mosaic_expanded = current_map_ptr->mosaic_expanded();
1361 const char* direction_names[] = {"North", "South", "East", "West"};
1362
1363 for (int i = 0; i < 4; i++) {
1364 if (ImGui::Checkbox(direction_names[i], &mosaic_expanded[i])) {
1365 current_map_ptr->set_mosaic_expanded(i, mosaic_expanded[i]);
1368 }
1369 }
1370 } else {
1371 if (ImGui::Checkbox(
1372 "Mosaic Effect",
1373 overworld_->mutable_overworld_map(current_map)->mutable_mosaic())) {
1376 }
1377 }
1378}
1379
1381 bool& show_overlay_preview) {
1382 uint8_t asm_version =
1384
1385 // Determine if this is a special overworld map (0x80-0x9F)
1386 bool is_special_overworld_map = (current_map >= 0x80 && current_map < 0xA0);
1387
1388 if (is_special_overworld_map) {
1389 // Special overworld maps (0x80-0x9F) serve as visual effect sources
1390 ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
1391 ICON_MD_INFO " Special Area Map (0x%02X)", current_map);
1392 ImGui::Separator();
1393 ImGui::TextWrapped(
1394 "This is a special area map (0x80-0x9F) used as a visual effect "
1395 "source. These maps provide the graphics data for subscreen overlays "
1396 "like fog, rain, forest canopy, and sky backgrounds that appear on "
1397 "normal maps (0x00-0x7F).");
1398 ImGui::Spacing();
1399 ImGui::TextWrapped(
1400 "You can edit the tile16 data here to customize how the visual effects "
1401 "appear when referenced by other maps.");
1402 } else {
1403 // Light World (0x00-0x3F) and Dark World (0x40-0x7F) maps support subscreen overlays
1404
1405 // Comprehensive help section
1406 ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
1407 ICON_MD_HELP_OUTLINE " Visual Effects Overview");
1408 ImGui::SameLine();
1409 if (ImGui::Button(ICON_MD_INFO "##HelpButton")) {
1410 ImGui::OpenPopup("OverlayTypesHelp");
1411 }
1412
1413 if (ImGui::BeginPopup("OverlayTypesHelp")) {
1414 ImGui::Text(ICON_MD_HELP " Understanding Overlay Types");
1415 ImGui::Separator();
1416
1417 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
1418 ICON_MD_LAYERS " 1. Subscreen Overlays (Visual Effects)");
1419 ImGui::Indent();
1420 ImGui::BulletText("Displayed as semi-transparent layers");
1421 ImGui::BulletText("Reference special area maps (0x80-0x9F)");
1422 ImGui::BulletText("Examples: fog, rain, forest canopy, sky");
1423 ImGui::BulletText("Purely visual - don't affect collision");
1424 ImGui::Unindent();
1425
1426 ImGui::Spacing();
1427 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f),
1428 ICON_MD_EDIT_NOTE " 2. Map Overlays (Interactive)");
1429 ImGui::Indent();
1430 ImGui::BulletText("Dynamic tile16 changes on the map");
1431 ImGui::BulletText("Used for bridges appearing, holes opening");
1432 ImGui::BulletText("Stored as tile16 ID arrays");
1433 ImGui::BulletText("Affect collision and interaction");
1434 ImGui::BulletText("Triggered by game events/progression");
1435 ImGui::Unindent();
1436
1437 ImGui::Separator();
1438 ImGui::TextWrapped(
1439 "Note: Subscreen overlays are what you configure here. "
1440 "Map overlays are event-driven and edited separately.");
1441
1442 ImGui::EndPopup();
1443 }
1444 ImGui::Separator();
1445
1446 // Subscreen Overlay Section
1447 ImGui::Text(ICON_MD_LAYERS " Subscreen Overlay (Visual Effects)");
1448
1449 uint16_t current_overlay =
1450 overworld_->mutable_overworld_map(current_map)->subscreen_overlay();
1451 if (gui::InputHexWord("Visual Effect Map ID", &current_overlay,
1452 kInputFieldSize + 20)) {
1453 overworld_->mutable_overworld_map(current_map)
1454 ->set_subscreen_overlay(current_overlay);
1457 }
1458 if (ImGui::IsItemHovered()) {
1459 ImGui::SetTooltip(
1460 "References a special area map (0x80-0x9F) for visual effects.\n"
1461 "The referenced map's tile16 data is drawn as a semi-transparent\n"
1462 "layer on top of or behind this area for atmospheric effects.");
1463 }
1464
1465 // Show subscreen overlay description with color coding
1466 std::string overlay_desc = GetOverlayDescription(current_overlay);
1467 if (current_overlay == 0x00FF) {
1468 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
1469 ICON_MD_CHECK " %s", overlay_desc.c_str());
1470 } else if (current_overlay >= 0x80 && current_overlay < 0xA0) {
1471 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
1472 ICON_MD_VISIBILITY " %s", overlay_desc.c_str());
1473 } else {
1474 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f),
1475 ICON_MD_HELP_OUTLINE " %s", overlay_desc.c_str());
1476 }
1477
1478 // Preview checkbox with better labeling
1479 ImGui::Spacing();
1480 if (ImGui::Checkbox(ICON_MD_PREVIEW " Preview Visual Effect on Map",
1481 &show_overlay_preview)) {
1482 // Toggle subscreen overlay preview
1483 }
1484 if (ImGui::IsItemHovered()) {
1485 ImGui::SetTooltip(
1486 "Shows a semi-transparent preview of the visual effect overlay\n"
1487 "drawn on top of the current map in the editor canvas.\n\n"
1488 "This preview shows how the subscreen overlay will appear in-game.");
1489 }
1490
1491 ImGui::Separator();
1492
1493 // Interactive/Dynamic Map Overlay Section (for vanilla ROMs)
1494 if (asm_version == 0xFF) {
1495 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f),
1496 ICON_MD_EDIT_NOTE " Map Overlay (Interactive)");
1497 ImGui::SameLine();
1498 if (ImGui::Button(ICON_MD_INFO "##MapOverlayHelp")) {
1499 ImGui::OpenPopup("InteractiveOverlayHelp");
1500 }
1501 if (ImGui::BeginPopup("InteractiveOverlayHelp")) {
1502 ImGui::Text(ICON_MD_HELP " Map Overlays (Interactive Tile Changes)");
1503 ImGui::Separator();
1504 ImGui::TextWrapped(
1505 "Map overlays are different from visual effect overlays. "
1506 "They contain tile16 data that dynamically replaces tiles on "
1507 "the map based on game events or progression.");
1508 ImGui::Spacing();
1509 ImGui::Text("Common uses:");
1510 ImGui::BulletText("Bridges appearing over water");
1511 ImGui::BulletText("Holes revealing secret passages");
1512 ImGui::BulletText("Rocks/bushes being moved");
1513 ImGui::BulletText("Environmental changes from story events");
1514 ImGui::Spacing();
1515 ImGui::TextWrapped(
1516 "These are triggered by game code and stored as separate "
1517 "tile data arrays in the ROM. ZSCustomOverworld v3+ provides "
1518 "extended control over these features.");
1519 ImGui::EndPopup();
1520 }
1521
1522 auto* current_map_ptr = overworld_->overworld_map(current_map);
1523 ImGui::Spacing();
1524 if (current_map_ptr->has_overlay()) {
1525 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
1526 ICON_MD_CHECK " Overlay ID: 0x%04X",
1527 current_map_ptr->overlay_id());
1528 ImGui::Text(ICON_MD_STORAGE " Data Size: %d bytes",
1529 static_cast<int>(current_map_ptr->overlay_data().size()));
1530 ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.4f, 1.0f),
1531 ICON_MD_INFO " Read-only in vanilla ROM");
1532 } else {
1533 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
1534 ICON_MD_BLOCK " No map overlay data for this area");
1535 }
1536 }
1537
1538 // Show version and capability info
1539 ImGui::Separator();
1540 if (asm_version == 0xFF) {
1541 ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
1542 ICON_MD_INFO " Vanilla ROM");
1543 ImGui::BulletText("Visual effects use maps 0x80-0x9F");
1544 ImGui::BulletText("Map overlays are read-only");
1545 } else {
1546 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
1547 ICON_MD_UPGRADE " ZSCustomOverworld v%d", asm_version);
1548 ImGui::BulletText("Enhanced visual effect control");
1549 if (asm_version >= 3) {
1550 ImGui::BulletText("Extended overlay system");
1551 ImGui::BulletText("Custom area sizes support");
1552 }
1553 }
1554 }
1555}
1556
1557std::string MapPropertiesSystem::GetOverlayDescription(uint16_t overlay_id) {
1558 if (overlay_id == 0x0093) {
1559 return "Triforce Room Curtain";
1560 } else if (overlay_id == 0x0094) {
1561 return "Under the Bridge";
1562 } else if (overlay_id == 0x0095) {
1563 return "Sky Background (LW Death Mountain)";
1564 } else if (overlay_id == 0x0096) {
1565 return "Pyramid Background";
1566 } else if (overlay_id == 0x0097) {
1567 return "First Fog Overlay (Master Sword Area)";
1568 } else if (overlay_id == 0x009C) {
1569 return "Lava Background (DW Death Mountain)";
1570 } else if (overlay_id == 0x009D) {
1571 return "Second Fog Overlay (Lost Woods/Skull Woods)";
1572 } else if (overlay_id == 0x009E) {
1573 return "Tree Canopy (Forest)";
1574 } else if (overlay_id == 0x009F) {
1575 return "Rain Effect (Misery Mire)";
1576 } else if (overlay_id == 0x00FF) {
1577 return "No Overlay";
1578 } else {
1579 return "Custom overlay";
1580 }
1581}
1582
1584 int current_world,
1585 bool show_overlay_preview) {
1586 gfx::ScopedTimer timer("map_properties_draw_overlay_preview");
1587
1588 if (!show_overlay_preview || !maps_bmp_ || !canvas_)
1589 return;
1590
1591 // Get subscreen overlay information based on ROM version and map type
1592 uint16_t overlay_id = 0x00FF;
1593 bool has_subscreen_overlay = false;
1594
1595 uint8_t asm_version =
1597 bool is_special_overworld_map = (current_map >= 0x80 && current_map < 0xA0);
1598
1599 if (is_special_overworld_map) {
1600 // Special overworld maps (0x80-0x9F) do not support subscreen overlays
1601 return;
1602 }
1603
1604 // Light World (0x00-0x3F) and Dark World (0x40-0x7F) maps support subscreen overlays for all versions
1605 overlay_id = overworld_->overworld_map(current_map)->subscreen_overlay();
1606 has_subscreen_overlay = (overlay_id != 0x00FF);
1607
1608 if (!has_subscreen_overlay)
1609 return;
1610
1611 // Map subscreen overlay ID to special area map for bitmap
1612 int overlay_map_index = -1;
1613 if (overlay_id >= 0x80 && overlay_id < 0xA0) {
1614 overlay_map_index = overlay_id;
1615 }
1616
1617 if (overlay_map_index < 0 || overlay_map_index >= zelda3::kNumOverworldMaps)
1618 return;
1619
1620 // Get the subscreen overlay map's bitmap
1621 const auto& overlay_bitmap = (*maps_bmp_)[overlay_map_index];
1622 if (!overlay_bitmap.is_active())
1623 return;
1624
1625 // Calculate position for subscreen overlay preview on the current map
1626 int current_map_x = current_map % 8;
1627 int current_map_y = current_map / 8;
1628 if (current_world == 1) {
1629 current_map_x = (current_map - 0x40) % 8;
1630 current_map_y = (current_map - 0x40) / 8;
1631 } else if (current_world == 2) {
1632 current_map_x = (current_map - 0x80) % 8;
1633 current_map_y = (current_map - 0x80) / 8;
1634 }
1635
1636 int scale = static_cast<int>(canvas_->global_scale());
1637 int map_x = current_map_x * kOverworldMapSize * scale;
1638 int map_y = current_map_y * kOverworldMapSize * scale;
1639
1640 // Determine if this is a background or foreground subscreen overlay
1641 bool is_background_overlay =
1642 (overlay_id == 0x0095 || overlay_id == 0x0096 || overlay_id == 0x009C);
1643
1644 // Set alpha for semi-transparent preview
1645 ImU32 overlay_color =
1646 is_background_overlay ? IM_COL32(255, 255, 255, 128)
1647 : // Background subscreen overlays - lighter
1648 IM_COL32(255, 255, 255,
1649 180); // Foreground subscreen overlays - more opaque
1650
1651 // Draw the subscreen overlay bitmap with semi-transparency
1652 canvas_->draw_list()->AddImage(
1653 (ImTextureID)(intptr_t)overlay_bitmap.texture(), ImVec2(map_x, map_y),
1654 ImVec2(map_x + kOverworldMapSize * scale,
1655 map_y + kOverworldMapSize * scale),
1656 ImVec2(0, 0), ImVec2(1, 1), overlay_color);
1657}
1658
1660 if (ImGui::BeginPopup("ViewPopup")) {
1661 ImGui::PushID("ViewPopup"); // Fix ImGui duplicate ID warnings
1662
1663 // Use theme-aware spacing instead of hardcoded constants
1665 float padding = gui::LayoutHelpers::GetButtonPadding();
1666 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1667 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
1668
1669 ImGui::Text("View Controls");
1670 ImGui::Separator();
1671
1672 // Horizontal layout for view controls
1673 if (ImGui::Button(ICON_MD_ZOOM_OUT, ImVec2(kIconButtonWidth, 0))) {
1674 // This would need to be connected to the canvas zoom function
1675 // For now, just show the option
1676 }
1677 HOVER_HINT("Zoom out on the canvas");
1678 ImGui::SameLine();
1679 if (ImGui::Button(ICON_MD_ZOOM_IN, ImVec2(kIconButtonWidth, 0))) {
1680 // This would need to be connected to the canvas zoom function
1681 // For now, just show the option
1682 }
1683 HOVER_HINT("Zoom in on the canvas");
1684 ImGui::SameLine();
1685 if (ImGui::Button(ICON_MD_OPEN_IN_FULL, ImVec2(kIconButtonWidth, 0))) {
1686 // This would need to be connected to the fullscreen toggle
1687 // For now, just show the option
1688 }
1689 HOVER_HINT("Toggle fullscreen canvas (F11)");
1690
1691 ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
1692 ImGui::PopID(); // Pop ViewPopup ID scope
1693 ImGui::EndPopup();
1694 }
1695}
1696
1698 if (ImGui::BeginPopup("QuickPopup")) {
1699 ImGui::PushID("QuickPopup"); // Fix ImGui duplicate ID warnings
1700
1701 // Use theme-aware spacing instead of hardcoded constants
1703 float padding = gui::LayoutHelpers::GetButtonPadding();
1704 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1705 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
1706
1707 ImGui::Text("Quick Access");
1708 ImGui::Separator();
1709
1710 // Horizontal layout for quick access buttons
1711 if (ImGui::Button(ICON_MD_GRID_VIEW, ImVec2(kIconButtonWidth, 0))) {
1712 // This would need to be connected to the Tile16 editor toggle
1713 // For now, just show the option
1714 }
1715 HOVER_HINT("Open Tile16 Editor (Ctrl+T)");
1716 ImGui::SameLine();
1717
1718 if (ImGui::Button(ICON_MD_CONTENT_COPY, ImVec2(kIconButtonWidth, 0))) {
1719 // This would need to be connected to the copy map function
1720 // For now, just show the option
1721 }
1722 HOVER_HINT("Copy current map to clipboard");
1723 ImGui::SameLine();
1724
1725 if (ImGui::Button(ICON_MD_LOCK, ImVec2(kIconButtonWidth, 0))) {
1726 // This would need to be connected to the map lock toggle
1727 // For now, just show the option
1728 }
1729 HOVER_HINT("Lock/unlock current map (Ctrl+L)");
1730
1731 ImGui::PopStyleVar(2); // Pop the 2 style variables we pushed
1732 ImGui::PopID(); // Pop QuickPopup ID scope
1733 ImGui::EndPopup();
1734 }
1735}
1736
1737} // namespace editor
1738} // namespace yaze
std::array< gfx::Bitmap, zelda3::kNumOverworldMaps > * maps_bmp_
void SetupCanvasContextMenu(gui::Canvas &canvas, int current_map, bool current_map_lock, bool &show_map_properties_panel, bool &show_custom_bg_color_editor, bool &show_overlay_editor, int current_mode=0)
void DrawOverlayEditor(int current_map, bool &show_overlay_editor)
void DrawPropertiesPopup(int current_map, bool &show_map_properties_panel, bool &show_overlay_preview, int &game_state)
RefreshPaletteCallback refresh_tile16_blockset_
void DrawOverlayPreviewOnMap(int current_map, int current_world, bool show_overlay_preview)
void DrawMosaicControls(int current_map)
void DrawMapPropertiesPanel(int current_map, bool &show_map_properties_panel)
std::function< void(const std::string &)> entity_insert_callback_
void DrawSpritePropertiesTab(int current_map)
RefreshPaletteCallback refresh_map_palette_
void DrawBasicPropertiesTab(int current_map)
void DrawCustomFeaturesTab(int current_map)
void DrawPalettesPopup(int current_map, int game_state, bool &show_custom_bg_color_editor)
void DrawCustomBackgroundColorEditor(int current_map, bool &show_custom_bg_color_editor)
void RefreshSiblingMapGraphics(int map_index, bool include_self=false)
void DrawTileGraphicsTab(int current_map)
ForceRefreshGraphicsCallback force_refresh_graphics_
std::string GetOverlayDescription(uint16_t overlay_id)
void DrawSimplifiedMapSettings(int &current_world, int &current_map, bool &current_map_lock, bool &show_map_properties_panel, bool &show_custom_bg_color_editor, bool &show_overlay_editor, bool &show_overlay_preview, int &game_state, int &current_mode)
void DrawOverlayControls(int current_map, bool &show_overlay_preview)
void DrawGraphicsPopup(int current_map, int game_state)
RAII timer for automatic timing management.
SNES Color container.
Definition snes_color.h:109
constexpr uint16_t snes() const
Get SNES 15-bit color.
Definition snes_color.h:192
Modern, robust canvas for drawing and manipulating graphics.
Definition canvas.h:59
void set_scrolling(ImVec2 scroll)
Definition canvas.h:296
auto global_scale() const
Definition canvas.h:329
auto draw_list() const
Definition canvas.h:293
void ClearContextMenuItems()
Definition canvas.cc:595
void AddContextMenuItem(const gui::CanvasMenuItem &item)
Definition canvas.cc:572
void set_global_scale(float scale)
Definition canvas.h:299
static float GetButtonPadding()
static float GetStandardSpacing()
auto is_loaded() const
Definition overworld.h:276
auto overworld_map(int i) const
Definition overworld.h:247
auto mutable_overworld_map(int i)
Definition overworld.h:248
absl::Status ConfigureMultiAreaMap(int parent_index, AreaSizeEnum size)
Configure a multi-area map structure (Large/Wide/Tall)
Definition overworld.cc:261
#define ICON_MD_BLOCK
Definition icons.h:267
#define ICON_MD_GRID_VIEW
Definition icons.h:895
#define ICON_MD_COLORIZE
Definition icons.h:439
#define ICON_MD_INFO
Definition icons.h:991
#define ICON_MD_STORAGE
Definition icons.h:1863
#define ICON_MD_WARNING
Definition icons.h:2121
#define ICON_MD_PETS
Definition icons.h:1429
#define ICON_MD_UPGRADE
Definition icons.h:2045
#define ICON_MD_LOCK_OPEN
Definition icons.h:1140
#define ICON_MD_LOCK
Definition icons.h:1138
#define ICON_MD_LIGHTBULB
Definition icons.h:1081
#define ICON_MD_PHOTO_SIZE_SELECT_LARGE
Definition icons.h:1457
#define ICON_MD_OFFLINE_BOLT
Definition icons.h:1342
#define ICON_MD_PLAY_ARROW
Definition icons.h:1477
#define ICON_MD_CHECK
Definition icons.h:395
#define ICON_MD_TUNE
Definition icons.h:2020
#define ICON_MD_ZOOM_OUT
Definition icons.h:2194
#define ICON_MD_OPEN_IN_FULL
Definition icons.h:1351
#define ICON_MD_MESSAGE
Definition icons.h:1199
#define ICON_MD_VISIBILITY
Definition icons.h:2099
#define ICON_MD_GRASS
Definition icons.h:889
#define ICON_MD_FORMAT_COLOR_FILL
Definition icons.h:828
#define ICON_MD_DOOR_BACK
Definition icons.h:610
#define ICON_MD_CASTLE
Definition icons.h:378
#define ICON_MD_AUTO_FIX_HIGH
Definition icons.h:216
#define ICON_MD_MUSIC_NOTE
Definition icons.h:1262
#define ICON_MD_RESTORE
Definition icons.h:1603
#define ICON_MD_ASPECT_RATIO
Definition icons.h:190
#define ICON_MD_LAYERS
Definition icons.h:1066
#define ICON_MD_ANIMATION
Definition icons.h:155
#define ICON_MD_DOOR_FRONT
Definition icons.h:611
#define ICON_MD_BOLT
Definition icons.h:280
#define ICON_MD_BLUR_ON
Definition icons.h:279
#define ICON_MD_IMAGE
Definition icons.h:980
#define ICON_MD_PREVIEW
Definition icons.h:1510
#define ICON_MD_FAVORITE
Definition icons.h:725
#define ICON_MD_HELP_OUTLINE
Definition icons.h:933
#define ICON_MD_ADD_LOCATION
Definition icons.h:98
#define ICON_MD_ZOOM_IN
Definition icons.h:2192
#define ICON_MD_EDIT_NOTE
Definition icons.h:648
#define ICON_MD_PALETTE
Definition icons.h:1368
#define ICON_MD_OPEN_IN_NEW
Definition icons.h:1352
#define ICON_MD_PEST_CONTROL_RODENT
Definition icons.h:1428
#define ICON_MD_CONTENT_COPY
Definition icons.h:463
#define ICON_MD_COLOR_LENS
Definition icons.h:438
#define ICON_MD_PHOTO
Definition icons.h:1449
#define ICON_MD_CYCLONE
Definition icons.h:512
#define ICON_MD_GAMEPAD
Definition icons.h:864
#define ICON_MD_HELP
Definition icons.h:931
#define HOVER_HINT(string)
Definition macro.h:24
constexpr const char * kAreaSizeNames[]
constexpr float kTableColumnView
constexpr unsigned int kOverworldMapSize
constexpr float kTableColumnQuick
constexpr float kTableColumnWorld
constexpr float kTableButtonView
constexpr float kTableColumnGraphics
constexpr const char * kWorldNames[]
constexpr float kHexByteInputWidth
constexpr float kTableButtonQuick
constexpr float kTableColumnPalettes
constexpr float kTableButtonProperties
constexpr float kComboWorldWidth
constexpr float kTableColumnMap
constexpr float kTableColumnAreaSize
constexpr float kTableButtonPalettes
constexpr float kComboGameStateWidth
constexpr float kInputFieldSize
Definition entity.cc:19
constexpr float kTableButtonGraphics
constexpr const char * kGameStateNames[]
Definition ui_constants.h:8
constexpr float kIconButtonWidth
constexpr float kHexWordInputWidth
constexpr float kComboAreaSizeWidth
constexpr float kTableColumnLock
constexpr float kTableColumnProperties
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
Definition input.cc:175
ImVec4 ConvertSnesColorToImVec4(const gfx::SnesColor &color)
Convert SnesColor to standard ImVec4 for display.
Definition color.cc:19
bool InputHexWordCustom(const char *label, uint16_t *data, float input_width)
Definition input.cc:492
gfx::SnesColor ConvertImVec4ToSnesColor(const ImVec4 &color)
Convert standard ImVec4 to SnesColor.
Definition color.cc:32
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:189
constexpr int OverworldCustomAreaSpecificBGEnabled
constexpr int kNumOverworldMaps
Definition common.h:46
constexpr int kOverworldMusicBeginning
Definition overworld.h:46
constexpr int OverworldCustomASMHasBeenApplied
Definition common.h:50
constexpr int kOverworldMusicAgahnim
Definition overworld.h:49
constexpr int kOverworldMusicMasterSword
Definition overworld.h:48
constexpr int kOverworldMusicZelda
Definition overworld.h:47
constexpr int OverworldCustomSubscreenOverlayEnabled
constexpr int OverworldCustomAreaSpecificBGPalette
constexpr int OverworldCustomSubscreenOverlayArray
Main namespace for the application.
Definition controller.cc:20
SNES color in 15-bit RGB format (BGR555)
Definition yaze.h:208
Declarative menu item definition.
Definition canvas_menu.h:63
std::vector< CanvasMenuItem > subitems
Definition canvas_menu.h:86
std::function< void()> callback
Definition canvas_menu.h:74