5#include "absl/strings/str_format.h"
11#include "imgui/misc/cpp/imgui_stdlib.h"
22 : editor_manager_(editor_manager), status_(absl::OkStatus()) {}
45 false,
false, [
this]() {
72 false,
false, [
this]() {
98 false,
false, [
this]() {
121 false,
false, [
this]() {
158 for (
auto& [name, params] :
popups_) {
159 if (params.is_visible) {
160 OpenPopup(name.c_str());
163 ImGuiWindowFlags popup_flags = params.allow_resize
164 ? ImGuiWindowFlags_None
165 : ImGuiWindowFlags_AlwaysAutoResize;
167 if (BeginPopupModal(name.c_str(),
nullptr, popup_flags)) {
168 params.draw_function();
180 std::string name_str(name);
181 auto it =
popups_.find(name_str);
183 it->second.is_visible =
true;
187 "[PopupManager] Warning: Popup '%s' not registered. Available popups: ",
189 for (
const auto& [key, _] :
popups_) {
190 printf(
"'%s' ", key.c_str());
201 std::string name_str(name);
202 auto it =
popups_.find(name_str);
204 it->second.is_visible =
false;
214 std::string name_str(name);
215 auto it =
popups_.find(name_str);
217 return it->second.is_visible;
231 ImGuiIO
const& io = GetIO();
232 ImVec2 pos(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f);
233 SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
234 ImGuiWindowFlags flags =
235 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
236 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings;
237 return Begin(name,
nullptr, flags);
264 Text(
"Written by: scawful");
266 Text(
"Special Thanks: Zarby89, JaredBrian");
279 Text(
"Title: %s", current_rom->title().c_str());
283 IsKeyPressed(ImGuiKey_Escape)) {
284 Hide(
"ROM Information");
289 using namespace ImGui;
294 static std::string save_as_filename =
"";
299 InputText(
"Filename", &save_as_filename);
306 if (!file_path.empty()) {
307 save_as_filename = file_path;
312 if (Button(absl::StrFormat(
"%s Save",
ICON_MD_SAVE).c_str(),
314 if (!save_as_filename.empty()) {
316 std::string final_filename = save_as_filename;
317 if (final_filename.find(
".sfc") == std::string::npos &&
318 final_filename.find(
".smc") == std::string::npos) {
319 final_filename +=
".sfc";
324 save_as_filename =
"";
333 save_as_filename =
"";
339 using namespace ImGui;
341 static std::string project_name =
"";
342 static std::string project_filepath =
"";
343 static std::string rom_filename =
"";
344 static std::string labels_filename =
"";
345 static std::string code_folder =
"";
347 InputText(
"Project Name", &project_name);
349 if (Button(absl::StrFormat(
"%s Destination Folder",
ICON_MD_FOLDER).c_str(),
354 Text(
"%s", project_filepath.empty() ?
"(Not set)" : project_filepath.c_str());
362 Text(
"%s", rom_filename.empty() ?
"(Not set)" : rom_filename.c_str());
364 if (Button(absl::StrFormat(
"%s Labels File",
ICON_MD_LABEL).c_str(),
369 Text(
"%s", labels_filename.empty() ?
"(Not set)" : labels_filename.c_str());
371 if (Button(absl::StrFormat(
"%s Code Folder",
ICON_MD_CODE).c_str(),
376 Text(
"%s", code_folder.empty() ?
"(Not set)" : code_folder.c_str());
380 if (Button(absl::StrFormat(
"%s Choose Project File Location",
ICON_MD_SAVE)
383 auto project_file_path =
385 if (!project_file_path.empty()) {
386 if (project_file_path.find(
".yaze") == std::string::npos) {
387 project_file_path +=
".yaze";
389 project_filepath = project_file_path;
393 if (Button(absl::StrFormat(
"%s Create Project",
ICON_MD_ADD).c_str(),
395 if (!project_filepath.empty() && !project_name.empty()) {
400 project_filepath =
"";
402 labels_filename =
"";
413 project_filepath =
"";
415 labels_filename =
"";
422 if (CollapsingHeader(
424 ImGuiTreeNodeFlags_DefaultOpen)) {
425 BulletText(
"LW/DW/SW Tilemap Editing");
426 BulletText(
"LW/DW/SW Map Properties");
427 BulletText(
"Create/Delete/Update Entrances");
428 BulletText(
"Create/Delete/Update Exits");
429 BulletText(
"Create/Delete/Update Sprites");
430 BulletText(
"Create/Delete/Update Items");
431 BulletText(
"Multi-session map editing support");
434 if (CollapsingHeader(
436 BulletText(
"View Room Header Properties");
437 BulletText(
"View Entrance Properties");
438 BulletText(
"Enhanced room navigation");
441 if (CollapsingHeader(
443 BulletText(
"View Decompressed Graphics Sheets");
444 BulletText(
"View/Update Graphics Groups");
446 "5+ Built-in themes (Classic, Cyberpunk, Sunset, Forest, Midnight)");
447 BulletText(
"Custom theme creation and editing");
448 BulletText(
"Theme import/export functionality");
449 BulletText(
"Animated background grid effects");
452 if (CollapsingHeader(
454 BulletText(
"View Palette Groups");
455 BulletText(
"Enhanced palette editing tools");
456 BulletText(
"Color conversion utilities");
459 if (CollapsingHeader(
460 absl::StrFormat(
"%s Project Management",
ICON_MD_FOLDER).c_str())) {
461 BulletText(
"Multi-session workspace support");
462 BulletText(
"Enhanced project creation and management");
463 BulletText(
"ZScream project format compatibility");
464 BulletText(
"Workspace settings and feature flags");
467 if (CollapsingHeader(
468 absl::StrFormat(
"%s Development Tools",
ICON_MD_BUILD).c_str())) {
469 BulletText(
"Asar 65816 assembler integration");
470 BulletText(
"Enhanced CLI tools with TUI interface");
471 BulletText(
"Memory editor with advanced features");
472 BulletText(
"Hex editor with search and navigation");
473 BulletText(
"Assembly validation and symbol extraction");
476 if (CollapsingHeader(
477 absl::StrFormat(
"%s Save Capabilities",
ICON_MD_SAVE).c_str())) {
478 BulletText(
"All Overworld editing features");
479 BulletText(
"Hex Editor changes");
480 BulletText(
"Theme configurations");
481 BulletText(
"Project settings and workspace layouts");
482 BulletText(
"Custom assembly patches");
486 Hide(
"Supported Features");
491 Text(
"File -> Open");
492 Text(
"Select a ROM file to open");
493 Text(
"Supported ROMs (headered or unheadered):");
494 Text(
"The Legend of Zelda: A Link to the Past");
495 Text(
"US Version 1.0");
496 Text(
"JP Version 1.0");
498 TextWrapped(
"ROM files are not bundled. Use a clean, legally obtained copy.");
506 Text(
"Project Menu");
507 Text(
"Create a new project or open an existing one.");
508 Text(
"Save the project to save the current state of the project.");
510 "To save a project, you need to first open a ROM and initialize your "
511 "code path and labels file. Label resource manager can be found in "
512 "the View menu. Code path is set in the Code editor after opening a "
516 Hide(
"Manage Project");
523 "YAZE lets you modify 'The Legend of Zelda: A Link to the Past' (US or "
524 "JP) ROMs with modern tooling.");
526 TextWrapped(
"Release Highlights:");
528 "AI-assisted workflows via z3ed agent and in-app panels "
529 "(Ollama/Gemini/OpenAI/Anthropic)");
530 BulletText(
"Web/WASM preview with collaboration server support");
531 BulletText(
"Music editor updates with SPC parsing and playback");
533 TextWrapped(
"General Tips:");
534 BulletText(
"Open a clean ROM and save a backup before editing");
535 BulletText(
"Use Help (F1) for context-aware guidance");
537 "Configure AI providers (Ollama/Gemini/OpenAI/Anthropic) in Settings > "
541 Hide(
"Getting Started");
546 TextWrapped(
"Asar 65816 Assembly Integration");
548 "YAZE v0.5.0 includes full Asar assembler support for ROM patching.");
550 TextWrapped(
"Features:");
551 BulletText(
"Cross-platform ROM patching with assembly code");
552 BulletText(
"Symbol export with addresses and opcodes");
553 BulletText(
"Assembly validation with detailed error reporting");
554 BulletText(
"Memory-safe patch application with size checks");
557 Hide(
"Asar Integration");
562 TextWrapped(
"Build Instructions");
563 TextWrapped(
"YAZE uses modern CMake for cross-platform builds.");
565 TextWrapped(
"Quick Start (examples):");
566 BulletText(
"cmake --preset mac-dbg | lin-dbg | win-dbg");
567 BulletText(
"cmake --build --preset <preset> --target yaze");
569 TextWrapped(
"AI Builds:");
570 BulletText(
"cmake --preset mac-ai | lin-ai | win-ai");
571 BulletText(
"cmake --build --preset <preset> --target yaze z3ed");
573 TextWrapped(
"Docs: docs/public/build/quick-reference.md");
576 Hide(
"Build Instructions");
581 TextWrapped(
"Command Line Interface (z3ed)");
582 TextWrapped(
"Scriptable ROM editing and AI agent workflows.");
584 TextWrapped(
"Commands:");
585 BulletText(
"z3ed rom-info --rom=zelda3.sfc");
586 BulletText(
"z3ed agent simple-chat --rom=zelda3.sfc --ai_provider=openai");
587 BulletText(
"z3ed --tui");
588 BulletText(
"z3ed patch apply-asar patch.asm --rom=zelda3.sfc");
596 TextWrapped(
"Troubleshooting");
597 TextWrapped(
"Common issues and solutions:");
599 BulletText(
"ROM won't load: Check file format (SFC/SMC supported)");
601 "AI agent missing: Start Ollama or set GEMINI_API_KEY/OPENAI_API_KEY/"
602 "ANTHROPIC_API_KEY");
603 BulletText(
"Graphics issues: Try disabling experimental features");
604 BulletText(
"Performance: Enable hardware acceleration in display settings");
605 BulletText(
"Crashes: Check ROM file integrity and available memory");
608 Hide(
"Troubleshooting");
613 TextWrapped(
"Contributing to YAZE");
614 TextWrapped(
"YAZE is open source and welcomes contributions!");
616 TextWrapped(
"How to contribute:");
617 BulletText(
"Fork the repository on GitHub");
618 BulletText(
"Create feature branches for new work");
619 BulletText(
"Follow C++ coding standards");
620 BulletText(
"Include tests for new features");
621 BulletText(
"Submit pull requests for review");
624 Hide(
"Contributing");
632 if (CollapsingHeader(
635 ImGuiTreeNodeFlags_DefaultOpen)) {
636 BulletText(
"Refreshed welcome screen and onboarding tips");
637 BulletText(
"Context-aware help panels and updated popups");
638 BulletText(
"Improved panel layouts and session workflows");
639 BulletText(
"Theme polish and icon refreshes");
642 if (CollapsingHeader(
643 absl::StrFormat(
"%s Development & Build System",
ICON_MD_BUILD)
645 ImGuiTreeNodeFlags_DefaultOpen)) {
646 BulletText(
"Asar 65816 assembler integration for ROM patching");
647 BulletText(
"z3ed CLI + TUI for scripting, test/doctor, and automation");
648 BulletText(
"Modern CMake presets for desktop, AI, and web builds");
649 BulletText(
"Cross-platform CI/CD hardening (Windows, macOS, Linux)");
650 BulletText(
"Quality release packaging for macOS/Windows/Linux");
653 if (CollapsingHeader(
655 BulletText(
"Improved ROM validation and project metadata handling");
656 BulletText(
"Stronger error reporting and status feedback");
657 BulletText(
"Performance and stability improvements across editors");
658 BulletText(
"Expanded logging and diagnostics tooling");
661 if (CollapsingHeader(
662 absl::StrFormat(
"%s Editor Features",
ICON_MD_EDIT).c_str())) {
663 BulletText(
"Music editor updates with SPC parsing/playback");
665 "AI agent-assisted editing workflows (Ollama/Gemini/OpenAI/"
667 BulletText(
"Expanded overworld/dungeon tooling and palettes");
668 BulletText(
"Web/WASM preview with collaboration hooks");
686 TextWrapped(
"Workspace Management");
688 "YAZE supports multiple ROM sessions and flexible workspace layouts.");
691 TextWrapped(
"Session Management:");
692 BulletText(
"Ctrl+Shift+N: Create new session");
693 BulletText(
"Ctrl+Shift+W: Close current session");
694 BulletText(
"Ctrl+Tab: Quick session switcher");
695 BulletText(
"Each session maintains its own ROM and editor state");
698 TextWrapped(
"Layout Management:");
699 BulletText(
"Drag window tabs to dock/undock");
700 BulletText(
"Ctrl+Shift+S: Save current layout");
701 BulletText(
"Ctrl+Shift+O: Load saved layout");
702 BulletText(
"F11: Maximize current window");
705 TextWrapped(
"Preset Layouts:");
706 BulletText(
"Developer: Code, memory, testing tools");
707 BulletText(
"Designer: Graphics, palettes, sprites");
708 BulletText(
"Modder: All gameplay editing tools");
711 Hide(
"Workspace Help");
716 TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
"%s Warning",
ICON_MD_WARNING);
717 TextWrapped(
"You have reached the recommended session limit.");
718 TextWrapped(
"Having too many sessions open may impact performance.");
720 TextWrapped(
"Consider closing unused sessions or saving your work.");
723 Hide(
"Session Limit Warning");
727 Hide(
"Session Limit Warning");
733 TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
"%s Confirm Reset",
735 TextWrapped(
"This will reset your current workspace layout to default.");
736 TextWrapped(
"Any custom window arrangements will be lost.");
738 TextWrapped(
"Do you want to continue?");
741 Hide(
"Layout Reset Confirm");
746 Hide(
"Layout Reset Confirm");
751 TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
"%s Layout Presets",
756 TextWrapped(
"Choose a workspace preset to quickly configure your layout:");
763 const char* description;
767 PresetInfo presets[] = {
769 "Essential cards only - maximum editing space",
774 "Debug and development focused - CPU/Memory/Breakpoints",
779 "Visual and artistic focused - Graphics/Palettes/Sprites",
784 "Full-featured - All tools available for comprehensive editing",
789 "Complete overworld editing toolkit with all map tools",
794 "Complete dungeon editing toolkit with room tools",
798 {
"Testing",
ICON_MD_SCIENCE,
"Quality assurance and ROM testing layout",
808 constexpr int kPresetCount = 8;
811 float button_width = 200.0f;
812 float button_height = 50.0f;
814 for (
int i = 0; i < kPresetCount; i++) {
818 PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
820 absl::StrFormat(
"%s %s", presets[i].icon, presets[i].name).c_str(),
821 ImVec2(button_width, button_height))) {
823 auto preset = presets[i].getter();
828 for (
const auto& panel_id : preset.default_visible_panels) {
829 panel_manager.ShowPanel(panel_id);
835 if (IsItemHovered()) {
837 TextUnformatted(presets[i].description);
852 if (current_editor) {
853 auto current_type = current_editor->type();
854 panel_manager.ResetToDefaults(0, current_type);
860 if (Button(
"Close", ImVec2(-1, 0))) {
866 TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
"%s Session Manager",
874 Text(
"Active Sessions: %zu", session_count);
878 if (BeginTable(
"SessionTable", 4,
879 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
880 TableSetupColumn(
"#", ImGuiTableColumnFlags_WidthFixed, 30.0f);
881 TableSetupColumn(
"ROM", ImGuiTableColumnFlags_WidthStretch);
882 TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 80.0f);
883 TableSetupColumn(
"Actions", ImGuiTableColumnFlags_WidthFixed, 120.0f);
886 for (
size_t i = 0; i < session_count; i++) {
890 TableSetColumnIndex(0);
894 TableSetColumnIndex(1);
895 if (i == active_session) {
897 if (rom && rom->is_loaded()) {
898 TextUnformatted(rom->filename().c_str());
900 TextDisabled(
"(No ROM loaded)");
903 TextDisabled(
"Session %zu", i + 1);
907 TableSetColumnIndex(2);
908 if (i == active_session) {
909 TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f),
"%s Active",
912 TextDisabled(
"Inactive");
916 TableSetColumnIndex(3);
917 PushID(
static_cast<int>(i));
919 if (i != active_session) {
920 if (SmallButton(
"Switch")) {
926 BeginDisabled(session_count <= 1);
927 if (SmallButton(
"Close")) {
943 if (Button(absl::StrFormat(
"%s New Session",
ICON_MD_ADD).c_str(),
949 if (Button(
"Close", ImVec2(-1, 0))) {
956 SetNextWindowSize(ImVec2(900, 700), ImGuiCond_FirstUseEver);
957 SetNextWindowSizeConstraints(ImVec2(600, 400), ImVec2(FLT_MAX, FLT_MAX));
960 TextWrapped(
"Customize your YAZE experience - accessible anytime!");
965 float available_height =
966 GetContentRegionAvail().y - 60;
967 if (BeginChild(
"DisplaySettingsContent", ImVec2(0, available_height),
true,
968 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
977 ImGuiIO& io = GetIO();
979 Text(
"Global Font Scale");
980 static float font_global_scale = io.FontGlobalScale;
981 if (SliderFloat(
"##global_scale", &font_global_scale, 0.5f, 1.8f,
"%.2f")) {
985 io.FontGlobalScale = font_global_scale;
993 Hide(
"Display Settings");
998 using namespace ImGui;
1001 Text(
"Feature Flags Configuration");
1004 BeginChild(
"##FlagsContent", ImVec2(0, -30),
true);
1009 if (BeginTabBar(
"FlagCategories")) {
1010 if (BeginTabItem(
"Overworld")) {
1014 if (BeginTabItem(
"Dungeon")) {
1018 if (BeginTabItem(
"Resources")) {
1022 if (BeginTabItem(
"System")) {
1038 using namespace ImGui;
1040 Text(
"Data Integrity Check Results");
1043 BeginChild(
"##IntegrityContent", ImVec2(0, -30),
true);
1047 Text(
"ROM Data Integrity:");
1049 TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"✓ ROM header valid");
1050 TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"✓ Checksum valid");
1051 TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"✓ Graphics data intact");
1052 TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"✓ Map data intact");
1055 Text(
"No issues detected.");
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)
size_t GetActiveSessionCount() const
absl::Status CreateNewProject(const std::string &template_name="Basic ROM Hack")
void SetFontGlobalScale(float scale)
auto GetCurrentEditor() const -> Editor *
PanelManager & card_registry()
PanelManager & panel_manager()
size_t GetCurrentSessionId() const
auto GetCurrentRom() const -> Rom *
void RemoveSession(size_t index)
static PanelLayoutPreset GetDungeonExpertPreset()
Get the "dungeon expert" workspace preset.
static PanelLayoutPreset GetTestingPreset()
Get the "testing" workspace preset (QA focused)
static PanelLayoutPreset GetDesignerPreset()
Get the "designer" workspace preset (visual-focused)
static PanelLayoutPreset GetAudioPreset()
Get the "audio" workspace preset (music focused)
static PanelLayoutPreset GetModderPreset()
Get the "modder" workspace preset (full-featured)
static PanelLayoutPreset GetOverworldExpertPreset()
Get the "overworld expert" workspace preset.
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)
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_CONTENT_COPY
#define ICON_MD_COLOR_LENS
#define ICON_MD_CROP_FREE
void DrawDisplaySettingsForPopup(ImGuiStyle *ref)
constexpr ImVec2 kDefaultModalSize
void TextWithSeparators(const absl::string_view &text)
std::string HexLongLong(uint64_t qword, HexStringParams params)
FileDialogOptions MakeRomFileDialogOptions(bool include_all_files)
Defines default panel visibility for an editor type.
Yet Another Zelda3 Editor (YAZE) - Public C API.