5#include "absl/strings/str_format.h"
16#include "imgui/imgui.h"
34 return "Notifications";
146 if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
152 const ImGuiViewport* viewport = ImGui::GetMainViewport();
153 const float viewport_height = viewport->WorkSize.y;
154 const float viewport_width = viewport->WorkSize.x;
161 ImGuiWindowFlags panel_flags =
162 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove |
163 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking |
164 ImGuiWindowFlags_NoNavFocus;
167 ImGui::SetNextWindowPos(
168 ImVec2(viewport->WorkPos.x + viewport_width - panel_width,
169 viewport->WorkPos.y));
170 ImGui::SetNextWindowSize(ImVec2(panel_width, viewport_height));
172 ImGui::PushStyleColor(ImGuiCol_WindowBg, panel_bg);
173 ImGui::PushStyleColor(ImGuiCol_Border, panel_border);
174 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
175 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
177 if (ImGui::Begin(
"##RightPanel",
nullptr, panel_flags)) {
183 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12.0f, 8.0f));
184 ImGui::BeginChild(
"##PanelContent", ImVec2(0, 0),
false,
185 ImGuiWindowFlags_AlwaysUseWindowPadding);
215 ImGui::PopStyleVar();
219 ImGui::PopStyleVar(2);
220 ImGui::PopStyleColor(2);
227 const float header_height = 44.0f;
228 const float padding = 12.0f;
231 ImVec2 header_min = ImGui::GetCursorScreenPos();
232 ImVec2 header_max = ImVec2(header_min.x + ImGui::GetWindowWidth(),
233 header_min.y + header_height);
235 ImDrawList* draw_list = ImGui::GetWindowDrawList();
236 draw_list->AddRectFilled(header_min, header_max,
240 draw_list->AddLine(ImVec2(header_min.x, header_max.y),
241 ImVec2(header_max.x, header_max.y),
245 ImGui::SetCursorPosX(padding);
246 ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (header_height - ImGui::GetTextLineHeight()) * 0.5f);
250 ImGui::Text(
"%s", icon);
251 ImGui::PopStyleColor();
256 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text));
257 ImGui::Text(
"%s", title);
258 ImGui::PopStyleColor();
261 const float button_size = 28.0f;
262 float current_x = ImGui::GetWindowWidth() - button_size - padding;
265 ImGui::SameLine(current_x);
266 ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 4.0f);
268 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
269 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
271 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
276 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
278 if (ImGui::Button(
ICON_MD_CLOSE, ImVec2(button_size, button_size))) {
281 if (ImGui::IsItemHovered()) {
282 ImGui::SetTooltip(
"Close Panel (Esc)");
287 current_x -= (button_size + 4.0f);
288 ImGui::SameLine(current_x);
291 static bool is_locked =
false;
293 ImGui::PushStyleColor(ImGuiCol_Text, lock_color);
296 is_locked = !is_locked;
298 ImGui::PopStyleColor();
300 if (ImGui::IsItemHovered()) {
301 ImGui::SetTooltip(is_locked ?
"Unlock Selection" :
"Lock Selection");
305 ImGui::PopStyleVar();
306 ImGui::PopStyleColor(4);
309 ImGui::SetCursorPosY(header_height + 8.0f);
319 ImGui::PushStyleColor(ImGuiCol_HeaderHovered,
321 ImGui::PushStyleColor(ImGuiCol_HeaderActive,
323 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(8.0f, 6.0f));
324 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
327 std::string header_text;
329 header_text = std::string(icon) +
" " + label;
334 ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Framed |
335 ImGuiTreeNodeFlags_SpanAvailWidth |
336 ImGuiTreeNodeFlags_AllowOverlap |
337 ImGuiTreeNodeFlags_FramePadding;
339 flags |= ImGuiTreeNodeFlags_DefaultOpen;
342 bool is_open = ImGui::TreeNodeEx(header_text.c_str(), flags);
344 ImGui::PopStyleVar(2);
345 ImGui::PopStyleColor(3);
356 ImGui::Unindent(4.0f);
365 ImGui::PopStyleColor();
371 ImGui::TextUnformatted(label);
372 ImGui::PopStyleColor();
377 ImGui::Text(
"%s:", label);
378 ImGui::PopStyleColor();
380 ImGui::TextUnformatted(value);
385 ImGui::PushTextWrapPos(ImGui::GetContentRegionAvail().x);
386 ImGui::TextWrapped(
"%s", text);
387 ImGui::PopTextWrapPos();
388 ImGui::PopStyleColor();
396#ifdef YAZE_BUILD_AGENT_UI
404 ImGui::PopStyleColor();
407 "The AI Agent is not initialized. "
408 "Open the AI Agent from View menu or use Ctrl+Shift+A.");
414 ImGui::PushStyleColor(ImGuiCol_ChildBg, header_bg);
415 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 8.0f);
416 if (ImGui::BeginChild(
"AgentHero", ImVec2(0, 110),
true)) {
417 ImGui::PushStyleColor(ImGuiCol_Text, hero_text);
419 ImGui::PopStyleColor();
422 ImGui::Text(
"Right Sidebar");
423 ImGui::PopStyleColor();
430 ImGui::PopStyleVar();
431 ImGui::PopStyleColor();
436 const float footer_height = ImGui::GetFrameHeightWithSpacing() * 3.5f;
437 float content_height =
438 std::max(120.0f, ImGui::GetContentRegionAvail().y - footer_height);
440 static int active_tab = 0;
441 if (ImGui::BeginTabBar(
"AgentSidebarTabs")) {
453 if (active_tab == 0) {
454 if (ImGui::BeginChild(
"AgentChatBody", ImVec2(0, content_height),
true)) {
459 if (ImGui::BeginChild(
"AgentQuickConfig", ImVec2(0, content_height),
true)) {
465 if (ImGui::Checkbox(
"Auto-scroll", &auto_scroll)) {
468 if (ImGui::Checkbox(
"Show timestamps", &show_ts)) {
471 if (ImGui::Checkbox(
"Show reasoning traces", &show_reasoning)) {
478 "Change provider/model in the main Agent Editor. This sidebar shows "
479 "active chat controls.");
485 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6, 6));
493 ImGui::PopStyleColor(3);
495 ImVec2 half_width(ImGui::GetContentRegionAvail().x / 2 - 4, 0);
497 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
499 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
508 ImGui::PopStyleColor(3);
509 ImGui::PopStyleVar();
513 ImGui::PopStyleColor();
517 "The AI Agent requires agent UI support. "
518 "Build with YAZE_BUILD_AGENT_UI=ON to enable.");
532 ImGui::PopStyleColor();
536 "The proposal system is not initialized. "
537 "Proposals will appear here when the AI Agent creates them.");
548 ImGui::PopStyleColor();
552 "Settings will be available once initialized. "
553 "This panel provides quick access to application settings.");
588 const char* editor_name =
"No Editor Selected";
593 editor_name =
"Overworld Editor";
597 editor_name =
"Dungeon Editor";
601 editor_name =
"Graphics Editor";
605 editor_name =
"Palette Editor";
609 editor_name =
"Music Editor";
613 editor_name =
"Screen Editor";
617 editor_name =
"Sprite Editor";
621 editor_name =
"Message Editor";
625 editor_name =
"Emulator";
634 ImGui::Text(
"%s %s Help", editor_icon, editor_name);
635 ImGui::PopStyleColor();
644 DrawPanelValue(absl::StrFormat(
"%s+O", ctrl).c_str(),
"Open ROM");
645 DrawPanelValue(absl::StrFormat(
"%s+S", ctrl).c_str(),
"Save ROM");
648 DrawPanelValue(absl::StrFormat(
"%s+B", ctrl).c_str(),
"Toggle Sidebar");
651 ImGui::Unindent(8.0f);
666 ImGui::Unindent(8.0f);
673 DrawPanelValue(absl::StrFormat(
"%s+D", ctrl).c_str(),
"Duplicate");
677 ImGui::Unindent(8.0f);
687 ImGui::Unindent(8.0f);
696 ImGui::Unindent(8.0f);
705 ImGui::Unindent(8.0f);
711 DrawPanelValue(absl::StrFormat(
"%s+Enter", ctrl).c_str(),
"Insert Line Break");
713 ImGui::Unindent(8.0f);
720 ImGui::TextWrapped(
"Select an editor to see specific shortcuts.");
721 ImGui::PopStyleColor();
722 ImGui::Unindent(8.0f);
730 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text));
731 ImGui::Bullet(); ImGui::TextWrapped(
"Paint tiles by selecting from Tile16 Selector");
732 ImGui::Bullet(); ImGui::TextWrapped(
"Switch between Light World, Dark World, and Special Areas");
733 ImGui::Bullet(); ImGui::TextWrapped(
"Use Entity Mode to place entrances, exits, items, and sprites");
734 ImGui::Bullet(); ImGui::TextWrapped(
"Right-click on the map to pick a tile for painting");
735 ImGui::PopStyleColor();
739 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text));
740 ImGui::Bullet(); ImGui::TextWrapped(
"Select rooms from the Room Selector or Room Matrix");
741 ImGui::Bullet(); ImGui::TextWrapped(
"Place objects using the Object Editor panel");
742 ImGui::Bullet(); ImGui::TextWrapped(
"Edit room headers for palette, GFX, and floor settings");
743 ImGui::Bullet(); ImGui::TextWrapped(
"Multiple rooms can be opened in separate tabs");
744 ImGui::PopStyleColor();
748 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text));
749 ImGui::Bullet(); ImGui::TextWrapped(
"Browse graphics sheets using the Sheet Browser");
750 ImGui::Bullet(); ImGui::TextWrapped(
"Edit pixels directly with the Pixel Editor");
751 ImGui::Bullet(); ImGui::TextWrapped(
"Choose palettes from Palette Controls");
752 ImGui::Bullet(); ImGui::TextWrapped(
"View 3D objects like rupees and crystals");
753 ImGui::PopStyleColor();
757 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text));
758 ImGui::Bullet(); ImGui::TextWrapped(
"Edit overworld, dungeon, and sprite palettes");
759 ImGui::Bullet(); ImGui::TextWrapped(
"Use Quick Access for color harmony tools");
760 ImGui::Bullet(); ImGui::TextWrapped(
"Changes update in real-time across all editors");
761 ImGui::PopStyleColor();
765 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text));
766 ImGui::Bullet(); ImGui::TextWrapped(
"Browse songs in the Song Browser");
767 ImGui::Bullet(); ImGui::TextWrapped(
"Use the tracker for playback control");
768 ImGui::Bullet(); ImGui::TextWrapped(
"Edit instruments and BRR samples");
769 ImGui::PopStyleColor();
773 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text));
774 ImGui::Bullet(); ImGui::TextWrapped(
"Edit all in-game dialog messages");
775 ImGui::Bullet(); ImGui::TextWrapped(
"Preview text rendering with the font atlas");
776 ImGui::Bullet(); ImGui::TextWrapped(
"Manage the compression dictionary");
777 ImGui::PopStyleColor();
781 ImGui::Bullet(); ImGui::TextWrapped(
"Open a ROM file via File > Open ROM");
782 ImGui::Bullet(); ImGui::TextWrapped(
"Select an editor from the sidebar");
783 ImGui::Bullet(); ImGui::TextWrapped(
"Use panels to access tools and settings");
784 ImGui::Bullet(); ImGui::TextWrapped(
"Save your work via File > Save ROM");
790 const float button_width = ImGui::GetContentRegionAvail().x;
792 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(8.0f, 6.0f));
793 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
801 ImGui::PopStyleColor(2);
811 ImGui::PopStyleColor(2);
818 if (ImGui::Button(
ICON_MD_FORUM " Join Discord", ImVec2(button_width, 0))) {
821 ImGui::PopStyleColor(2);
823 ImGui::PopStyleVar(2);
828 ImGui::Text(
"YAZE - Yet Another Zelda3 Editor");
829 ImGui::PopStyleColor();
833 "A comprehensive editor for The Legend of Zelda: "
834 "A Link to the Past ROM files.");
840 ImGui::Text(
"Written by: scawful");
841 ImGui::Text(
"Special Thanks: Zarby89, JaredBrian");
849 ImGui::PopStyleColor();
856 ImGui::PopStyleColor();
861 float button_width = 100.0f;
862 float avail = ImGui::GetContentRegionAvail().x;
868 if (ImGui::Button(
ICON_MD_DONE_ALL " Mark All Read", ImVec2(avail * 0.5f - 4.0f, 0))) {
876 ImGui::PopStyleColor(2);
883 if (history.empty()) {
887 ImGui::PopStyleColor();
895 if (unread_count > 0) {
897 ImGui::Text(
"%zu unread", unread_count);
898 ImGui::PopStyleColor();
901 ImGui::Text(
"All caught up");
902 ImGui::PopStyleColor();
908 ImGui::BeginChild(
"##NotificationList", ImVec2(0, 0),
false,
909 ImGuiWindowFlags_AlwaysVerticalScrollbar);
912 auto now = std::chrono::system_clock::now();
915 bool shown_today =
false;
916 bool shown_yesterday =
false;
917 bool shown_older =
false;
919 for (
const auto& entry : history) {
920 auto diff = std::chrono::duration_cast<std::chrono::hours>(
921 now - entry.timestamp).count();
924 if (diff < 24 && !shown_today) {
927 }
else if (diff >= 24 && diff < 48 && !shown_yesterday) {
930 shown_yesterday =
true;
931 }
else if (diff >= 48 && !shown_older) {
938 ImGui::PushID(&entry);
943 switch (entry.type) {
966 ImGui::PopStyleColor();
971 ImGui::PushStyleColor(ImGuiCol_Text, color);
972 ImGui::Text(
"%s", icon);
973 ImGui::PopStyleColor();
977 ImGui::TextWrapped(
"%s", entry.message.c_str());
980 auto diff_sec = std::chrono::duration_cast<std::chrono::seconds>(
981 now - entry.timestamp).count();
982 std::string time_str;
984 time_str =
"just now";
985 }
else if (diff_sec < 3600) {
986 time_str = absl::StrFormat(
"%dm ago", diff_sec / 60);
987 }
else if (diff_sec < 86400) {
988 time_str = absl::StrFormat(
"%dh ago", diff_sec / 3600);
990 time_str = absl::StrFormat(
"%dd ago", diff_sec / 86400);
994 ImGui::Text(
" %s", time_str.c_str());
995 ImGui::PopStyleColor();
1011 ImGui::PopStyleColor();
1015 "Select an item in the editor to view and edit its properties here.");
1050 ImGui::PopStyleColor();
1054 "Open a .yaze project file to access project management features "
1055 "including ROM versioning, snapshots, and configuration.");
1062 ImGui::TextWrapped(
"Create a new project via File > New Project");
1064 ImGui::TextWrapped(
"Open existing .yaze project files");
1066 ImGui::TextWrapped(
"Projects track ROM versions and settings");
1072 ImGui::TextWrapped(
"Version snapshots with Git integration");
1074 ImGui::TextWrapped(
"ROM backup and restore");
1076 ImGui::TextWrapped(
"Project-specific settings");
1078 ImGui::TextWrapped(
"Assembly code folder integration");
1085 bool clicked =
false;
1088 auto DrawPanelButton = [&](
const char* icon,
const char* tooltip,
1093 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
1094 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
1096 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
1099 ImGui::PushStyleColor(
1103 if (ImGui::SmallButton(icon)) {
1108 ImGui::PopStyleColor(4);
1110 if (ImGui::IsItemHovered()) {
1111 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()