Skip to content

Commit 095fc94

Browse files
committed
[editor] icons are now loaded in the imgui font atlas
1 parent f676cec commit 095fc94

15 files changed

Lines changed: 451 additions & 128 deletions

data/icons/arrow_left.png

6.8 KB
Loading

data/icons/arrow_right.png

6.97 KB
Loading

data/icons/arrow_up.png

7.02 KB
Loading

data/icons/refresh.png

12.9 KB
Loading

source/editor/ImGui/ImGui_Extension.h

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,39 @@ namespace ImGuiSp
140140
return result;
141141
}
142142

143+
// atlas icon variant, binds the shared atlas texture and samples the icon's uv sub rect
144+
static bool image_button(const spartan::IconType icon, const spartan::math::Vector2& size, bool border, ImVec4 tint = {1,1,1,1})
145+
{
146+
const spartan::Icon& entry = spartan::ResourceCache::GetIcon(icon);
147+
148+
if (!border)
149+
{
150+
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
151+
}
152+
153+
// use the icon type as a stable id, every icon now shares one atlas texture pointer
154+
// so an id derived from the texture would collide across different icon buttons
155+
ImGui::PushID(static_cast<int>(icon));
156+
bool result = ImGui::ImageButton
157+
(
158+
"",
159+
reinterpret_cast<ImTextureID>(entry.texture),
160+
size,
161+
ImVec2(entry.uv_min.x, entry.uv_min.y),
162+
ImVec2(entry.uv_max.x, entry.uv_max.y),
163+
ImColor(0, 0, 0, 0),
164+
tint
165+
);
166+
ImGui::PopID();
167+
168+
if (!border)
169+
{
170+
ImGui::PopStyleVar();
171+
}
172+
173+
return result;
174+
}
175+
143176
static void image(spartan::RHI_Texture* texture, const spartan::math::Vector2& size, bool border = false)
144177
{
145178
if (!border)
@@ -174,25 +207,27 @@ namespace ImGuiSp
174207
);
175208
}
176209

177-
static void image(const spartan::IconType icon, const float size)
210+
// standalone texture variant with explicit uvs, used for atlas icons drawn through ImGuiSp::image
211+
static void image(spartan::RHI_Texture* texture, const ImVec2& size, const spartan::math::Vector2& uv0, const spartan::math::Vector2& uv1, const ImVec4& tint = default_tint)
178212
{
179213
ImGui::ImageWithBg(
180-
reinterpret_cast<ImTextureID>(spartan::ResourceCache::GetIcon(icon)),
181-
ImVec2(size, size),
182-
ImVec2(0, 0),
183-
ImVec2(1, 1),
214+
reinterpret_cast<ImTextureID>(texture),
215+
size,
216+
ImVec2(uv0.x, uv0.y),
217+
ImVec2(uv1.x, uv1.y),
184218
ImColor(0, 0, 0, 0), // bg
185-
default_tint // tint
219+
tint
186220
);
187221
}
188222

189-
static void image(const spartan::IconType icon, const float size,const ImVec4 tint)
223+
static void image(const spartan::IconType icon, const float size, const ImVec4 tint = default_tint)
190224
{
225+
const spartan::Icon& entry = spartan::ResourceCache::GetIcon(icon);
191226
ImGui::ImageWithBg(
192-
reinterpret_cast<ImTextureID>(spartan::ResourceCache::GetIcon(icon)),
227+
reinterpret_cast<ImTextureID>(entry.texture),
193228
ImVec2(size, size),
194-
ImVec2(0, 0),
195-
ImVec2(1, 1),
229+
ImVec2(entry.uv_min.x, entry.uv_min.y),
230+
ImVec2(entry.uv_max.x, entry.uv_max.y),
196231
ImColor(0, 0, 0, 0), // bg
197232
tint // tint
198233
);
@@ -309,7 +344,7 @@ namespace ImGuiSp
309344
}
310345

311346
// draw x icon
312-
image(spartan::ResourceCache::GetIcon(spartan::IconType::X), ImVec2(button_size, button_size));
347+
image(spartan::IconType::X, button_size);
313348
}
314349
}
315350
ImGui::EndGroup();

