yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
window_sidebar.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cctype>
5#include <string>
6
7#include "absl/strings/str_format.h"
16#include "core/color.h"
17#include "imgui/imgui.h"
18
19namespace yaze {
20namespace editor {
21
22namespace {
23
24std::string LowercaseCopy(std::string value) {
25 std::transform(value.begin(), value.end(), value.begin(),
26 [](unsigned char c) { return static_cast<char>(::tolower(c)); });
27 return value;
28}
29
30bool MatchesWindowSearch(const std::string& query,
31 const WindowDescriptor& window) {
33 window.card_id,
34 window.shortcut_hint);
35}
36
37bool IsDungeonPanelModeWindow(const std::string& window_id) {
39}
40
41} // namespace
42
44 WorkspaceWindowManager& window_manager,
45 std::function<bool()> is_dungeon_workbench_mode,
46 std::function<void(bool)> set_dungeon_workflow_mode)
47 : window_manager_(window_manager),
48 is_dungeon_workbench_mode_(std::move(is_dungeon_workbench_mode)),
49 set_dungeon_workflow_mode_(std::move(set_dungeon_workflow_mode)) {}
50
51bool WindowSidebar::MatchesWindowSearch(const std::string& query,
52 const std::string& display_name,
53 const std::string& window_id,
54 const std::string& shortcut_hint) {
55 if (query.empty()) {
56 return true;
57 }
58
59 const std::string search_str = LowercaseCopy(query);
60 return LowercaseCopy(display_name).find(search_str) != std::string::npos ||
61 LowercaseCopy(window_id).find(search_str) != std::string::npos ||
62 LowercaseCopy(shortcut_hint).find(search_str) != std::string::npos;
63}
64
65bool WindowSidebar::IsDungeonWindowModeTarget(const std::string& window_id) {
66 const bool is_room_window = window_id.rfind("dungeon.room_", 0) == 0;
67 return window_id == "dungeon.room_selector" ||
68 window_id == "dungeon.room_matrix" || is_room_window;
69}
70
71void WindowSidebar::Draw(size_t session_id, const std::string& category,
72 std::function<bool()> has_rom) {
73 const auto& theme = gui::ThemeManager::Get().GetCurrentTheme();
74 const ImGuiViewport* viewport = ImGui::GetMainViewport();
75 const float bar_width = WorkspaceWindowManager::GetSidebarWidth();
76 const float panel_width =
77 window_manager_.GetActiveSidePanelWidth(viewport->WorkSize.x);
78
79 const float top_inset = gui::LayoutHelpers::GetTopInset();
80 const auto safe_area = gui::LayoutHelpers::GetSafeAreaInsets();
81 const float panel_height =
82 std::max(0.0f, viewport->WorkSize.y - top_inset - safe_area.bottom);
83
84 gui::FixedPanel panel(
85 "##SidePanel",
86 ImVec2(viewport->WorkPos.x + bar_width, viewport->WorkPos.y + top_inset),
87 ImVec2(panel_width, panel_height),
88 {.bg = gui::ConvertColorToImVec4(theme.surface),
89 .padding = {8.0f, 8.0f},
90 .border_size = 1.0f,
91 .rounding = 0.0f},
92 ImGuiWindowFlags_NoFocusOnAppearing);
93
94 if (!panel) {
95 return;
96 }
97
98 ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
99 ImGui::Text("%s", category.c_str());
100 ImGui::PopFont();
101
102 float avail_width = ImGui::GetContentRegionAvail().x;
103 const ImVec2 chrome_icon_size = gui::IconSize::Small();
104 ImGui::SameLine(ImGui::GetCursorPosX() + avail_width - chrome_icon_size.x);
106 "Collapse Sidebar", false, ImVec4(0, 0, 0, 0),
107 "window_sidebar", "collapse_side_panel")) {
109 }
110
111 ImGui::Separator();
112 ImGui::Spacing();
113
114 const ImVec2 search_button_size = gui::IconSize::Small();
115 const float standard_spacing =
116 std::clamp(gui::LayoutHelpers::GetStandardSpacing(), 4.0f, 8.0f);
117 const float compact_spacing = std::max(4.0f, standard_spacing * 0.75f);
118 const float search_spacing = compact_spacing;
119 const float search_width =
120 std::max(140.0f, ImGui::GetContentRegionAvail().x -
121 search_button_size.x - search_spacing);
122 ImGui::SetNextItemWidth(search_width);
123 ImGui::InputTextWithHint("##SidebarSearch", ICON_MD_SEARCH " Filter...",
125 ImGui::SameLine(0.0f, search_spacing);
126 const bool filter_empty = sidebar_search_[0] == '\0';
127 if (filter_empty) {
128 ImGui::BeginDisabled();
129 }
130 if (gui::TransparentIconButton(ICON_MD_CLEAR, search_button_size,
131 "Clear filter", false,
132 gui::GetTextSecondaryVec4(), "window_sidebar",
133 "clear_sidebar_filter")) {
134 sidebar_search_[0] = '\0';
135 }
136 if (filter_empty) {
137 ImGui::EndDisabled();
138 }
139
140 auto read_dungeon_workbench_mode = [&]() -> bool {
141 if (category != "Dungeon") {
142 return false;
143 }
146 }
147 return window_manager_.IsWindowOpen(session_id, "dungeon.workbench");
148 };
149 bool dungeon_workbench_mode = read_dungeon_workbench_mode();
150
151 auto switch_to_dungeon_workbench_mode = [&]() -> bool {
152 if (category != "Dungeon" || dungeon_workbench_mode) {
153 return false;
154 }
157 dungeon_workbench_mode = true;
158 return true;
159 }
160 window_manager_.OpenWindow(session_id, "dungeon.workbench");
161 for (const auto& descriptor :
162 window_manager_.GetWindowsInCategory(session_id, "Dungeon")) {
163 const std::string& window_id = descriptor.card_id;
164 if (window_id == "dungeon.workbench") {
165 continue;
166 }
167 if (window_manager_.IsWindowPinned(session_id, window_id)) {
168 continue;
169 }
170 if (IsDungeonPanelModeWindow(window_id)) {
171 window_manager_.CloseWindow(session_id, window_id);
172 }
173 }
174 dungeon_workbench_mode = read_dungeon_workbench_mode();
175 return dungeon_workbench_mode;
176 };
177
178 auto switch_to_dungeon_window_mode = [&]() -> bool {
179 if (category != "Dungeon" || !dungeon_workbench_mode) {
180 return false;
181 }
184 dungeon_workbench_mode = false;
185 return true;
186 }
187 window_manager_.CloseWindow(session_id, "dungeon.workbench");
188 window_manager_.OpenWindow(session_id, "dungeon.room_selector");
189 window_manager_.OpenWindow(session_id, "dungeon.room_matrix");
190 dungeon_workbench_mode = read_dungeon_workbench_mode();
191 return !dungeon_workbench_mode;
192 };
193
194 auto ensure_dungeon_window_mode_for_window =
195 [&](const std::string& window_id) -> bool {
196 if (category != "Dungeon" || !dungeon_workbench_mode ||
197 !IsDungeonPanelModeWindow(window_id)) {
198 return false;
199 }
200 return switch_to_dungeon_window_mode();
201 };
202
203 if (category == "Dungeon") {
204 ImGui::Spacing();
205 ImGui::TextDisabled(ICON_MD_WORKSPACES " Workflow");
206 ImGui::Spacing();
207
208 const float workflow_gap = compact_spacing;
209 const float workflow_min_button_width = 96.0f;
210 const float workflow_available_width =
211 std::max(1.0f, ImGui::GetContentRegionAvail().x);
212 const bool stack_workflow_buttons =
213 workflow_available_width <=
214 (workflow_min_button_width * 2.0f + workflow_gap);
215 const float workflow_button_width =
216 stack_workflow_buttons
217 ? workflow_available_width
218 : std::max(workflow_min_button_width,
219 (workflow_available_width - workflow_gap) * 0.5f);
220 const float workflow_button_height =
222 auto draw_workflow_button = [&](const char* id, const char* icon,
223 const char* label, bool active,
224 const char* tooltip,
225 const ImVec2& button_size) -> bool {
226 const ImVec4 active_bg = gui::GetPrimaryVec4();
227 const ImVec4 inactive_bg = gui::GetSurfaceContainerHighVec4();
228 const ImVec4 inactive_hover = gui::GetSurfaceContainerHighestVec4();
230 {{ImGuiCol_Button, active ? active_bg : inactive_bg},
231 {ImGuiCol_ButtonHovered, active ? active_bg : inactive_hover},
232 {ImGuiCol_ButtonActive, active ? active_bg : inactive_hover}});
233 const std::string button_label =
234 absl::StrFormat("%s %s##%s", icon, label, id);
235 const bool clicked = ImGui::Button(button_label.c_str(), button_size);
236 if (ImGui::IsItemHovered() && tooltip && *tooltip) {
237 ImGui::SetTooltip("%s", tooltip);
238 }
239 return clicked;
240 };
241 const ImVec2 workflow_button_size(workflow_button_width,
242 workflow_button_height);
243
244 if (draw_workflow_button("workflow_workbench", ICON_MD_WORKSPACES,
245 "Workbench", dungeon_workbench_mode,
246 "Workbench mode: integrated room browser + inspector",
247 workflow_button_size)) {
248 switch_to_dungeon_workbench_mode();
249 }
250 if (!stack_workflow_buttons) {
251 ImGui::SameLine(0.0f, workflow_gap);
252 }
253 if (draw_workflow_button("workflow_windows", ICON_MD_VIEW_QUILT,
254 "Windows", !dungeon_workbench_mode,
255 "Window mode: standalone Room List + Room Matrix + room windows",
256 workflow_button_size)) {
257 switch_to_dungeon_window_mode();
258 }
259 ImGui::Spacing();
260 ImGui::Separator();
261 ImGui::Spacing();
262 }
263
264 ImGui::Spacing();
265
266 const bool rom_loaded = has_rom ? has_rom() : true;
267 const bool disable_windows = !rom_loaded && category != "Emulator";
268
269 const auto category_windows =
270 window_manager_.GetWindowsInCategory(session_id, category);
271 int visible_windows_in_category = 0;
272 for (const auto& category_window : category_windows) {
273 if (category_window.visibility_flag && *category_window.visibility_flag) {
274 ++visible_windows_in_category;
275 }
276 }
277
278 ImGui::TextDisabled("%d / %d visible", visible_windows_in_category,
279 static_cast<int>(category_windows.size()));
280 ImGui::Spacing();
281
282 const float action_gap = compact_spacing;
283 const float action_min_button_width = 84.0f;
284 const float action_available_width =
285 std::max(1.0f, ImGui::GetContentRegionAvail().x);
286 const bool stack_action_buttons =
287 action_available_width <=
288 (action_min_button_width * 3.0f + (action_gap * 2.0f));
289 const float action_button_width =
290 stack_action_buttons
291 ? action_available_width
292 : std::max(action_min_button_width,
293 (action_available_width - (action_gap * 2.0f)) / 3.0f);
294 const float action_button_height =
296 auto draw_action_button = [&](const char* id, const char* icon,
297 const char* label, const char* tooltip,
298 const ImVec2& button_size) -> bool {
299 const std::string button_label =
300 absl::StrFormat("%s %s##%s", icon, label, id);
301 const bool clicked = ImGui::Button(button_label.c_str(), button_size);
302 if (ImGui::IsItemHovered() && tooltip && *tooltip) {
303 ImGui::SetTooltip("%s", tooltip);
304 }
305 return clicked;
306 };
307 const ImVec2 action_button_size(action_button_width, action_button_height);
308
309 if (draw_action_button("open_window_browser", ICON_MD_APPS, "Browser",
310 "Open Window Browser", action_button_size)) {
312 }
313 if (!stack_action_buttons) {
314 ImGui::SameLine(0.0f, action_gap);
315 }
316
317 const bool bulk_actions_enabled =
318 !disable_windows && !(category == "Dungeon" && dungeon_workbench_mode);
319 bool bulk_action_hovered = false;
320 if (!bulk_actions_enabled) {
321 ImGui::BeginDisabled();
322 }
323 if (draw_action_button("show_category_windows", ICON_MD_VISIBILITY, "Show",
324 "Show all windows in this category",
325 action_button_size)) {
326 window_manager_.ShowAllWindowsInCategory(session_id, category);
327 }
328 if (!stack_action_buttons) {
329 ImGui::SameLine(0.0f, action_gap);
330 }
331 if (!bulk_actions_enabled &&
332 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
333 bulk_action_hovered = true;
334 }
335 if (draw_action_button("hide_category_windows", ICON_MD_VISIBILITY_OFF,
336 "Hide", "Hide all windows in this category",
337 action_button_size)) {
338 window_manager_.HideAllWindowsInCategory(session_id, category);
339 }
340 if (!bulk_actions_enabled) {
341 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
342 bulk_action_hovered = true;
343 }
344 if (bulk_action_hovered && category == "Dungeon" &&
345 dungeon_workbench_mode) {
346 ImGui::SetTooltip(
347 "Switch to Window workflow to bulk-manage room windows.");
348 }
349 ImGui::EndDisabled();
350 }
351
352 ImGui::Spacing();
353
354 if (disable_windows) {
355 ImGui::TextUnformatted(ICON_MD_FOLDER_OPEN
356 " Open a ROM to enable this category");
357 ImGui::Spacing();
358 }
359
360 if (disable_windows) {
361 ImGui::BeginDisabled();
362 }
363
364 const auto pinned_windows = window_manager_.GetPinnedWindows();
365 const ImVec4 disabled_text =
366 ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
367 auto window_text_color = [&](bool visible) -> ImVec4 {
368 if (disable_windows) {
369 return disabled_text;
370 }
372 };
373 const float pin_button_side =
375 const ImVec2 pin_button_size(pin_button_side, pin_button_side);
376 auto draw_pin_toggle_button = [&](const std::string& widget_id,
377 bool pinned) -> bool {
378 ImGui::PushID(widget_id.c_str());
379 const ImVec4 pin_col = pinned ? gui::ConvertColorToImVec4(theme.primary)
381 const bool clicked = gui::TransparentIconButton(
382 pinned ? ICON_MD_PUSH_PIN : ICON_MD_PIN, pin_button_size,
383 pinned ? "Unpin window" : "Pin window", pinned, pin_col,
384 "window_sidebar", widget_id.c_str());
385 ImGui::PopID();
386 return clicked;
387 };
388
389 bool pinned_section_open = false;
390 if (sidebar_search_[0] == '\0' && !pinned_windows.empty()) {
391 bool has_pinned_in_category = false;
392 for (const auto& window_id : pinned_windows) {
393 const auto* window = window_manager_.GetWindowDescriptor(session_id, window_id);
394 if (window && window->category == category) {
395 has_pinned_in_category = true;
396 break;
397 }
398 }
399
400 if (has_pinned_in_category) {
401 pinned_section_open = ImGui::CollapsingHeader(
402 ICON_MD_PUSH_PIN " Pinned Windows",
403 ImGuiTreeNodeFlags_DefaultOpen);
404 if (pinned_section_open) {
405 for (const auto& window_id : pinned_windows) {
406 const auto* window = window_manager_.GetWindowDescriptor(session_id, window_id);
407 if (!window || window->category != category) {
408 continue;
409 }
410
411 const bool visible =
412 window->visibility_flag ? *window->visibility_flag : false;
413
414 if (draw_pin_toggle_button("pin_" + window->card_id, true)) {
415 window_manager_.SetWindowPinned(session_id, window->card_id, false);
416 }
417
418 ImGui::SameLine(0.0f, compact_spacing);
419
420 std::string label = absl::StrFormat("%s %s", window->icon.c_str(),
421 window->display_name.c_str());
422 ImGui::PushID(
423 (std::string("pinned_select_") + window->card_id).c_str());
424 {
425 gui::StyleColorGuard text_color(ImGuiCol_Text,
426 window_text_color(visible));
427 ImVec2 item_size(ImGui::GetContentRegionAvail().x,
428 pin_button_size.y);
429 if (ImGui::Selectable(label.c_str(), visible,
430 ImGuiSelectableFlags_None, item_size)) {
431 const bool switched_mode =
432 ensure_dungeon_window_mode_for_window(window->card_id);
433 if (switched_mode) {
434 window_manager_.OpenWindow(session_id, window->card_id);
435 } else {
436 window_manager_.ToggleWindow(session_id, window->card_id);
437 }
438
439 const bool new_visible =
440 window->visibility_flag ? *window->visibility_flag : false;
441 if (new_visible) {
442 window_manager_.TriggerWindowClicked(window->category);
443 const std::string window_name =
445 if (!window_name.empty()) {
446 ImGui::SetWindowFocus(window_name.c_str());
447 }
448 }
449 }
450 }
451 ImGui::PopID();
452 }
453 ImGui::Spacing();
454 ImGui::Separator();
455 ImGui::Spacing();
456 }
457 }
458 }
459
460 auto windows = window_manager_.GetWindowsSortedByMRU(session_id, category);
461 const bool window_content_open = gui::LayoutHelpers::BeginContentChild(
462 "##WindowContent", ImVec2(0.0f, gui::UIConfig::kContentMinHeightList));
463 if (window_content_open) {
464 for (const auto& window : windows) {
465 if (!MatchesWindowSearch(sidebar_search_, window.display_name,
466 window.card_id, window.shortcut_hint)) {
467 continue;
468 }
469
470 const bool is_pinned = window_manager_.IsWindowPinned(window.card_id);
471 if (pinned_section_open && is_pinned) {
472 continue;
473 }
474
475 const bool visible =
476 window.visibility_flag ? *window.visibility_flag : false;
477
478 if (draw_pin_toggle_button("pin_" + window.card_id, is_pinned)) {
479 window_manager_.SetWindowPinned(session_id, window.card_id, !is_pinned);
480 }
481 ImGui::SameLine(0.0f, compact_spacing);
482
483 std::string label =
484 absl::StrFormat("%s %s", window.icon.c_str(), window.display_name.c_str());
485 ImGui::PushID((std::string("window_select_") + window.card_id).c_str());
486 {
487 gui::StyleColorGuard text_color(ImGuiCol_Text,
488 window_text_color(visible));
489 ImVec2 item_size(ImGui::GetContentRegionAvail().x, pin_button_size.y);
490 if (ImGui::Selectable(label.c_str(), visible, ImGuiSelectableFlags_None,
491 item_size)) {
492 const bool switched_mode =
493 ensure_dungeon_window_mode_for_window(window.card_id);
494 if (switched_mode) {
495 window_manager_.OpenWindow(session_id, window.card_id);
496 } else {
497 window_manager_.ToggleWindow(session_id, window.card_id);
498 }
499
500 const bool new_visible =
501 window.visibility_flag ? *window.visibility_flag : false;
502 if (new_visible) {
504 window_manager_.TriggerWindowClicked(window.category);
505 const std::string window_name =
507 if (!window_name.empty()) {
508 ImGui::SetWindowFocus(window_name.c_str());
509 }
510 }
511 }
512 }
513 ImGui::PopID();
514
515 if (ImGui::IsItemHovered() && !window.shortcut_hint.empty()) {
516 ImGui::SetTooltip("%s", window.shortcut_hint.c_str());
517 }
518 }
519 }
521
522 if (disable_windows) {
523 ImGui::EndDisabled();
524 }
525
526 const float handle_width = 6.0f;
527 const ImVec2 panel_pos = ImGui::GetWindowPos();
528 const float panel_draw_height = ImGui::GetWindowHeight();
529 ImGui::SetCursorScreenPos(
530 ImVec2(panel_pos.x + panel_width - handle_width * 0.5f, panel_pos.y));
531 ImGui::InvisibleButton("##SidePanelResizeHandle",
532 ImVec2(handle_width, panel_draw_height));
533 const bool handle_hovered = ImGui::IsItemHovered();
534 const bool handle_active = ImGui::IsItemActive();
535 if (handle_hovered || handle_active) {
536 ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
537 }
538 if (handle_hovered && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
540 }
541 if (handle_active) {
542 const float new_width = panel_width + ImGui::GetIO().MouseDelta.x;
543 window_manager_.SetActiveSidePanelWidth(new_width, viewport->WorkSize.x);
544 ImGui::SetTooltip("Width: %.0f px",
545 window_manager_.GetActiveSidePanelWidth(viewport->WorkSize.x));
546 }
547
548 ImVec4 handle_color = gui::GetOutlineVec4();
549 handle_color.w = handle_active ? 0.95f : (handle_hovered ? 0.72f : 0.35f);
550 ImGui::GetWindowDrawList()->AddLine(
551 ImVec2(panel_pos.x + panel_width - 1.0f, panel_pos.y),
552 ImVec2(panel_pos.x + panel_width - 1.0f,
553 panel_pos.y + panel_draw_height),
554 ImGui::GetColorU32(handle_color), handle_active ? 2.0f : 1.0f);
555}
556
557} // namespace editor
558} // namespace yaze
void Draw(size_t session_id, const std::string &category, std::function< bool()> has_rom)
std::function< void(bool)> set_dungeon_workflow_mode_
std::function< bool()> is_dungeon_workbench_mode_
static bool IsDungeonWindowModeTarget(const std::string &window_id)
WindowSidebar(WorkspaceWindowManager &window_manager, std::function< bool()> is_dungeon_workbench_mode={}, std::function< void(bool)> set_dungeon_workflow_mode={})
WorkspaceWindowManager & window_manager_
static bool MatchesWindowSearch(const std::string &query, const std::string &display_name, const std::string &window_id, const std::string &shortcut_hint)
Central registry for all editor cards with session awareness and dependency injection.
void SetActiveSidePanelWidth(float width, float viewport_width=0.0f, bool notify=true)
void HideAllWindowsInCategory(size_t session_id, const std::string &category)
std::string GetWorkspaceWindowName(size_t session_id, const std::string &base_window_id) const
Resolve the exact ImGui window name for a panel by base ID.
std::vector< WindowDescriptor > GetWindowsInCategory(size_t session_id, const std::string &category) const
const WindowDescriptor * GetWindowDescriptor(size_t session_id, const std::string &base_window_id) const
void SetWindowPinned(size_t session_id, const std::string &base_window_id, bool pinned)
bool CloseWindow(size_t session_id, const std::string &base_window_id)
void TriggerWindowClicked(const std::string &category)
std::vector< std::string > GetPinnedWindows(size_t session_id) const
bool IsWindowOpen(size_t session_id, const std::string &base_window_id) const
float GetActiveSidePanelWidth(float viewport_width) const
bool OpenWindow(size_t session_id, const std::string &base_window_id)
std::vector< WindowDescriptor > GetWindowsSortedByMRU(size_t session_id, const std::string &category) const
bool IsWindowPinned(size_t session_id, const std::string &base_window_id) const
bool ToggleWindow(size_t session_id, const std::string &base_window_id)
void SetSidebarExpanded(bool expanded, bool notify=true)
void ShowAllWindowsInCategory(size_t session_id, const std::string &category)
void MarkWindowRecentlyUsed(const std::string &window_id)
RAII for fixed-position panels (activity bar, side panel, status bar).
static bool BeginContentChild(const char *id, const ImVec2 &min_size, bool border=false, ImGuiWindowFlags flags=0)
static void EndContentChild()
static SafeAreaInsets GetSafeAreaInsets()
static float GetStandardWidgetHeight()
static float GetStandardSpacing()
RAII guard for ImGui style colors.
Definition style_guard.h:27
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
#define ICON_MD_FOLDER_OPEN
Definition icons.h:813
#define ICON_MD_VIEW_QUILT
Definition icons.h:2094
#define ICON_MD_APPS
Definition icons.h:168
#define ICON_MD_SEARCH
Definition icons.h:1673
#define ICON_MD_VISIBILITY
Definition icons.h:2101
#define ICON_MD_VISIBILITY_OFF
Definition icons.h:2102
#define ICON_MD_CHEVRON_LEFT
Definition icons.h:405
#define ICON_MD_PIN
Definition icons.h:1470
#define ICON_MD_CLEAR
Definition icons.h:416
#define ICON_MD_PUSH_PIN
Definition icons.h:1529
#define ICON_MD_WORKSPACES
Definition icons.h:2186
bool IsDungeonPanelModeWindow(const std::string &window_id)
bool TransparentIconButton(const char *icon, const ImVec2 &size, const char *tooltip, bool is_active, const ImVec4 &active_color, const char *panel_id, const char *anim_id)
Draw a transparent icon button (hover effect only).
ImVec4 ConvertColorToImVec4(const Color &color)
Definition color.h:134
ImVec4 GetSurfaceContainerHighestVec4()
ImVec4 GetPrimaryVec4()
ImVec4 GetTextSecondaryVec4()
ImVec4 GetSurfaceContainerHighVec4()
ImVec4 GetOutlineVec4()
ImVec4 GetOnSurfaceVec4()
Metadata for a dockable editor window (formerly PanelInfo)
static constexpr float kContentMinHeightList
Definition ui_config.h:54