8#include <initializer_list>
10#include "absl/status/status.h"
11#include "absl/strings/match.h"
12#include "absl/strings/str_format.h"
22#include "imgui/misc/cpp/imgui_stdlib.h"
33 : editor_manager_(editor_manager), status_(absl::OkStatus()) {}
155 for (
auto& [name, params] :
popups_) {
156 if (params.is_visible) {
157 OpenPopup(name.c_str());
160 ImGuiWindowFlags popup_flags = params.allow_resize
161 ? ImGuiWindowFlags_None
162 : ImGuiWindowFlags_AlwaysAutoResize;
164 if (BeginPopupModal(name.c_str(),
nullptr, popup_flags)) {
165 params.draw_function();
177 std::string name_str(name);
178 auto it =
popups_.find(name_str);
180 it->second.is_visible =
true;
184 "[PopupManager] Warning: Popup '%s' not registered. Available popups: ",
186 for (
const auto& [key, _] :
popups_) {
187 printf(
"'%s' ", key.c_str());
198 std::string name_str(name);
199 auto it =
popups_.find(name_str);
201 it->second.is_visible =
false;
211 std::string name_str(name);
212 auto it =
popups_.find(name_str);
214 return it->second.is_visible;
228 ImGuiIO
const& io = GetIO();
229 ImVec2 pos(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f);
230 SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
231 ImGuiWindowFlags flags =
232 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
233 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings;
234 return Begin(name,
nullptr, flags);
248 IsKeyPressed(ImGuiKey_Space)) {
261 Text(tr(
"Yet Another Zelda3 Editor - v%s"),
263 Text(tr(
"Written by: scawful"));
265 Text(tr(
"Special Thanks: Zarby89, JaredBrian"));
278 Text(tr(
"Title: %s"), current_rom->title().c_str());
285 if (project && project->project_opened()) {
289 Text(tr(
"Write Policy: %s"),
292 Text(tr(
"Expected Hash: %s"),
293 project->rom_metadata.expected_hash.empty()
295 : project->rom_metadata.expected_hash.c_str());
299 tr(
"ROM hash mismatch detected"));
304 IsKeyPressed(ImGuiKey_Escape)) {
305 Hide(
"ROM Information");
310 using namespace ImGui;
315 static std::string save_as_filename =
"";
320 InputText(tr(
"Filename"), &save_as_filename);
327 if (!file_path.empty()) {
328 save_as_filename = file_path;
333 if (Button(absl::StrFormat(
"%s Save",
ICON_MD_SAVE).c_str(),
335 if (!save_as_filename.empty()) {
337 std::string final_filename = save_as_filename;
338 if (final_filename.find(
".sfc") == std::string::npos &&
339 final_filename.find(
".smc") == std::string::npos) {
340 final_filename +=
".sfc";
345 save_as_filename =
"";
354 save_as_filename =
"";
360 using namespace ImGui;
365 tr(
"Controls which data is written during File > Save ROM. "
366 "Changes apply immediately."));
369 if (CollapsingHeader(tr(
"Overworld"), ImGuiTreeNodeFlags_DefaultOpen)) {
370 Checkbox(tr(
"Save Overworld Maps"),
372 Checkbox(tr(
"Save Overworld Entrances"),
374 Checkbox(tr(
"Save Overworld Exits"),
376 Checkbox(tr(
"Save Overworld Items"),
378 Checkbox(tr(
"Save Overworld Properties"),
382 if (CollapsingHeader(tr(
"Dungeon"), ImGuiTreeNodeFlags_DefaultOpen)) {
383 Checkbox(tr(
"Save Dungeon Maps"),
385 Checkbox(tr(
"Save Objects"),
387 Checkbox(tr(
"Save Sprites"),
389 Checkbox(tr(
"Save Room Headers"),
391 Checkbox(tr(
"Save Torches"),
395 Checkbox(tr(
"Save Collision"),
398 Checkbox(tr(
"Save Pot Items"),
400 Checkbox(tr(
"Save Palettes"),
404 if (CollapsingHeader(tr(
"Graphics"), ImGuiTreeNodeFlags_DefaultOpen)) {
405 Checkbox(tr(
"Save Graphics Sheets"),
407 Checkbox(tr(
"Save All Palettes"),
412 if (CollapsingHeader(tr(
"Messages"), ImGuiTreeNodeFlags_DefaultOpen)) {
423 using namespace ImGui;
427 Text(tr(
"No ROM loaded."));
435 std::string backup_dir;
436 if (project && project->project_opened() &&
437 !project->rom_backup_folder.empty()) {
440 backup_dir = std::filesystem::path(rom->
filename()).parent_path().string();
445 TextWrapped(tr(
"Backup folder: %s"), backup_dir.c_str());
450 tr(
"A restored backup is staged in this session. Save ROM to commit "
451 "it. Discard reloads the backing ROM and abandons staged ROM-buffer "
452 "edits; resolve pending dungeon or palette edits first."));
457 toast->Show(absl::StrFormat(
"Discard failed: %s", status.message()),
461 toast->Show(
"Restored backup discarded; reloaded ROM from disk",
472 toast->Show(absl::StrFormat(
"Prune failed: %s", status.message()),
482 if (backups.empty()) {
483 TextDisabled(tr(
"No backups found."));
484 }
else if (BeginTable(
"RomBackupTable", 4,
485 ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
486 ImGuiTableFlags_Resizable)) {
487 TableSetupColumn(
"Timestamp");
488 TableSetupColumn(
"Size");
489 TableSetupColumn(
"Filename");
490 TableSetupColumn(
"Actions");
493 auto format_size = [](uintmax_t bytes) {
494 if (bytes > (1024 * 1024)) {
495 return absl::StrFormat(
"%.2f MB",
496 static_cast<double>(bytes) / (1024 * 1024));
499 return absl::StrFormat(
"%.1f KB",
static_cast<double>(bytes) / 1024.0);
501 return absl::StrFormat(
"%llu B",
static_cast<unsigned long long>(bytes));
504 for (
size_t i = 0; i < backups.size(); ++i) {
505 const auto& backup = backups[i];
508 char time_buffer[32] =
"unknown";
509 if (backup.timestamp != 0) {
512 localtime_s(&local_tm, &backup.timestamp);
514 localtime_r(&backup.timestamp, &local_tm);
516 std::strftime(time_buffer,
sizeof(time_buffer),
"%Y-%m-%d %H:%M:%S",
519 TextUnformatted(time_buffer);
522 TextUnformatted(format_size(backup.size_bytes).c_str());
525 TextUnformatted(backup.filename.c_str());
528 PushID(
static_cast<int>(i));
533 toast->Show(absl::StrFormat(
"Restore failed: %s", status.message()),
537 toast->Show(
"Backup loaded; inspect it, then save ROM to commit",
546 toast->Show(absl::StrFormat(
"Open failed: %s", status.message()),
553 SetClipboardText(backup.path.c_str());
567 using namespace ImGui;
569 static std::string project_name =
"";
570 static std::string project_filepath =
"";
571 static std::string rom_filename =
"";
572 static std::string labels_filename =
"";
573 static std::string code_folder =
"";
575 InputText(tr(
"Project Name"), &project_name);
577 if (Button(absl::StrFormat(
"%s Destination Folder",
ICON_MD_FOLDER).c_str(),
582 Text(
"%s", project_filepath.empty() ?
"(Not set)" : project_filepath.c_str());
590 Text(
"%s", rom_filename.empty() ?
"(Not set)" : rom_filename.c_str());
592 if (Button(absl::StrFormat(
"%s Labels File",
ICON_MD_LABEL).c_str(),
597 Text(
"%s", labels_filename.empty() ?
"(Not set)" : labels_filename.c_str());
599 if (Button(absl::StrFormat(
"%s Code Folder",
ICON_MD_CODE).c_str(),
604 Text(
"%s", code_folder.empty() ?
"(Not set)" : code_folder.c_str());
608 if (Button(absl::StrFormat(
"%s Choose Project File Location",
ICON_MD_SAVE)
611 auto project_file_path =
613 if (!project_file_path.empty()) {
614 if (!(absl::EndsWith(project_file_path,
".yaze") ||
615 absl::EndsWith(project_file_path,
".yazeproj"))) {
616 project_file_path +=
".yaze";
618 project_filepath = project_file_path;
622 if (Button(absl::StrFormat(
"%s Create Project",
ICON_MD_ADD).c_str(),
624 if (!project_filepath.empty() && !project_name.empty() &&
625 !rom_filename.empty()) {
627 "Basic ROM Hack", rom_filename, project_name, project_filepath);
631 if (!labels_filename.empty()) {
634 if (!code_folder.empty()) {
635 project->code_folder = code_folder;
637 if (!labels_filename.empty() || !code_folder.empty()) {
646 project_filepath =
"";
648 labels_filename =
"";
661 project_filepath =
"";
663 labels_filename =
"";
676 auto status_color = [&](
const char* status) -> ImVec4 {
677 if (strcmp(status,
"Stable") == 0 || strcmp(status,
"Working") == 0) {
680 if (strcmp(status,
"Beta") == 0 || strcmp(status,
"Experimental") == 0) {
683 if (strcmp(status,
"Preview") == 0) {
686 if (strcmp(status,
"Not available") == 0) {
695 const char* persistence;
699 auto draw_table = [&](
const char* table_id,
700 std::initializer_list<FeatureRow> rows) {
701 ImGuiTableFlags flags = ImGuiTableFlags_BordersInnerH |
702 ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable;
703 if (!BeginTable(table_id, 4, flags)) {
706 TableSetupColumn(
"Feature", ImGuiTableColumnFlags_WidthStretch);
707 TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 120.0f);
708 TableSetupColumn(
"Save/Load", ImGuiTableColumnFlags_WidthFixed, 180.0f);
709 TableSetupColumn(
"Notes", ImGuiTableColumnFlags_WidthStretch);
712 for (
const auto& row : rows) {
714 TableSetColumnIndex(0);
715 TextUnformatted(row.feature);
716 TableSetColumnIndex(1);
717 TextColored(status_color(row.status),
"%s", row.status);
718 TableSetColumnIndex(2);
719 TextUnformatted(row.persistence);
720 TableSetColumnIndex(3);
721 TextWrapped(
"%s", row.notes);
728 tr(
"Status: Stable = production ready, Beta = usable with gaps, "
729 "Experimental = WIP, Preview = web parity in progress."));
730 TextDisabled(tr(
"See Settings > Feature Flags for ROM-specific toggles."));
733 if (CollapsingHeader(tr(
"Desktop App (yaze)"),
734 ImGuiTreeNodeFlags_DefaultOpen)) {
735 draw_table(
"desktop_features",
737 {
"ROM load/save",
"Stable",
"ROM + backups",
738 "Backups on save when enabled."},
739 {
"Overworld Editor",
"Stable",
"ROM",
740 "Maps/entrances/exits/items; version-gated."},
741 {
"Dungeon Editor",
"Stable",
"ROM",
742 "Room objects/tiles/palettes persist."},
743 {
"Palette Editor",
"Stable",
"ROM",
744 "Palette edits persist; JSON IO pending."},
745 {
"Graphics Editor",
"Beta",
"ROM",
746 "Sheet edits persist; tooling still expanding."},
747 {
"Sprite Editor",
"Stable",
"ROM",
"Sprite edits persist."},
748 {
"Message Editor",
"Stable",
"ROM",
"Text edits persist."},
749 {
"Screen Editor",
"Experimental",
"ROM (partial)",
750 "Save coverage incomplete."},
751 {
"Hex Editor",
"Beta",
"ROM",
"Search UX incomplete."},
752 {
"Assembly/Asar",
"Beta",
"ROM + project",
753 "Patch apply + symbol export."},
754 {
"Emulator",
"Beta",
"Runtime only",
755 "Save-state UI partially wired."},
756 {
"Music Editor",
"Experimental",
"ROM (partial)",
757 "Serialization in progress."},
758 {
"Agent UI",
"Experimental",
".yaze/agent",
759 "Requires AI provider configuration."},
760 {
"Settings/Layouts",
"Beta",
".yaze config",
761 "Layout serialization improving."},
765 if (CollapsingHeader(tr(
"z3ed CLI"))) {
766 draw_table(
"cli_features",
768 {
"ROM read/write/validate",
"Stable",
"ROM file",
769 "Direct command execution."},
770 {
"Agent workflows",
"Stable",
".yaze/proposals + sandboxes",
771 "Commit writes ROM; revert reloads."},
772 {
"Snapshots/restore",
"Stable",
"Sandbox copies",
773 "Supports YAZE_SANDBOX_ROOT override."},
774 {
"Doctor/test suites",
"Stable",
"Reports",
775 "Structured output for automation."},
776 {
"TUI/REPL",
"Stable",
"Session history",
777 "Interactive command palette + logs."},
781 if (CollapsingHeader(tr(
"Web/WASM Preview"))) {
785 {
"ROM load/save",
"Preview",
"IndexedDB + download",
786 "Drag/drop or picker; download for backups."},
787 {
"Editors (OW/Dungeon/Palette/etc.)",
"Preview",
788 "IndexedDB + download",
"Parity work in progress."},
789 {
"Hex Editor",
"Working",
"IndexedDB + download",
790 "Direct ROM editing available."},
791 {
"Asar patching",
"Preview",
"ROM",
"Basic patch apply support."},
792 {
"Emulator",
"Not available",
"N/A",
"Desktop only."},
793 {
"Collaboration",
"Experimental",
"Server",
794 "Requires yaze-server."},
795 {
"AI features",
"Preview",
"Server",
"Requires AI-enabled server."},
805 Text(tr(
"File -> Open"));
806 Text(tr(
"Select a ROM file to open"));
807 Text(tr(
"Supported ROMs (headered or unheadered):"));
808 Text(tr(
"The Legend of Zelda: A Link to the Past"));
809 Text(tr(
"US Version 1.0"));
810 Text(tr(
"JP Version 1.0"));
813 tr(
"ROM files are not bundled. Use a clean, legally obtained copy."));
821 Text(tr(
"Project Menu"));
822 Text(tr(
"Create a new project or open an existing one."));
823 Text(tr(
"Save the project to save the current state of the project."));
825 tr(
"To save a project, you need to first open a ROM and initialize your "
826 "code path and labels file. Label resource manager can be found in "
827 "the View menu. Code path is set in the Code editor after opening a "
831 Hide(
"Manage Project");
838 "YAZE lets you modify 'The Legend of Zelda: A Link to the Past' (US or "
839 "JP) ROMs with modern tooling."));
841 TextWrapped(tr(
"Release Highlights:"));
843 tr(
"AI-assisted workflows via z3ed agent and in-app panels "
844 "(Ollama/Gemini/OpenAI/Anthropic)"));
845 BulletText(tr(
"Clear feature status panels and improved help/tooltips"));
846 BulletText(tr(
"Unified .yaze storage across desktop/CLI/web"));
848 TextWrapped(tr(
"General Tips:"));
849 BulletText(tr(
"Open a clean ROM and save a backup before editing"));
850 BulletText(tr(
"Use Help (F1) for context-aware guidance and shortcuts"));
852 "Configure AI providers (Ollama/Gemini/OpenAI/Anthropic) in Settings > "
856 Hide(
"Getting Started");
861 TextWrapped(tr(
"Asar 65816 Assembly Integration"));
863 tr(
"YAZE includes full Asar assembler support for ROM patching."));
865 TextWrapped(tr(
"Features:"));
866 BulletText(tr(
"Cross-platform ROM patching with assembly code"));
867 BulletText(tr(
"Symbol export with addresses and opcodes"));
868 BulletText(tr(
"Assembly validation with detailed error reporting"));
869 BulletText(tr(
"Memory-safe patch application with size checks"));
872 Hide(
"Asar Integration");
877 TextWrapped(tr(
"Build Instructions"));
878 TextWrapped(tr(
"YAZE uses modern CMake for cross-platform builds."));
880 TextWrapped(tr(
"Quick Start (examples):"));
881 BulletText(tr(
"cmake --preset mac-dbg | lin-dbg | win-dbg"));
882 BulletText(tr(
"cmake --build --preset <preset> --target yaze"));
884 TextWrapped(tr(
"AI Builds:"));
885 BulletText(tr(
"cmake --preset mac-ai | lin-ai | win-ai"));
886 BulletText(tr(
"cmake --build --preset <preset> --target yaze z3ed"));
888 TextWrapped(tr(
"Docs: docs/public/build/quick-reference.md"));
891 Hide(
"Build Instructions");
896 TextWrapped(tr(
"Command Line Interface (z3ed)"));
897 TextWrapped(tr(
"Scriptable ROM editing and AI agent workflows."));
899 TextWrapped(tr(
"Commands:"));
900 BulletText(tr(
"z3ed rom-info --rom=zelda3.sfc"));
901 BulletText(tr(
"z3ed agent simple-chat --rom=zelda3.sfc --ai_provider=auto"));
902 BulletText(tr(
"z3ed agent plan --rom=zelda3.sfc"));
903 BulletText(tr(
"z3ed test-list --format json"));
904 BulletText(tr(
"z3ed patch apply-asar patch.asm --rom=zelda3.sfc"));
905 BulletText(tr(
"z3ed help dungeon-place-sprite"));
907 TextWrapped(tr(
"Storage:"));
909 tr(
"Agent plans/proposals live under ~/.yaze (see docs for details)"));
917 TextWrapped(tr(
"Troubleshooting"));
918 TextWrapped(tr(
"Common issues and solutions:"));
920 BulletText(tr(
"ROM won't load: Check file format (SFC/SMC supported)"));
922 tr(
"AI agent missing: Start Ollama or set GEMINI_API_KEY/OPENAI_API_KEY/"
923 "ANTHROPIC_API_KEY (web uses AI_AGENT_ENDPOINT)"));
924 BulletText(tr(
"Graphics issues: Disable experimental flags in Settings"));
926 tr(
"Performance: Enable hardware acceleration in display settings"));
927 BulletText(tr(
"Crashes: Check ROM file integrity and available memory"));
928 BulletText(tr(
"Layout issues: Reset workspace layouts from View > Layouts"));
931 Hide(
"Troubleshooting");
936 TextWrapped(tr(
"Contributing to YAZE"));
937 TextWrapped(tr(
"YAZE is open source and welcomes contributions!"));
939 TextWrapped(tr(
"How to contribute:"));
940 BulletText(tr(
"Fork the repository on GitHub"));
941 BulletText(tr(
"Create feature branches for new work"));
942 BulletText(tr(
"Follow C++ coding standards"));
943 BulletText(tr(
"Include tests for new features"));
944 BulletText(tr(
"Submit pull requests for review"));
947 Hide(
"Contributing");
955 if (CollapsingHeader(
958 ImGuiTreeNodeFlags_DefaultOpen)) {
960 tr(
"Feature status/persistence summaries across desktop/CLI/web"));
961 BulletText(tr(
"Shortcut/help panels now match configured keybindings"));
962 BulletText(tr(
"Refined onboarding tips and error messaging"));
963 BulletText(tr(
"Help text refreshed across desktop, CLI, and web"));
966 if (CollapsingHeader(
967 absl::StrFormat(
"%s Development & Build System",
ICON_MD_BUILD)
969 ImGuiTreeNodeFlags_DefaultOpen)) {
970 BulletText(tr(
"Asar 65816 assembler integration for ROM patching"));
971 BulletText(tr(
"z3ed CLI + TUI for scripting, test/doctor, and automation"));
972 BulletText(tr(
"Modern CMake presets for desktop, AI, and web builds"));
973 BulletText(tr(
"Unified version + storage references for 0.5.1"));
976 if (CollapsingHeader(
978 BulletText(tr(
"Improved project metadata + .yaze storage alignment"));
979 BulletText(tr(
"Stronger error reporting and status feedback"));
980 BulletText(tr(
"Performance and stability improvements across editors"));
981 BulletText(tr(
"Expanded logging and diagnostics tooling"));
984 if (CollapsingHeader(
985 absl::StrFormat(
"%s Editor Features",
ICON_MD_EDIT).c_str())) {
986 BulletText(tr(
"Music editor updates with SPC parsing/playback"));
988 tr(
"AI agent-assisted editing workflows (multi-provider + vision)"));
989 BulletText(tr(
"Expanded overworld/dungeon tooling and palette accuracy"));
990 BulletText(tr(
"Web/WASM preview with collaboration hooks"));
1008 TextWrapped(tr(
"Workspace Management"));
1010 "YAZE supports multiple ROM sessions and flexible workspace layouts."));
1013 TextWrapped(tr(
"Session Management:"));
1014 BulletText(tr(
"Ctrl+Shift+N: Create new session"));
1015 BulletText(tr(
"Ctrl+Shift+W: Close current session"));
1016 BulletText(tr(
"Ctrl+Tab: Quick session switcher"));
1017 BulletText(tr(
"Each session maintains its own ROM and editor state"));
1020 TextWrapped(tr(
"Layout Management:"));
1021 BulletText(tr(
"Drag window tabs to dock/undock"));
1022 BulletText(tr(
"Ctrl+Shift+S: Save current layout"));
1023 BulletText(tr(
"Ctrl+Shift+O: Load saved layout"));
1024 BulletText(tr(
"F11: Maximize current window"));
1027 TextWrapped(tr(
"Preset Layouts:"));
1028 BulletText(tr(
"Developer: Code, memory, testing tools"));
1029 BulletText(tr(
"Designer: Graphics, palettes, sprites"));
1030 BulletText(tr(
"Modder: All gameplay editing tools"));
1033 Hide(
"Workspace Help");
1039 TextWrapped(tr(
"You have reached the recommended session limit."));
1040 TextWrapped(tr(
"Having too many sessions open may impact performance."));
1042 TextWrapped(tr(
"Consider closing unused sessions or saving your work."));
1045 Hide(
"Session Limit Warning");
1049 Hide(
"Session Limit Warning");
1056 TextWrapped(tr(
"This will reset your current workspace layout to default."));
1057 TextWrapped(tr(
"Any custom window arrangements will be lost."));
1059 TextWrapped(tr(
"Do you want to continue?"));
1062 Hide(
"Layout Reset Confirm");
1067 Hide(
"Layout Reset Confirm");
1077 tr(
"Choose a workspace preset to quickly configure your layout:"));
1084 const char* description;
1088 PresetInfo presets[] = {
1090 "Essential cards only - maximum editing space",
1093 "Debug and development focused - CPU/Memory/Breakpoints",
1096 "Visual and artistic focused - Graphics/Palettes/Sprites",
1099 "Full-featured - All tools available for comprehensive editing",
1102 "Complete overworld editing toolkit with all map tools",
1105 "Complete dungeon editing toolkit with room tools",
1107 {
"Testing",
ICON_MD_SCIENCE,
"Quality assurance and ROM testing layout",
1113 constexpr int kPresetCount = 8;
1116 float button_width = 200.0f;
1117 float button_height = 50.0f;
1119 for (
int i = 0; i < kPresetCount; i++) {
1125 ImVec2(0.0f, 0.5f));
1126 if (Button(absl::StrFormat(
"%s %s", presets[i].icon, presets[i].name)
1128 ImVec2(button_width, button_height))) {
1130 auto preset = presets[i].getter();
1135 for (
const auto& panel_id : preset.default_visible_panels) {
1136 window_manager.OpenWindow(panel_id);
1142 if (IsItemHovered()) {
1144 TextUnformatted(presets[i].description);
1159 if (current_editor) {
1160 auto current_type = current_editor->
type();
1161 window_manager.ResetToDefaults(0, current_type);
1167 if (Button(tr(
"Close"), ImVec2(-1, 0))) {
1180 Text(tr(
"Active Sessions: %zu"), session_count);
1184 if (BeginTable(
"SessionTable", 4,
1185 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
1186 TableSetupColumn(
"#", ImGuiTableColumnFlags_WidthFixed, 30.0f);
1187 TableSetupColumn(
"ROM", ImGuiTableColumnFlags_WidthStretch);
1188 TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 80.0f);
1189 TableSetupColumn(
"Actions", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1192 for (
size_t i = 0; i < session_count; i++) {
1196 TableSetColumnIndex(0);
1200 TableSetColumnIndex(1);
1201 if (i == active_session) {
1204 TextUnformatted(rom->
filename().c_str());
1206 TextDisabled(tr(
"(No ROM loaded)"));
1209 TextDisabled(tr(
"Session %zu"), i + 1);
1213 TableSetColumnIndex(2);
1214 if (i == active_session) {
1218 TextDisabled(tr(
"Inactive"));
1222 TableSetColumnIndex(3);
1223 PushID(
static_cast<int>(i));
1225 if (i != active_session) {
1226 if (SmallButton(tr(
"Switch"))) {
1232 BeginDisabled(session_count <= 1);
1233 if (SmallButton(tr(
"Close"))) {
1249 if (Button(absl::StrFormat(
"%s New Session",
ICON_MD_ADD).c_str(),
1255 if (Button(tr(
"Close"), ImVec2(-1, 0))) {
1262 SetNextWindowSize(ImVec2(900, 700), ImGuiCond_FirstUseEver);
1263 SetNextWindowSizeConstraints(ImVec2(600, 400), ImVec2(FLT_MAX, FLT_MAX));
1266 TextWrapped(tr(
"Customize your YAZE experience - accessible anytime!"));
1271 float available_height =
1272 GetContentRegionAvail().y - 60;
1273 if (BeginChild(
"DisplaySettingsContent", ImVec2(0, available_height),
true,
1274 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
1283 ImGuiIO& io = GetIO();
1285 Text(tr(
"Global Font Scale"));
1286 float font_global_scale = io.FontGlobalScale;
1287 if (SliderFloat(
"##global_scale", &font_global_scale, 0.5f, 2.0f,
"%.2f")) {
1291 io.FontGlobalScale = font_global_scale;
1299 Hide(
"Display Settings");
1304 using namespace ImGui;
1307 Text(tr(
"Feature Flags Configuration"));
1310 BeginChild(
"##FlagsContent", ImVec2(0, -30),
true);
1315 if (BeginTabBar(
"FlagCategories")) {
1316 if (BeginTabItem(tr(
"Overworld"))) {
1320 if (BeginTabItem(tr(
"Dungeon"))) {
1324 if (BeginTabItem(tr(
"Resources"))) {
1328 if (BeginTabItem(tr(
"System"))) {
1344 using namespace ImGui;
1346 Text(tr(
"Data Integrity Check Results"));
1349 BeginChild(
"##IntegrityContent", ImVec2(0, -30),
true);
1353 Text(tr(
"ROM Data Integrity:"));
1361 Text(tr(
"No issues detected."));
1372 using namespace ImGui;
1375 Text(tr(
"Editor manager unavailable."));
1385 Text(tr(
"Pot Item Save Confirmation"));
1387 TextWrapped(tr(
"Dungeon pot item saving is enabled, but %d of %d rooms are "
1392 tr(
"Saving now can overwrite pot items in unloaded rooms. Choose how to "
1396 if (Button(tr(
"Save without pot items"), ImVec2(0, 0))) {
1403 if (Button(tr(
"Save anyway"), ImVec2(0, 0))) {
1410 if (Button(tr(
"Cancel"), ImVec2(0, 0))) {
1418 using namespace ImGui;
1421 Text(tr(
"Editor manager unavailable."));
1437 const auto editable_path =
1438 project && project->hack_manifest.loaded() &&
1439 !project->hack_manifest.build_pipeline().dev_rom.empty()
1440 ? project->GetAbsolutePath(
1441 project->hack_manifest.build_pipeline().dev_rom)
1442 : (project ? project->rom_filename : std::string());
1444 Text(tr(
"ROM Write Confirmation"));
1447 tr(
"The loaded ROM hash does not match the project's expected hash."));
1449 Text(tr(
"Role: %s"), role.c_str());
1450 Text(tr(
"Write policy: %s"), policy.c_str());
1451 Text(tr(
"Loaded ROM: %s"),
1452 actual_path.empty() ?
"(unknown)" : actual_path.c_str());
1453 Text(tr(
"Editable target: %s"),
1454 editable_path.empty() ?
"(unset)" : editable_path.c_str());
1455 Text(tr(
"Expected: %s"), expected.empty() ?
"(unset)" : expected.c_str());
1456 Text(tr(
"Actual: %s"), actual.empty() ?
"(unknown)" : actual.c_str());
1459 "Proceeding will write to the current ROM file. This may corrupt a base "
1460 "or release ROM if it is not the intended editable project ROM."));
1463 if (Button(tr(
"Save anyway"), ImVec2(0, 0))) {
1467 if (!status.ok() && !absl::IsCancelled(status)) {
1469 toast->Show(absl::StrFormat(
"Save failed: %s", status.message()),
1476 if (Button(tr(
"Cancel"), ImVec2(0, 0)) || IsKeyPressed(ImGuiKey_Escape)) {
1483 using namespace ImGui;
1486 Text(tr(
"Editor manager unavailable."));
1499 tr(
"The following ROM addresses are owned by ASM hooks and will be "
1500 "overwritten on next build. Saving now will write data that asar "
1504 if (!conflicts.empty()) {
1505 if (BeginTable(
"WriteConflictTable", 3,
1506 ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
1507 ImGuiTableFlags_Resizable)) {
1508 TableSetupColumn(
"Address", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1509 TableSetupColumn(
"Ownership", ImGuiTableColumnFlags_WidthFixed, 140.0f);
1510 TableSetupColumn(
"Module", ImGuiTableColumnFlags_WidthStretch);
1513 for (
const auto& conflict : conflicts) {
1516 Text(
"$%06X", conflict.address);
1521 if (!conflict.module.empty()) {
1522 TextUnformatted(conflict.module.c_str());
1524 TextDisabled(tr(
"(unknown)"));
1532 Text(tr(
"%zu conflict(s) detected."), conflicts.size());
1535 if (Button(tr(
"Save Anyway"), ImVec2(0, 0))) {
1539 if (!status.ok() && !absl::IsCancelled(status)) {
1541 toast->Show(absl::StrFormat(
"Save failed: %s", status.message()),
1548 if (Button(tr(
"Cancel"), ImVec2(0, 0)) || IsKeyPressed(ImGuiKey_Escape)) {
1555 using namespace ImGui;
1573 const std::string save_label =
1581 const std::string continue_label =
1590 IsKeyPressed(ImGuiKey_Escape)) {
The EditorManager controls the main editor window and manages the various editor classes.
void ConfirmPendingUnsavedSessionActionSaveAndContinue()
absl::Status SaveRomAs(const std::string &filename)
void CancelPendingUnsavedSessionAction()
void SwitchToSession(size_t index)
absl::Status RestoreRomBackup(const std::string &backup_path)
size_t GetActiveSessionCount() const
Rom * GetCurrentRom() const override
std::vector< editor::RomFileManager::BackupEntry > GetRomBackups() const
void MarkCurrentProjectDirty()
project::RomWritePolicy GetProjectRomWritePolicy() const
absl::Status CreateNewProjectFromRom(const std::string &template_name, const std::string &rom_path, const std::string &project_name, const std::string &project_path=std::string())
void ConfirmPendingUnsavedSessionActionDiscardAndContinue()
std::string GetCurrentRomHash() const
bool HasPendingUnsavedSessionAction() const
void CancelRomWriteConfirm()
bool IsRomBackupRestorePending() const
absl::Status PruneRomBackups()
void SetFontGlobalScale(float scale)
void ResolvePotItemSaveConfirmation(PotItemSaveDecision decision)
auto GetCurrentEditor() const -> Editor *override
WorkspaceWindowManager & window_manager()
std::string GetProjectExpectedRomHash() const
absl::Status SaveProject()
absl::Status DiscardPendingRomBackupRestore()
const std::vector< core::WriteConflict > & pending_write_conflicts() const
std::string GetPendingUnsavedSessionActionContinueLabel() const
std::string GetPendingUnsavedSessionActionPrompt() const
project::RomRole GetProjectRomRole() const
void BypassWriteConflictOnce()
void ClearPendingWriteConflicts()
size_t GetCurrentSessionIndex() const
project::YazeProject * GetCurrentProject()
bool IsRomHashMismatch() const
absl::Status ResumePendingRomSave()
int pending_pot_item_unloaded_rooms() const
int pending_pot_item_total_rooms() const
absl::Status OpenRomOrProject(const std::string &filename)
void RemoveSession(size_t index)
std::string GetPendingUnsavedSessionActionSaveLabel() const
ToastManager * toast_manager()
static PanelLayoutPreset GetLogicDebuggerPreset()
Get the "logic debugger" workspace preset (QA and debug focused)
static PanelLayoutPreset GetDungeonMasterPreset()
Get the "dungeon master" workspace preset.
static PanelLayoutPreset GetAudioEngineerPreset()
Get the "audio engineer" workspace preset (music focused)
static PanelLayoutPreset GetDesignerPreset()
Get the "designer" workspace preset (visual-focused)
static PanelLayoutPreset GetOverworldArtistPreset()
Get the "overworld artist" workspace preset.
static PanelLayoutPreset GetModderPreset()
Get the "modder" workspace preset (full-featured)
static PanelLayoutPreset GetMinimalPreset()
Get the "minimal" workspace preset (minimal cards)
static PanelLayoutPreset GetDeveloperPreset()
Get the "developer" workspace preset (debug-focused)
void HideAll(size_t session_id)
RAII guard for ImGui style vars.
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
static std::string ShowSaveFileDialog(const std::string &default_name="", const std::string &default_extension="")
ShowSaveFileDialog opens a save file dialog and returns the selected filepath. Uses global feature fl...
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
static std::string ShowOpenFolderDialog()
ShowOpenFolderDialog opens a file dialog and returns the selected folder path. Uses global feature fl...
#define YAZE_VERSION_STRING
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_DOOR_SLIDING
#define ICON_MD_VIDEOGAME_ASSET
#define ICON_MD_BUG_REPORT
#define ICON_MD_MUSIC_NOTE
#define ICON_MD_DISPLAY_SETTINGS
#define ICON_MD_CHECK_CIRCLE
#define ICON_MD_DESCRIPTION
#define ICON_MD_DASHBOARD
#define ICON_MD_OPEN_IN_NEW
#define ICON_MD_CONTENT_COPY
#define ICON_MD_CROP_FREE
#define ICON_MD_DELETE_SWEEP
std::string AddressOwnershipToString(AddressOwnership ownership)
ImVec4 ConvertColorToImVec4(const Color &color)
void DrawDisplaySettingsForPopup(ImGuiStyle *ref)
constexpr ImVec2 kDefaultModalSize
void TextWithSeparators(const absl::string_view &text)
std::string RomRoleToString(RomRole role)
std::string RomWritePolicyToString(RomWritePolicy policy)
std::string HexLongLong(uint64_t qword, HexStringParams params)
FileDialogOptions MakeRomFileDialogOptions(bool include_all_files)
Defines default panel visibility for an editor type.
std::string labels_filename
std::string GetAbsolutePath(const std::string &relative_path) const
Public YAZE API umbrella header.