yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_sidebar.cc
Go to the documentation of this file.
3#include "util/i18n/tr.h"
4
5#include <algorithm>
6#include <cfloat>
7#include <cstring>
8
9#include "absl/strings/str_format.h"
12#include "app/gui/core/icons.h"
13#include "app/gui/core/input.h"
16#include "imgui/imgui.h"
17#include "zelda3/common.h"
20
21namespace yaze {
22namespace editor {
23
24namespace {
25
26constexpr float kFieldLabelWidth = 118.0f;
27constexpr const char* kLabelPopupId = "OverworldPropertyLabelPopup";
28
29// Music bytes are indexed by story progress, not by the preview game state.
30constexpr const char* kMusicLabels[] = {"Music: start", "Music: Zelda saved",
31 "Music: Master Sword",
32 "Music: Agahnim"};
33constexpr const char* kMusicTooltips[] = {
34 "Track before rescuing Zelda",
35 "Track after rescuing Zelda from Hyrule Castle",
36 "Track after drawing the Master Sword", "Track after defeating Agahnim"};
37
38std::string FormatId(int id, int width) {
39 return width <= 2 ? absl::StrFormat("0x%02X", id)
40 : absl::StrFormat("0x%04X", id);
41}
42
43} // namespace
44
46 MapPropertiesSystem* map_properties_system)
47 : overworld_(overworld),
48 rom_(rom),
49 map_properties_system_(map_properties_system) {}
50
51void OverworldSidebar::Draw(int& current_world, int& current_map,
52 bool& current_map_lock, int& game_state,
53 bool& show_custom_bg_color_editor,
54 bool& show_overlay_editor,
55 project::YazeProject* project) {
57 return;
58 }
59 project_ = project;
60
61 if (ImGui::BeginChild("OverworldSidebar", ImVec2(0, 0), false,
62 ImGuiWindowFlags_None)) {
63 ImGui::PushID("OverworldSidebar");
64 if (!overworld_->is_lyra_preview() && project &&
65 !project->lyra_terrain_file.empty() && current_map >= 0xA0 &&
66 current_map < 0xC0) {
67 const auto metadata = BuildOverworldMapMetadata(
68 *overworld_, rom_, project, current_map, game_state);
69 ImGui::TextUnformatted(metadata.map_title.c_str());
70 ImGui::Separator();
71 ImGui::TextUnformatted("32 x 32 Tile16 cells");
72 ImGui::TextUnformatted("Loom Beach graphics and palette");
73 ImGui::TextWrapped(
74 "Use the Tile16 selector to paint terrain across neighboring maps. "
75 "Save Project keeps these terrain edits.");
76 ImGui::Spacing();
77 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.85f, 0.3f, 1.0f));
78 ImGui::Text(ICON_MD_INFO " Tail Map Limitations ($A0-$BF)");
79 ImGui::PopStyleColor();
80 ImGui::TextWrapped(
81 "• Items & Bomb Doors: Disabled (pending SRAM event allocation in "
82 "save file)\n"
83 "• Exits: 1 free slot (full links require ASM exit table v2)\n"
84 "• Entrances: Trigger table v2 in development (Phase P2)\n"
85 "• Sprites: Draft state (actor compilation needed for ROM)");
86 ImGui::PopID();
87 ImGui::EndChild();
88 return;
89 }
90 const auto* selected = overworld_->overworld_map(current_map);
91 if (!selected) {
92 ImGui::TextDisabled(tr("Current map selection is invalid."));
93 ImGui::TextDisabled(
94 tr("Hover or jump to a valid overworld map to continue."));
95 ImGui::PopID();
96 ImGui::EndChild();
97 return;
98 }
99
100 // Multi-area maps store their properties on the parent.
101 const int parent = selected->parent();
102 const int property_map =
103 (parent >= 0 && parent < zelda3::kNumOverworldMaps &&
104 overworld_->overworld_map(parent))
105 ? parent
106 : current_map;
107 if (edit_error_map_ != property_map) {
108 edit_error_map_ = property_map;
109 edit_error_.clear();
110 }
111
112 DrawHeader(current_world, current_map, property_map, current_map_lock,
113 game_state);
114
115 if (ImGui::CollapsingHeader(tr("Area"), ImGuiTreeNodeFlags_DefaultOpen)) {
116 DrawAreaSection(property_map, game_state);
117 }
118 if (ImGui::CollapsingHeader(tr("Graphics"),
119 ImGuiTreeNodeFlags_DefaultOpen)) {
120 DrawGraphicsSection(property_map, game_state);
121 }
122 if (ImGui::CollapsingHeader(tr("Palettes"),
123 ImGuiTreeNodeFlags_DefaultOpen)) {
124 DrawPaletteSection(property_map, game_state, show_custom_bg_color_editor);
125 }
126 if (ImGui::CollapsingHeader(tr("Music"))) {
127 DrawMusicSection(property_map);
128 }
129 if (ImGui::CollapsingHeader(tr("Effects"))) {
130 DrawEffectsSection(property_map, show_overlay_editor);
131 }
132
133 if (!edit_error_.empty()) {
134 ImGui::Spacing();
135 ImGui::TextColored(gui::GetErrorColor(), "%s", edit_error_.c_str());
136 }
138 draw_project_tools(current_map, game_state);
140 ImGui::PopID();
141 }
142 ImGui::EndChild();
143}
144
146 bool current_map_lock,
147 project::YazeProject* project,
148 bool compact) {
149 if (!overworld_ || !overworld_->is_loaded() || !rom_ ||
151 return;
152 }
153 const auto* selected = overworld_->overworld_map(current_map);
154 if (!selected) {
155 return;
156 }
157 project_ = project;
158 const int parent = selected->parent();
159 const int property_map = parent >= 0 && parent < zelda3::kNumOverworldMaps &&
161 ? parent
162 : current_map;
163 const auto* map = overworld_->overworld_map(property_map);
164 if (edit_error_map_ != property_map) {
165 edit_error_map_ = property_map;
166 edit_error_.clear();
167 }
168
169 ImGui::PushID("OverworldAppearance");
170 // Include the target in widget IDs: an unfinished text edit must not migrate
171 // to another area when cursor-follow changes the current map.
172 ImGui::PushID(property_map);
173 if (!compact) {
174 ImGui::AlignTextToFramePadding();
175 ImGui::Text("Area %02X%s", property_map,
176 current_map_lock ? " (pinned)" : " (follow)");
177 if (ImGui::IsItemHovered()) {
178 ImGui::SetTooltip(
179 "Appearance edits apply to area %02X and its shared screens.\n"
180 "Unpinned controls follow the cursor over the canvas.\n"
181 "Pin the map to keep editing this area while navigating.",
182 property_map);
183 }
184 }
185 const float row_start = ImGui::GetCursorPosX();
186 const float right = row_start + ImGui::GetContentRegionAvail().x;
187 const float input_width =
188 ImGui::CalcTextSize("FF").x + ImGui::GetStyle().FramePadding.x * 2.0f;
189 bool first_field = true;
190 const auto field = [&](const char* label, const char* tip,
191 OverworldPropertyField kind, uint8_t value) {
192 const float width = ImGui::CalcTextSize(label).x + input_width +
193 ImGui::GetStyle().ItemInnerSpacing.x;
194 if (compact ? !first_field
195 : ImGui::GetItemRectMax().x - ImGui::GetWindowPos().x +
196 ImGui::GetScrollX() +
197 ImGui::GetStyle().ItemSpacing.x + width <=
198 right) {
199 ImGui::SameLine();
200 }
201 first_field = false;
202 ImGui::BeginGroup();
203 ImGui::AlignTextToFramePadding();
204 ImGui::TextUnformatted(
205 compact
206 ? (kind == OverworldPropertyField::kAreaGraphics ? "GFX" : "Pal")
207 : label);
208 ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
209 ImGui::PushID(label);
210 if (gui::InputHexByte("##Value", &value, input_width, /*no_step=*/true)) {
211 Apply(kind, 0, property_map, value);
212 }
214 std::string("OverworldToolbar/field:") + label, "input",
215 ImGui::GetItemID());
216 ImGui::PopID();
217 ImGui::EndGroup();
218 if (ImGui::IsItemHovered()) {
219 ImGui::SetTooltip(
220 "%s\nHexadecimal ID. Changes refresh the canvas and "
221 "Tile16 preview; undo restores the previous value.%s%s",
222 tip,
223 edit_error_.empty() ? "" : "\nEdit failed: ", edit_error_.c_str());
224 }
225 };
226 field("Graphics", "Tile graphics group assigned to this area",
227 OverworldPropertyField::kAreaGraphics, map->area_graphics());
228 field("Palette", "Area palette set assigned to this area",
229 OverworldPropertyField::kAreaPalette, map->area_palette());
231 if (!compact &&
233 field("Main palette", "Extended main palette assigned to this area",
234 OverworldPropertyField::kMainPalette, map->main_palette());
235 }
236 if (!edit_error_.empty() && !compact) {
237 ImGui::TextWrapped("%s", edit_error_.c_str());
238 }
239 ImGui::PopID();
240 ImGui::PopID();
241}
242
243void OverworldSidebar::DrawHeader(int current_world, int current_map,
244 int property_map, bool& current_map_lock,
245 int game_state) {
246 const auto metadata = BuildOverworldMapMetadata(*overworld_, rom_, project_,
247 current_map, game_state);
248 // Title on its own line (map names can be long); actions below it.
249 ImGui::TextWrapped(ICON_MD_MAP " %s", metadata.map_title.c_str());
250
252 current_map_lock ? ICON_MD_PUSH_PIN : ICON_MD_GPS_FIXED,
253 current_map_lock ? "Pinned: properties stay on this map.\n"
254 "Click to follow the cursor again."
255 : "Following the cursor.\n"
256 "Click to pin properties to this map.",
257 current_map_lock)) {
258 current_map_lock = !current_map_lock;
259 }
260 ImGui::SameLine(0, 2);
261 ImGui::AlignTextToFramePadding();
262 ImGui::TextDisabled("%s", current_map_lock ? "Pinned" : "Follow");
263 ImGui::SameLine(0, 6);
264 ImGui::BeginDisabled(project_ == nullptr);
266 project_ ? "Rename this map in the project"
267 : "Open a project to name maps")) {
268 label_target_ = {"Map name", "overworld_map", current_map, 2};
269 open_label_popup_ = true;
270 }
271 ImGui::EndDisabled();
272 ImGui::SameLine();
273 ImGui::AlignTextToFramePadding();
274 ImGui::TextDisabled("%s", metadata.area_size_label.c_str());
275
276 (void)current_world; // The title already names the world.
277 if (property_map != current_map) {
278 // Multi-screen areas: values below belong to the parent screen.
279 ImGui::TextDisabled("%s", metadata.parent_label.c_str());
280 ImGui::SameLine();
281 }
282 ImGui::TextDisabled(ICON_MD_INFO " %s", metadata.version_label.c_str());
283 if (ImGui::IsItemHovered()) {
284 ImGui::SetTooltip(
285 "%s", tr("ROM version determines available overworld features.\n"
286 "v2+: custom BG colors, main palettes\n"
287 "v3+: wide/tall areas, custom tile GFX, animated GFX"));
288 }
289 ImGui::Spacing();
290}
291
293 if (!ImGui::BeginTable(id, 2, ImGuiTableFlags_SizingFixedFit)) {
294 return false;
295 }
296 ImGui::TableSetupColumn("Label", ImGuiTableColumnFlags_WidthFixed,
297 kFieldLabelWidth);
298 ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
299 return true;
300}
301
302void OverworldSidebar::FieldLabel(const char* label, const char* tooltip) {
303 ImGui::TableNextRow();
304 ImGui::TableNextColumn();
305 ImGui::AlignTextToFramePadding();
306 ImGui::TextUnformatted(label);
307 if (tooltip && ImGui::IsItemHovered()) {
308 ImGui::SetTooltip("%s", tooltip);
309 }
310 ImGui::TableNextColumn();
311}
312
314 int property_map, int value) {
315 const auto status = map_properties_system_->ApplyPropertyEdit(
316 {property_map, field, index, value});
317 edit_error_ = status.ok() ? "" : std::string(status.message());
318}
319
320bool OverworldSidebar::HexByteField(const char* id, const char* label,
321 const char* tooltip,
322 OverworldPropertyField field, int index,
323 int property_map, uint8_t value,
324 const LabelTarget* label_target) {
325 FieldLabel(label, tooltip);
326 ImGui::PushID(id);
327 const bool changed =
328 gui::InputHexByte("##Value", &value, ImGui::GetContentRegionAvail().x,
329 /*no_step=*/true);
330 if (changed) {
331 Apply(field, index, property_map, value);
332 }
333 if (label_target) {
334 if (ImGui::IsItemHovered()) {
335 const std::string project_label = GetProjectResourceLabel(
336 project_, label_target->type, label_target->id);
337 ImGui::SetTooltip(
338 "%s\n%s\n%s", tooltip ? tooltip : label,
339 project_label.empty()
340 ? tr("No project label")
341 : absl::StrFormat("Label: %s", project_label).c_str(),
342 tr("Right-click to rename the label"));
343 }
344 LabelContextMenu(*label_target);
345 }
346 ImGui::PopID();
347 return changed;
348}
349
351 if (ImGui::BeginPopupContextItem("##LabelMenu")) {
352 ImGui::BeginDisabled(project_ == nullptr);
353 if (ImGui::MenuItem(ICON_MD_LABEL " Rename label...")) {
354 label_target_ = target;
355 open_label_popup_ = true;
356 }
357 ImGui::EndDisabled();
358 if (!project_) {
359 ImGui::TextDisabled("%s", tr("Open a project to store labels"));
360 }
361 ImGui::EndPopup();
362 }
363}
364
366 if (open_label_popup_) {
367 open_label_popup_ = false;
368 label_error_.clear();
369 const std::string current =
371 std::strncpy(label_buffer_.data(), current.c_str(),
372 label_buffer_.size() - 1);
373 label_buffer_[label_buffer_.size() - 1] = '\0';
374 ImGui::OpenPopup(kLabelPopupId);
375 }
376 if (!ImGui::BeginPopup(kLabelPopupId)) {
377 return;
378 }
379 ImGui::Text("%s %s %s", ICON_MD_LABEL, label_target_.title.c_str(),
380 FormatId(label_target_.id, label_target_.hex_width).c_str());
381 ImGui::SetNextItemWidth(260.0f);
382 if (ImGui::IsWindowAppearing()) {
383 ImGui::SetKeyboardFocusHere();
384 }
385 const bool submitted = ImGui::InputText("##LabelInput", label_buffer_.data(),
386 label_buffer_.size(),
387 ImGuiInputTextFlags_EnterReturnsTrue);
388 auto apply = [&](const std::string& label) {
389 const auto status =
393 label_target_.id, label);
394 if (status.ok()) {
395 label_error_.clear();
396 ImGui::CloseCurrentPopup();
397 } else {
398 label_error_ = std::string(status.message());
399 }
400 };
401 if (ImGui::Button(ICON_MD_CHECK " Apply") || submitted) {
402 apply(label_buffer_.data());
403 }
404 ImGui::SameLine();
405 if (ImGui::Button(ICON_MD_CLEAR " Clear")) {
406 apply("");
407 }
408 if (!label_error_.empty()) {
409 ImGui::TextWrapped("%s", label_error_.c_str());
410 }
411 ImGui::EndPopup();
412}
413
414void OverworldSidebar::DrawAreaSection(int property_map, int& game_state) {
415 const auto* map = overworld_->overworld_map(property_map);
416 if (!map || !BeginFieldTable("AreaFields")) {
417 return;
418 }
419
420 FieldLabel(tr("Game state"),
421 tr("Story state to preview. Sprite graphics and sprite "
422 "palettes below are stored per game state."));
423 ImGui::SetNextItemWidth(-FLT_MIN);
424 int selected_state = game_state;
425 if (ImGui::Combo("##GameState", &selected_state, kGameStateNames, 3) &&
427 on_story_changed(selected_state);
428 }
429
430 FieldLabel(tr("Area size"), tr("Screens this area spans. Wide and Tall need "
431 "ZSCustomOverworld v3."));
432 const auto rom_version = zelda3::OverworldVersionHelper::GetVersion(*rom_);
433 int area_size = static_cast<int>(map->area_size());
434 ImGui::SetNextItemWidth(-FLT_MIN);
436 if (ImGui::Combo("##AreaSize", &area_size, kAreaSizeNames, 4)) {
437 Apply(OverworldPropertyField::kAreaSize, 0, property_map, area_size);
438 }
439 } else {
440 const char* limited_names[] = {"Small (1x1)", "Large (2x2)"};
441 int limited = (area_size == 0 || area_size == 1) ? area_size : 0;
442 if (ImGui::Combo("##AreaSize", &limited, limited_names, 2)) {
443 const auto size = limited == 1 ? zelda3::AreaSizeEnum::LargeArea
446 static_cast<int>(size));
447 }
448 }
449
450 const LabelTarget message_label{"Message", "message", map->message_id(), 4};
451 FieldLabel(tr("Message"), tr("Area name message shown on entry (hex)"));
452 ImGui::PushID("Message");
453 uint16_t message_id = map->message_id();
454 if (gui::InputHexWord("##Value", &message_id,
455 ImGui::GetContentRegionAvail().x, /*no_step=*/true)) {
456 Apply(OverworldPropertyField::kMessageId, 0, property_map, message_id);
457 }
458 LabelContextMenu(message_label);
459 ImGui::PopID();
460 ImGui::EndTable();
461}
462
463void OverworldSidebar::DrawGraphicsSection(int property_map, int game_state) {
464 const auto* map = overworld_->overworld_map(property_map);
465 if (!map || !BeginFieldTable("GraphicsFields")) {
466 return;
467 }
468 const auto rom_version = zelda3::OverworldVersionHelper::GetVersion(*rom_);
469 const int state = std::clamp(game_state, 0, 2);
470
471 const LabelTarget area_gfx{"Area graphics", "graphics", map->area_graphics()};
472 HexByteField("AreaGfx", tr("Area graphics"),
473 tr("Tile graphics group for this area (hex)"),
475 map->area_graphics(), &area_gfx);
476
477 const std::string sprite_tip = absl::StrFormat(
478 "Sprite graphics group while in \"%s\" (hex)", kGameStateNames[state]);
479 const LabelTarget sprite_gfx{"Sprite graphics", "graphics",
480 map->sprite_graphics(state)};
481 HexByteField("SpriteGfx", tr("Sprite graphics"), sprite_tip.c_str(),
482 OverworldPropertyField::kSpriteGraphics, state, property_map,
483 map->sprite_graphics(state), &sprite_gfx);
484
486 const LabelTarget animated{"Animated graphics", "graphics",
487 map->animated_gfx()};
488 HexByteField("AnimatedGfx", tr("Animated graphics"),
489 tr("Animated tile sheet (water, flowers) (hex)"),
491 map->animated_gfx(), &animated);
492 }
493 ImGui::EndTable();
494
496 ImGui::TreeNode(tr("Custom tile sheets"))) {
497 if (BeginFieldTable("CustomTileSheets")) {
498 for (int i = 0; i < 8; ++i) {
499 const std::string id = absl::StrFormat("Sheet%d", i);
500 const std::string label = absl::StrFormat("Sheet %d", i);
501 const std::string tip =
502 absl::StrFormat("Custom graphics sheet slot %d (hex)", i);
503 HexByteField(id.c_str(), label.c_str(), tip.c_str(),
505 map->custom_tileset(i));
506 }
507 ImGui::EndTable();
508 }
509 ImGui::TreePop();
510 }
511}
512
513void OverworldSidebar::DrawPaletteSection(int property_map, int game_state,
514 bool& show_custom_bg_color_editor) {
515 const auto* map = overworld_->overworld_map(property_map);
516 if (!map || !BeginFieldTable("PaletteFields")) {
517 return;
518 }
519 const auto rom_version = zelda3::OverworldVersionHelper::GetVersion(*rom_);
520 const int state = std::clamp(game_state, 0, 2);
521
522 const LabelTarget area_palette{"Area palette", "overworld_area_palette",
523 map->area_palette()};
524 HexByteField("AreaPalette", tr("Area palette"), tr("Area palette set (hex)"),
526 map->area_palette(), &area_palette);
527
529 const LabelTarget main_palette{"Main palette", "overworld_main_palette",
530 map->main_palette()};
531 HexByteField("MainPalette", tr("Main palette"),
532 tr("Extended main palette (ZSCustomOverworld v2+) (hex)"),
534 map->main_palette(), &main_palette);
535 }
536
537 const std::string sprite_tip = absl::StrFormat(
538 "Sprite palette while in \"%s\" (hex)", kGameStateNames[state]);
539 const LabelTarget sprite_palette{"Sprite palette", "overworld_sprite_palette",
540 map->sprite_palette(state)};
541 HexByteField("SpritePalette", tr("Sprite palette"), sprite_tip.c_str(),
542 OverworldPropertyField::kSpritePalette, state, property_map,
543 map->sprite_palette(state), &sprite_palette);
544 ImGui::EndTable();
545
547 if (ImGui::Button(ICON_MD_FORMAT_COLOR_FILL " Background color...",
548 ImVec2(-FLT_MIN, 0))) {
549 show_custom_bg_color_editor = true;
550 }
551 }
552}
553
555 const auto* map = overworld_->overworld_map(property_map);
556 if (!map || !BeginFieldTable("MusicFields")) {
557 return;
558 }
559 for (int i = 0; i < 4; ++i) {
560 const std::string id = absl::StrFormat("Music%d", i);
561 const LabelTarget music{kMusicLabels[i], "overworld_music",
562 map->area_music(i)};
563 HexByteField(id.c_str(), tr(kMusicLabels[i]), tr(kMusicTooltips[i]),
564 OverworldPropertyField::kMusic, i, property_map,
565 map->area_music(i), &music);
566 }
567 ImGui::EndTable();
568}
569
571 bool& show_overlay_editor) {
572 auto* map = overworld_->mutable_overworld_map(property_map);
573 if (!map) {
574 return;
575 }
576 const auto rom_version = zelda3::OverworldVersionHelper::GetVersion(*rom_);
577 if (rom_version != zelda3::OverworldVersion::kVanilla) {
578 if (ImGui::Button(ICON_MD_LAYERS " Visual effects...",
579 ImVec2(-FLT_MIN, 0))) {
580 show_overlay_editor = true;
581 }
582 }
583
584 ImGui::TextUnformatted(tr("Mosaic transition"));
586 std::array<bool, 4> mosaic = map->mosaic_expanded();
587 const char* directions[] = {"North", "South", "East", "West"};
588 if (ImGui::BeginTable("MosaicTable", 2)) {
589 for (int i = 0; i < 4; ++i) {
590 ImGui::TableNextColumn();
591 if (ImGui::Checkbox(tr(directions[i]), &mosaic[i])) {
593 mosaic[i] ? 1 : 0);
594 }
595 }
596 ImGui::EndTable();
597 }
598 } else {
599 bool mosaic = *map->mutable_mosaic();
600 if (ImGui::Checkbox(tr("Mosaic effect"), &mosaic)) {
601 Apply(OverworldPropertyField::kMosaic, 0, property_map, mosaic ? 1 : 0);
602 }
603 }
604}
605
606} // namespace editor
607} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:52
absl::Status ApplyPropertyEdit(const OverworldPropertyEdit &edit)
void FieldLabel(const char *label, const char *tooltip)
std::function< void(int, int &) draw_project_tools)
void DrawQuickProperties(int current_map, bool current_map_lock, project::YazeProject *project=nullptr, bool compact=false)
void DrawAreaSection(int property_map, int &game_state)
void LabelContextMenu(const LabelTarget &target)
void DrawGraphicsSection(int property_map, int game_state)
MapPropertiesSystem * map_properties_system_
std::function< void(int)> on_story_changed
void DrawPaletteSection(int property_map, int game_state, bool &show_custom_bg_color_editor)
OverworldSidebar(zelda3::Overworld *overworld, Rom *rom, MapPropertiesSystem *map_properties_system)
bool HexByteField(const char *id, const char *label, const char *tooltip, OverworldPropertyField field, int index, int property_map, uint8_t value, const LabelTarget *label_target=nullptr)
void DrawMusicSection(int property_map)
std::array< char, 128 > label_buffer_
void Draw(int &current_world, int &current_map, bool &current_map_lock, int &game_state, bool &show_custom_bg_color_editor, bool &show_overlay_editor, project::YazeProject *project=nullptr)
void DrawEffectsSection(int property_map, bool &show_overlay_editor)
void Apply(OverworldPropertyField field, int index, int property_map, int value)
void DrawHeader(int current_world, int current_map, int property_map, bool &current_map_lock, int game_state)
project::YazeProject * project_
void RegisterWidget(const std::string &full_path, const std::string &type, ImGuiID imgui_id, const std::string &description="", const WidgetMetadata &metadata=WidgetMetadata())
static WidgetIdRegistry & Instance()
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+)
static bool SupportsExpandedSpace(OverworldVersion version)
Check if ROM uses expanded ROM space for overworld data.
bool is_lyra_preview() const
Definition overworld.h:444
auto is_loaded() const
Definition overworld.h:836
auto overworld_map(int i) const
Definition overworld.h:770
auto mutable_overworld_map(int i)
Definition overworld.h:776
#define ICON_MD_INFO
Definition icons.h:993
#define ICON_MD_GPS_FIXED
Definition icons.h:883
#define ICON_MD_CHECK
Definition icons.h:397
#define ICON_MD_MAP
Definition icons.h:1173
#define ICON_MD_LABEL
Definition icons.h:1053
#define ICON_MD_FORMAT_COLOR_FILL
Definition icons.h:830
#define ICON_MD_EDIT
Definition icons.h:645
#define ICON_MD_LAYERS
Definition icons.h:1068
#define ICON_MD_CLEAR
Definition icons.h:416
#define ICON_MD_PUSH_PIN
Definition icons.h:1529
absl::Status RenameProjectResourceLabel(project::YazeProject *project, const std::string &type, int id, const std::string &label)
constexpr const char * kAreaSizeNames[]
OverworldMapMetadata BuildOverworldMapMetadata(const zelda3::Overworld &overworld, const Rom *rom, const project::YazeProject *project, int map_id, int game_state)
std::string GetProjectResourceLabel(const project::YazeProject *project, const std::string &type, int id)
constexpr const char * kGameStateNames[]
Definition ui_constants.h:8
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
Definition input.cc:462
ImVec4 GetErrorColor()
Definition ui_helpers.cc:59
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:483
constexpr int kNumOverworldMaps
Definition common.h:85
@ kVanilla
0xFF in ROM, no ZScream ASM applied
Modern project structure with comprehensive settings consolidation.
Definition project.h:290
std::string lyra_terrain_file
Definition project.h:342