source/editor/Widgets/Console.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void Console::OnTickVisible()
7373
ImGui::PushID(static_cast<int>(index));
7474
bool& visibility = m_log_type_visibility[index];
7575
ImGui::PushStyleColor(ImGuiCol_Button, visibility ? ImGui::GetStyle().Colors[ImGuiCol_Button] : ImGui::GetStyle().Colors[ImGuiCol_FrameBg]);
76-
if (ImGuiSp::image_button(spartan::ResourceCache::GetIcon(IconType::Console), 15.0f * dpi, false, m_log_type_color[index]))
76+
if (ImGuiSp::image_button(IconType::Console, 15.0f * dpi, false, m_log_type_color[index]))
7777
{
7878
visibility = !visibility;
7979
}

source/editor/Widgets/FileDialog.cpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,13 @@ void FileDialog::ShowTop(bool* is_visible, Editor* editor)
386386
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1, 1, 1, 0.12f));
387387
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1, 1, 1, 0.18f));
388388

389+
// square icon size matched to the toolbar text height so the row stays consistent
390+
const spartan::math::Vector2 nav_icon_size(ImGui::GetFontSize(), ImGui::GetFontSize());
391+
389392
// navigation: back button
390393
bool can_go_back = m_history_index > 0;
391394
ImGui::BeginDisabled(!can_go_back);
392-
if (ImGui::Button("Back"))
395+
if (ImGuiSp::image_button(spartan::IconType::ArrowLeft, nav_icon_size, false))
393396
{
394397
m_history_index--;
395398
m_current_path = m_history[m_history_index];
@@ -405,7 +408,7 @@ void FileDialog::ShowTop(bool* is_visible, Editor* editor)
405408
// navigation: forward button
406409
bool can_go_forward = m_history_index < m_history.size() - 1;
407410
ImGui::BeginDisabled(!can_go_forward);
408-
if (ImGui::Button("Forward"))
411+
if (ImGuiSp::image_button(spartan::IconType::ArrowRight, nav_icon_size, false))
409412
{
410413
m_history_index++;
411414
m_current_path = m_history[m_history_index];
@@ -419,7 +422,7 @@ void FileDialog::ShowTop(bool* is_visible, Editor* editor)
419422
ImGui::SameLine();
420423

421424
// navigation: up button
422-
if (ImGui::Button("Up"))
425+
if (ImGuiSp::image_button(spartan::IconType::ArrowUp, nav_icon_size, false))
423426
{
424427
string parent = FileSystem::GetParentDirectory(m_current_path);
425428
if (!parent.empty() && parent != m_current_path)
@@ -437,7 +440,7 @@ void FileDialog::ShowTop(bool* is_visible, Editor* editor)
437440
ImGui::SameLine();
438441

439442
// navigation: refresh button
440-
if (ImGui::Button("Refresh"))
443+
if (ImGuiSp::image_button(spartan::IconType::Refresh, nav_icon_size, false))
441444
{
442445
m_is_dirty = true;
443446
}
@@ -817,12 +820,17 @@ void FileDialog::RenderGridView()
817820
}
818821

819822
// icon - draw directly to draw list
820-
float icon_area = icon_size - grid_item_padding;
821-
if (RHI_Texture* texture = item.GetIcon())
823+
float icon_area = icon_size - grid_item_padding;
824+
const spartan::Icon& icon = item.GetIcon();
825+
if (icon.texture)
822826
{
823-
if (texture->GetResourceState() == ResourceState::PreparedForGpu)
827+
if (icon.texture->GetResourceState() == ResourceState::PreparedForGpu)
824828
{
825-
ImVec2 img_size(static_cast<float>(texture->GetWidth()), static_cast<float>(texture->GetHeight()));
829+
// source size derived from the uv sub rect, works for both atlas icons and full thumbnails
830+
ImVec2 img_size(
831+
(icon.uv_max.x - icon.uv_min.x) * static_cast<float>(icon.texture->GetWidth()),
832+
(icon.uv_max.y - icon.uv_min.y) * static_cast<float>(icon.texture->GetHeight())
833+
);
826834
float scale = min(icon_area / img_size.x, icon_area / img_size.y);
827835
img_size.x *= scale;
828836
img_size.y *= scale;
@@ -832,9 +840,11 @@ void FileDialog::RenderGridView()
832840
float img_y = card_min.y + grid_item_padding + (icon_area - img_size.y) * 0.5f;
833841

834842
draw_list->AddImage(
835-
reinterpret_cast<ImTextureID>(texture),
843+
reinterpret_cast<ImTextureID>(icon.texture),
836844
ImVec2(img_x, img_y),
837-
ImVec2(img_x + img_size.x, img_y + img_size.y)
845+
ImVec2(img_x + img_size.x, img_y + img_size.y),
846+
ImVec2(icon.uv_min.x, icon.uv_min.y),
847+
ImVec2(icon.uv_max.x, icon.uv_max.y)
838848
);
839849
}
840850
}
@@ -1046,12 +1056,13 @@ void FileDialog::RenderListView()
10461056

10471057
// icon
10481058
ImGui::SameLine(0, 0);
1049-
if (RHI_Texture* texture = item.GetIcon())
1059+
const spartan::Icon& icon = item.GetIcon();
1060+
if (icon.texture)
10501061
{
1051-
if (texture->GetResourceState() == ResourceState::PreparedForGpu)
1062+
if (icon.texture->GetResourceState() == ResourceState::PreparedForGpu)
10521063
{
10531064
ImVec2 icon_size(20.0f, 20.0f);
1054-
ImGuiSp::image(texture, icon_size);
1065+
ImGuiSp::image(icon.texture, icon_size, icon.uv_min, icon.uv_max);
10551066
ImGui::SameLine(0, 8);
10561067
}
10571068
}
@@ -1196,7 +1207,8 @@ void FileDialog::ItemDrag(FileDialogItem* item)
11961207

11971208
// drag preview
11981209
ImGui::BeginTooltip();
1199-
ImGuiSp::image(item->GetIcon(), ImVec2(48, 48));
1210+
const spartan::Icon& drag_icon = item->GetIcon();
1211+
ImGuiSp::image(drag_icon.texture, ImVec2(48, 48), drag_icon.uv_min, drag_icon.uv_max);
12001212
ImGui::SameLine();
12011213
ImGui::Text("%s", item->GetLabel().c_str());
12021214
ImGui::EndTooltip();

source/editor/Widgets/FileDialog.h

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,27 @@ enum FileDialog_ViewMode
6666
class FileDialogItem
6767
{
6868
public:
69-
FileDialogItem(const std::string& path, spartan::RHI_Texture* icon)
69+
// atlas type icon, carries the shared atlas texture plus the icon's uv sub rect
70+
FileDialogItem(const std::string& path, const spartan::Icon& icon)
7071
{
71-
m_path = path;
72-
m_path_relative = spartan::FileSystem::GetRelativePath(path);
73-
m_icon = icon;
74-
static uint32_t id = 0;
75-
m_id = id++;
76-
m_isDirectory = spartan::FileSystem::IsDirectory(path);
77-
m_label = spartan::FileSystem::GetFileNameFromFilePath(path);
72+
m_icon = icon;
73+
Init(path);
7874
}
75+
76+
// standalone image thumbnail, samples the whole texture
77+
FileDialogItem(const std::string& path, spartan::RHI_Texture* thumbnail)
78+
{
79+
m_icon.texture = thumbnail;
80+
m_icon.uv_min = spartan::math::Vector2(0.0f, 0.0f);
81+
m_icon.uv_max = spartan::math::Vector2(1.0f, 1.0f);
82+
Init(path);
83+
}
84+
7985
const auto& GetPath() const { return m_path; }
8086
const auto& GetPathRelative() const { return m_path_relative; }
8187
const auto& GetLabel() const { return m_label; }
8288
uint32_t GetId() const { return m_id; }
83-
spartan::RHI_Texture* GetIcon() const { return m_icon; }
89+
const spartan::Icon& GetIcon() const { return m_icon; }
8490
auto IsDirectory() const { return m_isDirectory; }
8591
auto GetTimeSinceLastClickMs() const { return static_cast<float>(m_time_since_last_click.count()); }
8692
void Clicked()
@@ -91,7 +97,17 @@ class FileDialogItem
9197
}
9298

9399
private:
94-
spartan::RHI_Texture* m_icon;
100+
void Init(const std::string& path)
101+
{
102+
m_path = path;
103+
m_path_relative = spartan::FileSystem::GetRelativePath(path);
104+
static uint32_t id = 0;
105+
m_id = id++;
106+
m_isDirectory = spartan::FileSystem::IsDirectory(path);
107+
m_label = spartan::FileSystem::GetFileNameFromFilePath(path);
108+
}
109+
110+
spartan::Icon m_icon;
95111
uint32_t m_id;
96112
std::string m_path;
97113
std::string m_path_relative;

source/editor/Widgets/MenuBar.cpp

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,10 @@ namespace
310310
namespace buttons_toolbar
311311
{
312312
float button_size = 19.0f;
313-
unordered_map<spartan::RHI_Texture*, Widget*> widgets;
313+
// keyed by icon type, every icon shares one atlas texture pointer now so a pointer key would collide
314+
vector<pair<spartan::IconType, Widget*>> widgets;
314315

315-
void toolbar_button(spartan::RHI_Texture* icon_type, const char* tooltip_text, bool (*get_visibility)(Widget*), void (*on_press)(Widget*), Widget* widget = nullptr, float cursor_pos_x = -1.0f)
316+
void toolbar_button(spartan::IconType icon_type, const char* tooltip_text, bool (*get_visibility)(Widget*), void (*on_press)(Widget*), Widget* widget = nullptr, float cursor_pos_x = -1.0f)
316317
{
317318
ImGui::SameLine();
318319

@@ -495,7 +496,7 @@ namespace
495496
ImGui::SetCursorPosX(cursor_pos_x);
496497
ImGui::SetCursorPosY(offset_y);
497498

498-
if (ImGuiSp::image_button(spartan::ResourceCache::GetIcon(spartan::IconType::Play), button_size * dpi, false))
499+
if (ImGuiSp::image_button(spartan::IconType::Play, button_size * dpi, false))
499500
{
500501
toggle_playing();
501502
}
@@ -530,7 +531,7 @@ namespace
530531
{
531532
static auto screenshot_visible = [](Widget*) { return false; };
532533
static auto screenshot_press = [](Widget*) { spartan::Renderer::Screenshot(); };
533-
toolbar_button(spartan::ResourceCache::GetIcon(spartan::IconType::Screenshot), "Screenshot",
534+
toolbar_button(spartan::IconType::Screenshot, "Screenshot",
534535
screenshot_visible, screenshot_press, nullptr, cursor_pos_x);
535536

536537
static auto renderdoc_visible = [](Widget*) { return false; };
@@ -545,7 +546,7 @@ namespace
545546
SP_LOG_WARNING("RenderDoc integration is disabled. To enable, go to \"Debugging.h\", and set \"is_renderdoc_enabled\" to \"true\"");
546547
}
547548
};
548-
toolbar_button(spartan::ResourceCache::GetIcon(spartan::IconType::RenderDoc), "RenderDoc capture",
549+
toolbar_button(spartan::IconType::RenderDoc, "RenderDoc capture",
549550
renderdoc_visible, renderdoc_press, nullptr);
550551
}
551552

@@ -556,16 +557,16 @@ namespace
556557
{
557558
static auto world_visible = [](Widget*) { return GeneralWindows::GetVisibilityWorlds(); };
558559
static auto world_press = [](Widget*) { GeneralWindows::SetVisibilityWorlds(!GeneralWindows::GetVisibilityWorlds()); };
559-
toolbar_button(spartan::ResourceCache::GetIcon(spartan::IconType::Terrain), "Worlds",
560+
toolbar_button(spartan::IconType::Terrain, "Worlds",
560561
world_visible, world_press, nullptr);
561562

562563
for (auto& widget_it : widgets)
563564
{
564565
Widget* widget_ptr = widget_it.second;
565-
spartan::RHI_Texture* icon_tex = widget_it.first;
566+
spartan::IconType icon = widget_it.first;
566567
static auto is_widget_visible = [](Widget* w) { return w->GetVisible(); };
567568
static auto set_widget_visible = [](Widget* w) { w->SetVisible(true); };
568-
toolbar_button(icon_tex, widget_ptr->GetTitle(), is_widget_visible, set_widget_visible, widget_ptr);
569+
toolbar_button(icon, widget_ptr->GetTitle(), is_widget_visible, set_widget_visible, widget_ptr);
569570
}
570571
}
571572

@@ -617,7 +618,7 @@ namespace
617618
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1, 1, 1, 0.2f));
618619
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(button_padding_x * dpi, button_padding_y * dpi));
619620

620-
if (ImGuiSp::image_button(spartan::ResourceCache::GetIcon(spartan::IconType::Minimize), icon_size, false))
621+
if (ImGuiSp::image_button(spartan::IconType::Minimize, icon_size, false))
621622
{
622623
spartan::Window::Minimize();
623624
}
@@ -626,7 +627,7 @@ namespace
626627
ImGui::SetCursorPosY(offset_y);
627628

628629
// maximize/restore button
629-
if (ImGuiSp::image_button(spartan::ResourceCache::GetIcon(spartan::IconType::Maximize), icon_size, false))
630+
if (ImGuiSp::image_button(spartan::IconType::Maximize, icon_size, false))
630631
{
631632
spartan::Window::Maximize();
632633
}
@@ -641,7 +642,7 @@ namespace
641642
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.9f, 0.2f, 0.2f, 1.0f));
642643
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.7f, 0.1f, 0.1f, 1.0f));
643644

