2 #ifndef ENIGMA_IMGUI_WIDGETS_H
3 #define ENIGMA_IMGUI_WIDGETS_H
11 #include <imgui_internal.h>
31 if (data->EventFlag ==
static_cast<decltype(data-
>EventFlag)>(ImGuiInputTextFlags_CallbackResize)) {
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();
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;
52 cb_user_data.
Str = str;
55 ImGui::PushItemWidth(width);
56 return ImGui::InputText(label, (
char *) str->c_str(), str->capacity() + 1, flags,
InputTextCallback, &cb_user_data);
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;
65 cb_user_data.
Str = str;
68 return ImGui::InputTextMultiline(label, (
char *) str->c_str(), str->capacity() + 1, size, flags,
InputTextCallback, &cb_user_data);
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;
77 cb_user_data.
Str = str;
80 ImGui::PushItemWidth(width);
81 return ImGui::InputTextWithHint(label, hint, (
char *) str->c_str(), str->capacity() + 1, flags,
InputTextCallback, &cb_user_data);
87 if (data->EventFlag ==
static_cast<decltype(data-
>EventFlag)>(ImGuiInputTextFlags_CallbackResize))
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();
97 static bool InputTextMultiline(
const char* label, std::string* str,
const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
99 flags |= ImGuiInputTextFlags_CallbackResize;
102 static bool InputText(
const char* label, std::string* str,
const float width, ImGuiInputTextFlags flags = 0)
104 ImGui::PushItemWidth(width);
105 flags |= ImGuiInputTextFlags_CallbackResize;
107 ImGui::PopItemWidth();
110 static bool InputTextWithHint(
const char* label,
const char* hint, std::string* str,
const float width, ImGuiInputTextFlags flags = 0)
112 ImGui::PushItemWidth(width);
113 flags |= ImGuiInputTextFlags_CallbackResize;
115 ImGui::PopItemWidth();
125 const ImVec2& size = ImVec2(0.0f, 0.0f),
129 ImGui::PushStyleColor(ImGuiCol_Button, color);
130 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color_hover);
131 ImGui::PushStyleColor(ImGuiCol_ButtonActive, color_active);
132 bool pressed_or_selected = ImGui::Button(text, size);
133 ImGui::PopStyleColor(3);
135 return pressed_or_selected;
140 const ImVec2& size = ImVec2(0.0f, 0.0f),
144 ImGui::PushStyleColor(ImGuiCol_Button, color);
145 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color_hover);
146 ImGui::PushStyleColor(ImGuiCol_ButtonActive, color_active);
147 bool pressed_or_selected = ImGui::ArrowButtonEx(str_id, ImGuiDir_Left, size);
148 ImGui::PopStyleColor(3);
150 return pressed_or_selected;
160 static bool LoadingSpinner(
const char *label,
float radius,
float thickness,
const ImU32 color) {
161 ImGuiWindow *window = ImGui::GetCurrentWindow();
162 if (window->SkipItems)
165 ImGuiContext& g = *GImGui;
166 const ImGuiStyle& style = g.Style;
167 const ImGuiID
id = window->GetID(label);
169 ImVec2 pos = window->DC.CursorPos;
170 ImVec2 size((radius) * 2, (radius + style.FramePadding.y) * 2);
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))
178 window->DrawList->PathClear();
180 int num_segments = 30;
181 int start = (int) std::abs(sinf((
float) g.Time * 1.8f) * (num_segments - 5));
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;
186 const ImVec2 centre = ImVec2(pos.x + radius, pos.y + radius + style.FramePadding.y);
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));
194 window->DrawList->PathStroke(color,
false, thickness);
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)
209 ImGuiContext& g = *GImGui;
210 const ImGuiStyle& style = g.Style;
211 const ImGuiID
id = window->GetID(label);
213 ImVec2 pos = window->DC.CursorPos;
214 ImVec2 size = size_arg;
215 size.x -= style.FramePadding.x * 2;
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))
223 const float circleStart = size.x * 0.7f;
224 const float circleEnd = size.x;
225 const float circleWidth = circleEnd - circleStart;
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);
230 const float t =
static_cast<float>(g.Time);
231 const float r = size.y / 2;
232 const float speed = 1.5f;
234 const float a = speed * 0;
235 const float b = speed * 0.333f;
236 const float c = speed * 0.666f;
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;
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);
257 static void LoadingDialog(
const char *text,
const ImVec2& spinner_position,
const float spinner_radius,
const float spinner_thickness,
const ImVec4& spinner_color,
260 static constexpr
auto popup_id =
"loadingDialog";
263 static ImFont*
const& font_ubuntu_regular_20 = ResourceManager::getFont(
"Ubuntu-Regular-20");
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));
269 ImGui::SetWindowPos(ImVec2(0.0f, 0.0f));
271 static const std::uint32_t COLOR = ImGui::GetColorU32(spinner_color);
272 ImGui::SetCursorPos(spinner_position);
274 ImGui::PushFont(font_ubuntu_regular_20);
275 const auto text_size = ImGui::CalcTextSize(text);
276 ImGui::SetCursorPosX((win_w - text_size.x) / 2.0f);
277 ImGui::TextWrapped(
"%s",text);
291 explicit Image(
const char *file_name) {
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);
298 glAssert(glBindTexture(GL_TEXTURE_2D, m_id));
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));
304 glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
307 #if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
308 glAssert(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
312 glAssert(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer));
315 stbi_image_free(buffer);
319 ENIGMA_INFO(
"Deleting texture #{0} from GPU Memory", m_id);
320 glAssert(glDeleteTextures(1, &m_id));
323 void Draw(
const ImVec2& position,
const float width,
const float height) {
324 ImGui::SetCursorPos(position);
325 ImGui::Image((
void *) (std::intptr_t) m_id, ImVec2(width, height));
329 std::int32_t
GetWidth() const noexcept {
return m_width; };
330 std::int32_t
GetHeight() const noexcept {
return m_height; };
331 GLuint
GetID() const noexcept {
return m_id; };
335 std::int32_t m_width{};
336 std::int32_t m_height{};
#define NS_ENIGMA_BEGIN
Enable/Disable Assertions.
#define ENIGMA_ASSERT(x,...)
Asserts.
#define glAssert(call)
glAssert to handle opengl calls errors (for opengl versions less than 4.3 with no error callback func...
const std::unique_ptr< Window > & GetWindow() const noexcept
static Application * getInstance() noexcept
static std::string FriendlySize(const std::size_t bytes) noexcept
static const ImVec4 BACK_BUTTON_COLOR_ACTIVE
static const ImVec4 BACK_BUTTON_COLOR_HOVER
static const ImVec4 BUTTON_COLOR_ACTIVE
static const ImVec4 BACK_BUTTON_COLOR
static const ImVec4 BUTTON_COLOR_HOVER
static const ImVec4 BUTTON_COLOR
void * ChainCallbackUserData
ImGuiInputTextCallback ChainCallback