feat: Revamp EditorManager and UI Components for Enhanced User Experience

- Updated the EditorManager to streamline the editor selection process, integrating new menu items for ROM and project management.
- Enhanced the welcome screen logic to automatically show the editor selection dialog after loading a ROM, improving user flow.
- Introduced new menu options for saving and validating ROMs, creating backups, and accessing ROM information.
- Improved the editor selection dialog with distinct colors for each editor type, enhancing visual clarity and user interaction.
- Added advanced settings and collaboration features in the Agent Chat Widget, including improved connection management and model selection.
- Expanded the welcome screen with additional project card features and tips for user guidance.
This commit is contained in:
scawful
2025-10-05 03:19:36 -04:00
parent 81c67728a9
commit 33242a8803
7 changed files with 590 additions and 325 deletions

View File

@@ -14,41 +14,51 @@ namespace yaze {
namespace editor {
EditorSelectionDialog::EditorSelectionDialog() {
// Initialize editor metadata
// Initialize editor metadata with distinct colors
editors_ = {
{EditorType::kOverworld, "Overworld", ICON_MD_MAP,
"Edit overworld maps, entrances, and properties", "Ctrl+1", false, true},
"Edit overworld maps, entrances, and properties", "Ctrl+1", false, true,
ImVec4(0.133f, 0.545f, 0.133f, 1.0f)}, // Hyrule green
{EditorType::kDungeon, "Dungeon", ICON_MD_CASTLE,
"Design dungeon rooms, layouts, and mechanics", "Ctrl+2", false, true},
"Design dungeon rooms, layouts, and mechanics", "Ctrl+2", false, true,
ImVec4(0.502f, 0.0f, 0.502f, 1.0f)}, // Ganon purple
{EditorType::kGraphics, "Graphics", ICON_MD_PALETTE,
"Modify tiles, palettes, and graphics sets", "Ctrl+3", false, true},
"Modify tiles, palettes, and graphics sets", "Ctrl+3", false, true,
ImVec4(1.0f, 0.843f, 0.0f, 1.0f)}, // Triforce gold
{EditorType::kSprite, "Sprites", ICON_MD_EMOJI_EMOTIONS,
"Edit sprite graphics and properties", "Ctrl+4", false, true},
"Edit sprite graphics and properties", "Ctrl+4", false, true,
ImVec4(1.0f, 0.647f, 0.0f, 1.0f)}, // Spirit orange
{EditorType::kMessage, "Messages", ICON_MD_CHAT_BUBBLE,
"Edit dialogue, signs, and text", "Ctrl+5", false, true},
"Edit dialogue, signs, and text", "Ctrl+5", false, true,
ImVec4(0.196f, 0.6f, 0.8f, 1.0f)}, // Master sword blue
{EditorType::kMusic, "Music", ICON_MD_MUSIC_NOTE,
"Configure music and sound effects", "Ctrl+6", false, true},
"Configure music and sound effects", "Ctrl+6", false, true,
ImVec4(0.416f, 0.353f, 0.804f, 1.0f)}, // Shadow purple
{EditorType::kPalette, "Palettes", ICON_MD_COLOR_LENS,
"Edit color palettes and animations", "Ctrl+7", false, true},
"Edit color palettes and animations", "Ctrl+7", false, true,
ImVec4(0.863f, 0.078f, 0.235f, 1.0f)}, // Heart red
{EditorType::kScreen, "Screens", ICON_MD_TV,
"Edit title screen and ending screens", "Ctrl+8", false, true},
"Edit title screen and ending screens", "Ctrl+8", false, true,
ImVec4(0.4f, 0.8f, 1.0f, 1.0f)}, // Sky blue
{EditorType::kAssembly, "Assembly", ICON_MD_CODE,
"Write and edit assembly code", "Ctrl+9", false, false},
"Write and edit assembly code", "Ctrl+9", false, false,
ImVec4(0.8f, 0.8f, 0.8f, 1.0f)}, // Silver
// TODO: Fix this
// {EditorType::kHex, "Hex Editor", ICON_MD_DATA_ARRAY,
// "Direct ROM memory editing", "Ctrl+0", false, true},
{EditorType::kHex, "Hex Editor", ICON_MD_DATA_ARRAY,
"Direct ROM memory editing and comparison", "Ctrl+0", false, true,
ImVec4(0.2f, 0.8f, 0.4f, 1.0f)}, // Matrix green
{EditorType::kSettings, "Settings", ICON_MD_SETTINGS,
"Configure ROM and project settings", "", false, true},
"Configure ROM and project settings", "", false, true,
ImVec4(0.6f, 0.6f, 0.6f, 1.0f)}, // Gray
};
LoadRecentEditors();
@@ -66,13 +76,13 @@ bool EditorSelectionDialog::Show(bool* p_open) {
}
bool editor_selected = false;
bool* window_open = p_open ? p_open : &is_open_;
// Center the dialog
// Set window properties immediately before Begin to prevent them from affecting tooltips
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
ImGui::SetNextWindowSize(ImVec2(900, 600), ImGuiCond_Appearing);
ImGui::SetNextWindowSize(ImVec2(950, 650), ImGuiCond_Appearing); // Slightly larger for better layout
bool* window_open = p_open ? p_open : &is_open_;
if (ImGui::Begin("Editor Selection", window_open,
ImGuiWindowFlags_NoCollapse)) {
DrawWelcomeHeader();
@@ -131,19 +141,26 @@ bool EditorSelectionDialog::Show(bool* p_open) {
}
void EditorSelectionDialog::DrawWelcomeHeader() {
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]); // Larger font if available
ImDrawList* draw_list = ImGui::GetWindowDrawList();
ImVec2 header_start = ImGui::GetCursorScreenPos();
ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
ICON_MD_EDIT " Select an Editor");
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[2]); // Large font
// Colorful gradient title
ImVec4 title_color = ImVec4(1.0f, 0.843f, 0.0f, 1.0f); // Triforce gold
ImGui::TextColored(title_color, ICON_MD_EDIT " Select an Editor");
ImGui::PopFont();
ImGui::TextWrapped("Choose an editor to begin working on your ROM. "
// Subtitle with gradient separator
ImVec2 subtitle_pos = ImGui::GetCursorScreenPos();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.8f, 1.0f),
"Choose an editor to begin working on your ROM. "
"You can open multiple editors simultaneously.");
}
void EditorSelectionDialog::DrawQuickAccessButtons() {
ImGui::Text(ICON_MD_HISTORY " Recently Used");
ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_HISTORY " Recently Used");
ImGui::Spacing();
for (EditorType type : recent_editors_) {
@@ -154,14 +171,20 @@ void EditorSelectionDialog::DrawQuickAccessButtons() {
});
if (it != editors_.end()) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.5f, 0.8f, 0.6f));
// Use editor's theme color for button
ImVec4 color = it->color;
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(color.x * 0.5f, color.y * 0.5f,
color.z * 0.5f, 0.7f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(color.x * 0.7f, color.y * 0.7f,
color.z * 0.7f, 0.9f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
if (ImGui::Button(absl::StrCat(it->icon, " ", it->name).c_str(),
ImVec2(150, 30))) {
ImVec2(150, 35))) {
selected_editor_ = type;
}
ImGui::PopStyleColor();
ImGui::PopStyleColor(3);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", it->description);
@@ -177,44 +200,119 @@ void EditorSelectionDialog::DrawQuickAccessButtons() {
void EditorSelectionDialog::DrawEditorCard(const EditorInfo& info, int index) {
ImGui::PushID(index);
// Card styling
ImVec2 button_size(180, 120);
ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
ImDrawList* draw_list = ImGui::GetWindowDrawList();
// Card styling with gradients
bool is_recent = std::find(recent_editors_.begin(), recent_editors_.end(),
info.type) != recent_editors_.end();
// Create gradient background
ImVec4 base_color = info.color;
ImU32 color_top = ImGui::GetColorU32(ImVec4(base_color.x * 0.4f, base_color.y * 0.4f,
base_color.z * 0.4f, 0.8f));
ImU32 color_bottom = ImGui::GetColorU32(ImVec4(base_color.x * 0.2f, base_color.y * 0.2f,
base_color.z * 0.2f, 0.9f));
// Draw gradient card background
draw_list->AddRectFilledMultiColor(
cursor_pos,
ImVec2(cursor_pos.x + button_size.x, cursor_pos.y + button_size.y),
color_top, color_top, color_bottom, color_bottom);
// Colored border
ImU32 border_color = is_recent
? ImGui::GetColorU32(ImVec4(base_color.x, base_color.y, base_color.z, 1.0f))
: ImGui::GetColorU32(ImVec4(base_color.x * 0.6f, base_color.y * 0.6f,
base_color.z * 0.6f, 0.7f));
draw_list->AddRect(cursor_pos,
ImVec2(cursor_pos.x + button_size.x, cursor_pos.y + button_size.y),
border_color, 4.0f, 0, is_recent ? 3.0f : 2.0f);
// Recent indicator badge
if (is_recent) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.25f, 0.55f, 0.85f, 0.4f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.3f, 0.6f, 0.9f, 0.6f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.35f, 0.65f, 0.95f, 0.8f));
ImVec2 badge_pos(cursor_pos.x + button_size.x - 25, cursor_pos.y + 5);
draw_list->AddCircleFilled(badge_pos, 12, ImGui::GetColorU32(base_color), 16);
ImGui::SetCursorScreenPos(ImVec2(badge_pos.x - 6, badge_pos.y - 8));
ImGui::TextColored(ImVec4(1, 1, 1, 1), ICON_MD_STAR);
}
// Editor button with icon
ImVec2 button_size(180, 100);
if (ImGui::Button(absl::StrCat(info.icon, "\n", info.name).c_str(),
button_size)) {
selected_editor_ = info.type;
// Make button transparent (we draw our own background)
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(base_color.x * 0.3f, base_color.y * 0.3f,
base_color.z * 0.3f, 0.5f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(base_color.x * 0.5f, base_color.y * 0.5f,
base_color.z * 0.5f, 0.7f));
ImGui::SetCursorScreenPos(cursor_pos);
bool clicked = ImGui::Button(absl::StrCat("##", info.name).c_str(), button_size);
bool is_hovered = ImGui::IsItemHovered();
ImGui::PopStyleColor(3);
// Draw icon with colored background circle
ImVec2 icon_center(cursor_pos.x + button_size.x / 2, cursor_pos.y + 30);
ImU32 icon_bg = ImGui::GetColorU32(base_color);
draw_list->AddCircleFilled(icon_center, 22, icon_bg, 32);
// Draw icon
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[2]); // Larger font for icon
ImVec2 icon_size = ImGui::CalcTextSize(info.icon);
ImGui::SetCursorScreenPos(ImVec2(icon_center.x - icon_size.x / 2, icon_center.y - icon_size.y / 2));
ImGui::TextColored(ImVec4(1, 1, 1, 1), "%s", info.icon);
ImGui::PopFont();
// Draw name
ImGui::SetCursorScreenPos(ImVec2(cursor_pos.x + 10, cursor_pos.y + 65));
ImGui::PushTextWrapPos(cursor_pos.x + button_size.x - 10);
ImVec2 name_size = ImGui::CalcTextSize(info.name);
ImGui::SetCursorScreenPos(ImVec2(cursor_pos.x + (button_size.x - name_size.x) / 2,
cursor_pos.y + 65));
ImGui::TextColored(base_color, "%s", info.name);
ImGui::PopTextWrapPos();
// Draw shortcut hint if available
if (info.shortcut && info.shortcut[0]) {
ImGui::SetCursorScreenPos(ImVec2(cursor_pos.x + 10, cursor_pos.y + button_size.y - 20));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6f, 0.6f, 0.6f, 1.0f));
ImGui::Text("%s", info.shortcut);
ImGui::PopStyleColor();
}
if (is_recent) {
ImGui::PopStyleColor(3);
// Hover glow effect
if (is_hovered) {
ImU32 glow_color = ImGui::GetColorU32(ImVec4(base_color.x, base_color.y, base_color.z, 0.2f));
draw_list->AddRectFilled(cursor_pos,
ImVec2(cursor_pos.x + button_size.x, cursor_pos.y + button_size.y),
glow_color, 4.0f);
}
// Tooltip with description
if (ImGui::IsItemHovered()) {
// Enhanced tooltip with fixed sizing
if (is_hovered) {
// Force tooltip to have a fixed max width to prevent flickering
ImGui::SetNextWindowSize(ImVec2(300, 0), ImGuiCond_Always);
ImGui::BeginTooltip();
ImGui::Text("%s %s", info.icon, info.name);
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]); // Medium font
ImGui::TextColored(base_color, "%s %s", info.icon, info.name);
ImGui::PopFont();
ImGui::Separator();
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 280);
ImGui::TextWrapped("%s", info.description);
ImGui::PopTextWrapPos();
if (info.shortcut && info.shortcut[0]) {
ImGui::Spacing();
ImGui::TextDisabled("Shortcut: %s", info.shortcut);
ImGui::TextColored(base_color, ICON_MD_KEYBOARD " %s", info.shortcut);
}
if (is_recent) {
ImGui::Spacing();
ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_STAR " Recently used");
}
ImGui::EndTooltip();
}
// Recent indicator
if (is_recent) {
ImGui::SameLine();
ImGui::TextDisabled(ICON_MD_STAR);
if (clicked) {
selected_editor_ = info.type;
}
ImGui::PopID();