644-
if (ImGuiSp::image_button(spartan::ResourceCache::GetIcon(spartan::IconType::X), icon_size, false))
645+
if (ImGuiSp::image_button(spartan::IconType::X, icon_size, false))
645646
{
646647
spartan::Window::Close();
647648
}
@@ -657,11 +658,11 @@ void MenuBar::Initialize(Editor* _editor)
657658
editor = _editor;
658659
file_dialog = make_unique<FileDialog>(true, FileDialog_Type_FileSelection, FileDialog_Op_Open, FileDialog_Filter_World);
659660

660-
buttons_toolbar::widgets[spartan::ResourceCache::GetIcon(spartan::IconType::Profiler)] = editor->GetWidget<Profiler>();
661-
buttons_toolbar::widgets[spartan::ResourceCache::GetIcon(spartan::IconType::ResourceCache)] = editor->GetWidget<ResourceViewer>();
662-
buttons_toolbar::widgets[spartan::ResourceCache::GetIcon(spartan::IconType::Shader)] = editor->GetWidget<ShaderEditor>();
663-
buttons_toolbar::widgets[spartan::ResourceCache::GetIcon(spartan::IconType::Gear)] = editor->GetWidget<RenderOptions>();
664-
buttons_toolbar::widgets[spartan::ResourceCache::GetIcon(spartan::IconType::Texture)] = editor->GetWidget<TextureViewer>();
661+
buttons_toolbar::widgets.push_back({ spartan::IconType::Profiler, editor->GetWidget<Profiler>() });
662+
buttons_toolbar::widgets.push_back({ spartan::IconType::ResourceCache, editor->GetWidget<ResourceViewer>() });
663+
buttons_toolbar::widgets.push_back({ spartan::IconType::Shader, editor->GetWidget<ShaderEditor>() });
664+
buttons_toolbar::widgets.push_back({ spartan::IconType::Gear, editor->GetWidget<RenderOptions>() });
665+
buttons_toolbar::widgets.push_back({ spartan::IconType::Texture, editor->GetWidget<TextureViewer>() });
665666

