7#include <initializer_list>
9#include "absl/status/status.h"
10#include "absl/strings/match.h"
11#include "absl/strings/str_format.h"
21#include "imgui/misc/cpp/imgui_stdlib.h"
32 : editor_manager_(editor_manager), status_(absl::OkStatus()) {}
151 for (
auto& [name, params] :
popups_) {
152 if (params.is_visible) {
153 OpenPopup(name.c_str());
156 ImGuiWindowFlags popup_flags = params.allow_resize
157 ? ImGuiWindowFlags_None
158 : ImGuiWindowFlags_AlwaysAutoResize;
160 if (BeginPopupModal(name.c_str(),
nullptr, popup_flags)) {
161 params.draw_function();
173 std::string name_str(name);
174 auto it =
popups_.find(name_str);
176 it->second.is_visible =
true;
180 "[PopupManager] Warning: Popup '%s' not registered. Available popups: ",
182 for (
const auto& [key, _] :
popups_) {
183 printf(
"'%s' ", key.c_str());
194 std::string name_str(name);
195 auto it =
popups_.find(name_str);
197 it->second.is_visible =
false;
207 std::string name_str(name);
208 auto it =
popups_.find(name_str);
210 return it->second.is_visible;
224 ImGuiIO
const& io = GetIO();
225 ImVec2 pos(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f);
226 SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
227 ImGuiWindowFlags flags =
228 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
229 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings;
230 return Begin(name,
nullptr, flags);
244 IsKeyPressed(ImGuiKey_Space)) {
258 Text(
"Written by: scawful");
260 Text(
"Special Thanks: Zarby89, JaredBrian");
273 Text(
"Title: %s", current_rom->title().c_str());
280 if (project && project->project_opened()) {
284 Text(
"Write Policy: %s",
287 Text(
"Expected Hash: %s",
288 project->rom_metadata.expected_hash.empty()
290 : project->rom_metadata.expected_hash.c_str());
294 "ROM hash mismatch detected");
299 IsKeyPressed(ImGuiKey_Escape)) {
300 Hide(
"ROM Information");
305 using namespace ImGui;
310 static std::string save_as_filename =
"";
315 InputText(
"Filename", &save_as_filename);
322 if (!file_path.empty()) {
323 save_as_filename = file_path;
328 if (Button(absl::StrFormat(
"%s Save",
ICON_MD_SAVE).c_str(),
330 if (!save_as_filename.empty()) {
332 std::string final_filename = save_as_filename;
333 if (final_filename.find(
".sfc") == std::string::npos &&
334 final_filename.find(
".smc") == std::string::npos) {
335 final_filename +=
".sfc";
340 save_as_filename =
"";
349 save_as_filename =
"";
355 using namespace ImGui;
360 "Controls which data is written during File > Save ROM. "
361 "Changes apply immediately.");
364 if (CollapsingHeader(
"Overworld", ImGuiTreeNodeFlags_DefaultOpen)) {
365 Checkbox(
"Save Overworld Maps",
367 Checkbox(
"Save Overworld Entrances",
369 Checkbox(
"Save Overworld Exits",
371 Checkbox(
"Save Overworld Items",
373 Checkbox(
"Save Overworld Properties",
377 if (CollapsingHeader(
"Dungeon", ImGuiTreeNodeFlags_DefaultOpen)) {
381 Checkbox(
"Save Room Headers",
386 Checkbox(
"Save Collision",
389 Checkbox(
"Save Pot Items",
394 if (CollapsingHeader(
"Graphics", ImGuiTreeNodeFlags_DefaultOpen)) {
395 Checkbox(
"Save Graphics Sheets",
401 if (CollapsingHeader(
"Messages", ImGuiTreeNodeFlags_DefaultOpen)) {
412 using namespace ImGui;
416 Text(
"No ROM loaded.");
424 std::string backup_dir;
425 if (project && project->project_opened() &&
426 !project->rom_backup_folder.empty()) {
429 backup_dir = std::filesystem::path(rom->
filename()).parent_path().string();
434 TextWrapped(
"Backup folder: %s", backup_dir.c_str());
440 toast->Show(absl::StrFormat(
"Prune failed: %s", status.message()),
450 if (backups.empty()) {
451 TextDisabled(
"No backups found.");
452 }
else if (BeginTable(
"RomBackupTable", 4,
453 ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
454 ImGuiTableFlags_Resizable)) {
455 TableSetupColumn(
"Timestamp");
456 TableSetupColumn(
"Size");
457 TableSetupColumn(
"Filename");
458 TableSetupColumn(
"Actions");
461 auto format_size = [](uintmax_t bytes) {
462 if (bytes > (1024 * 1024)) {
463 return absl::StrFormat(
"%.2f MB",
464 static_cast<double>(bytes) / (1024 * 1024));
467 return absl::StrFormat(
"%.1f KB",
static_cast<double>(bytes) / 1024.0);
469 return absl::StrFormat(
"%llu B",
static_cast<unsigned long long>(bytes));
472 for (
size_t i = 0; i < backups.size(); ++i) {
473 const auto& backup = backups[i];
476 char time_buffer[32] =
"unknown";
477 if (backup.timestamp != 0) {
480 localtime_s(&local_tm, &backup.timestamp);
482 localtime_r(&backup.timestamp, &local_tm);
484 std::strftime(time_buffer,
sizeof(time_buffer),
"%Y-%m-%d %H:%M:%S",
487 TextUnformatted(time_buffer);
490 TextUnformatted(format_size(backup.size_bytes).c_str());
493 TextUnformatted(backup.filename.c_str());
496 PushID(
static_cast<int>(i));
501 toast->Show(absl::StrFormat(
"Restore failed: %s", status.message()),
513 toast->Show(absl::StrFormat(
"Open failed: %s", status.message()),
520 SetClipboardText(backup.path.c_str());
534 using namespace ImGui;
536 static std::string project_name =
"";
537 static std::string project_filepath =
"";
538 static std::string rom_filename =
"";
539 static std::string labels_filename =
"";
540 static std::string code_folder =
"";
542 InputText(
"Project Name", &project_name);
544 if (Button(absl::StrFormat(
"%s Destination Folder",
ICON_MD_FOLDER).c_str(),
549 Text(
"%s", project_filepath.empty() ?
"(Not set)" : project_filepath.c_str());
557 Text(
"%s", rom_filename.empty() ?
"(Not set)" : rom_filename.c_str());
559 if (Button(absl::StrFormat(
"%s Labels File",
ICON_MD_LABEL).c_str(),
564 Text(
"%s", labels_filename.empty() ?
"(Not set)" : labels_filename.c_str());
566 if (Button(absl::StrFormat(
"%s Code Folder",
ICON_MD_CODE).c_str(),
571 Text(
"%s", code_folder.empty() ?
"(Not set)" : code_folder.c_str());
575 if (Button(absl::StrFormat(
"%s Choose Project File Location",
ICON_MD_SAVE)
578 auto project_file_path =
580 if (!project_file_path.empty()) {
581 if (!(absl::EndsWith(project_file_path,
".yaze") ||
582 absl::EndsWith(project_file_path,
".yazeproj"))) {
583 project_file_path +=
".yaze";
585 project_filepath = project_file_path;
589 if (Button(absl::StrFormat(
"%s Create Project",
ICON_MD_ADD).c_str(),
591 if (!project_filepath.empty() && !project_name.empty()) {
596 project_filepath =
"";
598 labels_filename =
"";
609 project_filepath =
"";
611 labels_filename =
"";
624 auto status_color = [&](
const char* status) -> ImVec4 {
625 if (strcmp(status,
"Stable") == 0 || strcmp(status,
"Working") == 0) {
628 if (strcmp(status,
"Beta") == 0 || strcmp(status,
"Experimental") == 0) {
631 if (strcmp(status,
"Preview") == 0) {
634 if (strcmp(status,
"Not available") == 0) {
643 const char* persistence;
647 auto draw_table = [&](
const char* table_id,
648 std::initializer_list<FeatureRow> rows) {
649 ImGuiTableFlags flags = ImGuiTableFlags_BordersInnerH |
650 ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable;
651 if (!BeginTable(table_id, 4, flags)) {
654 TableSetupColumn(
"Feature", ImGuiTableColumnFlags_WidthStretch);
655 TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 120.0f);
656 TableSetupColumn(
"Save/Load", ImGuiTableColumnFlags_WidthFixed, 180.0f);
657 TableSetupColumn(
"Notes", ImGuiTableColumnFlags_WidthStretch);
660 for (
const auto& row : rows) {
662 TableSetColumnIndex(0);
663 TextUnformatted(row.feature);
664 TableSetColumnIndex(1);
665 TextColored(status_color(row.status),
"%s", row.status);
666 TableSetColumnIndex(2);
667 TextUnformatted(row.persistence);
668 TableSetColumnIndex(3);
669 TextWrapped(
"%s", row.notes);
676 "Status: Stable = production ready, Beta = usable with gaps, "
677 "Experimental = WIP, Preview = web parity in progress.");
678 TextDisabled(
"See Settings > Feature Flags for ROM-specific toggles.");
681 if (CollapsingHeader(
"Desktop App (yaze)", ImGuiTreeNodeFlags_DefaultOpen)) {
682 draw_table(
"desktop_features",
684 {
"ROM load/save",
"Stable",
"ROM + backups",
685 "Backups on save when enabled."},
686 {
"Overworld Editor",
"Stable",
"ROM",
687 "Maps/entrances/exits/items; version-gated."},
688 {
"Dungeon Editor",
"Stable",
"ROM",
689 "Room objects/tiles/palettes persist."},
690 {
"Palette Editor",
"Stable",
"ROM",
691 "Palette edits persist; JSON IO pending."},
692 {
"Graphics Editor",
"Beta",
"ROM",
693 "Sheet edits persist; tooling still expanding."},
694 {
"Sprite Editor",
"Stable",
"ROM",
"Sprite edits persist."},
695 {
"Message Editor",
"Stable",
"ROM",
"Text edits persist."},
696 {
"Screen Editor",
"Experimental",
"ROM (partial)",
697 "Save coverage incomplete."},
698 {
"Hex Editor",
"Beta",
"ROM",
"Search UX incomplete."},
699 {
"Assembly/Asar",
"Beta",
"ROM + project",
700 "Patch apply + symbol export."},
701 {
"Emulator",
"Beta",
"Runtime only",
702 "Save-state UI partially wired."},
703 {
"Music Editor",
"Experimental",
"ROM (partial)",
704 "Serialization in progress."},
705 {
"Agent UI",
"Experimental",
".yaze/agent",
706 "Requires AI provider configuration."},
707 {
"Settings/Layouts",
"Beta",
".yaze config",
708 "Layout serialization improving."},
712 if (CollapsingHeader(
"z3ed CLI")) {
713 draw_table(
"cli_features",
715 {
"ROM read/write/validate",
"Stable",
"ROM file",
716 "Direct command execution."},
717 {
"Agent workflows",
"Stable",
".yaze/proposals + sandboxes",
718 "Commit writes ROM; revert reloads."},
719 {
"Snapshots/restore",
"Stable",
"Sandbox copies",
720 "Supports YAZE_SANDBOX_ROOT override."},
721 {
"Doctor/test suites",
"Stable",
"Reports",
722 "Structured output for automation."},
723 {
"TUI/REPL",
"Stable",
"Session history",
724 "Interactive command palette + logs."},
728 if (CollapsingHeader(
"Web/WASM Preview")) {
732 {
"ROM load/save",
"Preview",
"IndexedDB + download",
733 "Drag/drop or picker; download for backups."},
734 {
"Editors (OW/Dungeon/Palette/etc.)",
"Preview",
735 "IndexedDB + download",
"Parity work in progress."},
736 {
"Hex Editor",
"Working",
"IndexedDB + download",
737 "Direct ROM editing available."},
738 {
"Asar patching",
"Preview",
"ROM",
"Basic patch apply support."},
739 {
"Emulator",
"Not available",
"N/A",
"Desktop only."},
740 {
"Collaboration",
"Experimental",
"Server",
741 "Requires yaze-server."},
742 {
"AI features",
"Preview",
"Server",
"Requires AI-enabled server."},
752 Text(
"File -> Open");
753 Text(
"Select a ROM file to open");
754 Text(
"Supported ROMs (headered or unheadered):");
755 Text(
"The Legend of Zelda: A Link to the Past");
756 Text(
"US Version 1.0");
757 Text(
"JP Version 1.0");
759 TextWrapped(
"ROM files are not bundled. Use a clean, legally obtained copy.");
767 Text(
"Project Menu");
768 Text(
"Create a new project or open an existing one.");
769 Text(
"Save the project to save the current state of the project.");
771 "To save a project, you need to first open a ROM and initialize your "
772 "code path and labels file. Label resource manager can be found in "
773 "the View menu. Code path is set in the Code editor after opening a "
777 Hide(
"Manage Project");
784 "YAZE lets you modify 'The Legend of Zelda: A Link to the Past' (US or "
785 "JP) ROMs with modern tooling.");
787 TextWrapped(
"Release Highlights:");
789 "AI-assisted workflows via z3ed agent and in-app panels "
790 "(Ollama/Gemini/OpenAI/Anthropic)");
791 BulletText(
"Clear feature status panels and improved help/tooltips");
792 BulletText(
"Unified .yaze storage across desktop/CLI/web");
794 TextWrapped(
"General Tips:");
795 BulletText(
"Open a clean ROM and save a backup before editing");
796 BulletText(
"Use Help (F1) for context-aware guidance and shortcuts");
798 "Configure AI providers (Ollama/Gemini/OpenAI/Anthropic) in Settings > "
802 Hide(
"Getting Started");
807 TextWrapped(
"Asar 65816 Assembly Integration");
808 TextWrapped(
"YAZE includes full Asar assembler support for ROM patching.");
810 TextWrapped(
"Features:");
811 BulletText(
"Cross-platform ROM patching with assembly code");
812 BulletText(
"Symbol export with addresses and opcodes");
813 BulletText(
"Assembly validation with detailed error reporting");
814 BulletText(
"Memory-safe patch application with size checks");
817 Hide(
"Asar Integration");
822 TextWrapped(
"Build Instructions");
823 TextWrapped(
"YAZE uses modern CMake for cross-platform builds.");
825 TextWrapped(
"Quick Start (examples):");
826 BulletText(
"cmake --preset mac-dbg | lin-dbg | win-dbg");
827 BulletText(
"cmake --build --preset <preset> --target yaze");
829 TextWrapped(
"AI Builds:");
830 BulletText(
"cmake --preset mac-ai | lin-ai | win-ai");
831 BulletText(
"cmake --build --preset <preset> --target yaze z3ed");
833 TextWrapped(
"Docs: docs/public/build/quick-reference.md");
836 Hide(
"Build Instructions");
841 TextWrapped(
"Command Line Interface (z3ed)");
842 TextWrapped(
"Scriptable ROM editing and AI agent workflows.");
844 TextWrapped(
"Commands:");
845 BulletText(
"z3ed rom-info --rom=zelda3.sfc");
846 BulletText(
"z3ed agent simple-chat --rom=zelda3.sfc --ai_provider=auto");
847 BulletText(
"z3ed agent plan --rom=zelda3.sfc");
848 BulletText(
"z3ed test-list --format json");
849 BulletText(
"z3ed patch apply-asar patch.asm --rom=zelda3.sfc");
850 BulletText(
"z3ed help dungeon-place-sprite");
852 TextWrapped(
"Storage:");
853 BulletText(
"Agent plans/proposals live under ~/.yaze (see docs for details)");
861 TextWrapped(
"Troubleshooting");
862 TextWrapped(
"Common issues and solutions:");
864 BulletText(
"ROM won't load: Check file format (SFC/SMC supported)");
866 "AI agent missing: Start Ollama or set GEMINI_API_KEY/OPENAI_API_KEY/"
867 "ANTHROPIC_API_KEY (web uses AI_AGENT_ENDPOINT)");
868 BulletText(
"Graphics issues: Disable experimental flags in Settings");
869 BulletText(
"Performance: Enable hardware acceleration in display settings");
870 BulletText(
"Crashes: Check ROM file integrity and available memory");
871 BulletText(
"Layout issues: Reset workspace layouts from View > Layouts");
874 Hide(
"Troubleshooting");
879 TextWrapped(
"Contributing to YAZE");
880 TextWrapped(
"YAZE is open source and welcomes contributions!");
882 TextWrapped(
"How to contribute:");
883 BulletText(
"Fork the repository on GitHub");
884 BulletText(
"Create feature branches for new work");
885 BulletText(
"Follow C++ coding standards");
886 BulletText(
"Include tests for new features");
887 BulletText(
"Submit pull requests for review");
890 Hide(
"Contributing");
898 if (CollapsingHeader(
901 ImGuiTreeNodeFlags_DefaultOpen)) {
902 BulletText(
"Feature status/persistence summaries across desktop/CLI/web");
903 BulletText(
"Shortcut/help panels now match configured keybindings");
904 BulletText(
"Refined onboarding tips and error messaging");
905 BulletText(
"Help text refreshed across desktop, CLI, and web");
908 if (CollapsingHeader(
909 absl::StrFormat(
"%s Development & Build System",
ICON_MD_BUILD)
911 ImGuiTreeNodeFlags_DefaultOpen)) {
912 BulletText(
"Asar 65816 assembler integration for ROM patching");
913 BulletText(
"z3ed CLI + TUI for scripting, test/doctor, and automation");
914 BulletText(
"Modern CMake presets for desktop, AI, and web builds");
915 BulletText(
"Unified version + storage references for 0.5.1");
918 if (CollapsingHeader(
920 BulletText(
"Improved project metadata + .yaze storage alignment");
921 BulletText(
"Stronger error reporting and status feedback");
922 BulletText(
"Performance and stability improvements across editors");
923 BulletText(
"Expanded logging and diagnostics tooling");
926 if (CollapsingHeader(
927 absl::StrFormat(
"%s Editor Features",
ICON_MD_EDIT).c_str())) {
928 BulletText(
"Music editor updates with SPC parsing/playback");
929 BulletText(
"AI agent-assisted editing workflows (multi-provider + vision)");
930 BulletText(
"Expanded overworld/dungeon tooling and palette accuracy");
931 BulletText(
"Web/WASM preview with collaboration hooks");
949 TextWrapped(
"Workspace Management");
951 "YAZE supports multiple ROM sessions and flexible workspace layouts.");
954 TextWrapped(
"Session Management:");
955 BulletText(
"Ctrl+Shift+N: Create new session");
956 BulletText(
"Ctrl+Shift+W: Close current session");
957 BulletText(
"Ctrl+Tab: Quick session switcher");
958 BulletText(
"Each session maintains its own ROM and editor state");
961 TextWrapped(
"Layout Management:");
962 BulletText(
"Drag window tabs to dock/undock");
963 BulletText(
"Ctrl+Shift+S: Save current layout");
964 BulletText(
"Ctrl+Shift+O: Load saved layout");
965 BulletText(
"F11: Maximize current window");
968 TextWrapped(
"Preset Layouts:");
969 BulletText(
"Developer: Code, memory, testing tools");
970 BulletText(
"Designer: Graphics, palettes, sprites");
971 BulletText(
"Modder: All gameplay editing tools");
974 Hide(
"Workspace Help");
980 TextWrapped(
"You have reached the recommended session limit.");
981 TextWrapped(
"Having too many sessions open may impact performance.");
983 TextWrapped(
"Consider closing unused sessions or saving your work.");
986 Hide(
"Session Limit Warning");
990 Hide(
"Session Limit Warning");
997 TextWrapped(
"This will reset your current workspace layout to default.");
998 TextWrapped(
"Any custom window arrangements will be lost.");
1000 TextWrapped(
"Do you want to continue?");
1003 Hide(
"Layout Reset Confirm");
1008 Hide(
"Layout Reset Confirm");
1017 TextWrapped(
"Choose a workspace preset to quickly configure your layout:");
1024 const char* description;
1028 PresetInfo presets[] = {
1030 "Essential cards only - maximum editing space",
1033 "Debug and development focused - CPU/Memory/Breakpoints",
1036 "Visual and artistic focused - Graphics/Palettes/Sprites",
1039 "Full-featured - All tools available for comprehensive editing",
1042 "Complete overworld editing toolkit with all map tools",
1045 "Complete dungeon editing toolkit with room tools",
1047 {
"Testing",
ICON_MD_SCIENCE,
"Quality assurance and ROM testing layout",
1053 constexpr int kPresetCount = 8;
1056 float button_width = 200.0f;
1057 float button_height = 50.0f;
1059 for (
int i = 0; i < kPresetCount; i++) {
1065 ImVec2(0.0f, 0.5f));
1066 if (Button(absl::StrFormat(
"%s %s", presets[i].icon, presets[i].name)
1068 ImVec2(button_width, button_height))) {
1070 auto preset = presets[i].getter();
1075 for (
const auto& panel_id : preset.default_visible_panels) {
1076 window_manager.OpenWindow(panel_id);
1082 if (IsItemHovered()) {
1084 TextUnformatted(presets[i].description);
1099 if (current_editor) {
1100 auto current_type = current_editor->
type();
1101 window_manager.ResetToDefaults(0, current_type);
1107 if (Button(
"Close", ImVec2(-1, 0))) {
1120 Text(
"Active Sessions: %zu", session_count);
1124 if (BeginTable(
"SessionTable", 4,
1125 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
1126 TableSetupColumn(
"#", ImGuiTableColumnFlags_WidthFixed, 30.0f);
1127 TableSetupColumn(
"ROM", ImGuiTableColumnFlags_WidthStretch);
1128 TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 80.0f);
1129 TableSetupColumn(
"Actions", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1132 for (
size_t i = 0; i < session_count; i++) {
1136 TableSetColumnIndex(0);
1140 TableSetColumnIndex(1);
1141 if (i == active_session) {
1144 TextUnformatted(rom->
filename().c_str());
1146 TextDisabled(
"(No ROM loaded)");
1149 TextDisabled(
"Session %zu", i + 1);
1153 TableSetColumnIndex(2);
1154 if (i == active_session) {
1157 TextDisabled(
"Inactive");
1161 TableSetColumnIndex(3);
1162 PushID(
static_cast<int>(i));
1164 if (i != active_session) {
1165 if (SmallButton(
"Switch")) {
1171 BeginDisabled(session_count <= 1);
1172 if (SmallButton(
"Close")) {
1188 if (Button(absl::StrFormat(
"%s New Session",
ICON_MD_ADD).c_str(),
1194 if (Button(
"Close", ImVec2(-1, 0))) {
1201 SetNextWindowSize(ImVec2(900, 700), ImGuiCond_FirstUseEver);
1202 SetNextWindowSizeConstraints(ImVec2(600, 400), ImVec2(FLT_MAX, FLT_MAX));
1205 TextWrapped(
"Customize your YAZE experience - accessible anytime!");
1210 float available_height =
1211 GetContentRegionAvail().y - 60;
1212 if (BeginChild(
"DisplaySettingsContent", ImVec2(0, available_height),
true,
1213 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
1222 ImGuiIO& io = GetIO();
1224 Text(
"Global Font Scale");
1225 float font_global_scale = io.FontGlobalScale;
1226 if (SliderFloat(
"##global_scale", &font_global_scale, 0.5f, 2.0f,
"%.2f")) {
1230 io.FontGlobalScale = font_global_scale;
1238 Hide(
"Display Settings");
1243 using namespace ImGui;
1246 Text(
"Feature Flags Configuration");
1249 BeginChild(
"##FlagsContent", ImVec2(0, -30),
true);
1254 if (BeginTabBar(
"FlagCategories")) {
1255 if (BeginTabItem(
"Overworld")) {
1259 if (BeginTabItem(
"Dungeon")) {
1263 if (BeginTabItem(
"Resources")) {
1267 if (BeginTabItem(
"System")) {
1283 using namespace ImGui;
1285 Text(
"Data Integrity Check Results");
1288 BeginChild(
"##IntegrityContent", ImVec2(0, -30),
true);
1292 Text(
"ROM Data Integrity:");
1300 Text(
"No issues detected.");
1311 using namespace ImGui;
1314 Text(
"Editor manager unavailable.");
1324 Text(
"Pot Item Save Confirmation");
1327 "Dungeon pot item saving is enabled, but %d of %d rooms are not loaded.",
1331 "Saving now can overwrite pot items in unloaded rooms. Choose how to "
1335 if (Button(
"Save without pot items", ImVec2(0, 0))) {
1342 if (Button(
"Save anyway", ImVec2(0, 0))) {
1349 if (Button(
"Cancel", ImVec2(0, 0))) {
1357 using namespace ImGui;
1360 Text(
"Editor manager unavailable.");
1376 const auto editable_path =
1377 project && project->hack_manifest.loaded() &&
1378 !project->hack_manifest.build_pipeline().dev_rom.empty()
1379 ? project->GetAbsolutePath(
1380 project->hack_manifest.build_pipeline().dev_rom)
1381 : (project ? project->rom_filename : std::string());
1383 Text(
"ROM Write Confirmation");
1386 "The loaded ROM hash does not match the project's expected hash.");
1388 Text(
"Role: %s", role.c_str());
1389 Text(
"Write policy: %s", policy.c_str());
1390 Text(
"Loaded ROM: %s",
1391 actual_path.empty() ?
"(unknown)" : actual_path.c_str());
1392 Text(
"Editable target: %s",
1393 editable_path.empty() ?
"(unset)" : editable_path.c_str());
1394 Text(
"Expected: %s", expected.empty() ?
"(unset)" : expected.c_str());
1395 Text(
"Actual: %s", actual.empty() ?
"(unknown)" : actual.c_str());
1398 "Proceeding will write to the current ROM file. This may corrupt a base "
1399 "or release ROM if it is not the intended editable project ROM.");
1402 if (Button(
"Save anyway", ImVec2(0, 0))) {
1406 if (!status.ok() && !absl::IsCancelled(status)) {
1408 toast->Show(absl::StrFormat(
"Save failed: %s", status.message()),
1415 if (Button(
"Cancel", ImVec2(0, 0)) || IsKeyPressed(ImGuiKey_Escape)) {
1422 using namespace ImGui;
1425 Text(
"Editor manager unavailable.");
1438 "The following ROM addresses are owned by ASM hooks and will be "
1439 "overwritten on next build. Saving now will write data that asar "
1443 if (!conflicts.empty()) {
1444 if (BeginTable(
"WriteConflictTable", 3,
1445 ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
1446 ImGuiTableFlags_Resizable)) {
1447 TableSetupColumn(
"Address", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1448 TableSetupColumn(
"Ownership", ImGuiTableColumnFlags_WidthFixed, 140.0f);
1449 TableSetupColumn(
"Module", ImGuiTableColumnFlags_WidthStretch);
1452 for (
const auto& conflict : conflicts) {
1455 Text(
"$%06X", conflict.address);
1460 if (!conflict.module.empty()) {
1461 TextUnformatted(conflict.module.c_str());
1463 TextDisabled(
"(unknown)");
1471 Text(
"%zu conflict(s) detected.", conflicts.size());
1474 if (Button(
"Save Anyway", ImVec2(0, 0))) {
1478 if (!status.ok() && !absl::IsCancelled(status)) {
1480 toast->Show(absl::StrFormat(
"Save failed: %s", status.message()),
1487 if (Button(
"Cancel", ImVec2(0, 0)) || IsKeyPressed(ImGuiKey_Escape)) {
The EditorManager controls the main editor window and manages the various editor classes.
absl::Status SaveRomAs(const std::string &filename)
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
project::RomWritePolicy GetProjectRomWritePolicy() const
absl::Status CreateNewProject(const std::string &template_name="Basic ROM Hack")
std::string GetCurrentRomHash() const
void CancelRomWriteConfirm()
absl::Status PruneRomBackups()
void SetFontGlobalScale(float scale)
void ResolvePotItemSaveConfirmation(PotItemSaveDecision decision)
WorkspaceWindowManager & window_manager()
auto GetCurrentEditor() const -> Editor *
std::string GetProjectExpectedRomHash() const
const std::vector< core::WriteConflict > & pending_write_conflicts() const
project::RomRole GetProjectRomRole() const
void BypassWriteConflictOnce()
void ClearPendingWriteConflicts()
size_t GetCurrentSessionId() const
project::YazeProject * GetCurrentProject()
bool IsRomHashMismatch() const
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)
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 GetAbsolutePath(const std::string &relative_path) const
Public YAZE API umbrella header.