7#define IMGUI_DEFINE_MATH_OPERATORS
9#include "absl/status/status.h"
10#include "absl/status/statusor.h"
11#include "absl/strings/match.h"
12#include "absl/strings/str_cat.h"
17#include "imgui/imgui.h"
41#ifdef YAZE_ENABLE_TESTING
47#ifdef YAZE_ENABLE_GTEST
65#include "absl/flags/flag.h"
73#include "imgui/imgui.h"
74#include "imgui/misc/cpp/imgui_stdlib.h"
77#include "yaze_config.h"
83using util::FileDialogWrapper;
95 ss << YAZE_VERSION_MAJOR <<
"." << YAZE_VERSION_MINOR <<
"."
96 << YAZE_VERSION_PATCH;
106#ifdef YAZE_ENABLE_TESTING
108 test_manager.RegisterTestSuite(std::make_unique<test::IntegratedTestSuite>());
109 test_manager.RegisterTestSuite(
110 std::make_unique<test::PerformanceTestSuite>());
111 test_manager.RegisterTestSuite(std::make_unique<test::UITestSuite>());
112 test_manager.RegisterTestSuite(
113 std::make_unique<test::RomDependentTestSuite>());
116 test_manager.RegisterTestSuite(std::make_unique<test::E2ETestSuite>());
117 test_manager.RegisterTestSuite(
118 std::make_unique<test::ZSCustomOverworldTestSuite>());
122#ifdef YAZE_ENABLE_GTEST
123 test_manager.RegisterTestSuite(std::make_unique<test::UnitTestSuite>());
132 test_manager.UpdateResourceStats();
155 if (!filename.empty()) {
171 agent_editor_.set_context(&
context_);
172 agent_editor_.Initialize();
177 if (agent_editor_.GetChatWidget()) {
184 [
this](std::filesystem::path* output_path) -> absl::Status {
187 absl::StatusOr<yaze::test::ScreenshotArtifact> result;
190 switch (agent_editor_.GetChatWidget()->capture_mode()) {
191 case CaptureMode::kFullWindow:
192 result = yaze::test::CaptureHarnessScreenshot(
"");
195 case CaptureMode::kActiveEditor:
196 result = yaze::test::CaptureActiveWindow(
"");
199 result = yaze::test::CaptureHarnessScreenshot(
"");
203 case CaptureMode::kSpecificWindow: {
204 const char* window_name = agent_editor_.GetChatWidget()->specific_window_name();
205 if (window_name && std::strlen(window_name) > 0) {
206 result = yaze::test::CaptureWindowByName(window_name,
"");
209 result = yaze::test::CaptureActiveWindow(
"");
212 result = yaze::test::CaptureActiveWindow(
"");
215 result = yaze::test::CaptureHarnessScreenshot(
"");
222 return result.status();
224 *output_path = result->file_path;
225 return absl::OkStatus();
228 [
this](
const std::filesystem::path& image_path,
229 const std::string& prompt) -> absl::Status {
231 const char* api_key = std::getenv(
"GEMINI_API_KEY");
232 if (!api_key || std::strlen(api_key) == 0) {
233 return absl::FailedPreconditionError(
234 "GEMINI_API_KEY environment variable not set");
240 config.
model =
"gemini-2.5-flash";
248 if (!response.ok()) {
249 return response.status();
255 agent_msg.
message = response->text_response;
257 agent_editor_.GetChatWidget()->SetRomContext(
current_rom_);
259 return absl::OkStatus();
261 agent_editor_.GetChatWidget()->SetMultimodalCallbacks(multimodal_callbacks);
266 z3ed_callbacks.
accept_proposal = [
this](
const std::string& proposal_id) -> absl::Status {
272 absl::StrFormat(
"%s View proposal %s in drawer to accept",
ICON_MD_PREVIEW, proposal_id),
275 return absl::OkStatus();
278 z3ed_callbacks.
reject_proposal = [
this](
const std::string& proposal_id) -> absl::Status {
284 absl::StrFormat(
"%s View proposal %s in drawer to reject",
ICON_MD_PREVIEW, proposal_id),
287 return absl::OkStatus();
290 z3ed_callbacks.
list_proposals = []() -> absl::StatusOr<std::vector<std::string>> {
292 return std::vector<std::string>{};
295 z3ed_callbacks.
diff_proposal = [
this](
const std::string& proposal_id) -> absl::StatusOr<std::string> {
299 return "See diff in proposal drawer";
302 agent_editor_.GetChatWidget()->SetZ3EDCommandCallbacks(z3ed_callbacks);
314 automation_callbacks.
focus_proposal = [
this](
const std::string& proposal_id) {
318 agent_editor_.GetChatWidget()->SetAutomationCallbacks(automation_callbacks);
320 harness_telemetry_bridge_.SetChatWidget(agent_editor_.GetChatWidget());
327 LOG_WARN(
"EditorManager",
"Failed to load user settings: %s",
status_.ToString().c_str());
359 agent_editor_.set_active(
true);
412#ifdef YAZE_ENABLE_TESTING
419 "Open", {ImGuiKey_O, ImGuiMod_Ctrl}, [
this]() {
status_ =
LoadRom(); });
421 "Save", {ImGuiKey_S, ImGuiMod_Ctrl}, [
this]() {
status_ =
SaveRom(); });
423 "Close", {ImGuiKey_W, ImGuiMod_Ctrl}, [
this]() {
428 "Quit", {ImGuiKey_Q, ImGuiMod_Ctrl}, [
this]() {
quit_ =
true; });
431 "Undo", {ImGuiKey_Z, ImGuiMod_Ctrl}, [
this]() {
436 "Redo", {ImGuiKey_Y, ImGuiMod_Ctrl}, [
this]() {
441 "Cut", {ImGuiKey_X, ImGuiMod_Ctrl}, [
this]() {
446 "Copy", {ImGuiKey_C, ImGuiMod_Ctrl}, [
this]() {
451 "Paste", {ImGuiKey_V, ImGuiMod_Ctrl}, [
this]() {
456 "Find", {ImGuiKey_F, ImGuiMod_Ctrl}, [
this]() {
463 "Command Palette", {ImGuiKey_P, ImGuiMod_Ctrl, ImGuiMod_Shift},
466 "Global Search", {ImGuiKey_K, ImGuiMod_Ctrl, ImGuiMod_Shift},
470 "Load Last ROM", {ImGuiKey_R, ImGuiMod_Ctrl}, [
this]() {
472 if (!manager.GetRecentFiles().empty()) {
473 auto front = manager.GetRecentFiles().front();
483 "Overworld Editor", {ImGuiKey_1, ImGuiMod_Ctrl},
486 "Dungeon Editor", {ImGuiKey_2, ImGuiMod_Ctrl},
489 "Graphics Editor", {ImGuiKey_3, ImGuiMod_Ctrl},
492 "Sprite Editor", {ImGuiKey_4, ImGuiMod_Ctrl},
495 "Message Editor", {ImGuiKey_5, ImGuiMod_Ctrl},
498 "Music Editor", {ImGuiKey_6, ImGuiMod_Ctrl},
501 "Palette Editor", {ImGuiKey_7, ImGuiMod_Ctrl},
504 "Screen Editor", {ImGuiKey_8, ImGuiMod_Ctrl},
507 "Assembly Editor", {ImGuiKey_9, ImGuiMod_Ctrl},
510 "Settings Editor", {ImGuiKey_0, ImGuiMod_Ctrl},
515 "Editor Selection", {ImGuiKey_E, ImGuiMod_Ctrl},
520 "Card Browser", {ImGuiKey_B, ImGuiMod_Ctrl, ImGuiMod_Shift},
532 "Show All Dungeon Cards", {ImGuiKey_D, ImGuiMod_Ctrl, ImGuiMod_Shift},
535 "Show All Graphics Cards", {ImGuiKey_G, ImGuiMod_Ctrl, ImGuiMod_Shift},
538 "Show All Screen Cards", {ImGuiKey_S, ImGuiMod_Ctrl, ImGuiMod_Shift},
544 "Agent Editor", {ImGuiKey_A, ImGuiMod_Ctrl, ImGuiMod_Shift},
545 [
this]() { agent_editor_.SetChatActive(
true); });
549 "Chat History Popup", {ImGuiKey_H, ImGuiMod_Ctrl},
554 "Proposal Drawer", {ImGuiKey_P, ImGuiMod_Ctrl},
565#ifdef YAZE_ENABLE_TESTING
567 "Test Dashboard", {ImGuiKey_T, ImGuiMod_Ctrl},
574 std::vector<ImGuiKey>{ImGuiKey_N, ImGuiMod_Ctrl, ImGuiMod_Shift},
578 std::vector<ImGuiKey>{ImGuiKey_W, ImGuiMod_Ctrl, ImGuiMod_Shift},
581 "Session Switcher", std::vector<ImGuiKey>{ImGuiKey_Tab, ImGuiMod_Ctrl},
585 std::vector<ImGuiKey>{ImGuiKey_S, ImGuiMod_Ctrl, ImGuiMod_Shift},
589 std::vector<ImGuiKey>{ImGuiKey_O, ImGuiMod_Ctrl, ImGuiMod_Shift},
596 const std::string& editor_name,
const std::string& cards_str) {
597 if (editor_name.empty()) {
601 LOG_INFO(
"EditorManager",
"Processing startup flags: editor='%s', cards='%s'",
602 editor_name.c_str(), cards_str.c_str());
606 if (GetEditorName(
static_cast<EditorType>(i)) == editor_name) {
607 editor_type_to_open =
static_cast<EditorType>(i);
613 LOG_WARN(
"EditorManager",
"Unknown editor specified via flag: %s",
614 editor_name.c_str());
622 editor->set_active(
true);
628 std::stringstream ss(cards_str);
629 std::string card_name;
630 while (std::getline(ss, card_name,
',')) {
632 card_name.erase(0, card_name.find_first_not_of(
" \t"));
633 card_name.erase(card_name.find_last_not_of(
" \t") + 1);
635 LOG_DEBUG(
"EditorManager",
"Attempting to open card: '%s'",
638 if (card_name ==
"Rooms List") {
640 }
else if (card_name ==
"Room Matrix") {
642 }
else if (card_name ==
"Entrances List") {
644 }
else if (card_name ==
"Room Graphics") {
646 }
else if (card_name ==
"Object Editor") {
648 }
else if (card_name ==
"Palette Editor") {
650 }
else if (absl::StartsWith(card_name,
"Room ")) {
652 int room_id = std::stoi(card_name.substr(5));
654 }
catch (
const std::exception& e) {
655 LOG_WARN(
"EditorManager",
"Invalid room ID format: %s",
659 LOG_WARN(
"EditorManager",
"Unknown card name for Dungeon Editor: %s",
688 status_ = agent_editor_.Update();
691 if (agent_editor_.GetChatWidget()) {
692 agent_editor_.GetChatWidget()->Draw();
697 if (ImGui::GetCurrentContext()) {
698 ImDrawList* bg_draw_list = ImGui::GetBackgroundDrawList();
699 const ImGuiViewport* viewport = ImGui::GetMainViewport();
702 auto current_theme = theme_manager.GetCurrentTheme();
706 ImVec2 grid_pos = viewport->WorkPos;
707 ImVec2 grid_size = viewport->WorkSize;
708 bg_renderer.RenderDockingBackground(bg_draw_list, grid_pos, grid_size,
709 current_theme.primary);
713 static Rom* last_test_rom =
nullptr;
716 "EditorManager::Update - ROM changed, updating TestManager: %p -> "
750 return absl::OkStatus();
759 return absl::OkStatus();
766 for (
size_t session_idx = 0; session_idx <
sessions_.size(); ++session_idx) {
768 if (!session.rom.is_loaded())
771 for (
auto editor : session.editors.active_editors_) {
772 if (*editor->active()) {
775 if (overworld_editor.jump_to_tab() != -1) {
776 session.editors.dungeon_editor_.
set_active(
true);
778 session.editors.dungeon_editor_.add_room(
779 overworld_editor.jump_to_tab());
780 overworld_editor.jump_to_tab_ = -1;
788 if (is_card_based_editor) {
804 std::string editor_name = GetEditorName(editor->type());
806 absl::StrFormat(
"%s Error: %s", editor_name,
status_.message()),
817 std::string window_title =
821 ImGui::SetNextWindowSize(ImGui::GetMainViewport()->WorkSize, ImGuiCond_FirstUseEver);
822 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->WorkPos, ImGuiCond_FirstUseEver);
824 if (ImGui::Begin(window_title.c_str(), editor->active(),
825 ImGuiWindowFlags_None)) {
840 std::string editor_name = GetEditorName(editor->type());
842 absl::StrFormat(
"%s Error: %s", editor_name,
status_.message()),
871 return absl::OkStatus();
875 SameLine((GetWindowWidth() / 2) - 100);
877 SetNextItemWidth(GetWindowWidth() / 6);
884 if (Selectable(rom->
short_name().c_str(), selected)) {
899 Text(
"No ROM loaded");
901 return absl::OkStatus();
910 std::string category;
914 category =
"Dungeon";
917 category =
"Graphics";
926 category =
"Overworld";
929 category =
"Message";
938 category =
"Emulator";
949 card_manager.DrawCompactCardControl(category);
953 card_manager.DrawInlineCardToggles(category);
1021 [
this]() {
quit_ =
true; },
"Ctrl+Q")
1067#ifdef YAZE_WITH_GRPC
1069 [
this]() { agent_editor_.set_active(
true); },
"Ctrl+Shift+A")
1106 [
this]() {
return sessions_.size() > 1; })
1110 [
this]() {
return sessions_.size() > 1; })
1137#ifdef YAZE_WITH_GRPC
1141 [
this]() { agent_editor_.SetChatActive(
true); },
"Ctrl+Shift+A",
1143 [
this]() {
return agent_editor_.IsChatActive(); })
1151 auto result = agent_editor_.HostSession(
"New Session");
1156 toast_manager_.
Show(
"Failed to host session: " + std::string(result.status().message()),
1161 [
this]() {
popup_manager_->Show(
"Join Collaboration Session"); })
1164 status_ = agent_editor_.LeaveSession();
1170 [
this]() {
return agent_editor_.IsInSession(); })
1173 auto result = agent_editor_.RefreshSession();
1175 toast_manager_.
Show(
"Session refreshed: " + std::to_string(result->participants.size()) +
" participants",
1180 [
this]() {
return agent_editor_.IsInSession(); })
1186 agent_editor_.DisconnectFromServer();
1190 [
this]() {
return agent_editor_.IsConnectedToServer(); })
1194 std::filesystem::path output;
1197 status_ = agent_editor_.CaptureSnapshot(&output, config);
1201 std::filesystem::path output;
1204 status_ = agent_editor_.CaptureSnapshot(&output, config);
1221#ifdef YAZE_ENABLE_TESTING
1250#ifdef YAZE_ENABLE_TESTING
1276 std::string version_str = (
version == 0xFF) ?
"Vanilla" : absl::StrFormat(
"v%d",
version);
1296 flags.overworld.kLoadCustomOverworld = !flags.overworld.kLoadCustomOverworld;
1298 flags.overworld.kLoadCustomOverworld ?
"Enabled" :
"Disabled"),
1309 flags.overworld.kApplyZSCustomOverworldASM = !flags.overworld.kApplyZSCustomOverworldASM;
1311 flags.overworld.kApplyZSCustomOverworldASM ?
"Enabled" :
"Disabled"),
1334#ifdef YAZE_WITH_GRPC
1362 std::string version_text = absl::StrFormat(
"v%s",
version_.c_str());
1363 float version_width = ImGui::CalcTextSize(version_text.c_str()).x;
1364 float session_rom_area_width = 280.0f;
1366 SameLine(ImGui::GetWindowWidth() - version_width - 10 - session_rom_area_width);
1372 if (ImGui::IsItemHovered()) {
1378 if (current_rom && current_rom->is_loaded()) {
1382 if (ImGui::IsItemHovered()) {
1389 if (ImGui::IsItemHovered()) {
1397 if (current_rom && current_rom->is_loaded()) {
1398 std::string rom_display = current_rom->title();
1399 if (rom_display.length() > 22) {
1400 rom_display = rom_display.substr(0, 19) +
"...";
1402 if (ImGui::SmallButton(absl::StrFormat(
"%s%s", rom_display.c_str(), current_rom->dirty() ?
"*" :
"").c_str())) {
1403 ImGui::OpenPopup(
"ROM Details");
1406 ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f),
"No ROM");
1410 SameLine(ImGui::GetWindowWidth() - version_width - 10);
1411 ImGui::Text(
"%s", version_text.c_str());
1421 static bool show_display_settings =
false;
1422 static bool save_as_menu =
false;
1423 std::string version_text = absl::StrFormat(
"v%s",
version_.c_str());
1424 float version_width = ImGui::CalcTextSize(version_text.c_str()).x;
1426 if (BeginMenuBar()) {
1435 SameLine(GetWindowWidth() - version_width - 10);
1436 Text(
"%s", version_text.c_str());
1440 if (show_display_settings) {
1443 show_display_settings =
false;
1469#ifdef YAZE_ENABLE_TESTING
1472 test_manager.UpdateResourceStats();
1497 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
1498 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
1499 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
1501 if (Begin(absl::StrFormat(
"%s Command Palette",
ICON_MD_SEARCH).c_str(),
1505 static char query[256] = {};
1506 static int selected_idx = 0;
1507 ImGui::SetNextItemWidth(-100);
1508 if (ImGui::IsWindowAppearing()) {
1509 ImGui::SetKeyboardFocusHere();
1513 bool input_changed = InputTextWithHint(
1515 absl::StrFormat(
"%s Search commands (fuzzy matching enabled)...",
ICON_MD_SEARCH).c_str(),
1516 query, IM_ARRAYSIZE(query));
1519 if (ImGui::Button(absl::StrFormat(
"%s Clear",
ICON_MD_CLEAR).c_str())) {
1521 input_changed =
true;
1528 std::vector<std::pair<int, std::pair<std::string, std::string>>> scored_commands;
1529 std::string query_lower = query;
1530 std::transform(query_lower.begin(), query_lower.end(), query_lower.begin(), ::tolower);
1533 const auto& name = entry.first;
1534 const auto& shortcut = entry.second;
1536 std::string name_lower = name;
1537 std::transform(name_lower.begin(), name_lower.end(), name_lower.begin(), ::tolower);
1540 if (query[0] ==
'\0') {
1542 }
else if (name_lower.find(query_lower) == 0) {
1544 }
else if (name_lower.find(query_lower) != std::string::npos) {
1548 size_t text_idx = 0, query_idx = 0;
1549 while (text_idx < name_lower.length() && query_idx < query_lower.length()) {
1550 if (name_lower[text_idx] == query_lower[query_idx]) {
1556 if (query_idx != query_lower.length()) score = 0;
1560 std::string shortcut_text = shortcut.keys.empty()
1561 ?
"" : absl::StrFormat(
"(%s)",
PrintShortcut(shortcut.keys).c_str());
1562 scored_commands.push_back({score, {name, shortcut_text}});
1566 std::sort(scored_commands.begin(), scored_commands.end(),
1567 [](
const auto& a,
const auto& b) { return a.first > b.first; });
1570 if (ImGui::BeginTabBar(
"CommandCategories")) {
1571 if (ImGui::BeginTabItem(
ICON_MD_LIST " All Commands")) {
1572 if (ImGui::BeginTable(
"CommandPaletteTable", 3,
1573 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
1574 ImGuiTableFlags_SizingStretchProp,
1577 ImGui::TableSetupColumn(
"Command", ImGuiTableColumnFlags_WidthStretch, 0.5f);
1578 ImGui::TableSetupColumn(
"Shortcut", ImGuiTableColumnFlags_WidthStretch, 0.3f);
1579 ImGui::TableSetupColumn(
"Score", ImGuiTableColumnFlags_WidthStretch, 0.2f);
1580 ImGui::TableHeadersRow();
1582 for (
size_t i = 0; i < scored_commands.size(); ++i) {
1583 const auto& [score, cmd_pair] = scored_commands[i];
1584 const auto& [command_name, shortcut_text] = cmd_pair;
1586 ImGui::TableNextRow();
1587 ImGui::TableNextColumn();
1589 ImGui::PushID(
static_cast<int>(i));
1590 bool is_selected = (
static_cast<int>(i) == selected_idx);
1591 if (Selectable(command_name.c_str(), is_selected,
1592 ImGuiSelectableFlags_SpanAllColumns)) {
1595 auto it = shortcuts.find(command_name);
1596 if (it != shortcuts.end() && it->second.callback) {
1597 it->second.callback();
1603 ImGui::TableNextColumn();
1604 ImGui::TextDisabled(
"%s", shortcut_text.c_str());
1606 ImGui::TableNextColumn();
1607 if (score > 0) ImGui::TextDisabled(
"%d", score);
1612 ImGui::EndTabItem();
1616 ImGui::Text(
"Recent commands coming soon...");
1617 ImGui::EndTabItem();
1621 ImGui::Text(
"Frequent commands coming soon...");
1622 ImGui::EndTabItem();
1630 ImGui::Text(
"%s %zu commands | Score: fuzzy match",
ICON_MD_INFO, scored_commands.size());
1632 ImGui::TextDisabled(
"| ↑↓=Navigate | Enter=Execute | Esc=Close");
1639 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
1640 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
1641 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
1648 static char query[256] = {};
1649 ImGui::SetNextItemWidth(-100);
1650 if (ImGui::IsWindowAppearing()) {
1651 ImGui::SetKeyboardFocusHere();
1654 bool input_changed = InputTextWithHint(
1656 absl::StrFormat(
"%s Search everything...",
ICON_MD_SEARCH).c_str(),
1657 query, IM_ARRAYSIZE(query));
1660 if (ImGui::Button(absl::StrFormat(
"%s Clear",
ICON_MD_CLEAR).c_str())) {
1662 input_changed =
true;
1668 if (ImGui::BeginTabBar(
"SearchResultTabs")) {
1671 if (ImGui::BeginTabItem(
1674 auto recent_files = manager.GetRecentFiles();
1676 if (ImGui::BeginTable(
"RecentFilesTable", 3,
1677 ImGuiTableFlags_ScrollY |
1678 ImGuiTableFlags_RowBg |
1679 ImGuiTableFlags_SizingStretchProp)) {
1681 ImGui::TableSetupColumn(
"File", ImGuiTableColumnFlags_WidthStretch,
1683 ImGui::TableSetupColumn(
"Type", ImGuiTableColumnFlags_WidthFixed,
1685 ImGui::TableSetupColumn(
"Action", ImGuiTableColumnFlags_WidthFixed,
1687 ImGui::TableHeadersRow();
1689 for (
const auto& file : recent_files) {
1690 if (query[0] !=
'\0' && file.find(query) == std::string::npos)
1693 ImGui::TableNextRow();
1694 ImGui::TableNextColumn();
1697 ImGui::TableNextColumn();
1699 if (ext ==
"sfc" || ext ==
"smc") {
1700 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f),
"%s ROM",
1702 }
else if (ext ==
"yaze") {
1703 ImGui::TextColored(ImVec4(0.2f, 0.6f, 0.8f, 1.0f),
"%s Project",
1709 ImGui::TableNextColumn();
1710 ImGui::PushID(file.c_str());
1711 if (ImGui::Button(
"Open")) {
1720 ImGui::EndTabItem();
1725 if (ImGui::BeginTabItem(
1729 if (ImGui::BeginTable(
"LabelsTable", 3,
1730 ImGuiTableFlags_ScrollY |
1731 ImGuiTableFlags_RowBg |
1732 ImGuiTableFlags_SizingStretchProp)) {
1734 ImGui::TableSetupColumn(
"Type", ImGuiTableColumnFlags_WidthFixed,
1736 ImGui::TableSetupColumn(
"Label",
1737 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1738 ImGui::TableSetupColumn(
"Value",
1739 ImGuiTableColumnFlags_WidthStretch, 0.6f);
1740 ImGui::TableHeadersRow();
1742 for (
const auto& type_pair : labels) {
1743 for (
const auto& kv : type_pair.second) {
1744 if (query[0] !=
'\0' &&
1745 kv.first.find(query) == std::string::npos &&
1746 kv.second.find(query) == std::string::npos)
1749 ImGui::TableNextRow();
1750 ImGui::TableNextColumn();
1751 ImGui::Text(
"%s", type_pair.first.c_str());
1753 ImGui::TableNextColumn();
1754 if (Selectable(kv.first.c_str(),
false,
1755 ImGuiSelectableFlags_SpanAllColumns)) {
1759 ImGui::TableNextColumn();
1760 ImGui::TextDisabled(
"%s", kv.second.c_str());
1766 ImGui::EndTabItem();
1772 if (ImGui::BeginTabItem(
1773 absl::StrFormat(
"%s Sessions",
ICON_MD_TAB).c_str())) {
1774 ImGui::Text(
"Search and switch between active sessions:");
1776 for (
size_t i = 0; i <
sessions_.size(); ++i) {
1778 if (session.custom_name ==
"[CLOSED SESSION]")
1781 std::string session_info = session.GetDisplayName();
1782 if (query[0] !=
'\0' &&
1783 session_info.find(query) == std::string::npos)
1788 ImGui::PushStyleColor(ImGuiCol_Text,
1789 ImVec4(0.2f, 0.8f, 0.2f, 1.0f));
1792 if (Selectable(absl::StrFormat(
"%s %s %s",
ICON_MD_TAB,
1793 session_info.c_str(),
1794 is_current ?
"(Current)" :
"")
1803 ImGui::PopStyleColor();
1806 ImGui::EndTabItem();
1815 ImGui::Text(
"%s Global search across all YAZE data",
ICON_MD_INFO);
1827 absl::StrFormat(
"Palette Editor Error: %s",
status_.message()),
1844 Begin(
"Save ROM As", &save_as_menu, ImGuiWindowFlags_AlwaysAutoResize);
1849 static std::string save_as_filename =
"";
1854 ImGui::InputText(
"Filename", &save_as_filename);
1863 if (!file_path.empty()) {
1864 save_as_filename = file_path;
1869 if (Button(absl::StrFormat(
"%s Save",
ICON_MD_SAVE).c_str(),
1871 if (!save_as_filename.empty()) {
1873 std::string final_filename = save_as_filename;
1874 if (final_filename.find(
".sfc") == std::string::npos &&
1875 final_filename.find(
".smc") == std::string::npos) {
1876 final_filename +=
".sfc";
1881 save_as_menu =
false;
1883 absl::StrFormat(
"ROM saved as: %s", final_filename),
1887 absl::StrFormat(
"Failed to save ROM: %s",
status_.message()),
1896 save_as_menu =
false;
1902 Begin(
"New Project", &
new_project_menu, ImGuiWindowFlags_AlwaysAutoResize);
1903 static std::string save_as_filename =
"";
1904 InputText(
"Project Name", &save_as_filename);
1905 if (Button(absl::StrFormat(
"%s Destination Folder",
ICON_MD_FOLDER).c_str(),
1919 if (Button(absl::StrFormat(
"%s Labels File",
ICON_MD_LABEL).c_str(),
1927 if (Button(absl::StrFormat(
"%s Code Folder",
ICON_MD_CODE).c_str(),
1936 if (Button(absl::StrFormat(
"%s Choose Project File Location",
ICON_MD_SAVE)
1939 auto project_file_path =
1941 if (!project_file_path.empty()) {
1943 if (project_file_path.find(
".yaze") == std::string::npos) {
1944 project_file_path +=
".yaze";
1951 size_t last_slash = project_file_path.find_last_of(
"/\\");
1952 if (last_slash != std::string::npos) {
1953 std::string project_dir = project_file_path.substr(0, last_slash);
1954 Text(
"Project will be saved to: %s", project_dir.c_str());
1959 if (Button(absl::StrFormat(
"%s Create Project",
ICON_MD_ADD).c_str(),
1983 ImGuiWindowFlags_AlwaysAutoResize);
1984 static std::string preset_name =
"";
1985 InputText(
"Name", &preset_name);
2000 ImGuiWindowFlags_AlwaysAutoResize);
2008 if (Selectable(name.c_str())) {
2015 Text(
"No presets found");
2028 if (file_name.empty()) {
2029 return absl::OkStatus();
2036 return absl::OkStatus();
2045 if (!session.rom.is_loaded()) {
2046 target_session = &session;
2047 LOG_DEBUG(
"EditorManager",
"Found empty session to populate with ROM: %s",
2053 if (target_session) {
2055 target_session->
rom = std::move(temp_rom);
2056 target_session->
filepath = file_name;
2074#ifdef YAZE_ENABLE_TESTING
2075 LOG_DEBUG(
"EditorManager",
"Setting ROM in TestManager - %p ('%s')",
2082 manager.AddFile(file_name);
2093 return absl::OkStatus();
2098 return absl::FailedPreconditionError(
"No ROM or editor set loaded");
2101 auto start_time = std::chrono::steady_clock::now();
2125 auto end_time = std::chrono::steady_clock::now();
2126 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
2127 end_time - start_time);
2128 LOG_DEBUG(
"EditorManager",
"ROM assets loaded in %lld ms", duration.count());
2130 return absl::OkStatus();
2135 return absl::FailedPreconditionError(
"No ROM or editor set loaded");
2157 return absl::FailedPreconditionError(
"No ROM or editor set loaded");
2160 if (filename.empty()) {
2161 return absl::InvalidArgumentError(
"Filename cannot be empty");
2183 if (save_status.ok()) {
2186 if (current_session_idx <
sessions_.size()) {
2187 sessions_[current_session_idx].filepath = filename;
2192 manager.AddFile(filename);
2203 if (filename.empty()) {
2204 return absl::OkStatus();
2206 if (absl::StrContains(filename,
".yaze")) {
2226 return absl::OkStatus();
2231 if (dialog_path.empty()) {
2232 return absl::OkStatus();
2237 return absl::OkStatus();
2242 if (file_path.empty()) {
2243 return absl::OkStatus();
2250 auto validation_status = new_project.
Validate();
2251 if (!validation_status.ok()) {
2253 validation_status.message()),
2287#ifdef YAZE_ENABLE_TESTING
2288 LOG_DEBUG(
"EditorManager",
"Setting ROM in TestManager - %p ('%s')",
2323 return absl::OkStatus();
2346 for (
const auto& file : manager.GetRecentFiles()) {
2358 :
"untitled_project";
2362 if (file_path.empty()) {
2363 return absl::OkStatus();
2367 if (file_path.find(
".yaze") == std::string::npos) {
2368 file_path +=
".yaze";
2376 if (save_status.ok()) {
2379 manager.AddFile(file_path);
2388 absl::StrFormat(
"Failed to save project: %s", save_status.message()),
2398 if (project_path.ends_with(
".zsproj")) {
2401 "ZScream project imported successfully. Please configure ROM and "
2409 return absl::OkStatus();
2414 return absl::FailedPreconditionError(
"No project is currently open");
2421 return absl::OkStatus();
2430 return absl::InvalidArgumentError(
"Invalid ROM pointer");
2434 if (&session.rom == rom) {
2441 return absl::OkStatus();
2446 return absl::NotFoundError(
"ROM not found in existing sessions");
2470 absl::StrFormat(
"New session created (Session %zu)",
sessions_.size()),
2476 "Tip: Use Workspace → Sessions → Session Switcher for quick navigation",
2499 absl::StrFormat(
"Session duplicated (Session %zu)",
sessions_.size()),
2514 size_t next_index = 0;
2515 for (
size_t i = 0; i <
sessions_.size(); ++i) {
2516 if (i != current_index &&
sessions_[i].custom_name !=
"[CLOSED SESSION]") {
2547 std::string session_name =
sessions_[index].GetDisplayName();
2552 sessions_[index].custom_name =
"[CLOSED SESSION]";
2555 LOG_DEBUG(
"EditorManager",
"Marked session as closed: %s (index %zu)",
2556 session_name.c_str(), index);
2558 absl::StrFormat(
"Session marked as closed: %s", session_name),
2576 util::logf(
"EditorManager: Setting ROM in TestManager - %p ('%s')",
2581 std::string session_name = session.GetDisplayName();
2587 for (
size_t i = 0; i <
sessions_.size(); ++i) {
2589 sessions_[i].custom_name !=
"[CLOSED SESSION]") {
2599 if (session.custom_name !=
"[CLOSED SESSION]") {
2607 EditorType type,
size_t session_index)
const {
2608 const char* base_name =
kEditorNames[
static_cast<int>(type)];
2612 return std::string(base_name);
2616 const auto& session =
sessions_[session_index];
2617 std::string session_name = session.GetDisplayName();
2620 if (session_name.length() > 20) {
2621 session_name = session_name.substr(0, 17) +
"...";
2624 return absl::StrFormat(
"%s - %s##session_%zu", base_name, session_name,
2634 ImGui::SaveIniSettingsToDisk(
"yaze_workspace.ini");
2639 ImGui::LoadIniSettingsFromDisk(
"yaze_workspace.ini");
2648 editor->set_active(
true);
2653#ifdef YAZE_ENABLE_TESTING
2665 editor->set_active(
false);
2670#ifdef YAZE_ENABLE_TESTING
2699#ifdef YAZE_ENABLE_TESTING
2724#ifdef YAZE_ENABLE_TESTING
2756 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
2757 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
2758 ImGui::SetNextWindowSize(ImVec2(700, 450), ImGuiCond_Appearing);
2767 ImGui::SameLine(ImGui::GetWindowWidth() - 120);
2768 if (ImGui::Button(absl::StrFormat(
"%s New",
ICON_MD_ADD).c_str(),
2781 const float TABLE_HEIGHT = ImGui::GetContentRegionAvail().y -
2784 if (ImGui::BeginTable(
"SessionSwitcherTable", 4,
2785 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
2786 ImGuiTableFlags_SizingStretchProp |
2787 ImGuiTableFlags_ScrollY |
2788 ImGuiTableFlags_Resizable,
2789 ImVec2(0, TABLE_HEIGHT))) {
2792 ImGui::TableSetupColumn(
"Session", ImGuiTableColumnFlags_WidthStretch,
2794 ImGui::TableSetupColumn(
"ROM Info", ImGuiTableColumnFlags_WidthStretch,
2796 ImGui::TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed,
2798 ImGui::TableSetupColumn(
"Actions", ImGuiTableColumnFlags_WidthFixed,
2800 ImGui::TableHeadersRow();
2802 for (
size_t i = 0; i <
sessions_.size(); ++i) {
2806 if (session.custom_name ==
"[CLOSED SESSION]") {
2812 ImGui::PushID(
static_cast<int>(i));
2813 ImGui::TableNextRow(ImGuiTableRowFlags_None,
2817 ImGui::TableNextColumn();
2818 ImGui::AlignTextToFramePadding();
2821 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.2f, 0.8f, 0.2f, 1.0f));
2822 ImGui::Text(
"%s %s",
ICON_MD_STAR, session.GetDisplayName().c_str());
2823 ImGui::PopStyleColor();
2825 ImGui::Text(
"%s %s",
ICON_MD_TAB, session.GetDisplayName().c_str());
2829 ImGui::TableNextColumn();
2830 ImGui::AlignTextToFramePadding();
2832 if (session.rom.is_loaded()) {
2834 session.rom.title().c_str());
2835 ImGui::Text(
"%.1f MB | %s", session.rom.size() / 1048576.0f,
2836 session.rom.dirty() ?
"Modified" :
"Clean");
2838 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
"%s No ROM loaded",
2843 ImGui::TableNextColumn();
2844 ImGui::AlignTextToFramePadding();
2846 if (session.rom.is_loaded()) {
2847 if (session.rom.dirty()) {
2848 ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
"%s",
2851 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f),
"%s",
2855 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
"%s",
2860 ImGui::TableNextColumn();
2863 ImGui::BeginGroup();
2866 if (ImGui::Button(
"Switch")) {
2871 ImGui::BeginDisabled();
2872 ImGui::Button(
"Current");
2873 ImGui::EndDisabled();
2877 if (ImGui::Button(
"Rename")) {
2880 const std::string& name = session.GetDisplayName();
2893 ImGui::BeginDisabled();
2896 if (ImGui::Button(
"Close")) {
2908 ImGui::EndDisabled();
2921 absl::StrFormat(
"%s Close Switcher",
ICON_MD_CLOSE).c_str(),
2938 if (ImGui::Button(absl::StrCat(
ICON_MD_ADD,
" New Session").c_str())) {
2949 ImGui::Text(
"%s Active Sessions (%zu)",
ICON_MD_TAB,
2953 const float AVAILABLE_HEIGHT = ImGui::GetContentRegionAvail().y;
2955 if (ImGui::BeginTable(
"SessionTable", 6,
2956 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
2957 ImGuiTableFlags_Resizable |
2958 ImGuiTableFlags_ScrollY |
2959 ImGuiTableFlags_SizingStretchProp |
2960 ImGuiTableFlags_ContextMenuInBody,
2961 ImVec2(0, AVAILABLE_HEIGHT))) {
2964 ImGui::TableSetupColumn(
"Session", ImGuiTableColumnFlags_WidthStretch,
2966 ImGui::TableSetupColumn(
"ROM Title", ImGuiTableColumnFlags_WidthStretch,
2968 ImGui::TableSetupColumn(
"Size", ImGuiTableColumnFlags_WidthFixed, 70.0f);
2969 ImGui::TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed,
2971 ImGui::TableSetupColumn(
"Custom OW", ImGuiTableColumnFlags_WidthFixed,
2973 ImGui::TableSetupColumn(
"Actions", ImGuiTableColumnFlags_WidthStretch,
2975 ImGui::TableHeadersRow();
2977 for (
size_t i = 0; i <
sessions_.size(); ++i) {
2981 if (session.custom_name ==
"[CLOSED SESSION]") {
2987 ImGui::TableNextRow(ImGuiTableRowFlags_None,
2989 ImGui::PushID(
static_cast<int>(i));
2992 ImGui::TableNextColumn();
2993 ImGui::AlignTextToFramePadding();
2995 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f),
"%s Session %zu",
2998 ImGui::Text(
"%s Session %zu",
ICON_MD_TAB, i + 1);
3002 ImGui::TableNextColumn();
3003 ImGui::AlignTextToFramePadding();
3004 std::string display_name = session.GetDisplayName();
3005 if (!session.custom_name.empty()) {
3006 ImGui::TextColored(ImVec4(0.7f, 0.9f, 1.0f, 1.0f),
"%s %s",
3010 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x +
3011 ImGui::GetColumnWidth());
3012 ImGui::Text(
"%s", display_name.c_str());
3013 ImGui::PopTextWrapPos();
3017 ImGui::TableNextColumn();
3018 ImGui::AlignTextToFramePadding();
3019 if (session.rom.is_loaded()) {
3020 ImGui::Text(
"%.1f MB", session.rom.size() / 1048576.0f);
3022 ImGui::TextDisabled(
"N/A");
3026 ImGui::TableNextColumn();
3027 ImGui::AlignTextToFramePadding();
3028 if (session.rom.is_loaded()) {
3029 if (session.rom.dirty()) {
3030 ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
"%s",
3033 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f),
"%s",
3037 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
"%s",
3042 ImGui::TableNextColumn();
3045 float checkbox_offset =
3046 (ImGui::GetFrameHeight() - ImGui::GetTextLineHeight()) * 0.5f;
3047 ImGui::SetCursorPosY(ImGui::GetCursorPosY() + checkbox_offset);
3050 static_cast<int>(i + 100));
3051 bool custom_ow_enabled =
3052 session.feature_flags.overworld.kLoadCustomOverworld;
3053 if (ImGui::Checkbox(
"##CustomOW", &custom_ow_enabled)) {
3054 session.feature_flags.overworld.kLoadCustomOverworld =
3061 absl::StrFormat(
"Session %zu: Custom Overworld %s", i + 1,
3062 custom_ow_enabled ?
"Enabled" :
"Disabled"),
3068 ImGui::TableNextColumn();
3071 ImGui::BeginGroup();
3074 if (ImGui::Button(
"Switch")) {
3078 ImGui::BeginDisabled();
3079 ImGui::Button(
"Current");
3080 ImGui::EndDisabled();
3084 if (ImGui::Button(
"Rename")) {
3087 const std::string& name = session.GetDisplayName();
3099 if (!can_close || is_current) {
3100 ImGui::BeginDisabled();
3103 if (ImGui::Button(
"Close")) {
3114 if (!can_close || is_current) {
3115 ImGui::EndDisabled();
3133 if (ImGui::Begin(absl::StrCat(
ICON_MD_BOOKMARK,
" Layout Presets").c_str(),
3145 ImGui::Text(
"Code editing, debugging, testing");
3153 ImGui::Text(
"Graphics, palettes, sprites");
3155 if (ImGui::Button(absl::StrCat(
ICON_MD_GAMEPAD,
" Modder Layout").c_str(),
3160 ImGui::Text(
"All gameplay editors");
3177 absl::StrFormat(
"Loaded preset: %s", preset.c_str()),
3183 ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f),
3184 "No custom presets saved");
3189 absl::StrCat(
ICON_MD_ADD,
" Save Current Layout").c_str())) {
3198 if (session.filepath == filepath) {
3207 sessions_[index].custom_name = new_name;
3209 absl::StrFormat(
"Session renamed to: %s", new_name.c_str()),
3218 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
3219 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
3220 ImGui::SetNextWindowSize(ImVec2(400, 150), ImGuiCond_Appearing);
3223 ImGuiWindowFlags_NoResize)) {
3227 ImGui::Text(
"Rename Session:");
3228 ImGui::Text(
"Current: %s", session.GetDisplayName().c_str());
3235 if (ImGui::Button(
"Rename", ImVec2(120, 0))) {
3237 if (!new_name.empty()) {
3244 if (ImGui::Button(
"Cancel", ImVec2(120, 0))) {
3320 LOG_WARN(
"EditorManager",
"Failed to save user settings: %s", status.ToString().c_str());
The Rom class is used to load, save, and modify Rom data.
absl::Status LoadFromFile(const std::string &filename, bool z3_load=true)
absl::Status SaveToFile(const SaveSettings &settings)
core::ResourceLabelManager * resource_label()
absl::StatusOr< AgentResponse > GenerateMultimodalResponse(const std::string &image_path, const std::string &prompt)
static RecentFilesManager & GetInstance()
static TimingManager & Get()
float Update()
Update the timing manager (call once per frame)
void OpenFolder(const std::string &folder_path)
void Update(bool &is_loaded)
void add_room(int room_id)
bool show_palette_editor_
void Initialize(gfx::IRenderer *renderer, Rom *rom)
bool show_entrances_list_
absl::Status SaveProjectAs()
std::deque< RomSession > sessions_
bool show_resource_label_manager
void SaveWorkspacePreset(const std::string &name)
bool show_command_palette_
void InitializeTestSuites()
bool show_save_workspace_preset_
bool show_proposal_drawer_
void ShowEditorSelection()
absl::Status SaveRomAs(const std::string &filename)
void DrawContextSensitiveCardControl()
bool show_test_dashboard_
MenuBuilder menu_builder_
void JumpToDungeonRoom(int room_id)
void SwitchToSession(size_t index)
bool show_palette_editor_
void DrawSessionSwitcher()
size_t GetActiveSessionCount() const
absl::Status OpenProject()
void CloseCurrentSession()
gfx::IRenderer * renderer_
bool HasDuplicateSession(const std::string &filepath)
void SwitchToEditor(EditorType editor_type)
absl::Status RepairCurrentProject()
EditorSelectionDialog editor_selection_dialog_
bool show_load_workspace_preset_
bool welcome_screen_manually_closed_
EditorSet * current_editor_set_
void LoadWorkspacePreset(const std::string &name)
std::string GenerateUniqueEditorTitle(EditorType type, size_t session_index) const
auto GetCurrentRom() -> Rom *
void RenameSession(size_t index, const std::string &new_name)
void ShowSessionSwitcher()
void LoadWorkspaceLayout()
void ShowDisplaySettings()
void DuplicateCurrentSession()
void Initialize(gfx::IRenderer *renderer, const std::string &filename="")
AgentChatHistoryPopup agent_chat_history_popup_
bool show_layout_presets_
void ResetWorkspaceLayout()
absl::Status CreateNewProject(const std::string &template_name="Basic ROM Hack")
void DrawSessionRenameDialog()
EditorSet blank_editor_set_
ToastManager toast_manager_
bool show_session_manager_
bool show_editor_selection_
void RefreshWorkspacePresets()
ProjectFileEditor project_file_editor_
size_t session_to_rename_
void CloseAllFloatingWindows()
void MaximizeCurrentWindow()
absl::Status SaveProject()
void LoadDesignerLayout()
void DrawSessionManager()
void SaveWorkspaceLayout()
void OpenEditorAndCardsFromFlags(const std::string &editor_name, const std::string &cards_str)
void JumpToOverworldMap(int map_id)
size_t GetCurrentSessionIndex() const
absl::Status ImportProject(const std::string &project_path)
bool show_welcome_screen_
void LoadDeveloperLayout()
core::YazeProject current_project_
bool show_session_rename_dialog_
UserSettings user_settings_
WorkspaceManager workspace_manager_
bool show_session_switcher_
ProposalDrawer proposal_drawer_
absl::Status DrawRomSelector()
WelcomeScreen welcome_screen_
absl::Status LoadAssets()
absl::Status OpenRomOrProject(const std::string &filename)
void RemoveSession(size_t index)
std::unique_ptr< PopupManager > popup_manager_
bool show_performance_dashboard_
absl::Status SetCurrentRom(Rom *rom)
char session_rename_buffer_[256]
void ClearRecentEditors()
Clear recent editors (for new ROM sessions)
void SetSelectionCallback(std::function< void(EditorType)> callback)
Set callback for when editor is selected.
void MarkRecentlyUsed(EditorType type)
Mark an editor as recently used.
bool Show(bool *p_open=nullptr)
Show the dialog.
Contains a complete set of editors for a single ROM instance.
SettingsEditor settings_editor_
MusicEditor music_editor_
ScreenEditor screen_editor_
DungeonEditorV2 dungeon_editor_
MemoryEditorWithDiffChecker memory_editor_
GraphicsEditor graphics_editor_
void set_user_settings(UserSettings *settings)
AssemblyEditor assembly_editor_
SpriteEditor sprite_editor_
OverworldEditor overworld_editor_
MessageEditor message_editor_
std::vector< Editor * > active_editors_
PaletteEditor palette_editor_
virtual absl::Status Cut()=0
virtual absl::Status Copy()=0
virtual absl::Status Redo()=0
void set_active(bool active)
virtual absl::Status Find()=0
virtual absl::Status Paste()=0
virtual absl::Status Undo()=0
absl::Status Load() override
void Initialize() override
absl::Status Load() override
Manipulates the Overworld and OverworldMap data in a Rom.
void set_current_map(int map_id)
absl::Status Load() override
void Initialize(gfx::IRenderer *renderer, Rom *rom)
absl::Status Save() override
absl::Status Update() override
absl::Status Load() override
void SetToastManager(ToastManager *toast_manager)
Set toast manager for notifications.
void FocusProposal(const std::string &proposal_id)
absl::Status Load() override
std::vector< zelda3::DungeonMap > dungeon_maps_
absl::Status Load() override
auto GetShortcuts() const
void RegisterShortcut(const std::string &name, const std::vector< ImGuiKey > &keys)
absl::Status Load() override
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
void SetNewProjectCallback(std::function< void()> callback)
Set callback for creating new project.
void MarkManuallyClosed()
Mark as manually closed (don't show again this session)
void RefreshRecentProjects()
Refresh recent projects list from the project manager.
void SetOpenRomCallback(std::function< void()> callback)
Set callback for opening ROM.
bool Show(bool *p_open)
Show the welcome screen.
void SetOpenProjectCallback(std::function< void(const std::string &)> callback)
Set callback for opening project.
bool workspace_presets_loaded() const
const std::vector< std::string > & workspace_presets() const
void set_renderer(gfx::IRenderer *renderer)
Defines an abstract interface for all rendering operations.
static BackgroundRenderer & Get()
void ShowAllCardsInCategory(const std::string &category)
void DrawCardBrowser(bool *p_open)
static EditorCardManager & Get()
static ThemeManager & Get()
absl::Status ShowHarnessActiveTests()
absl::Status ShowHarnessDashboard()
absl::Status RunTestSuite(const std::string &suite_name)
void SetCurrentRom(Rom *rom)
absl::Status RunAllTests()
static TestManager & Get()
absl::Status RunTestsByCategory(TestCategory category)
absl::Status ReplayLastPlan()
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 ICON_MD_CLOUD_OFF
#define ICON_MD_DEVELOPER_MODE
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_CONTENT_CUT
#define ICON_MD_FILE_OPEN
#define ICON_MD_EXIT_TO_APP
#define ICON_MD_RATE_REVIEW
#define ICON_MD_VIEW_LIST
#define ICON_MD_DATA_ARRAY
#define ICON_MD_PLAY_ARROW
#define ICON_MD_DESIGN_SERVICES
#define ICON_MD_FULLSCREEN_EXIT
#define ICON_MD_INTEGRATION_INSTRUCTIONS
#define ICON_MD_VIDEOGAME_ASSET
#define ICON_MD_CHAT_BUBBLE
#define ICON_MD_SWITCH_ACCOUNT
#define ICON_MD_VISIBILITY
#define ICON_MD_SCREENSHOT
#define ICON_MD_MUSIC_NOTE
#define ICON_MD_CONTENT_PASTE
#define ICON_MD_FULLSCREEN
#define ICON_MD_MANAGE_SEARCH
#define ICON_MD_CLEAR_ALL
#define ICON_MD_VISIBILITY_OFF
#define ICON_MD_CLOSE_FULLSCREEN
#define ICON_MD_DISPLAY_SETTINGS
#define ICON_MD_CHECK_CIRCLE
#define ICON_MD_DESCRIPTION
#define ICON_MD_MANAGE_ACCOUNTS
#define ICON_MD_CREATE_NEW_FOLDER
#define ICON_MD_DASHBOARD
#define ICON_MD_CONTENT_COPY
#define ICON_MD_RADIO_BUTTON_UNCHECKED
#define ICON_MD_ANALYTICS
#define ICON_MD_CLOUD_UPLOAD
#define ICON_MD_ADD_CIRCLE
#define ICON_MD_SMART_TOY
#define LOG_DEBUG(category, format,...)
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
#define PRINT_IF_ERROR(expression)
#define RETURN_IF_ERROR(expression)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
std::string GetEditorName(EditorType type)
constexpr std::array< const char *, 14 > kEditorNames
constexpr const char * kDungeonEditorName
constexpr const char * kMessageEditorName
constexpr const char * kGraphicsEditorName
constexpr const char * kScreenEditorName
constexpr const char * kSettingsEditorName
constexpr const char * kMusicEditorName
constexpr const char * kOverworldEditorName
std::string PrintShortcut(const std::vector< ImGuiKey > &keys)
constexpr const char * kAssemblyEditorName
constexpr const char * kSpriteEditorName
void ExecuteShortcuts(const ShortcutManager &shortcut_manager)
constexpr const char * kPaletteEditorName
constexpr ImVec2 kDefaultModalSize
void RegisterZ3edTestSuites()
std::string GetFileName(const std::string &filename)
Gets the filename from a full path.
std::string GetFileExtension(const std::string &filename)
Gets the file extension from a filename.
void logf(const absl::FormatSpec< Args... > &format, Args &&... args)
constexpr int OverworldCustomASMHasBeenApplied
absl::Status SaveDungeonMaps(Rom &rom, std::vector< DungeonMap > &dungeon_maps)
Save the dungeon maps to the ROM.
Main namespace for the application.
absl::StatusOr< std::array< gfx::Bitmap, kNumGfxSheets > > LoadAllGraphicsData(Rom &rom, bool defer_render)
This function iterates over all graphics sheets in the Rom and loads them into memory....
absl::Status SaveAllGraphicsData(Rom &rom, std::array< gfx::Bitmap, kNumGfxSheets > &gfx_sheets)
bool kLoadCustomOverworld
struct yaze::core::FeatureFlags::Flags::Overworld overworld
bool LoadLabels(const std::string &filename)
void DisplayLabels(bool *p_open)
std::unordered_map< std::string, std::unordered_map< std::string, std::string > > labels_
float autosave_interval_secs
std::vector< std::string > recent_files
Modern project structure with comprehensive settings consolidation.
absl::Status Open(const std::string &project_path)
bool project_opened() const
WorkspaceSettings workspace_settings
absl::Status Validate() const
FeatureFlags::Flags feature_flags
std::string labels_filename
absl::Status RepairProject()
std::string GetDisplayName() const
absl::Status Create(const std::string &project_name, const std::string &base_path)
absl::Status ImportZScreamProject(const std::string &zscream_project_path)
ShortcutManager shortcut_manager
PopupManager * popup_manager
core::FeatureFlags::Flags feature_flags
void Update(bool &show_memory_editor)
bool show_welcome_on_startup