666667
spartan::Engine::SetFlag(spartan::EngineMode::Playing, false);
667668
}
@@ -725,10 +726,10 @@ void MenuBar::Tick()
725726
// logo
726727
ImGui::SetCursorPosX(padding_x);
727728
ImGui::SetCursorPosY(icon_y);
728-
spartan::RHI_Texture* logo = spartan::ResourceCache::GetIcon(spartan::IconType::Logo);
729-
if (logo)
729+
const spartan::Icon& logo = spartan::ResourceCache::GetIcon(spartan::IconType::Logo);
730+
if (logo.texture)
730731
{
731-
ImGui::Image(reinterpret_cast<ImTextureID>(logo), ImVec2(icon_size, icon_size));
732+
ImGuiSp::image(logo.texture, ImVec2(icon_size, icon_size), logo.uv_min, logo.uv_max);
732733
}
733734
ImGui::SameLine(0, padding_x * 0.5f);
734735

source/editor/Widgets/Properties.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ namespace
343343
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
344344
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1, 1, 1, 0.1f));
345345
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
346-
if (ImGuiSp::image_button(spartan::ResourceCache::GetIcon(IconType::Gear), icon_size, false))
346+
if (ImGuiSp::image_button(IconType::Gear, icon_size, false))
347347
{
348348
context_menu_id = name;
349349
ImGui::OpenPopup(context_menu_id.c_str());

0 commit comments

Comments
 (0)