12#include "imgui/imgui.h"
17using ImGui::BeginTable;
19using ImGui::Separator;
20using ImGui::TableNextColumn;
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,
30 (void)show_overlay_editor;
33 if (BeginTable(
"SimplifiedMapSettings", 9,
34 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit,
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,
57 ImGui::Combo(
"##world", ¤t_world,
kWorldNames, 3);
60 ImGui::Text(
"%d (0x%02X)", current_map, current_map);
67 int current_area_size =
71 if (asm_version >= 3 && asm_version != 0xFF) {
73 if (ImGui::Combo(
"##AreaSize", ¤t_area_size,
kAreaSizeNames, 4)) {
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;
87 if (ImGui::Combo(
"##AreaSize", &limited_size, limited_names, 2)) {
98 if (asm_version == 0xFF || asm_version < 3) {
99 HOVER_HINT(
"Small (1x1) and Large (2x2) maps. Wide/Tall require v3+");
106 current_map_lock = !current_map_lock;
108 HOVER_HINT(current_map_lock ?
"Unlock Map" :
"Lock Map");
112 ImGui::OpenPopup(
"GraphicsPopup");
114 if (ImGui::IsItemHovered()) {
116 "Graphics Settings\n\n"
118 " • Area graphics (tileset)\n"
119 " • Sprite graphics sheets\n"
120 " • Animated graphics (v3+)\n"
121 " • Custom tile16 sheets (8 slots)");
127 ImGui::OpenPopup(
"PalettesPopup");
129 if (ImGui::IsItemHovered()) {
131 "Palette Settings\n\n"
133 " • Area palette (background colors)\n"
134 " • Main palette (v2+)\n"
135 " • Sprite palettes\n"
136 " • Custom background colors");
142 ImGui::OpenPopup(
"ConfigPopup");
144 if (ImGui::IsItemHovered()) {
146 "Area Configuration\n\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.");
158 show_overlay_preview, game_state);
163 ImGui::OpenPopup(
"ViewPopup");
165 if (ImGui::IsItemHovered()) {
170 " • Toggle fullscreen\n"
178 ImGui::OpenPopup(
"QuickPopup");
180 if (ImGui::IsItemHovered()) {
182 "Quick Access Tools\n\n"
184 " • Tile16 editor (Ctrl+T)\n"
185 " • Copy current map\n"
186 " • Lock/unlock map (Ctrl+L)");
195 int current_map,
bool& show_map_properties_panel) {
196 (void)show_map_properties_panel;
198 Text(
"No overworld loaded");
204 Text(
"Current Map: %d (0x%02X)", current_map, current_map);
210 if (ImGui::BeginTabBar(
"MapPropertiesTabs",
211 ImGuiTabBarFlags_FittingPolicyScroll)) {
214 if (ImGui::BeginTabItem(
"Basic Properties")) {
220 if (ImGui::BeginTabItem(
"Sprite Properties")) {
226 uint8_t asm_version =
228 if (asm_version != 0xFF && ImGui::BeginTabItem(
"Custom Features")) {
234 if (ImGui::BeginTabItem(
"Tile Graphics")) {
240 if (ImGui::BeginTabItem(
"Music")) {
250 int current_map,
bool& show_custom_bg_color_editor) {
251 (void)show_custom_bg_color_editor;
253 Text(
"No overworld loaded");
257 uint8_t asm_version =
259 if (asm_version < 2) {
260 Text(
"Custom background colors require ZSCustomOverworld v2+");
264 Text(
"Custom Background Color Editor");
268 static bool use_area_specific_bg_color =
false;
269 if (ImGui::Checkbox(
"Use Area-Specific Background Color",
270 &use_area_specific_bg_color)) {
273 use_area_specific_bg_color ? 1 : 0;
276 if (use_area_specific_bg_color) {
278 uint16_t current_color =
285 if (ImGui::ColorPicker4(
286 "Background Color", (
float*)&color_vec,
287 ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHex)) {
291 ->set_area_specific_bg_color(new_snes_color.
snes());
296 (*rom_)[rom_address] = new_snes_color.
snes() & 0xFF;
297 (*rom_)[rom_address + 1] = (new_snes_color.
snes() >> 8) & 0xFF;
300 Text(
"SNES Color: 0x%04X", current_color);
305 bool& show_overlay_editor) {
306 (void)show_overlay_editor;
308 Text(
"No overworld loaded");
312 uint8_t asm_version =
315 ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
317 ImGui::Text(
"Map: 0x%02X", current_map);
320 if (asm_version < 1) {
321 ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.4f, 1.0f),
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.");
333 ImGuiTreeNodeFlags_DefaultOpen)) {
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.");
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");
351 static bool use_subscreen_overlay =
false;
353 &use_subscreen_overlay)) {
356 use_subscreen_overlay ? 1 : 0;
358 if (ImGui::IsItemHovered()) {
359 ImGui::SetTooltip(
"Enable/disable visual effect overlay for this map area");
362 if (use_subscreen_overlay) {
364 uint16_t current_overlay =
369 ->set_subscreen_overlay(current_overlay);
374 (*rom_)[rom_address] = current_overlay & 0xFF;
375 (*rom_)[rom_address + 1] = (current_overlay >> 8) & 0xFF;
377 if (ImGui::IsItemHovered()) {
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.");
386 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
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)");
406 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
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) {
432 entity_menu.
subitems.push_back(entrance_item);
442 entity_menu.
subitems.push_back(hole_item);
452 entity_menu.
subitems.push_back(exit_item);
462 entity_menu.
subitems.push_back(item_item);
472 entity_menu.
subitems.push_back(sprite_item);
479 lock_item.
label = current_map_lock ?
"Unlock Map" :
"Lock to This Map";
480 lock_item.
callback = [¤t_map_lock]() {
481 current_map_lock = !current_map_lock;
488 properties_item.
callback = [&show_map_properties_panel]() {
489 show_map_properties_panel =
true;
494 uint8_t asm_version =
496 if (asm_version >= 3 && asm_version != 0xFF) {
500 bg_color_item.
callback = [&show_custom_bg_color_editor]() {
501 show_custom_bg_color_editor =
true;
508 overlay_item.
callback = [&show_overlay_editor]() {
509 show_overlay_editor =
true;
517 reset_view_item.
callback = [&canvas]() {
525 zoom_in_item.
callback = [&canvas]() {
526 float scale = std::min(2.0f, canvas.
global_scale() + 0.25f);
533 zoom_out_item.
callback = [&canvas]() {
534 float scale = std::max(0.25f, canvas.
global_scale() - 0.25f);
542 if (ImGui::BeginPopup(
"GraphicsPopup")) {
543 ImGui::PushID(
"GraphicsPopup");
548 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
549 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
551 ImGui::Text(
"Graphics Settings");
557 ->mutable_area_graphics(),
565 (*maps_bmp_)[current_map].set_modified(
true);
577 HOVER_HINT(
"Main tileset graphics for this map area");
584 ->mutable_sprite_graphics(game_state),
590 HOVER_HINT(
"Sprite graphics sheet for current game state");
592 uint8_t asm_version =
594 if (asm_version >= 3) {
597 ->mutable_animated_gfx(),
604 HOVER_HINT(
"Animated tile graphics (water, lava, etc.)");
608 if (asm_version >= 1 && asm_version != 0xFF) {
614 if (BeginTable(
"CustomTileGraphics", 2,
615 ImGuiTableFlags_SizingFixedFit)) {
616 for (
int i = 0; i < 8; i++) {
618 std::string label = absl::StrFormat(
ICON_MD_LAYERS " Sheet %d", i);
621 ->mutable_custom_tileset(i),
628 if (ImGui::IsItemHovered()) {
629 ImGui::SetTooltip(
"Custom graphics sheet %d (0x00-0xFF)", i);
634 }
else if (asm_version == 0xFF) {
636 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
639 "Custom tile graphics require ZSCustomOverworld v1+.\n"
640 "Upgrade your ROM to access 8 customizable graphics sheets.");
643 ImGui::PopStyleVar(2);
650 bool& show_custom_bg_color_editor) {
651 if (ImGui::BeginPopup(
"PalettesPopup")) {
652 ImGui::PushID(
"PalettesPopup");
657 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
658 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
660 ImGui::Text(
"Palette Settings");
666 ->mutable_area_palette(),
672 HOVER_HINT(
"Main color palette for background tiles");
676 if (asm_version >= 2) {
679 ->mutable_main_palette(),
685 HOVER_HINT(
"Extended main palette (ZSCustomOverworld v2+)");
693 ->mutable_sprite_palette(game_state),
698 HOVER_HINT(
"Color palette for sprites in current game state");
703 show_custom_bg_color_editor = !show_custom_bg_color_editor;
705 HOVER_HINT(
"Open custom background color editor (v2+)");
707 ImGui::PopStyleVar(2);
714 bool& show_map_properties_panel,
715 bool& show_overlay_preview,
717 if (ImGui::BeginPopup(
"ConfigPopup")) {
718 ImGui::PushID(
"ConfigPopup");
723 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
724 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
730 if (BeginTable(
"BasicProps", 2, ImGuiTableFlags_SizingFixedFit)) {
737 ->mutable_message_id(),
742 if (ImGui::IsItemHovered()) {
743 ImGui::SetTooltip(
"Message ID shown when entering this area");
755 if (ImGui::IsItemHovered()) {
756 ImGui::SetTooltip(
"Affects sprite graphics/palettes based on story progress");
768 uint8_t asm_version =
771 int current_area_size =
775 if (asm_version >= 3 && asm_version != 0xFF) {
786 HOVER_HINT(
"Map area size (1x1, 2x2, 2x1, 1x2 screens)");
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;
801 HOVER_HINT(
"Small (1x1) and Large (2x2) maps. Wide/Tall require v3+");
816 show_map_properties_panel =
true;
817 ImGui::CloseCurrentPopup();
819 HOVER_HINT(
"Open detailed area configuration with all settings tabs");
821 ImGui::PopStyleVar(2);
828 if (BeginTable(
"BasicProperties", 2,
829 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
830 ImGui::TableSetupColumn(
"Property", ImGuiTableColumnFlags_WidthFixed, 180);
831 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
838 ->mutable_area_graphics(),
842 (*maps_bmp_)[current_map].set_modified(
true);
848 if (ImGui::IsItemHovered()) {
849 ImGui::SetTooltip(
"Main tileset graphics for this map area");
857 ->mutable_area_palette(),
863 if (ImGui::IsItemHovered()) {
864 ImGui::SetTooltip(
"Color palette for background tiles");
872 ->mutable_message_id(),
877 if (ImGui::IsItemHovered()) {
878 ImGui::SetTooltip(
"Message displayed when entering this area");
890 if (ImGui::IsItemHovered()) {
891 ImGui::SetTooltip(
"Enable pixelated mosaic transition effect");
900 ->mutable_area_music(0),
904 if (ImGui::IsItemHovered()) {
905 ImGui::SetTooltip(
"Music track before rescuing Zelda");
913 ->mutable_area_music(1),
917 if (ImGui::IsItemHovered()) {
918 ImGui::SetTooltip(
"Music track after rescuing Zelda");
926 ->mutable_area_music(2),
930 if (ImGui::IsItemHovered()) {
931 ImGui::SetTooltip(
"Music track after obtaining Master Sword");
939 ->mutable_area_music(3),
943 if (ImGui::IsItemHovered()) {
944 ImGui::SetTooltip(
"Music track after defeating Agahnim (Dark World)");
952 if (BeginTable(
"SpriteProperties", 2,
953 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
954 ImGui::TableSetupColumn(
"Property", ImGuiTableColumnFlags_WidthFixed, 180);
955 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
960 static int game_state = 0;
961 ImGui::SetNextItemWidth(120.f);
966 if (ImGui::IsItemHovered()) {
967 ImGui::SetTooltip(
"Affects which sprite graphics/palettes are used");
975 ->mutable_sprite_graphics(1),
980 if (ImGui::IsItemHovered()) {
981 ImGui::SetTooltip(
"First sprite graphics sheet for Zelda rescued state");
989 ->mutable_sprite_graphics(2),
994 if (ImGui::IsItemHovered()) {
995 ImGui::SetTooltip(
"Second sprite graphics sheet for Master Sword obtained state");
1003 ->mutable_sprite_palette(1),
1008 if (ImGui::IsItemHovered()) {
1009 ImGui::SetTooltip(
"Color palette for sprites - Zelda rescued state");
1017 ->mutable_sprite_palette(2),
1022 if (ImGui::IsItemHovered()) {
1023 ImGui::SetTooltip(
"Color palette for sprites - Master Sword obtained state");
1031 if (BeginTable(
"CustomFeatures", 2,
1032 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
1033 ImGui::TableSetupColumn(
"Property", ImGuiTableColumnFlags_WidthFixed, 180);
1034 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
1040 uint8_t asm_version =
1043 int current_area_size =
1045 ImGui::SetNextItemWidth(130.f);
1047 if (asm_version >= 3 && asm_version != 0xFF) {
1049 static const char* all_sizes[] = {
"Small (1x1)",
"Large (2x2)",
1050 "Wide (2x1)",
"Tall (1x2)"};
1051 if (ImGui::Combo(
"##AreaSize", ¤t_area_size, all_sizes, 4)) {
1060 if (ImGui::IsItemHovered()) {
1061 ImGui::SetTooltip(
"Map size: Small (1x1), Large (2x2), Wide (2x1), Tall (1x2)");
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;
1068 if (ImGui::Combo(
"##AreaSize", &limited_size, limited_sizes, 2)) {
1077 if (ImGui::IsItemHovered()) {
1078 ImGui::SetTooltip(
"Map size: Small (1x1), Large (2x2). Wide/Tall require v3+");
1082 if (asm_version >= 2) {
1088 ->mutable_main_palette(),
1094 if (ImGui::IsItemHovered()) {
1095 ImGui::SetTooltip(
"Extended main palette (ZSCustomOverworld v2+)");
1099 if (asm_version >= 3) {
1105 ->mutable_animated_gfx(),
1110 if (ImGui::IsItemHovered()) {
1111 ImGui::SetTooltip(
"Animated tile graphics ID (water, lava, etc.)");
1119 ->mutable_subscreen_overlay(),
1124 if (ImGui::IsItemHovered()) {
1125 ImGui::SetTooltip(
"Visual effects overlay ID (fog, rain, backgrounds)");
1137 if (asm_version >= 1 && asm_version != 0xFF) {
1141 if (BeginTable(
"TileGraphics", 2,
1142 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
1143 ImGui::TableSetupColumn(
"Property", ImGuiTableColumnFlags_WidthFixed, 180);
1144 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
1146 for (
int i = 0; i < 8; i++) {
1152 ->mutable_custom_tileset(i),
1161 if (ImGui::IsItemHovered()) {
1162 ImGui::SetTooltip(
"Custom graphics sheet %d (0x00-0xFF)", i);
1170 ImGui::TextWrapped(
"These 8 sheets allow custom tile graphics per map. "
1171 "Each sheet references a graphics ID loaded into VRAM.");
1174 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
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.");
1189 if (BeginTable(
"MusicSettings", 2,
1190 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
1191 ImGui::TableSetupColumn(
"Game State", ImGuiTableColumnFlags_WidthFixed,
1193 ImGui::TableSetupColumn(
"Music Track ID",
1194 ImGuiTableColumnFlags_WidthStretch);
1196 const char* music_state_names[] = {
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)"};
1208 for (
int i = 0; i < 4; i++) {
1210 ImGui::Text(
"%s", music_state_names[i]);
1215 ->mutable_area_music(i),
1220 int music_address = 0;
1236 if (music_address > 0) {
1237 (*rom_)[music_address] =
1239 ->mutable_area_music(i);
1242 if (ImGui::IsItemHovered()) {
1243 ImGui::SetTooltip(
"%s", music_descriptions[i]);
1251 ImGui::TextWrapped(
"Music tracks control the background music for different "
1252 "game progression states on this overworld map.");
1257 ImGuiTreeNodeFlags_DefaultOpen)) {
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");
1285 return absl::OkStatus();
1292 return absl::OkStatus();
1311 int parent_id = map->parent();
1312 std::vector<int> siblings;
1314 switch (map->area_size()) {
1316 siblings = {parent_id, parent_id + 1, parent_id + 8, parent_id + 9};
1319 siblings = {parent_id, parent_id + 1};
1322 siblings = {parent_id, parent_id + 8};
1328 for (
int sibling : siblings) {
1331 if (sibling == map_index && !include_self) {
1336 (*maps_bmp_)[sibling].set_modified(
true);
1353 uint8_t asm_version =
1355 if (asm_version >= 2) {
1357 ImGui::Text(
"Mosaic Effects (per direction):");
1360 std::array<bool, 4> mosaic_expanded = current_map_ptr->mosaic_expanded();
1361 const char* direction_names[] = {
"North",
"South",
"East",
"West"};
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]);
1371 if (ImGui::Checkbox(
1381 bool& show_overlay_preview) {
1382 uint8_t asm_version =
1386 bool is_special_overworld_map = (current_map >= 0x80 && current_map < 0xA0);
1388 if (is_special_overworld_map) {
1390 ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
1391 ICON_MD_INFO " Special Area Map (0x%02X)", current_map);
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).");
1400 "You can edit the tile16 data here to customize how the visual effects "
1401 "appear when referenced by other maps.");
1406 ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
1410 ImGui::OpenPopup(
"OverlayTypesHelp");
1413 if (ImGui::BeginPopup(
"OverlayTypesHelp")) {
1414 ImGui::Text(
ICON_MD_HELP " Understanding Overlay Types");
1417 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
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");
1427 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f),
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");
1439 "Note: Subscreen overlays are what you configure here. "
1440 "Map overlays are event-driven and edited separately.");
1447 ImGui::Text(
ICON_MD_LAYERS " Subscreen Overlay (Visual Effects)");
1449 uint16_t current_overlay =
1454 ->set_subscreen_overlay(current_overlay);
1458 if (ImGui::IsItemHovered()) {
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.");
1467 if (current_overlay == 0x00FF) {
1468 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
1470 }
else if (current_overlay >= 0x80 && current_overlay < 0xA0) {
1471 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
1474 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f),
1481 &show_overlay_preview)) {
1484 if (ImGui::IsItemHovered()) {
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.");
1494 if (asm_version == 0xFF) {
1495 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f),
1499 ImGui::OpenPopup(
"InteractiveOverlayHelp");
1501 if (ImGui::BeginPopup(
"InteractiveOverlayHelp")) {
1502 ImGui::Text(
ICON_MD_HELP " Map Overlays (Interactive Tile Changes)");
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.");
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");
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.");
1524 if (current_map_ptr->has_overlay()) {
1525 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
1527 current_map_ptr->overlay_id());
1529 static_cast<int>(current_map_ptr->overlay_data().size()));
1530 ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.4f, 1.0f),
1533 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
1540 if (asm_version == 0xFF) {
1541 ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
1543 ImGui::BulletText(
"Visual effects use maps 0x80-0x9F");
1544 ImGui::BulletText(
"Map overlays are read-only");
1546 ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f),
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");
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";
1579 return "Custom overlay";
1585 bool show_overlay_preview) {
1592 uint16_t overlay_id = 0x00FF;
1593 bool has_subscreen_overlay =
false;
1595 uint8_t asm_version =
1597 bool is_special_overworld_map = (current_map >= 0x80 && current_map < 0xA0);
1599 if (is_special_overworld_map) {
1606 has_subscreen_overlay = (overlay_id != 0x00FF);
1608 if (!has_subscreen_overlay)
1612 int overlay_map_index = -1;
1613 if (overlay_id >= 0x80 && overlay_id < 0xA0) {
1614 overlay_map_index = overlay_id;
1621 const auto& overlay_bitmap = (*maps_bmp_)[overlay_map_index];
1622 if (!overlay_bitmap.is_active())
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;
1641 bool is_background_overlay =
1642 (overlay_id == 0x0095 || overlay_id == 0x0096 || overlay_id == 0x009C);
1645 ImU32 overlay_color =
1646 is_background_overlay ? IM_COL32(255, 255, 255, 128)
1648 IM_COL32(255, 255, 255,
1653 (ImTextureID)(intptr_t)overlay_bitmap.texture(), ImVec2(map_x, map_y),
1656 ImVec2(0, 0), ImVec2(1, 1), overlay_color);
1660 if (ImGui::BeginPopup(
"ViewPopup")) {
1661 ImGui::PushID(
"ViewPopup");
1666 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1667 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
1669 ImGui::Text(
"View Controls");
1689 HOVER_HINT(
"Toggle fullscreen canvas (F11)");
1691 ImGui::PopStyleVar(2);
1698 if (ImGui::BeginPopup(
"QuickPopup")) {
1699 ImGui::PushID(
"QuickPopup");
1704 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1705 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding, padding));
1707 ImGui::Text(
"Quick Access");
1729 HOVER_HINT(
"Lock/unlock current map (Ctrl+L)");
1731 ImGui::PopStyleVar(2);
RefreshCallback refresh_overworld_map_
std::array< gfx::Bitmap, zelda3::kNumOverworldMaps > * maps_bmp_
void RefreshMapProperties()
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)
RefreshCallback refresh_map_properties_
void RefreshOverworldMap()
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)
absl::Status RefreshTile16Blockset()
std::function< void(const std::string &)> entity_insert_callback_
void DrawSpritePropertiesTab(int current_map)
RefreshPaletteCallback refresh_map_palette_
void DrawMusicTab(int current_map)
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)
zelda3::Overworld * overworld_
void ForceRefreshGraphics(int map_index)
void RefreshSiblingMapGraphics(int map_index, bool include_self=false)
void DrawTileGraphicsTab(int current_map)
ForceRefreshGraphicsCallback force_refresh_graphics_
void DrawQuickAccessPopup()
std::string GetOverlayDescription(uint16_t overlay_id)
void DrawSimplifiedMapSettings(int ¤t_world, int ¤t_map, bool ¤t_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 ¤t_mode)
void DrawOverlayControls(int current_map, bool &show_overlay_preview)
absl::Status RefreshMapPalette()
void DrawGraphicsPopup(int current_map, int game_state)
RAII timer for automatic timing management.
constexpr uint16_t snes() const
Get SNES 15-bit color.
Modern, robust canvas for drawing and manipulating graphics.
void set_scrolling(ImVec2 scroll)
auto global_scale() const
void ClearContextMenuItems()
void AddContextMenuItem(const gui::CanvasMenuItem &item)
void set_global_scale(float scale)
static float GetButtonPadding()
static float GetStandardSpacing()
auto overworld_map(int i) const
auto mutable_overworld_map(int i)
absl::Status ConfigureMultiAreaMap(int parent_index, AreaSizeEnum size)
Configure a multi-area map structure (Large/Wide/Tall)
#define ICON_MD_GRID_VIEW
#define ICON_MD_LOCK_OPEN
#define ICON_MD_LIGHTBULB
#define ICON_MD_PHOTO_SIZE_SELECT_LARGE
#define ICON_MD_OFFLINE_BOLT
#define ICON_MD_PLAY_ARROW
#define ICON_MD_OPEN_IN_FULL
#define ICON_MD_VISIBILITY
#define ICON_MD_FORMAT_COLOR_FILL
#define ICON_MD_DOOR_BACK
#define ICON_MD_AUTO_FIX_HIGH
#define ICON_MD_MUSIC_NOTE
#define ICON_MD_ASPECT_RATIO
#define ICON_MD_ANIMATION
#define ICON_MD_DOOR_FRONT
#define ICON_MD_HELP_OUTLINE
#define ICON_MD_ADD_LOCATION
#define ICON_MD_EDIT_NOTE
#define ICON_MD_OPEN_IN_NEW
#define ICON_MD_PEST_CONTROL_RODENT
#define ICON_MD_CONTENT_COPY
#define ICON_MD_COLOR_LENS
#define HOVER_HINT(string)
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
constexpr float kTableButtonGraphics
constexpr const char * kGameStateNames[]
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)
ImVec4 ConvertSnesColorToImVec4(const gfx::SnesColor &color)
Convert SnesColor to standard ImVec4 for display.
bool InputHexWordCustom(const char *label, uint16_t *data, float input_width)
gfx::SnesColor ConvertImVec4ToSnesColor(const ImVec4 &color)
Convert standard ImVec4 to SnesColor.
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
constexpr int OverworldCustomAreaSpecificBGEnabled
constexpr int kNumOverworldMaps
constexpr int kOverworldMusicBeginning
constexpr int OverworldCustomASMHasBeenApplied
constexpr int kOverworldMusicAgahnim
constexpr int kOverworldMusicMasterSword
constexpr int kOverworldMusicZelda
constexpr int OverworldCustomSubscreenOverlayEnabled
constexpr int OverworldCustomAreaSpecificBGPalette
constexpr int OverworldCustomSubscreenOverlayArray
Main namespace for the application.
SNES color in 15-bit RGB format (BGR555)