SleakEngine 0.1.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
UI.cpp
Go to the documentation of this file.
1#include <UI/UI.hpp>
2#include <imgui.h>
3#include <misc/cpp/imgui_stdlib.h>
7#include <Runtime/Texture.hpp>
8#include <stb_image.h>
9#include <cstdarg>
10#include <unordered_map>
11
12namespace Sleak::UI {
13
14void BeginPanel(const char* name, float x, float y, float bgAlpha, int flags) {
15 // Only set position if explicitly provided (non-zero),
16 // so SetNextWindowPos() called before BeginPanel is not overridden
17 if (x != 0.0f || y != 0.0f) {
18 ImGuiCond posCond = (flags & PanelFlags_NoMove) ? ImGuiCond_Always : ImGuiCond_FirstUseEver;
19 ImGui::SetNextWindowPos(ImVec2(x, y), posCond);
20 }
21 ImGui::SetNextWindowBgAlpha(bgAlpha);
22
23 ImGuiWindowFlags imFlags = 0;
24 if (flags & PanelFlags_NoTitleBar) imFlags |= ImGuiWindowFlags_NoTitleBar;
25 if (flags & PanelFlags_AutoResize) imFlags |= ImGuiWindowFlags_AlwaysAutoResize;
26 if (flags & PanelFlags_NoMove) imFlags |= ImGuiWindowFlags_NoMove;
27 if (flags & PanelFlags_NoInput) imFlags |= ImGuiWindowFlags_NoInputs;
28 if (flags & PanelFlags_NoFocusOnAppear) imFlags |= ImGuiWindowFlags_NoFocusOnAppearing;
29
30 ImGui::Begin(name, nullptr, imFlags);
31}
32
33void EndPanel() {
34 ImGui::End();
35}
36
37void Text(const char* fmt, ...) {
38 va_list args;
39 va_start(args, fmt);
40 ImGui::TextV(fmt, args);
41 va_end(args);
42}
43
44void TextColored(float r, float g, float b, float a, const char* fmt, ...) {
45 va_list args;
46 va_start(args, fmt);
47 ImGui::TextColoredV(ImVec4(r, g, b, a), fmt, args);
48 va_end(args);
49}
50
51void TextDisabled(const char* fmt, ...) {
52 va_list args;
53 va_start(args, fmt);
54 ImGui::TextDisabledV(fmt, args);
55 va_end(args);
56}
57
58bool Checkbox(const char* label, bool* value) {
59 return ImGui::Checkbox(label, value);
60}
61
62bool Button(const char* label) {
63 return ImGui::Button(label);
64}
65
66bool DragFloat(const char* label, float* value, float speed, float min, float max) {
67 return ImGui::DragFloat(label, value, speed, min, max);
68}
69
70bool Combo(const char* label, int* current, const char* const items[], int count) {
71 return ImGui::Combo(label, current, items, count);
72}
73
74void Separator() {
75 ImGui::Separator();
76}
77
78void SameLine() {
79 ImGui::SameLine();
80}
81
82void BeginGroup() {
83 ImGui::BeginGroup();
84}
85
86void EndGroup() {
87 ImGui::EndGroup();
88}
89
90void BeginChild(const char* name) {
91 ImGui::BeginChild(name, {0, 0}, ImGuiChildFlags_AutoResizeY);
92}
93
94void BeginChildSized(const char* name, float width, float height) {
95 ImGui::BeginChild(name, {width, height}, ImGuiChildFlags_AutoResizeY);
96}
97
98void EndChild() {
99 ImGui::EndChild();
100}
101
103 return ImGui::GetMainViewport()->Size.x;
104}
105
107 return ImGui::GetMainViewport()->Size.y;
108}
109
110void DrawLine(float x1, float y1, float x2, float y2,
111 float r, float g, float b, float a, float thickness) {
112 ImGui::GetForegroundDrawList()->AddLine(
113 ImVec2(x1, y1), ImVec2(x2, y2), ImColor(r, g, b, a), thickness);
114}
115
116void DrawRect(float x, float y, float w, float h,
117 float r, float g, float b, float a, float thickness,
118 float rounding) {
119 ImGui::GetForegroundDrawList()->AddRect(
120 ImVec2(x, y), ImVec2(x + w, y + h), ImColor(r, g, b, a), rounding, 0, thickness);
121}
122
123void DrawFilledRect(float x, float y, float w, float h,
124 float r, float g, float b, float a,
125 float rounding) {
126 ImGui::GetForegroundDrawList()->AddRectFilled(
127 ImVec2(x, y), ImVec2(x + w, y + h), ImColor(r, g, b, a), rounding);
128}
129
130void DrawText(const char* text, float x, float y,
131 float r, float g, float b, float a) {
132 ImGui::GetForegroundDrawList()->AddText(
133 ImVec2(x, y), ImColor(r, g, b, a), text);
134}
135
136bool InputText(const char* label, char* buf, size_t bufSize) {
137 return ImGui::InputText(label, buf, bufSize);
138}
139
140bool InputTextString(const char* label, std::string* str) {
141 return ImGui::InputText(label, str);
142}
143
144bool ButtonSized(const char* label, float width, float height) {
145 return ImGui::Button(label, ImVec2(width, height));
146}
147
148bool Selectable(const char* label, bool selected) {
149 return ImGui::Selectable(label, selected);
150}
151
153 ImGui::SetNextItemWidth(width);
154}
155
156void Spacing() {
157 ImGui::Spacing();
158}
159
160void Dummy(float width, float height) {
161 ImGui::Dummy(ImVec2(width, height));
162}
163
164static ImGuiCol ToImGuiCol(StyleColor color) {
165 switch (color) {
166 case StyleColor_Text:
167 return ImGuiCol_Text;
169 return ImGuiCol_WindowBg;
171 return ImGuiCol_ChildBg;
173 return ImGuiCol_Button;
175 return ImGuiCol_ButtonHovered;
177 return ImGuiCol_ButtonActive;
179 return ImGuiCol_FrameBg;
181 return ImGuiCol_Header;
183 return ImGuiCol_HeaderHovered;
185 return ImGuiCol_HeaderActive;
187 return ImGuiCol_ScrollbarBg;
188 }
189 return ImGuiCol_Text;
190}
191
192void PushStyleColor(StyleColor idx, float r, float g, float b, float a) {
193 ImGui::PushStyleColor(ToImGuiCol(idx), ImVec4(r, g, b, a));
194}
195
196void PushStyleColor(int idx, float r, float g, float b, float a) {
197 ImGui::PushStyleColor(static_cast<ImGuiCol>(idx), ImVec4(r, g, b, a));
198}
199
200void PopStyleColor(int count) {
201 ImGui::PopStyleColor(count);
202}
203
204void PushStyleVar(int idx, float val) {
205 ImGui::PushStyleVar(static_cast<ImGuiStyleVar>(idx), val);
206}
207
208void PushStyleVarVec(int idx, float x, float y) {
209 ImGui::PushStyleVar(static_cast<ImGuiStyleVar>(idx), ImVec2(x, y));
210}
211
212void PopStyleVar(int count) {
213 ImGui::PopStyleVar(count);
214}
215
216bool BeginListBox(const char* label, float width, float height) {
217 return ImGui::BeginListBox(label, ImVec2(width, height));
218}
219
221 ImGui::EndListBox();
222}
223
224void SetCursorPosX(float x) {
225 ImGui::SetCursorPosX(x);
226}
227
228void SetCursorPosY(float y) {
229 ImGui::SetCursorPosY(y);
230}
231
233 return ImGui::GetCursorPosY();
234}
235
237 return ImGui::GetContentRegionAvail().x;
238}
239
240void SetNextWindowPos(float x, float y, bool always) {
241 ImGui::SetNextWindowPos(ImVec2(x, y), always ? ImGuiCond_Always : ImGuiCond_FirstUseEver);
242}
243
244void SetNextWindowSize(float w, float h, bool always) {
245 ImGui::SetNextWindowSize(ImVec2(w, h), always ? ImGuiCond_Always : ImGuiCond_FirstUseEver);
246}
247
248void ProgressBar(float fraction, float width, float height, const char* overlay) {
249 ImGui::ProgressBar(fraction, ImVec2(width, height), overlay);
250}
251
252void TextWrapped(const char* fmt, ...) {
253 va_list args;
254 va_start(args, fmt);
255 ImGui::TextWrappedV(fmt, args);
256 va_end(args);
257}
258
259void Image(uint64_t textureID, float width, float height) {
260 // OpenGL textures are vertically flipped relative to ImGui's expectation
261 bool flipY = false;
262 auto* app = Application::GetInstance();
263 if (app && app->GetRenderer() &&
264 app->GetRenderer()->GetType() == RenderEngine::RendererType::OpenGL)
265 flipY = true;
266
267 ImVec2 uv0 = flipY ? ImVec2(0, 1) : ImVec2(0, 0);
268 ImVec2 uv1 = flipY ? ImVec2(1, 0) : ImVec2(1, 1);
269 ImGui::Image(static_cast<ImTextureID>(textureID), ImVec2(width, height), uv0, uv1);
270}
271
272void DrawImage(uint64_t textureID, float x, float y, float width, float height) {
273 bool flipY = false;
274 auto* app = Application::GetInstance();
275 if (app && app->GetRenderer() &&
276 app->GetRenderer()->GetType() == RenderEngine::RendererType::OpenGL)
277 flipY = true;
278
279 ImVec2 uv0 = flipY ? ImVec2(0, 1) : ImVec2(0, 0);
280 ImVec2 uv1 = flipY ? ImVec2(1, 0) : ImVec2(1, 1);
281 ImGui::GetForegroundDrawList()->AddImage(
282 static_cast<ImTextureID>(textureID),
283 ImVec2(x, y), ImVec2(x + width, y + height), uv0, uv1);
284}
285
286static std::unordered_map<std::string, Sleak::Texture*> s_uiTextures;
287
288uint64_t LoadTextureForUI(const std::string& filePath, float* outWidth, float* outHeight) {
289 auto it = s_uiTextures.find(filePath);
290 if (it != s_uiTextures.end()) {
291 if (outWidth) *outWidth = static_cast<float>(it->second->GetWidth());
292 if (outHeight) *outHeight = static_cast<float>(it->second->GetHeight());
293 return it->second->GetImGuiTextureID();
294 }
295
297 if (!tex) return 0;
298
299 s_uiTextures[filePath] = tex;
300 if (outWidth) *outWidth = static_cast<float>(tex->GetWidth());
301 if (outHeight) *outHeight = static_cast<float>(tex->GetHeight());
302 return tex->GetImGuiTextureID();
303}
304
306 // Must run before device teardown — cached textures own VkImage/memory
307 for (auto& [path, tex] : s_uiTextures) delete tex;
308 s_uiTextures.clear();
309}
310
311Sleak::Texture* CreateTextureFromPixels(uint32_t width, uint32_t height, const void* rgbaPixels, uint32_t maxMipLevels) {
313 rgbaPixels, width, height, TextureFormat::RGBA8, maxMipLevels);
314}
315
316unsigned char* LoadImagePixels(const char* path, int* w, int* h) {
317 int channels;
318 return stbi_load(path, w, h, &channels, 4); // force RGBA
319}
320
321void FreeImagePixels(unsigned char* pixels) {
322 stbi_image_free(pixels);
323}
324
325} // namespace Sleak::UI
int width
int height
static Application * GetInstance()
The one Application for this process, or null before construction.
static Sleak::Texture * CreateTexture(const std::string &TexturePath)
Loads a texture via the currently registered backend factory.
static Sleak::Texture * CreateTextureFromMemory(const void *data, uint32_t width, uint32_t height, TextureFormat format, uint32_t maxMipLevels=0)
Creates a texture from raw pixel data via the currently registered backend factory.
StyleColor
Definition UI.hpp:108
@ StyleColor_ScrollbarBg
Definition UI.hpp:119
@ StyleColor_ChildBg
Definition UI.hpp:111
@ StyleColor_HeaderActive
Definition UI.hpp:118
@ StyleColor_FrameBg
Definition UI.hpp:115
@ StyleColor_ButtonActive
Definition UI.hpp:114
@ StyleColor_ButtonHovered
Definition UI.hpp:113
@ StyleColor_Text
Definition UI.hpp:109
@ StyleColor_HeaderHovered
Definition UI.hpp:117
@ StyleColor_Button
Definition UI.hpp:112
@ StyleColor_Header
Definition UI.hpp:116
@ StyleColor_WindowBg
Definition UI.hpp:110
@ PanelFlags_AutoResize
Definition UI.hpp:17
@ PanelFlags_NoMove
Definition UI.hpp:18
@ PanelFlags_NoFocusOnAppear
Definition UI.hpp:20
@ PanelFlags_NoInput
Definition UI.hpp:19
@ PanelFlags_NoTitleBar
Definition UI.hpp:16
Immediate-mode UI calls available to game code.
Definition UI.hpp:10
ENGINE_API void ShutdownTextureCache()
Definition UI.cpp:305
ENGINE_API void PushStyleColor(StyleColor idx, float r, float g, float b, float a)
Pushes a color for one of the StyleColor slots.
Definition UI.cpp:192
ENGINE_API void DrawText(const char *text, float x, float y, float r, float g, float b, float a=1.0f)
Definition UI.cpp:130
ENGINE_API void Separator()
Definition UI.cpp:74
ENGINE_API float GetViewportHeight()
Definition UI.cpp:106
ENGINE_API uint64_t LoadTextureForUI(const std::string &filePath, float *outWidth=nullptr, float *outHeight=nullptr)
Loads an image file and caches it as a UI-bindable texture id, reusing the cache on repeat calls for ...
Definition UI.cpp:288
ENGINE_API bool Button(const char *label)
Definition UI.cpp:62
ENGINE_API float GetViewportWidth()
Definition UI.cpp:102
ENGINE_API void ProgressBar(float fraction, float width=-1.0f, float height=0.0f, const char *overlay=nullptr)
Definition UI.cpp:248
ENGINE_API void FreeImagePixels(unsigned char *pixels)
Definition UI.cpp:321
ENGINE_API void BeginGroup()
Definition UI.cpp:82
ENGINE_API void SetCursorPosY(float y)
Definition UI.cpp:228
ENGINE_API void PushStyleVar(int idx, float val)
Definition UI.cpp:204
ENGINE_API void TextColored(float r, float g, float b, float a, const char *fmt,...)
Definition UI.cpp:44
ENGINE_API unsigned char * LoadImagePixels(const char *path, int *w, int *h)
Load image file into RGBA pixels (caller must free with FreeImagePixels).
Definition UI.cpp:316
ENGINE_API void EndGroup()
Definition UI.cpp:86
ENGINE_API void DrawLine(float x1, float y1, float x2, float y2, float r, float g, float b, float a=1.0f, float thickness=1.0f)
Definition UI.cpp:110
ENGINE_API Sleak::Texture * CreateTextureFromPixels(uint32_t width, uint32_t height, const void *rgbaPixels, uint32_t maxMipLevels=0)
Create a texture from raw RGBA pixel data (for runtime atlas building etc.).
Definition UI.cpp:311
ENGINE_API void PopStyleVar(int count=1)
Definition UI.cpp:212
ENGINE_API void BeginChild(const char *name)
Definition UI.cpp:90
ENGINE_API float GetCursorPosY()
Definition UI.cpp:232
ENGINE_API bool InputText(const char *label, char *buf, size_t bufSize)
Definition UI.cpp:136
ENGINE_API void EndChild()
Definition UI.cpp:98
ENGINE_API void Spacing()
Definition UI.cpp:156
ENGINE_API void SetNextItemWidth(float width)
Definition UI.cpp:152
ENGINE_API void Text(const char *fmt,...)
Definition UI.cpp:37
ENGINE_API bool ButtonSized(const char *label, float width, float height=0.0f)
Definition UI.cpp:144
ENGINE_API void DrawFilledRect(float x, float y, float w, float h, float r, float g, float b, float a=1.0f, float rounding=0.0f)
Definition UI.cpp:123
ENGINE_API void TextDisabled(const char *fmt,...)
Definition UI.cpp:51
ENGINE_API void Dummy(float width, float height)
Definition UI.cpp:160
ENGINE_API void SameLine()
Definition UI.cpp:78
ENGINE_API bool Selectable(const char *label, bool selected)
Definition UI.cpp:148
ENGINE_API void SetNextWindowPos(float x, float y, bool always=false)
Definition UI.cpp:240
ENGINE_API void EndListBox()
Definition UI.cpp:220
ENGINE_API void SetNextWindowSize(float w, float h, bool always=false)
Definition UI.cpp:244
ENGINE_API bool BeginListBox(const char *label, float width, float height)
Definition UI.cpp:216
ENGINE_API void PopStyleColor(int count=1)
Definition UI.cpp:200
ENGINE_API void DrawImage(uint64_t textureID, float x, float y, float width, float height)
Definition UI.cpp:272
ENGINE_API void SetCursorPosX(float x)
Definition UI.cpp:224
static std::unordered_map< std::string, Sleak::Texture * > s_uiTextures
Definition UI.cpp:286
ENGINE_API void BeginChildSized(const char *name, float width, float height=0.0f)
Definition UI.cpp:94
ENGINE_API void TextWrapped(const char *fmt,...)
Definition UI.cpp:252
ENGINE_API void BeginPanel(const char *name, float x, float y, float bgAlpha=0.4f, int flags=PanelFlags_NoTitleBar|PanelFlags_AutoResize|PanelFlags_NoMove|PanelFlags_NoInput|PanelFlags_NoFocusOnAppear)
Opens a floating overlay window at (x, y); pair with EndPanel.
Definition UI.cpp:14
ENGINE_API bool Checkbox(const char *label, bool *value)
Definition UI.cpp:58
ENGINE_API void Image(uint64_t textureID, float width, float height)
Definition UI.cpp:259
ENGINE_API void DrawRect(float x, float y, float w, float h, float r, float g, float b, float a=1.0f, float thickness=1.0f, float rounding=0.0f)
Definition UI.cpp:116
ENGINE_API void PushStyleVarVec(int idx, float x, float y)
Definition UI.cpp:208
ENGINE_API bool InputTextString(const char *label, std::string *str)
Definition UI.cpp:140
ENGINE_API float GetContentRegionAvailWidth()
Definition UI.cpp:236
ENGINE_API bool Combo(const char *label, int *current, const char *const items[], int count)
Definition UI.cpp:70
ENGINE_API void EndPanel()
Definition UI.cpp:33
ENGINE_API bool DragFloat(const char *label, float *value, float speed=1.0f, float min=0.0f, float max=0.0f)
Definition UI.cpp:66
static ImGuiCol ToImGuiCol(StyleColor color)
Definition UI.cpp:164