yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_toolbar.cc
Go to the documentation of this file.
2#include "util/i18n/tr.h"
3
4#include <algorithm>
5#include <array>
6#include <cstring>
7#include <string>
8
9#include "absl/strings/str_format.h"
10#include "app/editor/editor.h"
15#include "app/gui/core/input.h"
19#include "core/project.h"
20#include "zelda3/common.h"
22
23namespace yaze::editor {
24
25using ImGui::BeginTable;
26using ImGui::TableNextColumn;
27
28namespace {
29
31 std::string title;
32 std::string type;
33 int id = 0;
34 int hex_width = 2;
35};
36
37std::string FormatResourceId(int id, int width) {
38 return width <= 2 ? absl::StrFormat("0x%02X", id)
39 : absl::StrFormat("0x%04X", id);
40}
41
42} // namespace
43
44void OverworldToolbar::Draw(int& current_world, int& current_map,
45 bool& current_map_lock, EditingMode& current_mode,
46 EntityEditMode& entity_edit_mode,
47 WorkspaceWindowManager* window_manager,
48 bool has_selection, bool scratch_has_data, Rom* rom,
49 zelda3::Overworld* overworld,
50 project::YazeProject* project, int game_state,
51 SharedClipboard* shared_clipboard) {
52 if (!overworld || !overworld->is_loaded() || !window_manager || !rom)
53 return;
54
55 const zelda3::OverworldMap* map = overworld->overworld_map(current_map);
56 if (!map) {
57 return;
58 }
59 const auto metadata = BuildOverworldMapMetadata(*overworld, rom, project,
60 current_map, game_state);
61 const auto apply_property_edit =
62 [this](const OverworldPropertyEdit& edit) -> absl::Status {
64 return absl::FailedPreconditionError(
65 "Overworld property edit callback is not configured");
66 }
67 return on_apply_property_edit(edit);
68 };
69
70 gui::StyleVarGuard toolbar_style_guard(
71 {{ImGuiStyleVar_FramePadding, ImVec2(6.0f, 5.0f)},
72 {ImGuiStyleVar_CellPadding, ImVec2(6.0f, 5.0f)}});
73 ImGui::PushID("OverworldToolbar");
74
75 // Simplified canvas toolbar - Navigation and Mode controls
76 if (BeginTable("OverworldCanvasToolbar", 8,
77 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchProp,
78 ImVec2(0, 0), -1)) {
79 ImGui::TableSetupColumn("World", ImGuiTableColumnFlags_WidthFixed,
81 ImGui::TableSetupColumn("Map", ImGuiTableColumnFlags_WidthFixed,
83 ImGui::TableSetupColumn("Area Size", ImGuiTableColumnFlags_WidthFixed,
85 ImGui::TableSetupColumn("Lock", ImGuiTableColumnFlags_WidthFixed,
87 ImGui::TableSetupColumn("Mode", ImGuiTableColumnFlags_WidthFixed,
88 124.0f); // Mouse/Brush/Fill
89 ImGui::TableSetupColumn("Context", ImGuiTableColumnFlags_WidthStretch);
90 ImGui::TableSetupColumn("Panels", ImGuiTableColumnFlags_WidthStretch);
91 ImGui::TableSetupColumn("Sidebar", ImGuiTableColumnFlags_WidthFixed, 44.0f);
92
93 TableNextColumn();
94 const char* world_buttons[] = {"LW", "DW", "SW"};
95 ImGui::PushID("WorldButtons");
96 for (int world_index = 0; world_index < 3; ++world_index) {
97 if (world_index > 0) {
98 ImGui::SameLine(0, 2);
99 }
100 if (gui::ToggleButton(world_buttons[world_index],
101 current_world == world_index,
102 ImVec2(30.0f, 0.0f))) {
103 if (on_world_changed) {
104 on_world_changed(world_index);
105 } else {
106 current_world = world_index;
107 int local_map = current_map & 0x3F;
108 const int world_start = world_index * 0x40;
109 const int maps_remaining = zelda3::kNumOverworldMaps - world_start;
110 if (maps_remaining > 0) {
111 if (local_map >= maps_remaining) {
112 local_map = maps_remaining - 1;
113 }
114 current_map = world_start + local_map;
115 }
116 }
117 }
118 if (ImGui::IsItemHovered()) {
119 ImGui::SetTooltip("%s", kWorldNames[world_index]);
120 }
121 }
122 ImGui::PopID();
123
124 TableNextColumn();
125 ImGui::TextUnformatted(metadata.map_id_label.c_str());
126 if (ImGui::IsItemHovered()) {
127 ImGui::SetTooltip("%s", metadata.map_title.c_str());
128 }
129
130 TableNextColumn();
131 // Use centralized version detection
132 auto rom_version = zelda3::OverworldVersionHelper::GetVersion(*rom);
133
134 // ALL ROMs support Small/Large. Only v3+ supports Wide/Tall.
135 int current_area_size = static_cast<int>(map->area_size());
136 ImGui::SetNextItemWidth(kComboAreaSizeWidth);
137
139 // v3+ ROM: Show all 4 area size options
140 if (ImGui::Combo("##ToolbarAreaSize", &current_area_size, kAreaSizeNames,
141 4)) {
142 auto status =
144 ? on_apply_property_edit({current_map,
146 current_area_size})
147 : overworld->ConfigureMultiAreaMap(
148 current_map,
149 static_cast<zelda3::AreaSizeEnum>(current_area_size));
150 if (status.ok() && !on_apply_property_edit) {
153 if (on_refresh_map)
155 }
156 }
157 } else {
158 // Vanilla/v1/v2 ROM: Show only Small/Large (first 2 options)
159 const char* limited_names[] = {"Small (1x1)", "Large (2x2)"};
160 int limited_size = (current_area_size == 0 || current_area_size == 1)
161 ? current_area_size
162 : 0;
163
164 if (ImGui::Combo("##ToolbarAreaSize", &limited_size, limited_names, 2)) {
165 // limited_size is 0 (Small) or 1 (Large)
166 auto size = (limited_size == 1) ? zelda3::AreaSizeEnum::LargeArea
168 auto status = on_apply_property_edit
171 0, static_cast<int>(size)})
172 : overworld->ConfigureMultiAreaMap(current_map, size);
173 if (status.ok() && !on_apply_property_edit) {
176 if (on_refresh_map)
178 }
179 }
180
181 if (rom_version == zelda3::OverworldVersion::kVanilla ||
183 HOVER_HINT("Small (1x1) and Large (2x2) maps. Wide/Tall require v3+");
184 }
185 }
186
187 TableNextColumn();
189 current_map_lock ? ICON_MD_LOCK : ICON_MD_LOCK_OPEN,
190 current_map_lock ? "Unpin Map" : "Pin Map")) {
191 current_map_lock = !current_map_lock;
192 }
193
194 TableNextColumn();
195 // Mode Controls
196 {
199 "Mouse Mode (1)\nNavigate, pan, and manage entities",
200 current_mode == EditingMode::MOUSE)) {
201 current_mode = EditingMode::MOUSE;
202 }
203
204 ImGui::SameLine(0, 2);
207 "Brush Mode (2/B)\nDraw tiles on the map\nRight-click or I to "
208 "sample tile16 under cursor",
209 current_mode == EditingMode::DRAW_TILE)) {
210 current_mode = EditingMode::DRAW_TILE;
211 }
212
213 ImGui::SameLine(0, 2);
216 "Fill Screen Mode (F)\nFill the 32x32 screen under the cursor "
217 "with the selected tile\nRight-click or I to sample tile16 under "
218 "cursor",
219 current_mode == EditingMode::FILL_TILE)) {
220 current_mode = EditingMode::FILL_TILE;
221 }
222 }
223
224 TableNextColumn();
225 // Entity status / ROM version plus high-value selected-map metadata.
226 const auto& theme = AgentUI::GetTheme();
227 const float context_width = ImGui::GetContentRegionAvail().x;
228 const bool show_entity_context = entity_edit_mode != EntityEditMode::NONE;
229 const bool show_overlay_toggle = context_width >= 132.0f;
230 const bool has_metadata_clipboard =
231 shared_clipboard && shared_clipboard->has_overworld_map_metadata &&
232 shared_clipboard->overworld_map_metadata.valid;
233
234 ImVec4 version_color = theme.status_inactive;
235 bool show_upgrade = false;
236
237 switch (rom_version) {
239 version_color = theme.text_warning_yellow;
240 show_upgrade = true;
241 break;
243 version_color = theme.status_active;
244 break;
246 version_color = theme.status_active;
247 break;
249 version_color = theme.status_success;
250 break;
251 default:
252 break;
253 }
254 const float map_summary_min_width =
255 show_upgrade ? 400.0f : (show_entity_context ? 340.0f : 280.0f);
256 const bool show_map_summary = context_width >= map_summary_min_width;
257
258 bool wrote_metadata_item = false;
259 if (show_entity_context) {
260 const char* entity_icon = "";
261 const char* entity_label = "";
262 switch (entity_edit_mode) {
264 entity_icon = ICON_MD_DOOR_FRONT;
265 entity_label = "Entrances";
266 break;
268 entity_icon = ICON_MD_DOOR_BACK;
269 entity_label = "Exits";
270 break;
272 entity_icon = ICON_MD_GRASS;
273 entity_label = "Items";
274 break;
276 entity_icon = ICON_MD_PEST_CONTROL_RODENT;
277 entity_label = "Sprites";
278 break;
280 entity_icon = ICON_MD_ADD_LOCATION;
281 entity_label = "Transports";
282 break;
284 entity_icon = ICON_MD_MUSIC_NOTE;
285 entity_label = "Music";
286 break;
287 default:
288 break;
289 }
290 ImGui::TextColored(theme.selection_secondary, "%s %s", entity_icon,
291 entity_label);
292 wrote_metadata_item = true;
293 }
294
295 if (wrote_metadata_item) {
296 ImGui::SameLine();
297 }
298 ImGui::TextColored(version_color, ICON_MD_INFO " %s",
299 metadata.version_label.c_str());
300 wrote_metadata_item = true;
301 if (ImGui::IsItemHovered()) {
302 ImGui::SetTooltip(
303 tr("ROM version determines available overworld features.\n"
304 "v2+: Custom BG colors, main palettes\n"
305 "v3+: Wide/Tall maps, custom tile GFX, animated GFX"));
306 }
307
308 if (has_metadata_clipboard && context_width >= 440.0f) {
309 ImGui::SameLine();
310 ImGui::TextColored(theme.text_secondary_gray, ICON_MD_CONTENT_PASTE " %s",
312 shared_clipboard->overworld_map_metadata.scope));
313 if (ImGui::IsItemHovered()) {
314 ImGui::SetTooltip(
315 tr("%s\nPaste from the canvas context menu onto the hovered map."),
317 shared_clipboard->overworld_map_metadata)
318 .c_str());
319 }
320 wrote_metadata_item = true;
321 }
322
323 if (show_map_summary) {
324 ImGui::SameLine();
325 ImGui::TextDisabled("%s | %s | %s | %s", metadata.map_name.c_str(),
326 metadata.area_gfx_label.c_str(),
327 metadata.area_palette_label.c_str(),
328 metadata.message_label.c_str());
329 if (ImGui::IsItemHovered()) {
330 ImGui::SetTooltip("%s\n%s\n%s\n%s\n%s\n%s", metadata.map_title.c_str(),
331 metadata.area_size_label.c_str(),
332 metadata.parent_label.c_str(),
333 metadata.sprite_gfx_label.c_str(),
334 metadata.sprite_palette_label.c_str(),
335 metadata.music_label.c_str());
336 }
337 wrote_metadata_item = true;
338
339 ImGui::SameLine();
340 static std::array<char, 128> rename_label_buffer{};
341 static int rename_map_id = -1;
342 static std::string rename_error;
343 ImGui::BeginDisabled(project == nullptr);
345 ICON_MD_EDIT, project ? "Rename selected map label in project"
346 : "Open a project to rename map labels")) {
347 rename_map_id = current_map;
348 rename_error.clear();
349 std::strncpy(rename_label_buffer.data(), metadata.map_name.c_str(),
350 rename_label_buffer.size() - 1);
351 rename_label_buffer[rename_label_buffer.size() - 1] = '\0';
352 ImGui::OpenPopup("RenameOverworldMapLabel");
353 }
354 ImGui::EndDisabled();
355
356 if (ImGui::BeginPopup("RenameOverworldMapLabel")) {
357 ImGui::Text(tr("%s Map Label"), ICON_MD_LABEL);
358 ImGui::TextDisabled(tr("Map 0x%02X"), rename_map_id);
359 ImGui::SetNextItemWidth(260.0f);
360 ImGui::InputText("##OverworldMapLabel", rename_label_buffer.data(),
361 rename_label_buffer.size());
362 if (ImGui::Button(ICON_MD_CHECK " Apply")) {
363 auto status =
365 ? on_rename_resource_label("overworld_map", rename_map_id,
366 rename_label_buffer.data())
367 : RenameProjectResourceLabel(project, "overworld_map",
368 rename_map_id,
369 rename_label_buffer.data());
370 if (status.ok()) {
371 ImGui::CloseCurrentPopup();
372 } else {
373 rename_error = std::string(status.message());
374 }
375 }
376 ImGui::SameLine();
377 if (ImGui::Button(ICON_MD_CLEAR " Clear")) {
378 auto status =
380 ? on_rename_resource_label("overworld_map", rename_map_id, "")
381 : RenameProjectResourceLabel(project, "overworld_map",
382 rename_map_id, "");
383 if (status.ok()) {
384 rename_label_buffer[0] = '\0';
385 ImGui::CloseCurrentPopup();
386 } else {
387 rename_error = std::string(status.message());
388 }
389 }
390 if (!rename_error.empty()) {
391 ImGui::TextWrapped("%s", rename_error.c_str());
392 }
393 ImGui::EndPopup();
394 }
395
396 ImGui::SameLine();
399 "Edit selected map metadata\nGraphics, palettes, message, and "
400 "music")) {
401 ImGui::OpenPopup("OverworldToolbarMetadataEditor");
402 }
403 if (ImGui::BeginPopup("OverworldToolbarMetadataEditor")) {
404 static std::string metadata_error;
405 static std::array<char, 128> resource_label_buffer{};
406 static std::string resource_label_type;
407 static std::string resource_label_title;
408 static std::string resource_label_error;
409 static int resource_label_id = -1;
410 static int resource_label_hex_width = 2;
411 const auto apply_toolbar_edit = [&](const OverworldPropertyEdit& edit) {
412 const auto status = apply_property_edit(edit);
413 if (status.ok()) {
414 metadata_error.clear();
415 } else {
416 metadata_error = std::string(status.message());
417 }
418 };
419 const auto begin_resource_label_edit =
420 [&](const ToolbarResourceLabelTarget& target) {
421 resource_label_title = target.title;
422 resource_label_type = target.type;
423 resource_label_id = target.id;
424 resource_label_hex_width = target.hex_width;
425 resource_label_error.clear();
426 const std::string current_label =
427 GetProjectResourceLabel(project, target.type, target.id);
428 std::strncpy(resource_label_buffer.data(), current_label.c_str(),
429 resource_label_buffer.size() - 1);
430 resource_label_buffer[resource_label_buffer.size() - 1] = '\0';
431 ImGui::OpenPopup("OverworldMetadataResourceLabel");
432 };
433 auto apply_resource_label = [&](const std::string& label) {
434 auto status =
436 ? on_rename_resource_label(resource_label_type,
437 resource_label_id, label)
438 : RenameProjectResourceLabel(project, resource_label_type,
439 resource_label_id, label);
440 if (status.ok()) {
441 resource_label_error.clear();
442 ImGui::CloseCurrentPopup();
443 } else {
444 resource_label_error = std::string(status.message());
445 }
446 };
447
448 ImGui::Text(tr("%s Map 0x%02X Metadata"), ICON_MD_TUNE, current_map);
449 ImGui::Separator();
450
451 if (ImGui::BeginTable("ToolbarMetadataEditor", 2,
452 ImGuiTableFlags_SizingFixedFit)) {
453 ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed,
454 142.0f);
455 ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthFixed,
456 108.0f);
457
458 TableNextColumn();
459 ImGui::TextUnformatted(tr("Area GFX"));
460 TableNextColumn();
461 uint8_t area_gfx = map->area_graphics();
462 if (gui::InputHexByte("##ToolbarMetaAreaGfx", &area_gfx, 96.0f)) {
463 apply_toolbar_edit({current_map,
465 area_gfx});
466 }
467
468 TableNextColumn();
469 ImGui::TextUnformatted(tr("Area Palette"));
470 TableNextColumn();
471 uint8_t area_palette = map->area_palette();
472 if (gui::InputHexByte("##ToolbarMetaAreaPalette", &area_palette,
473 96.0f)) {
474 apply_toolbar_edit({current_map,
476 area_palette});
477 }
478
480 rom_version)) {
481 TableNextColumn();
482 ImGui::TextUnformatted(tr("Main Palette"));
483 TableNextColumn();
484 uint8_t main_palette = map->main_palette();
485 if (gui::InputHexByte("##ToolbarMetaMainPalette", &main_palette,
486 96.0f)) {
487 apply_toolbar_edit({current_map,
489 main_palette});
490 }
491 }
492
493 TableNextColumn();
494 ImGui::TextUnformatted(tr("Sprite GFX"));
495 TableNextColumn();
496 uint8_t sprite_gfx = map->sprite_graphics(game_state);
497 if (gui::InputHexByte("##ToolbarMetaSpriteGfx", &sprite_gfx, 96.0f)) {
498 apply_toolbar_edit({current_map,
500 game_state, sprite_gfx});
501 }
502
503 TableNextColumn();
504 ImGui::TextUnformatted(tr("Sprite Palette"));
505 TableNextColumn();
506 uint8_t sprite_palette = map->sprite_palette(game_state);
507 if (gui::InputHexByte("##ToolbarMetaSpritePalette", &sprite_palette,
508 96.0f)) {
509 apply_toolbar_edit({current_map,
511 game_state, sprite_palette});
512 }
513
515 rom_version)) {
516 TableNextColumn();
517 ImGui::TextUnformatted(tr("Animated GFX"));
518 TableNextColumn();
519 uint8_t animated_gfx = map->animated_gfx();
520 if (gui::InputHexByte("##ToolbarMetaAnimatedGfx", &animated_gfx,
521 96.0f)) {
522 apply_toolbar_edit({current_map,
524 animated_gfx});
525 }
526 }
527
528 TableNextColumn();
529 ImGui::TextUnformatted(tr("Message"));
530 TableNextColumn();
531 uint16_t message_id = map->message_id();
532 if (gui::InputHexWord("##ToolbarMetaMessage", &message_id, 96.0f)) {
533 apply_toolbar_edit({current_map, OverworldPropertyField::kMessageId,
534 0, message_id});
535 }
536
537 for (int i = 0; i < 4; ++i) {
538 TableNextColumn();
539 ImGui::Text(tr("Music %d"), i);
540 TableNextColumn();
541 uint8_t music = map->area_music(i);
542 const std::string id = absl::StrFormat("##ToolbarMetaMusic%d", i);
543 if (gui::InputHexByte(id.c_str(), &music, 96.0f)) {
544 apply_toolbar_edit(
545 {current_map, OverworldPropertyField::kMusic, i, music});
546 }
547 }
548
549 ImGui::EndTable();
550 }
551
552 ImGui::Separator();
553 ImGui::Text(tr("%s Project Labels"), ICON_MD_LABEL);
554 ImGui::BeginDisabled(project == nullptr);
555 if (ImGui::BeginTable(
556 "ToolbarMetadataProjectLabels", 4,
557 ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
558 ImGui::TableSetupColumn("Resource", ImGuiTableColumnFlags_WidthFixed,
559 112.0f);
560 ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed,
561 62.0f);
562 ImGui::TableSetupColumn("Label", ImGuiTableColumnFlags_WidthFixed,
563 160.0f);
564 ImGui::TableSetupColumn("Edit", ImGuiTableColumnFlags_WidthFixed,
565 36.0f);
566
567 auto draw_label_row = [&](const ToolbarResourceLabelTarget& target) {
568 TableNextColumn();
569 ImGui::TextUnformatted(target.title.c_str());
570 TableNextColumn();
571 ImGui::TextDisabled(
572 "%s", FormatResourceId(target.id, target.hex_width).c_str());
573 TableNextColumn();
574 const std::string project_label =
575 GetProjectResourceLabel(project, target.type, target.id);
576 if (project_label.empty()) {
577 ImGui::TextDisabled(tr("default"));
578 } else {
579 ImGui::TextUnformatted(project_label.c_str());
580 }
581 TableNextColumn();
582 const std::string row_id =
583 absl::StrFormat("Label%s%d", target.type, target.id);
584 ImGui::PushID(row_id.c_str());
585 if (ImGui::SmallButton(ICON_MD_EDIT)) {
586 begin_resource_label_edit(target);
587 }
588 if (ImGui::IsItemHovered()) {
589 ImGui::SetTooltip(
590 tr("Rename %s %s in the open project"), target.title.c_str(),
591 FormatResourceId(target.id, target.hex_width).c_str());
592 }
593 ImGui::PopID();
594 };
595
596 draw_label_row({"Area GFX", "graphics", map->area_graphics()});
597 draw_label_row({absl::StrFormat("Sprite GFX %d", game_state),
598 "graphics", map->sprite_graphics(game_state)});
600 rom_version)) {
601 draw_label_row({"Animated GFX", "graphics", map->animated_gfx()});
602 }
603 draw_label_row(
604 {"Area Palette", "overworld_area_palette", map->area_palette()});
606 rom_version)) {
607 draw_label_row({"Main Palette", "overworld_main_palette",
608 map->main_palette()});
609 }
610 draw_label_row({"Sprite Palette", "overworld_sprite_palette",
611 map->sprite_palette(game_state)});
612 draw_label_row(
613 {"Message", "message", map->message_id(), /*hex_width=*/4});
614 for (int i = 0; i < 4; ++i) {
615 draw_label_row({absl::StrFormat("Music %d", i), "overworld_music",
616 map->area_music(i)});
617 }
618
619 ImGui::EndTable();
620 }
621 ImGui::EndDisabled();
622 if (!project) {
623 ImGui::TextDisabled(tr("Open a project to store metadata labels."));
624 }
625
626 if (ImGui::BeginPopup("OverworldMetadataResourceLabel")) {
627 ImGui::Text("%s %s", ICON_MD_LABEL, resource_label_title.c_str());
628 ImGui::TextDisabled("%s", FormatResourceId(resource_label_id,
629 resource_label_hex_width)
630 .c_str());
631 ImGui::SetNextItemWidth(260.0f);
632 ImGui::InputText("##OverworldMetadataResourceLabelInput",
633 resource_label_buffer.data(),
634 resource_label_buffer.size());
635 if (ImGui::Button(ICON_MD_CHECK " Apply")) {
636 apply_resource_label(resource_label_buffer.data());
637 }
638 ImGui::SameLine();
639 if (ImGui::Button(ICON_MD_CLEAR " Clear")) {
640 apply_resource_label("");
641 }
642 if (!resource_label_error.empty()) {
643 ImGui::TextWrapped("%s", resource_label_error.c_str());
644 }
645 ImGui::EndPopup();
646 }
647
648 if (!metadata_error.empty()) {
649 ImGui::Separator();
650 ImGui::TextWrapped("%s", metadata_error.c_str());
651 }
652 ImGui::EndPopup();
653 }
654 }
655
656 if (show_upgrade && on_upgrade_rom_version) {
657 if (wrote_metadata_item) {
658 ImGui::SameLine();
659 }
660 if (gui::PrimaryButton(ICON_MD_UPGRADE " Upgrade")) {
661 on_upgrade_rom_version(3); // Upgrade to v3
662 }
664 "Upgrade ROM to ZSCustomOverworld v3\n"
665 "Enables all advanced features");
666 } else if (!show_map_summary && show_overlay_toggle &&
668 const bool overlay_preview_enabled = is_overlay_preview_enabled();
669 if (wrote_metadata_item) {
670 ImGui::SameLine();
671 }
673 overlay_preview_enabled
674 ? "Hide overlay preview"
675 : "Show overlay preview",
676 overlay_preview_enabled)) {
678 }
679 }
680
681 TableNextColumn();
682 // Panel Toggle Controls - using WorkspaceWindowManager for visibility
683 const size_t session_id = window_manager->GetActiveSessionId();
684 const float panel_width = ImGui::GetContentRegionAvail().x;
685 const bool compact_panel_controls = panel_width < 320.0f;
686 const auto toggle_window = [&](const char* panel_id) {
687 window_manager->ToggleWindow(session_id, panel_id);
688 };
689 const auto popup_toggle_item = [&](const char* label, const char* panel_id,
690 const char* shortcut = nullptr) {
691 const bool open = window_manager->IsWindowOpen(panel_id);
692 if (ImGui::MenuItem(label, shortcut, open)) {
693 toggle_window(panel_id);
694 }
695 };
696 {
697 gui::StyleVarGuard panel_spacing_guard(ImGuiStyleVar_ItemSpacing,
698 ImVec2(4, 0));
699
700 if (compact_panel_controls) {
702 ICON_MD_APPS, "Overworld Windows\nOpen panel toggle menu")) {
703 ImGui::OpenPopup("OverworldWindowsPopup");
704 }
705
706 if (ImGui::BeginPopup("OverworldWindowsPopup")) {
707 popup_toggle_item("Tile16 Editor", OverworldPanelIds::kTile16Editor,
708 "Ctrl+T");
709 popup_toggle_item("Tile16 Selector",
711 popup_toggle_item("Tile8 Selector",
713 popup_toggle_item("Area Graphics", OverworldPanelIds::kAreaGraphics);
714 popup_toggle_item("GFX Groups", OverworldPanelIds::kGfxGroups);
715 popup_toggle_item("Usage Statistics", OverworldPanelIds::kUsageStats);
716 popup_toggle_item("Item List", OverworldPanelIds::kItemList,
717 "Ctrl+Shift+I");
718 popup_toggle_item("Scratch Workspace",
720 ImGui::EndPopup();
721 }
722 } else {
723 // Tile16 Editor toggle (Ctrl+T)
724 if (gui::ToolbarIconButton(ICON_MD_EDIT, "Tile16 Editor (Ctrl+T)",
725 window_manager->IsWindowOpen(
728 }
729
730 ImGui::SameLine();
731 if (gui::ToolbarIconButton(ICON_MD_GRID_ON, "Tile16 Selector",
732 window_manager->IsWindowOpen(
735 }
736
737 ImGui::SameLine();
738 if (gui::ToolbarIconButton(ICON_MD_GRID_VIEW, "Tile8 Selector",
739 window_manager->IsWindowOpen(
742 }
743
744 ImGui::SameLine();
745 if (gui::ToolbarIconButton(ICON_MD_IMAGE, "Area Graphics",
746 window_manager->IsWindowOpen(
749 }
750
751 ImGui::SameLine();
753 ICON_MD_LAYERS, "GFX Groups",
755 toggle_window(OverworldPanelIds::kGfxGroups);
756 }
757
758 ImGui::SameLine();
760 ICON_MD_ANALYTICS, "Usage Statistics",
762 toggle_window(OverworldPanelIds::kUsageStats);
763 }
764
765 ImGui::SameLine();
768 "Overworld Item List (Ctrl+Shift+I)\nFilter/select items and "
769 "use "
770 "duplicate/nudge shortcuts",
771 window_manager->IsWindowOpen(OverworldPanelIds::kItemList))) {
772 toggle_window(OverworldPanelIds::kItemList);
773 }
774
775 ImGui::SameLine();
776 if (gui::ToolbarIconButton(ICON_MD_AUTO_FIX_HIGH, "Scratch Workspace",
777 window_manager->IsWindowOpen(
780 }
781 }
782 }
783
784 TableNextColumn();
785 // Sidebar Toggle (Map Properties)
787 ICON_MD_TUNE, "Toggle Map Properties Sidebar",
789 window_manager->ToggleWindow(window_manager->GetActiveSessionId(),
791 }
792
793 ImGui::EndTable();
794 }
795 ImGui::PopID();
796}
797
798} // namespace yaze::editor
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:28
std::function< void()> on_refresh_map
std::function< void()> on_refresh_graphics
std::function< void(int)> on_upgrade_rom_version
void Draw(int &current_world, int &current_map, bool &current_map_lock, EditingMode &current_mode, EntityEditMode &entity_edit_mode, WorkspaceWindowManager *window_manager, bool has_selection, bool scratch_has_data, Rom *rom, zelda3::Overworld *overworld, project::YazeProject *project, int game_state, SharedClipboard *shared_clipboard=nullptr)
std::function< bool()> is_overlay_preview_enabled
std::function< void(int)> on_world_changed
std::function< absl::Status(const std::string &, int, const std::string &) on_rename_resource_label)
std::function< void()> on_toggle_overlay_preview
std::function< absl::Status(const OverworldPropertyEdit &) on_apply_property_edit)
Central registry for all editor cards with session awareness and dependency injection.
bool IsWindowOpen(size_t session_id, const std::string &base_window_id) const
bool ToggleWindow(size_t session_id, const std::string &base_window_id)
RAII guard for ImGui style vars.
Definition style_guard.h:68
Represents a single Overworld map screen.
auto sprite_graphics(int i) const
auto area_music(int i) const
auto sprite_palette(int i) const
static bool SupportsCustomBGColors(OverworldVersion version)
Check if ROM supports custom background colors per area (v2+)
static OverworldVersion GetVersion(const Rom &rom)
Detect ROM version from ASM marker byte.
static bool SupportsAreaEnum(OverworldVersion version)
Check if ROM supports area enum system (v3+ only)
static bool SupportsAnimatedGFX(OverworldVersion version)
Check if ROM supports animated GFX selection (v3+)
Represents the full Overworld data, light and dark world.
Definition overworld.h:389
auto is_loaded() const
Definition overworld.h:728
auto overworld_map(int i) const
Definition overworld.h:662
absl::Status ConfigureMultiAreaMap(int parent_index, AreaSizeEnum size)
Configure a multi-area map structure (Large/Wide/Tall)
Definition overworld.cc:406
#define ICON_MD_GRID_VIEW
Definition icons.h:897
#define ICON_MD_APPS
Definition icons.h:168
#define ICON_MD_INFO
Definition icons.h:993
#define ICON_MD_UPGRADE
Definition icons.h:2047
#define ICON_MD_LOCK_OPEN
Definition icons.h:1142
#define ICON_MD_LOCK
Definition icons.h:1140
#define ICON_MD_CHECK
Definition icons.h:397
#define ICON_MD_DRAW
Definition icons.h:625
#define ICON_MD_TUNE
Definition icons.h:2022
#define ICON_MD_LABEL
Definition icons.h:1053
#define ICON_MD_VISIBILITY
Definition icons.h:2101
#define ICON_MD_GRASS
Definition icons.h:891
#define ICON_MD_FORMAT_COLOR_FILL
Definition icons.h:830
#define ICON_MD_EDIT
Definition icons.h:645
#define ICON_MD_DOOR_BACK
Definition icons.h:612
#define ICON_MD_AUTO_FIX_HIGH
Definition icons.h:218
#define ICON_MD_MUSIC_NOTE
Definition icons.h:1264
#define ICON_MD_CONTENT_PASTE
Definition icons.h:467
#define ICON_MD_GRID_ON
Definition icons.h:896
#define ICON_MD_LIST
Definition icons.h:1094
#define ICON_MD_LAYERS
Definition icons.h:1068
#define ICON_MD_DOOR_FRONT
Definition icons.h:613
#define ICON_MD_IMAGE
Definition icons.h:982
#define ICON_MD_CLEAR
Definition icons.h:416
#define ICON_MD_ADD_LOCATION
Definition icons.h:100
#define ICON_MD_MOUSE
Definition icons.h:1251
#define ICON_MD_PEST_CONTROL_RODENT
Definition icons.h:1430
#define ICON_MD_ANALYTICS
Definition icons.h:154
#define HOVER_HINT(string)
Definition macro.h:24
const AgentUITheme & GetTheme()
Editors are the view controllers for the application.
absl::Status RenameProjectResourceLabel(project::YazeProject *project, const std::string &type, int id, const std::string &label)
constexpr const char * kAreaSizeNames[]
constexpr float kTableColumnWorld
constexpr const char * kWorldNames[]
const char * OverworldMapMetadataClipboardScopeName(OverworldMapMetadataClipboardScope scope)
constexpr float kTableColumnMap
OverworldMapMetadata BuildOverworldMapMetadata(const zelda3::Overworld &overworld, const Rom *rom, const project::YazeProject *project, int map_id, int game_state)
constexpr float kTableColumnAreaSize
std::string GetProjectResourceLabel(const project::YazeProject *project, const std::string &type, int id)
std::string DescribeOverworldMapMetadataClipboard(const OverworldMapMetadataClipboard &clipboard)
constexpr float kComboAreaSizeWidth
constexpr float kTableColumnLock
bool PrimaryButton(const char *label, const ImVec2 &size, const char *panel_id, const char *anim_id)
Draw a primary action button (accented color).
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
Definition input.cc:355
bool ToggleButton(const char *label, bool active, const ImVec2 &size)
bool ToolbarIconButton(const char *icon, const char *tooltip, bool is_active)
Convenience wrapper for toolbar-sized icon buttons.
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:376
constexpr int kNumOverworldMaps
Definition common.h:85
AreaSizeEnum
Area size enumeration for v3+ ROMs.
@ kZSCustomV2
Parent system, BG colors, main palettes.
@ kZSCustomV1
Basic features, expanded pointers.
@ kVanilla
0xFF in ROM, no ZScream ASM applied
@ kZSCustomV3
Area enum, wide/tall areas, all features.
static constexpr const char * kMapProperties
static constexpr const char * kTile8Selector
static constexpr const char * kAreaGraphics
static constexpr const char * kItemList
static constexpr const char * kScratchSpace
static constexpr const char * kTile16Editor
static constexpr const char * kTile16Selector
static constexpr const char * kGfxGroups
static constexpr const char * kUsageStats
OverworldMapMetadataClipboard overworld_map_metadata
Definition editor.h:123
Modern project structure with comprehensive settings consolidation.
Definition project.h:172