Enigma 3.2.2
A Simple, Reliable and Efficient Encryption Tool
Loading...
Searching...
No Matches
ImGuiWidgets.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef ENIGMA_IMGUI_WIDGETS_H
3#define ENIGMA_IMGUI_WIDGETS_H
4
7#include <Core/Core.hpp>
10#include <imgui.h>
11#include <imgui_internal.h>
12
14
15class ImGuiWidgets final {
17
18 public:
25 std::string *Str;
26 ImGuiInputTextCallback ChainCallback;
28 };
29 static int InputTextCallback(ImGuiInputTextCallbackData *data) {
30 InputTextCallback_UserData *user_data = static_cast<InputTextCallback_UserData *>(data->UserData);
31 if (data->EventFlag == static_cast<decltype(data->EventFlag)>(ImGuiInputTextFlags_CallbackResize)) {
32 // Resize string callback
33 // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want.
34 std::string *str = user_data->Str;
35 IM_ASSERT(data->Buf == str->c_str());
36 str->resize(data->BufTextLen);
37 data->Buf = (char *) str->c_str();
38 } else if (user_data->ChainCallback) {
39 // Forward to user callback, if any
40 data->UserData = user_data->ChainCallbackUserData;
41 return user_data->ChainCallback(data);
42 }
43 return 0;
44 }
45
47 static bool InputText(const char *label, std::string *str, const float width, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void *user_data = nullptr) {
48 IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
49 flags |= ImGuiInputTextFlags_CallbackResize;
50
51 InputTextCallback_UserData cb_user_data;
52 cb_user_data.Str = str;
53 cb_user_data.ChainCallback = callback;
54 cb_user_data.ChainCallbackUserData = user_data;
55 ImGui::PushItemWidth(width);
56 return ImGui::InputText(label, (char *) str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
57 }
58
60 static bool InputTextMultiline(const char *label, std::string *str, const ImVec2& size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void *user_data = nullptr) {
61 IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
62 flags |= ImGuiInputTextFlags_CallbackResize;
63
64 InputTextCallback_UserData cb_user_data;
65 cb_user_data.Str = str;
66 cb_user_data.ChainCallback = callback;
67 cb_user_data.ChainCallbackUserData = user_data;
68 return ImGui::InputTextMultiline(label, (char *) str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data);
69 }
70
72 static bool InputTextWithHint(const char *label, const char *hint, std::string *str, const float width, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void *user_data = nullptr) {
73 IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
74 flags |= ImGuiInputTextFlags_CallbackResize;
75
76 InputTextCallback_UserData cb_user_data;
77 cb_user_data.Str = str;
78 cb_user_data.ChainCallback = callback;
79 cb_user_data.ChainCallbackUserData = user_data;
80 ImGui::PushItemWidth(width);
81 return ImGui::InputTextWithHint(label, hint, (char *) str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
82 }
83
84#if 0
85 static int InputTextCallback(ImGuiInputTextCallbackData* data)
86 {
87 if (data->EventFlag == static_cast<decltype(data->EventFlag)>(ImGuiInputTextFlags_CallbackResize))
88 {
89 // Resize string callback
90 std::string* str = (std::string*)data->UserData;
91 IM_ASSERT(data->Buf == str->c_str());
92 str->resize(data->BufTextLen);
93 data->Buf = (char*)str->c_str();
94 }
95 return 0;
96 }
97 static bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
98 {
99 flags |= ImGuiInputTextFlags_CallbackResize;
100 return ImGui::InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, ImGuiWidgets::InputTextCallback, (void*)str);
101 }
102 static bool InputText(const char* label, std::string* str, const float width, ImGuiInputTextFlags flags = 0)
103 {
104 ImGui::PushItemWidth(width);
105 flags |= ImGuiInputTextFlags_CallbackResize;
106 bool ret = ImGui::InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, ImGuiWidgets::InputTextCallback, (void*)str);
107 ImGui::PopItemWidth();
108 return ret;
109 }
110 static bool InputTextWithHint(const char* label, const char* hint, std::string* str, const float width, ImGuiInputTextFlags flags = 0)
111 {
112 ImGui::PushItemWidth(width);
113 flags |= ImGuiInputTextFlags_CallbackResize;
114 bool ret = ImGui::InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, ImGuiWidgets::InputTextCallback, (void*)str);
115 ImGui::PopItemWidth();
116 return ret;
117
118 }
119#endif
121
122
124 static bool Button(const char *text,
125 const ImVec2& size = ImVec2(0.0f, 0.0f),
126 const ImVec4& color = Constants::Colors::BUTTON_COLOR,
127 const ImVec4& color_hover = Constants::Colors::BUTTON_COLOR_HOVER,
128 const ImVec4& color_active = Constants::Colors::BUTTON_COLOR_ACTIVE) {
129 ImGui::PushStyleColor(ImGuiCol_Button, color); // buttons color idle
130 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color_hover); // buttons color hover
131 ImGui::PushStyleColor(ImGuiCol_ButtonActive, color_active); // buttons color pressed
132 bool pressed_or_selected = ImGui::Button(text, size);
133 ImGui::PopStyleColor(3);
134
135 return pressed_or_selected;
136 }
137
139 static bool BackButton(const char *str_id,
140 const ImVec2& size = ImVec2(0.0f, 0.0f),
141 const ImVec4& color = Constants::Colors::BACK_BUTTON_COLOR,
142 const ImVec4& color_hover = Constants::Colors::BACK_BUTTON_COLOR_HOVER,
143 const ImVec4& color_active = Constants::Colors::BACK_BUTTON_COLOR_ACTIVE) {
144 ImGui::PushStyleColor(ImGuiCol_Button, color); // buttons color idle
145 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color_hover); // buttons color hover
146 ImGui::PushStyleColor(ImGuiCol_ButtonActive, color_active); // buttons color pressed
147 bool pressed_or_selected = ImGui::ArrowButtonEx(str_id, ImGuiDir_Left, size);
148 ImGui::PopStyleColor(3);
149
150 return pressed_or_selected;
151 }
152
154
160 static bool LoadingSpinner(const char *label, float radius, float thickness, const ImU32 color) {
161 ImGuiWindow *window = ImGui::GetCurrentWindow();
162 if (window->SkipItems)
163 return false;
164
165 ImGuiContext& g = *GImGui;
166 const ImGuiStyle& style = g.Style;
167 const ImGuiID id = window->GetID(label);
168
169 ImVec2 pos = window->DC.CursorPos;
170 ImVec2 size((radius) * 2, (radius + style.FramePadding.y) * 2);
171
172 const ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y));
173 ImGui::ItemSize(bb, style.FramePadding.y);
174 if (!ImGui::ItemAdd(bb, id))
175 return false;
176
177 // Render
178 window->DrawList->PathClear();
179
180 int num_segments = 30;
181 int start = (int) std::abs(sinf((float) g.Time * 1.8f) * (num_segments - 5));
182
183 const float a_min = IM_PI * 2.0f * ((float) start) / (float) num_segments;
184 const float a_max = IM_PI * 2.0f * ((float) num_segments - 3) / (float) num_segments;
185
186 const ImVec2 centre = ImVec2(pos.x + radius, pos.y + radius + style.FramePadding.y);
187
188 for (int i = 0; i < num_segments; i++) {
189 const float a = a_min + ((float) i / (float) num_segments) * (a_max - a_min);
190 window->DrawList->PathLineTo(ImVec2(centre.x + cosf(a + (float) g.Time * 8.0f) * radius,
191 centre.y + sinf(a + (float) g.Time * 8.0f) * radius));
192 }
193
194 window->DrawList->PathStroke(color, false, thickness);
195
196 return true;
197 }
198
204 static bool LoadingBar(const char *label, float value, const ImVec2& size_arg, const ImU32 bg_col, const ImU32 fg_col) {
205 ImGuiWindow *window = ImGui::GetCurrentWindow();
206 if (window->SkipItems)
207 return false;
208
209 ImGuiContext& g = *GImGui;
210 const ImGuiStyle& style = g.Style;
211 const ImGuiID id = window->GetID(label);
212
213 ImVec2 pos = window->DC.CursorPos;
214 ImVec2 size = size_arg;
215 size.x -= style.FramePadding.x * 2;
216
217 const ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y));
218 ImGui::ItemSize(bb, style.FramePadding.y);
219 if (!ImGui::ItemAdd(bb, id))
220 return false;
221
222 // Render
223 const float circleStart = size.x * 0.7f;
224 const float circleEnd = size.x;
225 const float circleWidth = circleEnd - circleStart;
226
227 window->DrawList->AddRectFilled(bb.Min, ImVec2(pos.x + circleStart, bb.Max.y), bg_col);
228 window->DrawList->AddRectFilled(bb.Min, ImVec2(pos.x + circleStart * value, bb.Max.y), fg_col);
229
230 const float t = static_cast<float>(g.Time);
231 const float r = size.y / 2;
232 const float speed = 1.5f;
233
234 const float a = speed * 0;
235 const float b = speed * 0.333f;
236 const float c = speed * 0.666f;
237
238 const float o1 = (circleWidth + r) * (t + a - speed * (int) ((t + a) / speed)) / speed;
239 const float o2 = (circleWidth + r) * (t + b - speed * (int) ((t + b) / speed)) / speed;
240 const float o3 = (circleWidth + r) * (t + c - speed * (int) ((t + c) / speed)) / speed;
241
242 window->DrawList->AddCircleFilled(ImVec2(pos.x + circleEnd - o1, bb.Min.y + r), r, bg_col);
243 window->DrawList->AddCircleFilled(ImVec2(pos.x + circleEnd - o2, bb.Min.y + r), r, bg_col);
244 window->DrawList->AddCircleFilled(ImVec2(pos.x + circleEnd - o3, bb.Min.y + r), r, bg_col);
245
246 return true;
247 }
248
250
257 static void LoadingDialog(const char *text, const ImVec2& spinner_position, const float spinner_radius, const float spinner_thickness, const ImVec4& spinner_color,
258 const float container_width = (float) Application::getInstance()->GetWindow()->GetWidth(),
259 const float container_height = (float) Application::getInstance()->GetWindow()->GetHeight()) {
260 static constexpr auto popup_id = "loadingDialog";
261
262 const auto& [win_w, win_h] = Application::getInstance()->GetWindow()->GetSize();
263 static ImFont* const& font_ubuntu_regular_20 = ResourceManager::getFont("Ubuntu-Regular-20");
264
265 ImGui::OpenPopup(popup_id, ImGuiPopupFlags_AnyPopup);
266 static constexpr const auto popup_window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground;
267 if (ImGui::BeginPopupModal(popup_id, nullptr, popup_window_flags)) {
268 ImGui::SetWindowSize(ImVec2(container_width, container_height)); // set spinner container's size same size as window (to centerize it)
269 ImGui::SetWindowPos(ImVec2(0.0f, 0.0f)); // top left
270
271 static const std::uint32_t COLOR = ImGui::GetColorU32(spinner_color); // 0xrrggbbaa
272 ImGui::SetCursorPos(spinner_position);
273 ImGuiWidgets::LoadingSpinner("##spinner", spinner_radius, spinner_thickness, COLOR);
274 ImGui::PushFont(font_ubuntu_regular_20); // text font
275 const auto text_size = ImGui::CalcTextSize(text);
276 ImGui::SetCursorPosX((win_w - text_size.x) / 2.0f);
277 ImGui::TextWrapped("%s",text);
278 ImGui::PopFont();
279 ImGui::EndPopup();
280 }
281 }
283
289 class Image {
290 public:
291 explicit Image(const char *file_name) {
292 // Load from file
293 byte *buffer = stbi_load(file_name, &m_width, &m_height, nullptr, 4);
294 ENIGMA_ASSERT(buffer, std::string("Failed to read image from ") + file_name);
295
296 // Create a OpenGL texture identifier
297 glAssert(glGenTextures(1, &m_id));
298 glAssert(glBindTexture(GL_TEXTURE_2D, m_id));
299
300 // Setup filtering parameters for display
301 glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
302 glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
303 glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); // This is required on WebGL for non power-of-two textures
304 glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // Same
305
306 // Upload pixels into texture
307#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
308 glAssert(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
309#endif
310 ENIGMA_INFO("Storing texture #{0} {1} to GPU Memory", m_id, SizeUtils::FriendlySize((std::size_t) m_width * (std::size_t) m_height * sizeof(byte)));
311
312 glAssert(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer));
313
314 // at this point the buffer is uploaded to the gpu, no need to keep in the memory
315 stbi_image_free(buffer);
316 }
317
319 ENIGMA_INFO("Deleting texture #{0} from GPU Memory", m_id);
320 glAssert(glDeleteTextures(1, &m_id));
321 }
322
323 void Draw(const ImVec2& position, const float width, const float height) {
324 ImGui::SetCursorPos(position);
325 ImGui::Image(m_id, ImVec2(width, height));
326 }
327
328 public:
329 [[nodiscard]] std::int32_t GetWidth() const noexcept { return m_width; };
330 [[nodiscard]] std::int32_t GetHeight() const noexcept { return m_height; };
331 [[nodiscard]] GLuint GetID() const noexcept { return m_id; };
332
333 private:
334 GLuint m_id{}; // OpenGL texture id
335 std::int32_t m_width{};
336 std::int32_t m_height{};
337 };
338};
339
341
342#endif // !ENIGMA_IMGUI_WIDGETS_H
#define ENIGMA_INFO(...)
Definition Logger.hpp:41
#define NS_ENIGMA_BEGIN
Enable/Disable Assertions.
Definition Macros.hpp:13
#define NS_ENIGMA_END
Definition Macros.hpp:14
#define ENIGMA_STATIC_CLASS(Class)
Makes a class static, which will prevent creating instances from it and only use it as Class::Func()....
Definition Macros.hpp:120
#define ENIGMA_ASSERT(x,...)
Asserts.
Definition Macros.hpp:37
#define glAssert(call)
glAssert to handle opengl calls errors (for opengl versions less than 4.3 with no error callback func...
static Application * getInstance() noexcept
const std::unique_ptr< Window > & GetWindow() const noexcept
Image(const char *file_name)
std::int32_t GetHeight() const noexcept
std::int32_t GetWidth() const noexcept
void Draw(const ImVec2 &position, const float width, const float height)
GLuint GetID() const noexcept
static bool LoadingBar(const char *label, float value, const ImVec2 &size_arg, const ImU32 bg_col, const ImU32 fg_col)
static bool InputTextMultiline(const char *label, std::string *str, const ImVec2 &size, ImGuiInputTextFlags flags=0, ImGuiInputTextCallback callback=nullptr, void *user_data=nullptr)
static bool InputText(const char *label, std::string *str, const float width, ImGuiInputTextFlags flags=0, ImGuiInputTextCallback callback=nullptr, void *user_data=nullptr)
static void LoadingDialog(const char *text, const ImVec2 &spinner_position, const float spinner_radius, const float spinner_thickness, const ImVec4 &spinner_color, const float container_width=(float) Application::getInstance() ->GetWindow() ->GetWidth(), const float container_height=(float) Application::getInstance() ->GetWindow() ->GetHeight())
static bool Button(const char *text, const ImVec2 &size=ImVec2(0.0f, 0.0f), const ImVec4 &color=Constants::Colors::BUTTON_COLOR, const ImVec4 &color_hover=Constants::Colors::BUTTON_COLOR_HOVER, const ImVec4 &color_active=Constants::Colors::BUTTON_COLOR_ACTIVE)
static bool InputTextWithHint(const char *label, const char *hint, std::string *str, const float width, ImGuiInputTextFlags flags=0, ImGuiInputTextCallback callback=nullptr, void *user_data=nullptr)
static bool BackButton(const char *str_id, const ImVec2 &size=ImVec2(0.0f, 0.0f), const ImVec4 &color=Constants::Colors::BACK_BUTTON_COLOR, const ImVec4 &color_hover=Constants::Colors::BACK_BUTTON_COLOR_HOVER, const ImVec4 &color_active=Constants::Colors::BACK_BUTTON_COLOR_ACTIVE)
static int InputTextCallback(ImGuiInputTextCallbackData *data)
static bool LoadingSpinner(const char *label, float radius, float thickness, const ImU32 color)
static std::string FriendlySize(const std::size_t bytes) noexcept
Definition SizeUtils.hpp:19