yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_status_bar.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cstdio>
5
13#include "imgui/imgui.h"
14
15namespace yaze::editor {
16
18 const auto& theme = gui::ThemeManager::Get().GetCurrentTheme();
19
20 // Reserve a fixed-height bar at the bottom, respecting UIConfig minimum
21 const float font_bar =
22 ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f;
23 const float bar_height = std::max(font_bar, gui::UIConfig::kStatusBarHeight);
24
25 gui::StyleColorGuard bar_colors({
26 {ImGuiCol_ChildBg, gui::ConvertColorToImVec4(theme.frame_bg)},
27 });
28
29 ImGui::BeginChild(
30 "##DungeonStatusBar", ImVec2(-1, bar_height), false,
31 ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
32
33 const float spacing = ImGui::GetStyle().ItemSpacing.x;
34
35 // Tool mode indicator
36 ImGui::AlignTextToFramePadding();
37 ImGui::TextDisabled(ICON_MD_BUILD);
38 ImGui::SameLine(0, 4);
39 ImGui::Text("%s", state.tool_mode);
40 ImGui::SameLine(0, spacing * 2);
41
42 // Separator
43 ImGui::TextDisabled("|");
44 ImGui::SameLine(0, spacing * 2);
45
46 // Undo/Redo buttons with depth indicator
47 {
48 if (!state.can_undo)
49 ImGui::BeginDisabled();
50
51 // Build tooltip string for undo
52 char undo_tip[128];
53 snprintf(undo_tip, sizeof(undo_tip), "Undo%s%s",
54 state.undo_desc ? ": " : "",
55 state.undo_desc ? state.undo_desc : "");
56 if (gui::InlineIconButton(ICON_MD_UNDO, undo_tip)) {
57 if (state.on_undo)
58 state.on_undo();
59 }
60 if (!state.can_undo)
61 ImGui::EndDisabled();
62 ImGui::SameLine(0, 4);
63
64 if (!state.can_redo)
65 ImGui::BeginDisabled();
66
67 // Build tooltip string for redo
68 char redo_tip[128];
69 snprintf(redo_tip, sizeof(redo_tip), "Redo%s%s",
70 state.redo_desc ? ": " : "",
71 state.redo_desc ? state.redo_desc : "");
72 if (gui::InlineIconButton(ICON_MD_REDO, redo_tip)) {
73 if (state.on_redo)
74 state.on_redo();
75 }
76 if (!state.can_redo)
77 ImGui::EndDisabled();
78
79 if (state.undo_depth > 0) {
80 ImGui::SameLine(0, 4);
81 ImGui::TextDisabled("(%d)", state.undo_depth);
82 }
83 }
84 ImGui::SameLine(0, spacing * 2);
85
86 // Separator
87 ImGui::TextDisabled("|");
88 ImGui::SameLine(0, spacing * 2);
89
90 // Selection summary
91 if (state.selection_count > 0) {
92 ImGui::TextDisabled(ICON_MD_SELECT_ALL);
93 ImGui::SameLine(0, 4);
94 if (state.selection_layer >= 0) {
95 ImGui::Text("%d obj, L%d", state.selection_count,
96 state.selection_layer + 1);
97 } else {
98 ImGui::Text("%d obj", state.selection_count);
99 }
100 } else {
101 ImGui::TextDisabled("No selection");
102 }
103 ImGui::SameLine(0, spacing * 2);
104
105 // Separator
106 ImGui::TextDisabled("|");
107 ImGui::SameLine(0, spacing * 2);
108
109 // Zoom level
110 ImGui::TextDisabled(ICON_MD_ZOOM_IN);
111 ImGui::SameLine(0, 4);
112 ImGui::Text("%d%%", state.zoom_percent);
113 ImGui::SameLine(0, spacing * 2);
114
115 // Separator
116 ImGui::TextDisabled("|");
117 ImGui::SameLine(0, spacing * 2);
118
119 // Cursor tile coordinates
120 if (state.cursor_tile_x >= 0 && state.cursor_tile_y >= 0) {
121 ImGui::TextDisabled(ICON_MD_MY_LOCATION);
122 ImGui::SameLine(0, 4);
123 ImGui::Text("(%d, %d)", state.cursor_tile_x, state.cursor_tile_y);
124 } else {
125 ImGui::TextDisabled(ICON_MD_MY_LOCATION " --");
126 }
127
128 // Right-aligned section: dirty indicator + room ID
129 {
130 char right_text[64];
131 if (state.room_id >= 0) {
132 if (state.room_dirty) {
133 snprintf(right_text, sizeof(right_text), ICON_MD_CIRCLE " Room 0x%03X",
134 state.room_id);
135 } else {
136 snprintf(right_text, sizeof(right_text), "Room 0x%03X", state.room_id);
137 }
138 } else {
139 snprintf(right_text, sizeof(right_text), "No room");
140 }
141
142 const float text_width = ImGui::CalcTextSize(right_text).x;
143 const float right_x = ImGui::GetWindowWidth() - text_width -
144 ImGui::GetStyle().WindowPadding.x;
145
146 ImGui::SameLine(std::max(ImGui::GetCursorPosX(), right_x));
147
148 if (state.room_dirty) {
149 ImGui::TextColored(gui::ConvertColorToImVec4(theme.warning), "%s",
150 right_text);
151 if (ImGui::IsItemHovered()) {
152 ImGui::SetTooltip("Room has unsaved changes");
153 }
154 } else {
155 ImGui::TextDisabled("%s", right_text);
156 }
157 }
158
159 ImGui::EndChild();
160}
161
163 const DungeonCanvasViewer& viewer, const char* tool_mode, bool room_dirty) {
165 state.tool_mode = tool_mode;
166 state.room_dirty = room_dirty;
167 state.room_id = viewer.current_room_id();
168
169 // Zoom from canvas
170 float scale = viewer.canvas().GetGlobalScale();
171 state.zoom_percent = static_cast<int>(scale * 100.0f + 0.5f);
172
173 // Selection from object interaction
174 const auto& interaction =
175 const_cast<DungeonCanvasViewer&>(viewer).object_interaction();
176 auto selected = interaction.GetSelectedObjectIndices();
177 state.selection_count = static_cast<int>(selected.size());
178
179 // Determine layer from first selected object (if any)
180 if (!selected.empty() && viewer.rooms() && viewer.current_room_id() >= 0 &&
181 viewer.current_room_id() < static_cast<int>(viewer.rooms()->size())) {
182 const auto& objects =
183 (*viewer.rooms())[viewer.current_room_id()].GetTileObjects();
184 if (selected[0] < objects.size()) {
185 state.selection_layer = objects[selected[0]].layer_;
186 }
187 }
188
189 // Cursor coordinates from ImGui hover state on canvas
190 // Note: the actual tile coordinates are derived from the canvas hover
191 // position. Since we don't have direct access to the canvas mouse pos
192 // from outside the draw call, we leave these at -1 (the canvas viewer
193 // itself could populate this if we add a public accessor later).
194 state.cursor_tile_x = -1;
195 state.cursor_tile_y = -1;
196
197 return state;
198}
199
200} // namespace yaze::editor
std::array< zelda3::Room, 0x128 > * rooms() const
static void Draw(const DungeonStatusBarState &state)
static DungeonStatusBarState BuildState(const DungeonCanvasViewer &viewer, const char *tool_mode, bool room_dirty)
float GetGlobalScale() const
Definition canvas.h:470
RAII guard for ImGui style colors.
Definition style_guard.h:27
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
#define ICON_MD_MY_LOCATION
Definition icons.h:1270
#define ICON_MD_CIRCLE
Definition icons.h:411
#define ICON_MD_REDO
Definition icons.h:1570
#define ICON_MD_BUILD
Definition icons.h:328
#define ICON_MD_ZOOM_IN
Definition icons.h:2194
#define ICON_MD_SELECT_ALL
Definition icons.h:1680
#define ICON_MD_UNDO
Definition icons.h:2039
Editors are the view controllers for the application.
ImVec4 ConvertColorToImVec4(const Color &color)
Definition color.h:134
bool InlineIconButton(const char *icon, const char *tooltip, bool is_active)
Convenience wrapper for small inline icon buttons.
static constexpr float kStatusBarHeight
Definition ui_config.h:21