6#include "absl/strings/str_format.h"
17#include "imgui/imgui.h"
25std::string ResolveAgentChatHistoryPath() {
28 return (*agent_dir /
"agent_chat_history.json").string();
32 return (*docs_dir /
"agent_chat_history.json").string();
36 return (*temp_dir /
"agent_chat_history.json").string();
38 return (std::filesystem::current_path() /
"agent_chat_history.json").string();
56 return "Notifications";
142 ImGuiContext* context = ImGui::GetCurrentContext();
147 const ImGuiViewport* viewport = ImGui::GetMainViewport();
152 const float max_width = viewport->WorkSize.x * 0.35f;
153 if (max_width > 0.0f && width > max_width) {
194 if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
200 const ImGuiViewport* viewport = ImGui::GetMainViewport();
201 const float viewport_height = viewport->WorkSize.y;
202 const float viewport_width = viewport->WorkSize.x;
209 ImGuiWindowFlags panel_flags =
210 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove |
211 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking |
212 ImGuiWindowFlags_NoNavFocus;
215 ImGui::SetNextWindowPos(ImVec2(
216 viewport->WorkPos.x + viewport_width - panel_width, viewport->WorkPos.y));
217 ImGui::SetNextWindowSize(ImVec2(panel_width, viewport_height));
219 ImGui::PushStyleColor(ImGuiCol_WindowBg, panel_bg);
220 ImGui::PushStyleColor(ImGuiCol_Border, panel_border);
221 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
222 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
224 if (ImGui::Begin(
"##RightPanel",
nullptr, panel_flags)) {
230 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12.0f, 8.0f));
231 ImGui::BeginChild(
"##PanelContent", ImVec2(0, 0),
false,
232 ImGuiWindowFlags_AlwaysUseWindowPadding);
262 ImGui::PopStyleVar();
266 ImGui::PopStyleVar(2);
267 ImGui::PopStyleColor(2);
272 const float header_height = 44.0f;
273 const float padding = 12.0f;
276 ImVec2 header_min = ImGui::GetCursorScreenPos();
277 ImVec2 header_max = ImVec2(header_min.x + ImGui::GetWindowWidth(),
278 header_min.y + header_height);
280 ImDrawList* draw_list = ImGui::GetWindowDrawList();
281 draw_list->AddRectFilled(
282 header_min, header_max,
286 draw_list->AddLine(ImVec2(header_min.x, header_max.y),
287 ImVec2(header_max.x, header_max.y),
291 ImGui::SetCursorPosX(padding);
292 ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
293 (header_height - ImGui::GetTextLineHeight()) * 0.5f);
297 ImGui::Text(
"%s", icon);
298 ImGui::PopStyleColor();
303 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text));
304 ImGui::Text(
"%s", title);
305 ImGui::PopStyleColor();
308 const float button_size = 28.0f;
309 float current_x = ImGui::GetWindowWidth() - button_size - padding;
312 ImGui::SameLine(current_x);
313 ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 4.0f);
315 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
316 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
318 ImGui::PushStyleColor(
319 ImGuiCol_ButtonActive,
323 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
325 if (ImGui::Button(
ICON_MD_CLOSE, ImVec2(button_size, button_size))) {
328 if (ImGui::IsItemHovered()) {
329 ImGui::SetTooltip(
"Close Panel (Esc)");
334 current_x -= (button_size + 4.0f);
335 ImGui::SameLine(current_x);
338 static bool is_locked =
false;
341 ImGui::PushStyleColor(ImGuiCol_Text, lock_color);
344 ImVec2(button_size, button_size))) {
345 is_locked = !is_locked;
347 ImGui::PopStyleColor();
349 if (ImGui::IsItemHovered()) {
350 ImGui::SetTooltip(is_locked ?
"Unlock Selection" :
"Lock Selection");
354 ImGui::PopStyleVar();
355 ImGui::PopStyleColor(4);
358 ImGui::SetCursorPosY(header_height + 8.0f);
368 ImGui::PushStyleColor(ImGuiCol_HeaderHovered,
370 ImGui::PushStyleColor(ImGuiCol_HeaderActive,
372 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(8.0f, 6.0f));
373 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
376 std::string header_text;
378 header_text = std::string(icon) +
" " + label;
383 ImGuiTreeNodeFlags flags =
384 ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth |
385 ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_FramePadding;
387 flags |= ImGuiTreeNodeFlags_DefaultOpen;
390 bool is_open = ImGui::TreeNodeEx(header_text.c_str(), flags);
392 ImGui::PopStyleVar(2);
393 ImGui::PopStyleColor(3);
404 ImGui::Unindent(4.0f);
413 ImGui::PopStyleColor();
419 ImGui::TextUnformatted(label);
420 ImGui::PopStyleColor();
425 ImGui::Text(
"%s:", label);
426 ImGui::PopStyleColor();
428 ImGui::TextUnformatted(value);
433 ImGui::PushTextWrapPos(ImGui::GetContentRegionAvail().x);
434 ImGui::TextWrapped(
"%s", text);
435 ImGui::PopTextWrapPos();
436 ImGui::PopStyleColor();
444#ifdef YAZE_BUILD_AGENT_UI
452 ImGui::PopStyleColor();
455 "The AI Agent is not initialized. "
456 "Open the AI Agent from View menu or use Ctrl+Shift+A.");
462 ImGui::PushStyleColor(ImGuiCol_ChildBg, header_bg);
463 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 8.0f);
464 if (ImGui::BeginChild(
"AgentHero", ImVec2(0, 110),
true)) {
465 ImGui::PushStyleColor(ImGuiCol_Text, hero_text);
467 ImGui::PopStyleColor();
470 ImGui::Text(
"Right Sidebar");
471 ImGui::PopStyleColor();
478 ImGui::PopStyleVar();
479 ImGui::PopStyleColor();
484 const float footer_height = ImGui::GetFrameHeightWithSpacing() * 3.5f;
485 float content_height =
486 std::max(120.0f, ImGui::GetContentRegionAvail().y - footer_height);
488 static int active_tab = 0;
489 if (ImGui::BeginTabBar(
"AgentSidebarTabs")) {
501 if (active_tab == 0) {
502 if (ImGui::BeginChild(
"AgentChatBody", ImVec2(0, content_height),
true)) {
507 if (ImGui::BeginChild(
"AgentQuickConfig", ImVec2(0, content_height),
514 if (ImGui::Checkbox(
"Auto-scroll", &auto_scroll)) {
517 if (ImGui::Checkbox(
"Show timestamps", &show_ts)) {
520 if (ImGui::Checkbox(
"Show reasoning traces", &show_reasoning)) {
527 "Change provider/model in the main Agent Editor. This sidebar shows "
528 "active chat controls.");
534 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6, 6));
542 ImGui::PopStyleColor(3);
544 ImVec2 half_width(ImGui::GetContentRegionAvail().x / 2 - 4, 0);
546 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
548 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
557 ImGui::PopStyleColor(3);
558 ImGui::PopStyleVar();
562 ImGui::PopStyleColor();
566 "The AI Agent requires agent UI support. "
567 "Build with YAZE_BUILD_AGENT_UI=ON to enable.");
581 ImGui::PopStyleColor();
585 "The proposal system is not initialized. "
586 "Proposals will appear here when the AI Agent creates them.");
597 ImGui::PopStyleColor();
601 "Settings will be available once initialized. "
602 "This panel provides quick access to application settings.");
637 const char* editor_name =
"No Editor Selected";
642 editor_name =
"Overworld Editor";
646 editor_name =
"Dungeon Editor";
650 editor_name =
"Graphics Editor";
654 editor_name =
"Palette Editor";
658 editor_name =
"Music Editor";
662 editor_name =
"Screen Editor";
666 editor_name =
"Sprite Editor";
670 editor_name =
"Message Editor";
674 editor_name =
"Emulator";
683 ImGui::Text(
"%s %s Help", editor_icon, editor_name);
684 ImGui::PopStyleColor();
693 DrawPanelValue(absl::StrFormat(
"%s+O", ctrl).c_str(),
"Open ROM");
694 DrawPanelValue(absl::StrFormat(
"%s+S", ctrl).c_str(),
"Save ROM");
697 DrawPanelValue(absl::StrFormat(
"%s+B", ctrl).c_str(),
"Toggle Sidebar");
700 ImGui::Unindent(8.0f);
715 ImGui::Unindent(8.0f);
722 DrawPanelValue(absl::StrFormat(
"%s+D", ctrl).c_str(),
"Duplicate");
726 ImGui::Unindent(8.0f);
736 ImGui::Unindent(8.0f);
745 ImGui::Unindent(8.0f);
754 ImGui::Unindent(8.0f);
761 "Insert Line Break");
763 ImGui::Unindent(8.0f);
770 ImGui::TextWrapped(
"Select an editor to see specific shortcuts.");
771 ImGui::PopStyleColor();
772 ImGui::Unindent(8.0f);
780 ImGui::PushStyleColor(ImGuiCol_Text,
781 ImGui::GetStyleColorVec4(ImGuiCol_Text));
783 ImGui::TextWrapped(
"Paint tiles by selecting from Tile16 Selector");
786 "Switch between Light World, Dark World, and Special Areas");
789 "Use Entity Mode to place entrances, exits, items, and sprites");
791 ImGui::TextWrapped(
"Right-click on the map to pick a tile for painting");
792 ImGui::PopStyleColor();
796 ImGui::PushStyleColor(ImGuiCol_Text,
797 ImGui::GetStyleColorVec4(ImGuiCol_Text));
799 ImGui::TextWrapped(
"Select rooms from the Room Selector or Room Matrix");
801 ImGui::TextWrapped(
"Place objects using the Object Editor panel");
804 "Edit room headers for palette, GFX, and floor settings");
806 ImGui::TextWrapped(
"Multiple rooms can be opened in separate tabs");
807 ImGui::PopStyleColor();
811 ImGui::PushStyleColor(ImGuiCol_Text,
812 ImGui::GetStyleColorVec4(ImGuiCol_Text));
814 ImGui::TextWrapped(
"Browse graphics sheets using the Sheet Browser");
816 ImGui::TextWrapped(
"Edit pixels directly with the Pixel Editor");
818 ImGui::TextWrapped(
"Choose palettes from Palette Controls");
820 ImGui::TextWrapped(
"View 3D objects like rupees and crystals");
821 ImGui::PopStyleColor();
825 ImGui::PushStyleColor(ImGuiCol_Text,
826 ImGui::GetStyleColorVec4(ImGuiCol_Text));
828 ImGui::TextWrapped(
"Edit overworld, dungeon, and sprite palettes");
830 ImGui::TextWrapped(
"Use Quick Access for color harmony tools");
832 ImGui::TextWrapped(
"Changes update in real-time across all editors");
833 ImGui::PopStyleColor();
837 ImGui::PushStyleColor(ImGuiCol_Text,
838 ImGui::GetStyleColorVec4(ImGuiCol_Text));
840 ImGui::TextWrapped(
"Browse songs in the Song Browser");
842 ImGui::TextWrapped(
"Use the tracker for playback control");
844 ImGui::TextWrapped(
"Edit instruments and BRR samples");
845 ImGui::PopStyleColor();
849 ImGui::PushStyleColor(ImGuiCol_Text,
850 ImGui::GetStyleColorVec4(ImGuiCol_Text));
852 ImGui::TextWrapped(
"Edit all in-game dialog messages");
854 ImGui::TextWrapped(
"Preview text rendering with the font atlas");
856 ImGui::TextWrapped(
"Manage the compression dictionary");
857 ImGui::PopStyleColor();
862 ImGui::TextWrapped(
"Open a ROM file via File > Open ROM");
864 ImGui::TextWrapped(
"Select an editor from the sidebar");
866 ImGui::TextWrapped(
"Use panels to access tools and settings");
868 ImGui::TextWrapped(
"Save your work via File > Save ROM");
874 const float button_width = ImGui::GetContentRegionAvail().x;
876 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(8.0f, 6.0f));
877 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
881 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
884 ImVec2(button_width, 0))) {
887 ImGui::PopStyleColor(2);
893 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
896 ImVec2(button_width, 0))) {
899 ImGui::PopStyleColor(2);
905 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
907 if (ImGui::Button(
ICON_MD_FORUM " Join Discord", ImVec2(button_width, 0))) {
910 ImGui::PopStyleColor(2);
912 ImGui::PopStyleVar(2);
917 ImGui::Text(
"YAZE - Yet Another Zelda3 Editor");
918 ImGui::PopStyleColor();
922 "A comprehensive editor for The Legend of Zelda: "
923 "A Link to the Past ROM files.");
929 ImGui::Text(
"Written by: scawful");
930 ImGui::Text(
"Special Thanks: Zarby89, JaredBrian");
938 ImGui::PopStyleColor();
945 ImGui::PopStyleColor();
950 float button_width = 100.0f;
951 float avail = ImGui::GetContentRegionAvail().x;
955 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
959 ImVec2(avail * 0.5f - 4.0f, 0))) {
964 ImVec2(avail * 0.5f - 4.0f, 0))) {
968 ImGui::PopStyleColor(2);
975 if (history.empty()) {
979 ImGui::PopStyleColor();
982 "Notifications will appear here when actions complete.");
988 if (unread_count > 0) {
990 ImGui::Text(
"%zu unread", unread_count);
991 ImGui::PopStyleColor();
994 ImGui::Text(
"All caught up");
995 ImGui::PopStyleColor();
1001 ImGui::BeginChild(
"##NotificationList", ImVec2(0, 0),
false,
1002 ImGuiWindowFlags_AlwaysVerticalScrollbar);
1005 auto now = std::chrono::system_clock::now();
1008 bool shown_today =
false;
1009 bool shown_yesterday =
false;
1010 bool shown_older =
false;
1012 for (
const auto& entry : history) {
1014 std::chrono::duration_cast<std::chrono::hours>(now - entry.timestamp)
1018 if (diff < 24 && !shown_today) {
1021 }
else if (diff >= 24 && diff < 48 && !shown_yesterday) {
1024 shown_yesterday =
true;
1025 }
else if (diff >= 48 && !shown_older) {
1032 ImGui::PushID(&entry);
1037 switch (entry.type) {
1060 ImGui::PopStyleColor();
1065 ImGui::PushStyleColor(ImGuiCol_Text, color);
1066 ImGui::Text(
"%s", icon);
1067 ImGui::PopStyleColor();
1071 ImGui::TextWrapped(
"%s", entry.message.c_str());
1075 std::chrono::duration_cast<std::chrono::seconds>(now - entry.timestamp)
1077 std::string time_str;
1078 if (diff_sec < 60) {
1079 time_str =
"just now";
1080 }
else if (diff_sec < 3600) {
1081 time_str = absl::StrFormat(
"%dm ago", diff_sec / 60);
1082 }
else if (diff_sec < 86400) {
1083 time_str = absl::StrFormat(
"%dh ago", diff_sec / 3600);
1085 time_str = absl::StrFormat(
"%dd ago", diff_sec / 86400);
1089 ImGui::Text(
" %s", time_str.c_str());
1090 ImGui::PopStyleColor();
1106 ImGui::PopStyleColor();
1110 "Select an item in the editor to view and edit its properties here.");
1145 ImGui::PopStyleColor();
1149 "Open a .yaze project file to access project management features "
1150 "including ROM versioning, snapshots, and configuration.");
1157 ImGui::TextWrapped(
"Create a new project via File > New Project");
1159 ImGui::TextWrapped(
"Open existing .yaze project files");
1161 ImGui::TextWrapped(
"Projects track ROM versions and settings");
1167 ImGui::TextWrapped(
"Version snapshots with Git integration");
1169 ImGui::TextWrapped(
"ROM backup and restore");
1171 ImGui::TextWrapped(
"Project-specific settings");
1173 ImGui::TextWrapped(
"Assembly code folder integration");
1180 bool clicked =
false;
1183 auto DrawPanelButton = [&](
const char* icon,
const char* tooltip,
1188 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
1189 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
1191 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
1194 ImGui::PushStyleColor(ImGuiCol_Text, is_active
1198 if (ImGui::SmallButton(icon)) {
1203 ImGui::PopStyleColor(4);
1205 if (ImGui::IsItemHovered()) {
1206 ImGui::SetTooltip(
"%s", tooltip);
bool show_reasoning() const
void set_auto_scroll(bool v)
void set_show_timestamps(bool v)
void set_show_reasoning(bool v)
void Draw(float available_height=0.0f)
void set_active(bool active)
bool show_timestamps() const
absl::Status SaveHistory(const std::string &filepath)
void Draw()
Draw the panel and its contents.
void DrawEditorSpecificShortcuts()
float notifications_width_
float GetPanelWidth() const
Get the width of the panel when expanded.
void DrawPropertiesPanel()
void ClosePanel()
Close the currently active panel.
void DrawPanelValue(const char *label, const char *value)
void SetPanelWidth(PanelType type, float width)
Set panel width for a specific panel type.
void DrawEditorSpecificHelp()
ToastManager * toast_manager_
EditorType active_editor_type_
void TogglePanel(PanelType type)
Toggle a specific panel on/off.
bool BeginPanelSection(const char *label, const char *icon=nullptr, bool default_open=true)
ProposalDrawer * proposal_drawer_
void DrawGlobalShortcuts()
bool DrawPanelToggleButtons()
Draw toggle buttons for the status cluster.
bool IsPanelActive(PanelType type) const
Check if a specific panel is active.
void DrawNotificationsPanel()
void OpenPanel(PanelType type)
Open a specific panel.
void DrawPanelLabel(const char *label)
void DrawProposalsPanel()
SelectionPropertiesPanel * properties_panel_
void DrawPanelDescription(const char *text)
void DrawEditorContextHeader()
void DrawPanelHeader(const char *title, const char *icon)
void DrawAgentChatPanel()
ProjectManagementPanel * project_panel_
void DrawQuickActionButtons()
SettingsPanel * settings_panel_
void Draw()
Draw the properties panel content.
size_t GetUnreadCount() const
const std::deque< NotificationEntry > & GetHistory() const
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
#define ICON_MD_ROCKET_LAUNCH
#define ICON_MD_NOTIFICATIONS
#define ICON_MD_LANDSCAPE
#define ICON_MD_LOCK_OPEN
#define ICON_MD_FOLDER_SPECIAL
#define ICON_MD_CHECKLIST
#define ICON_MD_FILE_DOWNLOAD
#define ICON_MD_VIDEOGAME_ASSET
#define ICON_MD_BUG_REPORT
#define ICON_MD_MUSIC_NOTE
#define ICON_MD_CHECK_CIRCLE
#define ICON_MD_DESCRIPTION
#define ICON_MD_HELP_OUTLINE
#define ICON_MD_STRAIGHTEN
#define ICON_MD_NOTIFICATIONS_OFF
#define ICON_MD_SELECT_ALL
#define ICON_MD_OPEN_IN_NEW
#define ICON_MD_DELETE_FOREVER
#define ICON_MD_FIBER_MANUAL_RECORD
#define ICON_MD_SMART_TOY
#define ICON_MD_DELETE_SWEEP
const char * GetPanelTypeName(RightPanelManager::PanelType type)
Get the name of a panel type.
const char * GetPanelTypeIcon(RightPanelManager::PanelType type)
Get the icon for a panel type.
const char * GetCtrlDisplayName()
Get the display name for the primary modifier key.
ImVec4 ConvertColorToImVec4(const Color &color)
ImVec4 GetSurfaceContainerHighestVec4()
ImVec4 GetPrimaryActiveVec4()
ImVec4 GetTextDisabledVec4()
ImVec4 GetTextSecondaryVec4()
ImVec4 GetSurfaceContainerHighVec4()
ImVec4 GetPrimaryHoverVec4()
ImVec4 GetOnSurfaceVec4()
ImVec4 GetSurfaceContainerVec4()