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()) {}
55 false,
false, [
this]() {
59 false,
true, [
this]() {
89 false,
false, [
this]() {
115 false,
false, [
this]() {
138 false,
false, [
this]() {
185 for (
auto& [name, params] :
popups_) {
186 if (params.is_visible) {
187 OpenPopup(name.c_str());
190 ImGuiWindowFlags popup_flags = params.allow_resize
191 ? ImGuiWindowFlags_None
192 : ImGuiWindowFlags_AlwaysAutoResize;
194 if (BeginPopupModal(name.c_str(),
nullptr, popup_flags)) {
195 params.draw_function();
207 std::string name_str(name);
208 auto it =
popups_.find(name_str);
210 it->second.is_visible =
true;
214 "[PopupManager] Warning: Popup '%s' not registered. Available popups: ",
216 for (
const auto& [key, _] :
popups_) {
217 printf(
"'%s' ", key.c_str());
228 std::string name_str(name);
229 auto it =
popups_.find(name_str);
231 it->second.is_visible =
false;
241 std::string name_str(name);
242 auto it =
popups_.find(name_str);
244 return it->second.is_visible;
258 ImGuiIO
const& io = GetIO();
259 ImVec2 pos(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f);
260 SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
261 ImGuiWindowFlags flags =
262 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
263 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings;
264 return Begin(name,
nullptr, flags);
291 Text(
"Written by: scawful");
293 Text(
"Special Thanks: Zarby89, JaredBrian");
306 Text(
"Title: %s", current_rom->title().c_str());
314 if (project && project->project_opened()) {
317 Text(
"Write Policy: %s",
320 Text(
"Expected Hash: %s",
321 project->rom_metadata.expected_hash.empty()
323 : project->rom_metadata.expected_hash.c_str());
327 "ROM hash mismatch detected");
332 IsKeyPressed(ImGuiKey_Escape)) {
333 Hide(
"ROM Information");
338 using namespace ImGui;
343 static std::string save_as_filename =
"";
348 InputText(
"Filename", &save_as_filename);
355 if (!file_path.empty()) {
356 save_as_filename = file_path;
361 if (Button(absl::StrFormat(
"%s Save",
ICON_MD_SAVE).c_str(),
363 if (!save_as_filename.empty()) {
365 std::string final_filename = save_as_filename;
366 if (final_filename.find(
".sfc") == std::string::npos &&
367 final_filename.find(
".smc") == std::string::npos) {
368 final_filename +=
".sfc";
373 save_as_filename =
"";
382 save_as_filename =
"";
388 using namespace ImGui;
393 "Controls which data is written during File > Save ROM. "
394 "Changes apply immediately.");
397 if (CollapsingHeader(
"Overworld", ImGuiTreeNodeFlags_DefaultOpen)) {
398 Checkbox(
"Save Overworld Maps",
400 Checkbox(
"Save Overworld Entrances",
402 Checkbox(
"Save Overworld Exits",
404 Checkbox(
"Save Overworld Items",
406 Checkbox(
"Save Overworld Properties",
410 if (CollapsingHeader(
"Dungeon", ImGuiTreeNodeFlags_DefaultOpen)) {
414 Checkbox(
"Save Room Headers",
419 Checkbox(
"Save Collision",
422 Checkbox(
"Save Pot Items",
424 Checkbox(
"Save Palettes",
428 if (CollapsingHeader(
"Graphics", ImGuiTreeNodeFlags_DefaultOpen)) {
429 Checkbox(
"Save Graphics Sheets",
435 if (CollapsingHeader(
"Messages", ImGuiTreeNodeFlags_DefaultOpen)) {
446 using namespace ImGui;
450 Text(
"No ROM loaded.");
458 std::string backup_dir;
459 if (project && project->project_opened() &&
460 !project->rom_backup_folder.empty()) {
463 backup_dir = std::filesystem::path(rom->
filename()).parent_path().string();
468 TextWrapped(
"Backup folder: %s", backup_dir.c_str());
474 toast->Show(absl::StrFormat(
"Prune failed: %s", status.message()),
484 if (backups.empty()) {
485 TextDisabled(
"No backups found.");
486 }
else if (BeginTable(
"RomBackupTable", 4,
487 ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
488 ImGuiTableFlags_Resizable)) {
489 TableSetupColumn(
"Timestamp");
490 TableSetupColumn(
"Size");
491 TableSetupColumn(
"Filename");
492 TableSetupColumn(
"Actions");
495 auto format_size = [](uintmax_t bytes) {
496 if (bytes > (1024 * 1024)) {
497 return absl::StrFormat(
"%.2f MB",
498 static_cast<double>(bytes) / (1024 * 1024));
501 return absl::StrFormat(
"%.1f KB",
502 static_cast<double>(bytes) / 1024.0);
504 return absl::StrFormat(
"%llu B",
505 static_cast<unsigned long long>(bytes));
508 for (
size_t i = 0; i < backups.size(); ++i) {
509 const auto& backup = backups[i];
512 char time_buffer[32] =
"unknown";
513 if (backup.timestamp != 0) {
516 localtime_s(&local_tm, &backup.timestamp);
518 localtime_r(&backup.timestamp, &local_tm);
520 std::strftime(time_buffer,
sizeof(time_buffer),
"%Y-%m-%d %H:%M:%S",
523 TextUnformatted(time_buffer);
526 TextUnformatted(format_size(backup.size_bytes).c_str());
529 TextUnformatted(backup.filename.c_str());
532 PushID(
static_cast<int>(i));
538 absl::StrFormat(
"Restore failed: %s", status.message()),
551 absl::StrFormat(
"Open failed: %s", status.message()),
558 SetClipboardText(backup.path.c_str());
572 using namespace ImGui;
574 static std::string project_name =
"";
575 static std::string project_filepath =
"";
576 static std::string rom_filename =
"";
577 static std::string labels_filename =
"";
578 static std::string code_folder =
"";
580 InputText(
"Project Name", &project_name);
582 if (Button(absl::StrFormat(
"%s Destination Folder",
ICON_MD_FOLDER).c_str(),
587 Text(
"%s", project_filepath.empty() ?
"(Not set)" : project_filepath.c_str());
595 Text(
"%s", rom_filename.empty() ?
"(Not set)" : rom_filename.c_str());
597 if (Button(absl::StrFormat(
"%s Labels File",
ICON_MD_LABEL).c_str(),
602 Text(
"%s", labels_filename.empty() ?
"(Not set)" : labels_filename.c_str());
604 if (Button(absl::StrFormat(
"%s Code Folder",
ICON_MD_CODE).c_str(),
609 Text(
"%s", code_folder.empty() ?
"(Not set)" : code_folder.c_str());
613 if (Button(absl::StrFormat(
"%s Choose Project File Location",
ICON_MD_SAVE)
616 auto project_file_path =
618 if (!project_file_path.empty()) {
619 if (!(absl::EndsWith(project_file_path,
".yaze") ||
620 absl::EndsWith(project_file_path,
".yazeproj"))) {
621 project_file_path +=
".yaze";
623 project_filepath = project_file_path;
627 if (Button(absl::StrFormat(
"%s Create Project",
ICON_MD_ADD).c_str(),
629 if (!project_filepath.empty() && !project_name.empty()) {
634 project_filepath =
"";
636 labels_filename =
"";
647 project_filepath =
"";
649 labels_filename =
"";
662 auto status_color = [&](
const char* status) -> ImVec4 {
663 if (strcmp(status,
"Stable") == 0 || strcmp(status,
"Working") == 0) {
666 if (strcmp(status,
"Beta") == 0 || strcmp(status,
"Experimental") == 0) {
669 if (strcmp(status,
"Preview") == 0) {
672 if (strcmp(status,
"Not available") == 0) {
681 const char* persistence;
685 auto draw_table = [&](
const char* table_id,
686 std::initializer_list<FeatureRow> rows) {
687 ImGuiTableFlags flags = ImGuiTableFlags_BordersInnerH |
688 ImGuiTableFlags_RowBg |
689 ImGuiTableFlags_Resizable;
690 if (!BeginTable(table_id, 4, flags)) {
693 TableSetupColumn(
"Feature", ImGuiTableColumnFlags_WidthStretch);
694 TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 120.0f);
695 TableSetupColumn(
"Save/Load", ImGuiTableColumnFlags_WidthFixed, 180.0f);
696 TableSetupColumn(
"Notes", ImGuiTableColumnFlags_WidthStretch);
699 for (
const auto& row : rows) {
701 TableSetColumnIndex(0);
702 TextUnformatted(row.feature);
703 TableSetColumnIndex(1);
704 TextColored(status_color(row.status),
"%s", row.status);
705 TableSetColumnIndex(2);
706 TextUnformatted(row.persistence);
707 TableSetColumnIndex(3);
708 TextWrapped(
"%s", row.notes);
715 "Status: Stable = production ready, Beta = usable with gaps, "
716 "Experimental = WIP, Preview = web parity in progress.");
717 TextDisabled(
"See Settings > Feature Flags for ROM-specific toggles.");
720 if (CollapsingHeader(
"Desktop App (yaze)", ImGuiTreeNodeFlags_DefaultOpen)) {
724 {
"ROM load/save",
"Stable",
"ROM + backups",
725 "Backups on save when enabled."},
726 {
"Overworld Editor",
"Stable",
"ROM",
727 "Maps/entrances/exits/items; version-gated."},
728 {
"Dungeon Editor",
"Stable",
"ROM",
729 "Room objects/tiles/palettes persist."},
730 {
"Palette Editor",
"Stable",
"ROM",
731 "Palette edits persist; JSON IO pending."},
732 {
"Graphics Editor",
"Beta",
"ROM",
733 "Sheet edits persist; tooling still expanding."},
734 {
"Sprite Editor",
"Stable",
"ROM",
"Sprite edits persist."},
735 {
"Message Editor",
"Stable",
"ROM",
"Text edits persist."},
736 {
"Screen Editor",
"Experimental",
"ROM (partial)",
737 "Save coverage incomplete."},
738 {
"Hex Editor",
"Beta",
"ROM",
"Search UX incomplete."},
739 {
"Assembly/Asar",
"Beta",
"ROM + project",
740 "Patch apply + symbol export."},
741 {
"Emulator",
"Beta",
"Runtime only",
742 "Save-state UI partially wired."},
743 {
"Music Editor",
"Experimental",
"ROM (partial)",
744 "Serialization in progress."},
745 {
"Agent UI",
"Experimental",
".yaze/agent",
746 "Requires AI provider configuration."},
747 {
"Settings/Layouts",
"Beta",
".yaze config",
748 "Layout serialization improving."},
752 if (CollapsingHeader(
"z3ed CLI")) {
756 {
"ROM read/write/validate",
"Stable",
"ROM file",
757 "Direct command execution."},
758 {
"Agent workflows",
"Stable",
".yaze/proposals + sandboxes",
759 "Commit writes ROM; revert reloads."},
760 {
"Snapshots/restore",
"Stable",
"Sandbox copies",
761 "Supports YAZE_SANDBOX_ROOT override."},
762 {
"Doctor/test suites",
"Stable",
"Reports",
763 "Structured output for automation."},
764 {
"TUI/REPL",
"Stable",
"Session history",
765 "Interactive command palette + logs."},
769 if (CollapsingHeader(
"Web/WASM Preview")) {
773 {
"ROM load/save",
"Preview",
"IndexedDB + download",
774 "Drag/drop or picker; download for backups."},
775 {
"Editors (OW/Dungeon/Palette/etc.)",
"Preview",
776 "IndexedDB + download",
"Parity work in progress."},
777 {
"Hex Editor",
"Working",
"IndexedDB + download",
778 "Direct ROM editing available."},
779 {
"Asar patching",
"Preview",
"ROM",
780 "Basic patch apply support."},
781 {
"Emulator",
"Not available",
"N/A",
"Desktop only."},
782 {
"Collaboration",
"Experimental",
"Server",
783 "Requires yaze-server."},
784 {
"AI features",
"Preview",
"Server",
785 "Requires AI-enabled server."},
795 Text(
"File -> Open");
796 Text(
"Select a ROM file to open");
797 Text(
"Supported ROMs (headered or unheadered):");
798 Text(
"The Legend of Zelda: A Link to the Past");
799 Text(
"US Version 1.0");
800 Text(
"JP Version 1.0");
802 TextWrapped(
"ROM files are not bundled. Use a clean, legally obtained copy.");
810 Text(
"Project Menu");
811 Text(
"Create a new project or open an existing one.");
812 Text(
"Save the project to save the current state of the project.");
814 "To save a project, you need to first open a ROM and initialize your "
815 "code path and labels file. Label resource manager can be found in "
816 "the View menu. Code path is set in the Code editor after opening a "
820 Hide(
"Manage Project");
827 "YAZE lets you modify 'The Legend of Zelda: A Link to the Past' (US or "
828 "JP) ROMs with modern tooling.");
830 TextWrapped(
"Release Highlights:");
832 "AI-assisted workflows via z3ed agent and in-app panels "
833 "(Ollama/Gemini/OpenAI/Anthropic)");
834 BulletText(
"Clear feature status panels and improved help/tooltips");
835 BulletText(
"Unified .yaze storage across desktop/CLI/web");
837 TextWrapped(
"General Tips:");
838 BulletText(
"Open a clean ROM and save a backup before editing");
839 BulletText(
"Use Help (F1) for context-aware guidance and shortcuts");
841 "Configure AI providers (Ollama/Gemini/OpenAI/Anthropic) in Settings > "
845 Hide(
"Getting Started");
850 TextWrapped(
"Asar 65816 Assembly Integration");
852 "YAZE includes full Asar assembler support for ROM patching.");
854 TextWrapped(
"Features:");
855 BulletText(
"Cross-platform ROM patching with assembly code");
856 BulletText(
"Symbol export with addresses and opcodes");
857 BulletText(
"Assembly validation with detailed error reporting");
858 BulletText(
"Memory-safe patch application with size checks");
861 Hide(
"Asar Integration");
866 TextWrapped(
"Build Instructions");
867 TextWrapped(
"YAZE uses modern CMake for cross-platform builds.");
869 TextWrapped(
"Quick Start (examples):");
870 BulletText(
"cmake --preset mac-dbg | lin-dbg | win-dbg");
871 BulletText(
"cmake --build --preset <preset> --target yaze");
873 TextWrapped(
"AI Builds:");
874 BulletText(
"cmake --preset mac-ai | lin-ai | win-ai");
875 BulletText(
"cmake --build --preset <preset> --target yaze z3ed");
877 TextWrapped(
"Docs: docs/public/build/quick-reference.md");
880 Hide(
"Build Instructions");
885 TextWrapped(
"Command Line Interface (z3ed)");
886 TextWrapped(
"Scriptable ROM editing and AI agent workflows.");
888 TextWrapped(
"Commands:");
889 BulletText(
"z3ed rom-info --rom=zelda3.sfc");
890 BulletText(
"z3ed agent simple-chat --rom=zelda3.sfc --ai_provider=auto");
891 BulletText(
"z3ed agent plan --rom=zelda3.sfc");
892 BulletText(
"z3ed test-list --format json");
893 BulletText(
"z3ed patch apply-asar patch.asm --rom=zelda3.sfc");
894 BulletText(
"z3ed help dungeon-place-sprite");
896 TextWrapped(
"Storage:");
897 BulletText(
"Agent plans/proposals live under ~/.yaze (see docs for details)");
905 TextWrapped(
"Troubleshooting");
906 TextWrapped(
"Common issues and solutions:");
908 BulletText(
"ROM won't load: Check file format (SFC/SMC supported)");
910 "AI agent missing: Start Ollama or set GEMINI_API_KEY/OPENAI_API_KEY/"
911 "ANTHROPIC_API_KEY (web uses AI_AGENT_ENDPOINT)");
912 BulletText(
"Graphics issues: Disable experimental flags in Settings");
913 BulletText(
"Performance: Enable hardware acceleration in display settings");
914 BulletText(
"Crashes: Check ROM file integrity and available memory");
915 BulletText(
"Layout issues: Reset workspace layouts from View > Layouts");
918 Hide(
"Troubleshooting");
923 TextWrapped(
"Contributing to YAZE");
924 TextWrapped(
"YAZE is open source and welcomes contributions!");
926 TextWrapped(
"How to contribute:");
927 BulletText(
"Fork the repository on GitHub");
928 BulletText(
"Create feature branches for new work");
929 BulletText(
"Follow C++ coding standards");
930 BulletText(
"Include tests for new features");
931 BulletText(
"Submit pull requests for review");
934 Hide(
"Contributing");
942 if (CollapsingHeader(
945 ImGuiTreeNodeFlags_DefaultOpen)) {
946 BulletText(
"Feature status/persistence summaries across desktop/CLI/web");
947 BulletText(
"Shortcut/help panels now match configured keybindings");
948 BulletText(
"Refined onboarding tips and error messaging");
949 BulletText(
"Help text refreshed across desktop, CLI, and web");
952 if (CollapsingHeader(
953 absl::StrFormat(
"%s Development & Build System",
ICON_MD_BUILD)
955 ImGuiTreeNodeFlags_DefaultOpen)) {
956 BulletText(
"Asar 65816 assembler integration for ROM patching");
957 BulletText(
"z3ed CLI + TUI for scripting, test/doctor, and automation");
958 BulletText(
"Modern CMake presets for desktop, AI, and web builds");
959 BulletText(
"Unified version + storage references for 0.5.1");
962 if (CollapsingHeader(
964 BulletText(
"Improved project metadata + .yaze storage alignment");
965 BulletText(
"Stronger error reporting and status feedback");
966 BulletText(
"Performance and stability improvements across editors");
967 BulletText(
"Expanded logging and diagnostics tooling");
970 if (CollapsingHeader(
971 absl::StrFormat(
"%s Editor Features",
ICON_MD_EDIT).c_str())) {
972 BulletText(
"Music editor updates with SPC parsing/playback");
973 BulletText(
"AI agent-assisted editing workflows (multi-provider + vision)");
974 BulletText(
"Expanded overworld/dungeon tooling and palette accuracy");
975 BulletText(
"Web/WASM preview with collaboration hooks");
993 TextWrapped(
"Workspace Management");
995 "YAZE supports multiple ROM sessions and flexible workspace layouts.");
998 TextWrapped(
"Session Management:");
999 BulletText(
"Ctrl+Shift+N: Create new session");
1000 BulletText(
"Ctrl+Shift+W: Close current session");
1001 BulletText(
"Ctrl+Tab: Quick session switcher");
1002 BulletText(
"Each session maintains its own ROM and editor state");
1005 TextWrapped(
"Layout Management:");
1006 BulletText(
"Drag window tabs to dock/undock");
1007 BulletText(
"Ctrl+Shift+S: Save current layout");
1008 BulletText(
"Ctrl+Shift+O: Load saved layout");
1009 BulletText(
"F11: Maximize current window");
1012 TextWrapped(
"Preset Layouts:");
1013 BulletText(
"Developer: Code, memory, testing tools");
1014 BulletText(
"Designer: Graphics, palettes, sprites");
1015 BulletText(
"Modder: All gameplay editing tools");
1018 Hide(
"Workspace Help");
1024 TextWrapped(
"You have reached the recommended session limit.");
1025 TextWrapped(
"Having too many sessions open may impact performance.");
1027 TextWrapped(
"Consider closing unused sessions or saving your work.");
1030 Hide(
"Session Limit Warning");
1034 Hide(
"Session Limit Warning");
1042 TextWrapped(
"This will reset your current workspace layout to default.");
1043 TextWrapped(
"Any custom window arrangements will be lost.");
1045 TextWrapped(
"Do you want to continue?");
1048 Hide(
"Layout Reset Confirm");
1053 Hide(
"Layout Reset Confirm");
1063 TextWrapped(
"Choose a workspace preset to quickly configure your layout:");
1070 const char* description;
1074 PresetInfo presets[] = {
1076 "Essential cards only - maximum editing space",
1081 "Debug and development focused - CPU/Memory/Breakpoints",
1086 "Visual and artistic focused - Graphics/Palettes/Sprites",
1091 "Full-featured - All tools available for comprehensive editing",
1096 "Complete overworld editing toolkit with all map tools",
1101 "Complete dungeon editing toolkit with room tools",
1105 {
"Testing",
ICON_MD_SCIENCE,
"Quality assurance and ROM testing layout",
1115 constexpr int kPresetCount = 8;
1118 float button_width = 200.0f;
1119 float button_height = 50.0f;
1121 for (
int i = 0; i < kPresetCount; i++) {
1127 ImVec2(0.0f, 0.5f));
1129 absl::StrFormat(
"%s %s", presets[i].icon, presets[i].name).c_str(),
1130 ImVec2(button_width, button_height))) {
1132 auto preset = presets[i].getter();
1137 for (
const auto& panel_id : preset.default_visible_panels) {
1138 panel_manager.ShowPanel(panel_id);
1144 if (IsItemHovered()) {
1146 TextUnformatted(presets[i].description);
1161 if (current_editor) {
1162 auto current_type = current_editor->
type();
1163 panel_manager.ResetToDefaults(0, current_type);
1169 if (Button(
"Close", ImVec2(-1, 0))) {
1183 Text(
"Active Sessions: %zu", session_count);
1187 if (BeginTable(
"SessionTable", 4,
1188 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
1189 TableSetupColumn(
"#", ImGuiTableColumnFlags_WidthFixed, 30.0f);
1190 TableSetupColumn(
"ROM", ImGuiTableColumnFlags_WidthStretch);
1191 TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 80.0f);
1192 TableSetupColumn(
"Actions", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1195 for (
size_t i = 0; i < session_count; i++) {
1199 TableSetColumnIndex(0);
1203 TableSetColumnIndex(1);
1204 if (i == active_session) {
1207 TextUnformatted(rom->
filename().c_str());
1209 TextDisabled(
"(No ROM loaded)");
1212 TextDisabled(
"Session %zu", i + 1);
1216 TableSetColumnIndex(2);
1217 if (i == active_session) {
1221 TextDisabled(
"Inactive");
1225 TableSetColumnIndex(3);
1226 PushID(
static_cast<int>(i));
1228 if (i != active_session) {
1229 if (SmallButton(
"Switch")) {
1235 BeginDisabled(session_count <= 1);
1236 if (SmallButton(
"Close")) {
1252 if (Button(absl::StrFormat(
"%s New Session",
ICON_MD_ADD).c_str(),
1258 if (Button(
"Close", ImVec2(-1, 0))) {
1265 SetNextWindowSize(ImVec2(900, 700), ImGuiCond_FirstUseEver);
1266 SetNextWindowSizeConstraints(ImVec2(600, 400), ImVec2(FLT_MAX, FLT_MAX));
1269 TextWrapped(
"Customize your YAZE experience - accessible anytime!");
1274 float available_height =
1275 GetContentRegionAvail().y - 60;
1276 if (BeginChild(
"DisplaySettingsContent", ImVec2(0, available_height),
true,
1277 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
1286 ImGuiIO& io = GetIO();
1288 Text(
"Global Font Scale");
1289 float font_global_scale = io.FontGlobalScale;
1290 if (SliderFloat(
"##global_scale", &font_global_scale, 0.5f, 1.8f,
"%.2f")) {
1294 io.FontGlobalScale = font_global_scale;
1302 Hide(
"Display Settings");
1307 using namespace ImGui;
1310 Text(
"Feature Flags Configuration");
1313 BeginChild(
"##FlagsContent", ImVec2(0, -30),
true);
1318 if (BeginTabBar(
"FlagCategories")) {
1319 if (BeginTabItem(
"Overworld")) {
1323 if (BeginTabItem(
"Dungeon")) {
1327 if (BeginTabItem(
"Resources")) {
1331 if (BeginTabItem(
"System")) {
1347 using namespace ImGui;
1349 Text(
"Data Integrity Check Results");
1352 BeginChild(
"##IntegrityContent", ImVec2(0, -30),
true);
1356 Text(
"ROM Data Integrity:");
1364 Text(
"No issues detected.");
1375 using namespace ImGui;
1378 Text(
"Editor manager unavailable.");
1388 Text(
"Pot Item Save Confirmation");
1391 "Dungeon pot item saving is enabled, but %d of %d rooms are not loaded.",
1395 "Saving now can overwrite pot items in unloaded rooms. Choose how to "
1399 if (Button(
"Save without pot items", ImVec2(0, 0))) {
1406 if (Button(
"Save anyway", ImVec2(0, 0))) {
1413 if (Button(
"Cancel", ImVec2(0, 0))) {
1421 using namespace ImGui;
1424 Text(
"Editor manager unavailable.");
1437 Text(
"ROM Write Confirmation");
1440 "The loaded ROM hash does not match the project's expected hash.");
1442 Text(
"Role: %s", role.c_str());
1443 Text(
"Write policy: %s", policy.c_str());
1444 Text(
"Expected: %s", expected.empty() ?
"(unset)" : expected.c_str());
1445 Text(
"Actual: %s", actual.empty() ?
"(unknown)" : actual.c_str());
1448 "Proceeding will write to the current ROM file. This may corrupt a base "
1449 "or release ROM if it is not the intended dev ROM.");
1452 if (Button(
"Save anyway", ImVec2(0, 0))) {
1456 if (!status.ok() && !absl::IsCancelled(status)) {
1459 absl::StrFormat(
"Save failed: %s", status.message()),
1466 if (Button(
"Cancel", ImVec2(0, 0)) || IsKeyPressed(ImGuiKey_Escape)) {
1473 using namespace ImGui;
1476 Text(
"Editor manager unavailable.");
1489 "The following ROM addresses are owned by ASM hooks and will be "
1490 "overwritten on next build. Saving now will write data that asar "
1494 if (!conflicts.empty()) {
1495 if (BeginTable(
"WriteConflictTable", 3,
1496 ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
1497 ImGuiTableFlags_Resizable)) {
1498 TableSetupColumn(
"Address", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1499 TableSetupColumn(
"Ownership", ImGuiTableColumnFlags_WidthFixed, 140.0f);
1500 TableSetupColumn(
"Module", ImGuiTableColumnFlags_WidthStretch);
1503 for (
const auto& conflict : conflicts) {
1506 Text(
"$%06X", conflict.address);
1511 if (!conflict.module.empty()) {
1512 TextUnformatted(conflict.module.c_str());
1514 TextDisabled(
"(unknown)");
1522 Text(
"%zu conflict(s) detected.", conflicts.size());
1525 if (Button(
"Save Anyway", ImVec2(0, 0))) {
1529 if (!status.ok() && !absl::IsCancelled(status)) {
1531 toast->Show(absl::StrFormat(
"Save failed: %s", status.message()),
1538 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)
auto GetCurrentEditor() const -> Editor *
PanelManager & card_registry()
std::string GetProjectExpectedRomHash() const
const std::vector< core::WriteConflict > & pending_write_conflicts() const
project::RomRole GetProjectRomRole() const
void BypassWriteConflictOnce()
PanelManager & panel_manager()
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.