feat: Enhance Welcome Screen and Menu Structure in EditorManager
- Integrated a new `WelcomeScreen` class for a modernized user experience, featuring callbacks for opening ROMs, creating new projects, and opening existing projects. - Updated the menu structure to include new items for message and music editors, as well as an AI Agent menu for collaboration features. - Added functionality for hosting and joining collaboration sessions, along with options for network settings and session management. - Improved the welcome screen display logic to handle recent projects and user interactions more effectively.
This commit is contained in:
@@ -324,6 +324,31 @@ void EditorManager::Initialize(const std::string& filename) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Load critical user settings first
|
// Load critical user settings first
|
||||||
|
// Initialize welcome screen callbacks
|
||||||
|
welcome_screen_.SetOpenRomCallback([this]() {
|
||||||
|
status_ = LoadRom();
|
||||||
|
if (status_.ok()) {
|
||||||
|
show_welcome_screen_ = false;
|
||||||
|
welcome_screen_manually_closed_ = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
welcome_screen_.SetNewProjectCallback([this]() {
|
||||||
|
status_ = CreateNewProject();
|
||||||
|
if (status_.ok()) {
|
||||||
|
show_welcome_screen_ = false;
|
||||||
|
welcome_screen_manually_closed_ = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
welcome_screen_.SetOpenProjectCallback([this](const std::string& filepath) {
|
||||||
|
status_ = OpenRomOrProject(filepath);
|
||||||
|
if (status_.ok()) {
|
||||||
|
show_welcome_screen_ = false;
|
||||||
|
welcome_screen_manually_closed_ = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
LoadUserSettings();
|
LoadUserSettings();
|
||||||
|
|
||||||
// Defer workspace presets loading to avoid initialization crashes
|
// Defer workspace presets loading to avoid initialization crashes
|
||||||
@@ -1159,12 +1184,23 @@ void EditorManager::BuildModernMenu() {
|
|||||||
[this]() { current_editor_set_->sprite_editor_.set_active(true); })
|
[this]() { current_editor_set_->sprite_editor_.set_active(true); })
|
||||||
.Item("Palette", ICON_MD_PALETTE,
|
.Item("Palette", ICON_MD_PALETTE,
|
||||||
[this]() { current_editor_set_->palette_editor_.set_active(true); })
|
[this]() { current_editor_set_->palette_editor_.set_active(true); })
|
||||||
|
.Item("Message", ICON_MD_CHAT_BUBBLE,
|
||||||
|
[this]() { current_editor_set_->message_editor_.set_active(true); })
|
||||||
|
.Item("Music", ICON_MD_MUSIC_NOTE,
|
||||||
|
[this]() { current_editor_set_->music_editor_.set_active(true); })
|
||||||
.EndMenu()
|
.EndMenu()
|
||||||
.Separator()
|
.Separator()
|
||||||
.Item("Welcome Screen", ICON_MD_HOME,
|
.Item("Welcome Screen", ICON_MD_HOME,
|
||||||
[this]() { show_welcome_screen_ = true; })
|
[this]() { show_welcome_screen_ = true; })
|
||||||
.Item("Command Palette", ICON_MD_TERMINAL,
|
.Item("Command Palette", ICON_MD_TERMINAL,
|
||||||
[this]() { show_command_palette_ = true; }, "Ctrl+Shift+P")
|
[this]() { show_command_palette_ = true; }, "Ctrl+Shift+P")
|
||||||
|
#ifdef YAZE_WITH_GRPC
|
||||||
|
.Separator()
|
||||||
|
.Item("AI Agent Editor", ICON_MD_SMART_TOY,
|
||||||
|
[this]() { agent_editor_.SetChatActive(true); }, "Ctrl+Shift+A",
|
||||||
|
nullptr,
|
||||||
|
[this]() { return agent_editor_.IsChatActive(); })
|
||||||
|
#endif
|
||||||
.EndMenu();
|
.EndMenu();
|
||||||
|
|
||||||
// Workspace Menu
|
// Workspace Menu
|
||||||
@@ -1188,6 +1224,98 @@ void EditorManager::BuildModernMenu() {
|
|||||||
[this]() { show_performance_dashboard_ = true; }, "Ctrl+Shift+P")
|
[this]() { show_performance_dashboard_ = true; }, "Ctrl+Shift+P")
|
||||||
.EndMenu();
|
.EndMenu();
|
||||||
|
|
||||||
|
#ifdef YAZE_WITH_GRPC
|
||||||
|
// AI Agent Menu
|
||||||
|
menu_builder_.BeginMenu("AI Agent", ICON_MD_SMART_TOY)
|
||||||
|
.Item("Open Agent Chat", ICON_MD_CHAT,
|
||||||
|
[this]() { agent_editor_.SetChatActive(true); }, "Ctrl+Shift+A")
|
||||||
|
.Separator()
|
||||||
|
.BeginSubMenu("Vision & Multimodal", ICON_MD_CAMERA)
|
||||||
|
.Item("Capture Active Editor", ICON_MD_SCREENSHOT,
|
||||||
|
[this]() {
|
||||||
|
std::filesystem::path output;
|
||||||
|
AgentEditor::CaptureConfig config;
|
||||||
|
config.mode = AgentEditor::CaptureConfig::CaptureMode::kActiveEditor;
|
||||||
|
status_ = agent_editor_.CaptureSnapshot(&output, config);
|
||||||
|
})
|
||||||
|
.Item("Capture Full Window", ICON_MD_FULLSCREEN,
|
||||||
|
[this]() {
|
||||||
|
std::filesystem::path output;
|
||||||
|
AgentEditor::CaptureConfig config;
|
||||||
|
config.mode = AgentEditor::CaptureConfig::CaptureMode::kFullWindow;
|
||||||
|
status_ = agent_editor_.CaptureSnapshot(&output, config);
|
||||||
|
})
|
||||||
|
.EndMenu()
|
||||||
|
.Separator()
|
||||||
|
.Item("Proposal Drawer", ICON_MD_RATE_REVIEW,
|
||||||
|
[this]() { show_proposal_drawer_ = !show_proposal_drawer_; },
|
||||||
|
nullptr, nullptr,
|
||||||
|
[this]() { return show_proposal_drawer_; })
|
||||||
|
.EndMenu();
|
||||||
|
|
||||||
|
// Collaboration Menu
|
||||||
|
menu_builder_.BeginMenu("Collaboration", ICON_MD_PEOPLE)
|
||||||
|
.BeginSubMenu("Session", ICON_MD_MEETING_ROOM)
|
||||||
|
.Item("Host Session", ICON_MD_ADD_CIRCLE,
|
||||||
|
[this]() {
|
||||||
|
auto result = agent_editor_.HostSession("New Session");
|
||||||
|
if (result.ok()) {
|
||||||
|
toast_manager_.AddToast(ToastType::Success,
|
||||||
|
"Hosted session: " + result->session_name);
|
||||||
|
} else {
|
||||||
|
toast_manager_.AddToast(ToastType::Error,
|
||||||
|
"Failed to host session: " + std::string(result.status().message()));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.Item("Join Session", ICON_MD_LOGIN,
|
||||||
|
[this]() { popup_manager_->Show("Join Collaboration Session"); })
|
||||||
|
.Separator()
|
||||||
|
.Item("Leave Session", ICON_MD_LOGOUT,
|
||||||
|
[this]() {
|
||||||
|
status_ = agent_editor_.LeaveSession();
|
||||||
|
if (status_.ok()) {
|
||||||
|
toast_manager_.AddToast(ToastType::Info, "Left collaboration session");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nullptr,
|
||||||
|
[this]() { return agent_editor_.IsInSession(); })
|
||||||
|
.Item("Refresh Session", ICON_MD_REFRESH,
|
||||||
|
[this]() {
|
||||||
|
auto result = agent_editor_.RefreshSession();
|
||||||
|
if (result.ok()) {
|
||||||
|
toast_manager_.AddToast(ToastType::Success,
|
||||||
|
"Session refreshed: " + std::to_string(result->participants.size()) + " participants");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nullptr,
|
||||||
|
[this]() { return agent_editor_.IsInSession(); })
|
||||||
|
.EndMenu()
|
||||||
|
.Separator()
|
||||||
|
.BeginSubMenu("Network", ICON_MD_CLOUD)
|
||||||
|
.Item("Connect to Server", ICON_MD_CLOUD_UPLOAD,
|
||||||
|
[this]() { popup_manager_->Show("Connect to Server"); })
|
||||||
|
.Item("Disconnect", ICON_MD_CLOUD_OFF,
|
||||||
|
[this]() {
|
||||||
|
agent_editor_.DisconnectFromServer();
|
||||||
|
toast_manager_.AddToast(ToastType::Info, "Disconnected from server");
|
||||||
|
},
|
||||||
|
nullptr,
|
||||||
|
[this]() { return agent_editor_.IsConnectedToServer(); })
|
||||||
|
.EndMenu()
|
||||||
|
.Separator()
|
||||||
|
.BeginSubMenu("Mode", ICON_MD_SETTINGS_ETHERNET)
|
||||||
|
.Item("Local (Filesystem)", ICON_MD_FOLDER,
|
||||||
|
[this]() { /* Set local mode */ },
|
||||||
|
nullptr, nullptr,
|
||||||
|
[this]() { return agent_editor_.GetCurrentMode() == AgentEditor::CollaborationMode::kLocal; })
|
||||||
|
.Item("Network (WebSocket)", ICON_MD_WIFI,
|
||||||
|
[this]() { /* Set network mode */ },
|
||||||
|
nullptr, nullptr,
|
||||||
|
[this]() { return agent_editor_.GetCurrentMode() == AgentEditor::CollaborationMode::kNetwork; })
|
||||||
|
.EndMenu()
|
||||||
|
.EndMenu();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Debug Menu
|
// Debug Menu
|
||||||
menu_builder_.BeginMenu("Debug", ICON_MD_BUG_REPORT)
|
menu_builder_.BeginMenu("Debug", ICON_MD_BUG_REPORT)
|
||||||
.Item("Test Dashboard", ICON_MD_SCIENCE,
|
.Item("Test Dashboard", ICON_MD_SCIENCE,
|
||||||
@@ -3194,391 +3322,15 @@ void EditorManager::DrawSessionRenameDialog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorManager::DrawWelcomeScreen() {
|
void EditorManager::DrawWelcomeScreen() {
|
||||||
// Make welcome screen moveable but with a good default position
|
// Use the new WelcomeScreen class for a modern, feature-rich experience
|
||||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
|
welcome_screen_.RefreshRecentProjects();
|
||||||
ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
|
bool was_open = show_welcome_screen_;
|
||||||
ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
|
bool action_taken = welcome_screen_.Show(&show_welcome_screen_);
|
||||||
|
|
||||||
// Create a subtle animated background effect
|
|
||||||
static float animation_time = 0.0f;
|
|
||||||
animation_time += ImGui::GetIO().DeltaTime;
|
|
||||||
|
|
||||||
// Make it moveable and resizable but keep the custom styling
|
|
||||||
ImGuiWindowFlags flags =
|
|
||||||
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBackground;
|
|
||||||
|
|
||||||
// Use a unique window name to prevent stacking
|
|
||||||
static int welcome_window_id = 0;
|
|
||||||
std::string window_name =
|
|
||||||
absl::StrFormat("Welcome to YAZE##welcome_%d", welcome_window_id);
|
|
||||||
|
|
||||||
bool welcome_was_open = show_welcome_screen_;
|
|
||||||
if (ImGui::Begin(window_name.c_str(), &show_welcome_screen_, flags)) {
|
|
||||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
|
||||||
ImVec2 window_pos = ImGui::GetWindowPos();
|
|
||||||
ImVec2 window_size = ImGui::GetWindowSize();
|
|
||||||
|
|
||||||
// Get theme colors for welcome screen
|
|
||||||
auto& theme_manager = gui::ThemeManager::Get();
|
|
||||||
auto bg_color = theme_manager.GetWelcomeScreenBackground();
|
|
||||||
auto border_color = theme_manager.GetWelcomeScreenBorder();
|
|
||||||
auto accent_color = theme_manager.GetWelcomeScreenAccent();
|
|
||||||
|
|
||||||
// Draw themed gradient background
|
|
||||||
ImU32 bg_top = ImGui::ColorConvertFloat4ToU32(
|
|
||||||
ImVec4(bg_color.red, bg_color.green, bg_color.blue, bg_color.alpha));
|
|
||||||
ImU32 bg_bottom = ImGui::ColorConvertFloat4ToU32(
|
|
||||||
ImVec4(bg_color.red * 0.8f, bg_color.green * 0.8f, bg_color.blue * 0.8f,
|
|
||||||
bg_color.alpha));
|
|
||||||
draw_list->AddRectFilledMultiColor(
|
|
||||||
window_pos,
|
|
||||||
ImVec2(window_pos.x + window_size.x, window_pos.y + window_size.y),
|
|
||||||
bg_top, bg_top, bg_bottom, bg_bottom);
|
|
||||||
|
|
||||||
// Themed animated border
|
|
||||||
float border_thickness = 3.0f;
|
|
||||||
float pulse = 0.8f + 0.2f * sinf(animation_time * 2.0f);
|
|
||||||
ImU32 themed_border = ImGui::ColorConvertFloat4ToU32(
|
|
||||||
ImVec4(border_color.red, border_color.green, border_color.blue,
|
|
||||||
pulse * border_color.alpha));
|
|
||||||
draw_list->AddRect(
|
|
||||||
window_pos,
|
|
||||||
ImVec2(window_pos.x + window_size.x, window_pos.y + window_size.y),
|
|
||||||
themed_border, 12.0f, 0, border_thickness);
|
|
||||||
|
|
||||||
// Enhanced floating particles effect with multiple layers
|
|
||||||
for (int layer = 0; layer < 2; ++layer) {
|
|
||||||
int particle_count = layer == 0 ? 12 : 8;
|
|
||||||
float layer_speed = layer == 0 ? 1.0f : 0.6f;
|
|
||||||
float layer_alpha = layer == 0 ? 0.4f : 0.2f;
|
|
||||||
|
|
||||||
for (int i = 0; i < particle_count; ++i) {
|
|
||||||
float time_offset = layer * 3.14159f + i * 0.8f;
|
|
||||||
float offset_x =
|
|
||||||
sinf(animation_time * 0.5f * layer_speed + time_offset) *
|
|
||||||
(30.0f + layer * 10.0f);
|
|
||||||
float offset_y =
|
|
||||||
cosf(animation_time * 0.3f * layer_speed + time_offset) *
|
|
||||||
(20.0f + layer * 8.0f);
|
|
||||||
|
|
||||||
// Distribute particles across the window
|
|
||||||
float base_x = window_pos.x + (window_size.x / particle_count) * i + 40;
|
|
||||||
float base_y = window_pos.y + 80 + layer * 30;
|
|
||||||
|
|
||||||
ImVec2 particle_pos = ImVec2(base_x + offset_x, base_y + offset_y);
|
|
||||||
|
|
||||||
// Pulsing alpha effect
|
|
||||||
float alpha =
|
|
||||||
layer_alpha + 0.3f * sinf(animation_time * 1.5f + time_offset);
|
|
||||||
ImU32 particle_color = ImGui::ColorConvertFloat4ToU32(ImVec4(
|
|
||||||
accent_color.red, accent_color.green, accent_color.blue, alpha));
|
|
||||||
|
|
||||||
// Varying particle sizes
|
|
||||||
float radius = 1.5f + layer * 0.5f +
|
|
||||||
sinf(animation_time * 2.0f + time_offset) * 0.8f;
|
|
||||||
draw_list->AddCircleFilled(particle_pos, radius, particle_color);
|
|
||||||
|
|
||||||
// Add subtle glow effect for layer 0
|
|
||||||
if (layer == 0) {
|
|
||||||
ImU32 glow_color = ImGui::ColorConvertFloat4ToU32(
|
|
||||||
ImVec4(accent_color.red, accent_color.green, accent_color.blue,
|
|
||||||
alpha * 0.3f));
|
|
||||||
draw_list->AddCircleFilled(particle_pos, radius + 1.0f, glow_color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header with themed styling
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::SetCursorPosX(
|
|
||||||
(window_size.x -
|
|
||||||
ImGui::CalcTextSize("Welcome to Yet Another Zelda3 Editor").x) *
|
|
||||||
0.5f);
|
|
||||||
auto text_color = theme_manager.GetCurrentTheme().text_primary;
|
|
||||||
ImGui::PushStyleColor(
|
|
||||||
ImGuiCol_Text, ImVec4(text_color.red, text_color.green, text_color.blue,
|
|
||||||
text_color.alpha));
|
|
||||||
ImGui::Text("Welcome to Yet Another Zelda3 Editor");
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
|
|
||||||
ImGui::SetCursorPosX(
|
|
||||||
(window_size.x -
|
|
||||||
ImGui::CalcTextSize("The Legend of Zelda: A Link to the Past").x) *
|
|
||||||
0.5f);
|
|
||||||
auto subtitle_color = theme_manager.GetCurrentTheme().text_secondary;
|
|
||||||
ImGui::PushStyleColor(
|
|
||||||
ImGuiCol_Text,
|
|
||||||
ImVec4(subtitle_color.red, subtitle_color.green, subtitle_color.blue,
|
|
||||||
subtitle_color.alpha * 0.9f));
|
|
||||||
ImGui::Text("The Legend of Zelda: A Link to the Past");
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Themed decorative line with glow effect (positioned closer to header)
|
|
||||||
float line_y =
|
|
||||||
window_pos.y + 30; // Move even higher for tighter header integration
|
|
||||||
float line_margin = 80; // Maintain good horizontal balance
|
|
||||||
ImVec2 line_start = ImVec2(window_pos.x + line_margin, line_y);
|
|
||||||
ImVec2 line_end =
|
|
||||||
ImVec2(window_pos.x + window_size.x - line_margin, line_y);
|
|
||||||
|
|
||||||
// Enhanced glow effect with multiple line layers for depth
|
|
||||||
float glow_alpha = 0.6f + 0.4f * sinf(animation_time * 1.5f);
|
|
||||||
ImU32 line_color = ImGui::ColorConvertFloat4ToU32(ImVec4(
|
|
||||||
accent_color.red, accent_color.green, accent_color.blue, glow_alpha));
|
|
||||||
|
|
||||||
// Draw main line with glow effect
|
|
||||||
draw_list->AddLine(
|
|
||||||
line_start, line_end,
|
|
||||||
ImGui::ColorConvertFloat4ToU32(ImVec4(
|
|
||||||
accent_color.red, accent_color.green, accent_color.blue, 0.3f)),
|
|
||||||
4.0f); // Glow layer
|
|
||||||
draw_list->AddLine(line_start, line_end, line_color, 2.0f); // Main line
|
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Show different messages based on state
|
|
||||||
if (!sessions_.empty() && !current_rom_) {
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::TextColored(ImVec4(1.0f, 0.7f, 0.0f, 1.0f),
|
|
||||||
ICON_MD_WARNING " ROM Loading Required");
|
|
||||||
TextWrapped(
|
|
||||||
"A session exists but no ROM is loaded. Please load a ROM file to "
|
|
||||||
"continue editing.");
|
|
||||||
ImGui::Text("Active Sessions: %zu", GetActiveSessionCount());
|
|
||||||
} else {
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Spacing();
|
|
||||||
TextWrapped("No ROM loaded.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Enhanced primary actions with glowing buttons
|
|
||||||
ImGui::Text("Get Started:");
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Themed primary buttons with enhanced effects
|
|
||||||
auto current_theme = theme_manager.GetCurrentTheme();
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button,
|
|
||||||
ConvertColorToImVec4(current_theme.primary));
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
|
|
||||||
ConvertColorToImVec4(current_theme.accent));
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive,
|
|
||||||
ConvertColorToImVec4(current_theme.secondary));
|
|
||||||
|
|
||||||
if (ImGui::Button(ICON_MD_FILE_OPEN " Open ROM File", ImVec2(200, 40))) {
|
|
||||||
status_ = LoadRom();
|
|
||||||
if (!status_.ok()) {
|
|
||||||
toast_manager_.Show(std::string(status_.message()),
|
|
||||||
editor::ToastType::kError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_MD_FOLDER_OPEN " Open Project", ImVec2(200, 40))) {
|
|
||||||
auto file_name = util::FileDialogWrapper::ShowOpenFileDialog();
|
|
||||||
if (!file_name.empty()) {
|
|
||||||
status_ = OpenRomOrProject(file_name);
|
|
||||||
if (!status_.ok()) {
|
|
||||||
toast_manager_.Show(std::string(status_.message()),
|
|
||||||
editor::ToastType::kError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::PopStyleColor(3);
|
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Feature flags section (per-session)
|
|
||||||
ImGui::Text("Options:");
|
|
||||||
auto* flags = GetCurrentFeatureFlags();
|
|
||||||
Checkbox("Load custom overworld features",
|
|
||||||
&flags->overworld.kLoadCustomOverworld);
|
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Recent files section (reuse homepage logic)
|
|
||||||
ImGui::Text("Recent Files:");
|
|
||||||
ImGui::BeginChild("RecentFiles", ImVec2(0, 100), true);
|
|
||||||
auto& manager = core::RecentFilesManager::GetInstance();
|
|
||||||
for (const auto& file : manager.GetRecentFiles()) {
|
|
||||||
if (gui::ClickableText(file.c_str())) {
|
|
||||||
status_ = OpenRomOrProject(file);
|
|
||||||
if (!status_.ok()) {
|
|
||||||
toast_manager_.Show(std::string(status_.message()),
|
|
||||||
editor::ToastType::kError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndChild();
|
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Show editor access buttons for loaded sessions
|
|
||||||
bool has_loaded_sessions = false;
|
|
||||||
for (const auto& session : sessions_) {
|
|
||||||
if (session.rom.is_loaded()) {
|
|
||||||
has_loaded_sessions = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_loaded_sessions) {
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Text("Available Editors:");
|
|
||||||
ImGui::Text(
|
|
||||||
"Click to open editor windows that can be docked side by side");
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Show sessions and their editors
|
|
||||||
for (size_t session_idx = 0; session_idx < sessions_.size();
|
|
||||||
++session_idx) {
|
|
||||||
const auto& session = sessions_[session_idx];
|
|
||||||
if (!session.rom.is_loaded())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ImGui::Text("Session: %s", session.GetDisplayName().c_str());
|
|
||||||
|
|
||||||
// Editor buttons in a grid layout for this session
|
|
||||||
if (ImGui::BeginTable(
|
|
||||||
absl::StrFormat("EditorsTable##%zu", session_idx).c_str(), 4,
|
|
||||||
ImGuiTableFlags_SizingFixedFit |
|
|
||||||
ImGuiTableFlags_NoHostExtendX)) {
|
|
||||||
|
|
||||||
// Row 1: Primary editors
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat(ICON_MD_MAP " Overworld##%zu", session_idx)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(120, 30))) {
|
|
||||||
sessions_[session_idx].editors.overworld_editor_.set_active(true);
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat(ICON_MD_DOMAIN " Dungeon##%zu", session_idx)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(120, 30))) {
|
|
||||||
sessions_[session_idx].editors.dungeon_editor_.set_active(true);
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat(ICON_MD_IMAGE " Graphics##%zu", session_idx)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(120, 30))) {
|
|
||||||
sessions_[session_idx].editors.graphics_editor_.set_active(true);
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat(ICON_MD_PALETTE " Palette##%zu", session_idx)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(120, 30))) {
|
|
||||||
sessions_[session_idx].editors.palette_editor_.set_active(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Row 2: Secondary editors
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat(ICON_MD_MESSAGE " Message##%zu", session_idx)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(120, 30))) {
|
|
||||||
sessions_[session_idx].editors.message_editor_.set_active(true);
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat(ICON_MD_PERSON " Sprite##%zu", session_idx)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(120, 30))) {
|
|
||||||
sessions_[session_idx].editors.sprite_editor_.set_active(true);
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat(ICON_MD_MUSIC_NOTE " Music##%zu", session_idx)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(120, 30))) {
|
|
||||||
sessions_[session_idx].editors.music_editor_.set_active(true);
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat(ICON_MD_MONITOR " Screen##%zu", session_idx)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(120, 30))) {
|
|
||||||
sessions_[session_idx].editors.screen_editor_.set_active(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session_idx < sessions_.size() - 1) {
|
|
||||||
ImGui::Spacing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Links section
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Text("Help & Support:");
|
|
||||||
if (gui::ClickableText(ICON_MD_HELP " Getting Started Guide")) {
|
|
||||||
gui::OpenUrl(
|
|
||||||
"https://github.com/scawful/yaze/blob/master/docs/"
|
|
||||||
"01-getting-started.md");
|
|
||||||
}
|
|
||||||
if (gui::ClickableText(ICON_MD_BUG_REPORT " Report Issues")) {
|
|
||||||
gui::OpenUrl("https://github.com/scawful/yaze/issues");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show tip about drag and drop
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), ICON_MD_TIPS_AND_UPDATES
|
|
||||||
" Tip: Drag and drop ROM files onto the window");
|
|
||||||
|
|
||||||
// Add settings and customization section (accessible before ROM loading)
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Text("%s Customization & Settings", ICON_MD_SETTINGS);
|
|
||||||
|
|
||||||
// Theme and display settings buttons (always accessible)
|
|
||||||
static bool show_welcome_theme_selector = false;
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat("%s Theme Settings", ICON_MD_PALETTE).c_str(),
|
|
||||||
ImVec2(180, 35))) {
|
|
||||||
show_welcome_theme_selector = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show theme selector if requested
|
|
||||||
if (show_welcome_theme_selector) {
|
|
||||||
auto& theme_manager = gui::ThemeManager::Get();
|
|
||||||
theme_manager.ShowThemeSelector(&show_welcome_theme_selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat("%s Display Settings", ICON_MD_DISPLAY_SETTINGS)
|
|
||||||
.c_str(),
|
|
||||||
ImVec2(180, 35))) {
|
|
||||||
// Open display settings popup (make it accessible without ROM)
|
|
||||||
popup_manager_->Show("Display Settings");
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(
|
|
||||||
absl::StrFormat("%s Command Palette", ICON_MD_TERMINAL).c_str(),
|
|
||||||
ImVec2(180, 35))) {
|
|
||||||
show_command_palette_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
|
|
||||||
// Check if the welcome screen was manually closed via the close button
|
// Check if the welcome screen was manually closed via the close button
|
||||||
if (welcome_was_open && !show_welcome_screen_) {
|
if (was_open && !show_welcome_screen_) {
|
||||||
welcome_screen_manually_closed_ = true;
|
welcome_screen_manually_closed_ = true;
|
||||||
|
welcome_screen_.MarkManuallyClosed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "app/editor/system/settings_editor.h"
|
#include "app/editor/system/settings_editor.h"
|
||||||
#include "app/editor/system/toast_manager.h"
|
#include "app/editor/system/toast_manager.h"
|
||||||
#include "app/editor/ui/editor_selection_dialog.h"
|
#include "app/editor/ui/editor_selection_dialog.h"
|
||||||
|
#include "app/editor/ui/welcome_screen.h"
|
||||||
#include "app/emu/emulator.h"
|
#include "app/emu/emulator.h"
|
||||||
#include "app/gfx/performance_dashboard.h"
|
#include "app/gfx/performance_dashboard.h"
|
||||||
#include "app/rom.h"
|
#include "app/rom.h"
|
||||||
@@ -196,6 +197,9 @@ class EditorManager {
|
|||||||
EditorSelectionDialog editor_selection_dialog_;
|
EditorSelectionDialog editor_selection_dialog_;
|
||||||
bool show_editor_selection_ = false;
|
bool show_editor_selection_ = false;
|
||||||
|
|
||||||
|
// Welcome screen
|
||||||
|
WelcomeScreen welcome_screen_;
|
||||||
|
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
// Agent editor - manages chat, collaboration, and network coordination
|
// Agent editor - manages chat, collaboration, and network coordination
|
||||||
AgentEditor agent_editor_;
|
AgentEditor agent_editor_;
|
||||||
|
|||||||
Reference in New Issue
Block a user