SleakEngine 1.0.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
164void PushStyleColor(int idx, float r, float g, float b, float a) {
165 ImGui::PushStyleColor(static_cast<ImGuiCol>(idx), ImVec4(r, g, b, a));
166}
167
168void PopStyleColor(int count) {
169 ImGui::PopStyleColor(count);
170}
171
172void PushStyleVar(int idx, float val) {
173 ImGui::PushStyleVar(static_cast<ImGuiStyleVar>(idx), val);
174}
175
176void PushStyleVarVec(int idx, float x, float y) {
177 ImGui::PushStyleVar(static_cast<ImGuiStyleVar>(idx), ImVec2(x, y));
178}
179
180void PopStyleVar(int count) {
181 ImGui::PopStyleVar(count);
182}
183
184bool BeginListBox(const char* label, float width, float height) {
185 return ImGui::BeginListBox(label, ImVec2(width, height));
186}
187
189 ImGui::EndListBox();
190}
191
192void SetCursorPosX(float x) {
193 ImGui::SetCursorPosX(x);
194}
195
196void SetCursorPosY(float y) {
197 ImGui::SetCursorPosY(y);
198}
199
201 return ImGui::GetCursorPosY();
202}
203
205 return ImGui::GetContentRegionAvail().x;
206}
207
208void SetNextWindowPos(float x, float y, bool always) {
209 ImGui::SetNextWindowPos(ImVec2(x, y), always ? ImGuiCond_Always : ImGuiCond_FirstUseEver);
210}
211
212void SetNextWindowSize(float w, float h, bool always) {
213 ImGui::SetNextWindowSize(ImVec2(w, h), always ? ImGuiCond_Always : ImGuiCond_FirstUseEver);
214}
215
216void ProgressBar(float fraction, float width, float height, const char* overlay) {
217 ImGui::ProgressBar(fraction, ImVec2(width, height), overlay);
218}
219
220void TextWrapped(const char* fmt, ...) {
221 va_list args;
222 va_start(args, fmt);
223 ImGui::TextWrappedV(fmt, args);
224 va_end(args);
225}
226
227void Image(uint64_t textureID, float width, float height) {
228 // OpenGL textures are vertically flipped relative to ImGui's expectation
229 bool flipY = false;
230 auto* app = Application::GetInstance();
231 if (app && app->GetRenderer() &&
232 app->GetRenderer()->GetType() == RenderEngine::RendererType::OpenGL)
233 flipY = true;
234
235 ImVec2 uv0 = flipY ? ImVec2(0, 1) : ImVec2(0, 0);
236 ImVec2 uv1 = flipY ? ImVec2(1, 0) : ImVec2(1, 1);
237 ImGui::Image(static_cast<ImTextureID>(textureID), ImVec2(width, height), uv0, uv1);
238}
239
240void DrawImage(uint64_t textureID, float x, float y, float width, float height) {
241 bool flipY = false;
242 auto* app = Application::GetInstance();
243 if (app && app->GetRenderer() &&
244 app->GetRenderer()->GetType() == RenderEngine::RendererType::OpenGL)
245 flipY = true;
246
247 ImVec2 uv0 = flipY ? ImVec2(0, 1) : ImVec2(0, 0);
248 ImVec2 uv1 = flipY ? ImVec2(1, 0) : ImVec2(1, 1);
249 ImGui::GetForegroundDrawList()->AddImage(
250 static_cast<ImTextureID>(textureID),
251 ImVec2(x, y), ImVec2(x + width, y + height), uv0, uv1);
252}
253
254static std::unordered_map<std::string, Sleak::Texture*> s_uiTextures;
255
256uint64_t LoadTextureForUI(const std::string& filePath, float* outWidth, float* outHeight) {
257 auto it = s_uiTextures.find(filePath);
258 if (it != s_uiTextures.end()) {
259 if (outWidth) *outWidth = static_cast<float>(it->second->GetWidth());
260 if (outHeight) *outHeight = static_cast<float>(it->second->GetHeight());
261 return it->second->GetImGuiTextureID();
262 }
263
265 if (!tex) return 0;
266
267 s_uiTextures[filePath] = tex;
268 if (outWidth) *outWidth = static_cast<float>(tex->GetWidth());
269 if (outHeight) *outHeight = static_cast<float>(tex->GetHeight());
270 return tex->GetImGuiTextureID();
271}
272
274 // Must run before device teardown — cached textures own VkImage/memory
275 for (auto& [path, tex] : s_uiTextures) delete tex;
276 s_uiTextures.clear();
277}
278
279Sleak::Texture* CreateTextureFromPixels(uint32_t width, uint32_t height, const void* rgbaPixels, uint32_t maxMipLevels) {
281 rgbaPixels, width, height, TextureFormat::RGBA8, maxMipLevels);
282}
283
284unsigned char* LoadImagePixels(const char* path, int* w, int* h) {
285 int channels;
286 return stbi_load(path, w, h, &channels, 4); // force RGBA
287}
288
289void FreeImagePixels(unsigned char* pixels) {
290 stbi_image_free(pixels);
291}
292
293} // 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.
@ 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:273
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:256
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:216
ENGINE_API void PushStyleColor(int idx, float r, float g, float b, float a)
Definition UI.cpp:164
ENGINE_API void FreeImagePixels(unsigned char *pixels)
Definition UI.cpp:289
ENGINE_API void BeginGroup()
Definition UI.cpp:82
ENGINE_API void SetCursorPosY(float y)
Definition UI.cpp:196
ENGINE_API void PushStyleVar(int idx, float val)
Definition UI.cpp:172
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:284
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:279
ENGINE_API void PopStyleVar(int count=1)
Definition UI.cpp:180
ENGINE_API void BeginChild(const char *name)
Definition UI.cpp:90
ENGINE_API float GetCursorPosY()
Definition UI.cpp:200
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:208
ENGINE_API void EndListBox()
Definition UI.cpp:188
ENGINE_API void SetNextWindowSize(float w, float h, bool always=false)
Definition UI.cpp:212
ENGINE_API bool BeginListBox(const char *label, float width, float height)
Definition UI.cpp:184
ENGINE_API void PopStyleColor(int count=1)
Definition UI.cpp:168
ENGINE_API void DrawImage(uint64_t textureID, float x, float y, float width, float height)
Definition UI.cpp:240
ENGINE_API void SetCursorPosX(float x)
Definition UI.cpp:192
static std::unordered_map< std::string, Sleak::Texture * > s_uiTextures
Definition UI.cpp:254
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:220
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:227
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:176
ENGINE_API bool InputTextString(const char *label, std::string *str)
Definition UI.cpp:140
ENGINE_API float GetContentRegionAvailWidth()
Definition UI.cpp:204
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