7#include "LkEngine/Core/LObject/Enum.h"
8#include "LkEngine/Core/Delegate/Delegate.h"
13#include <imgui/imgui.h>
14#include <imgui/imgui_internal.h>
16namespace LkEngine::UI {
38 inline static constexpr float TablePaddingX = 17.0f;
43 inline static constexpr int LABEL_BUFSIZE = 72;
45 FORCEINLINE
bool DragFloat(
const char* Label,
47 float ValueSpeed = 1.0f,
48 float ValueMin = 0.0f,
49 float ValueMax = 0.0f,
50 const char* Format =
"%.3f",
51 ImGuiSliderFlags Flags = 0)
53 const int LabelSize = std::strlen(Label);
55 std::array<char, LABEL_BUFSIZE> LabelBuf{};
56 std::snprintf(LabelBuf.data(), LabelBuf.size(),
"##%s", Label);
60 if ((LabelSize > 0) && (Label[0] !=
'#'))
62 ImGui::TableSetColumnIndex(0);
63 UI::ShiftCursor(Slider::TablePaddingX, 7.0f);
66 UI::Draw::Underline(
false, 0.0f, 2.0f);
70 ImGui::TableSetColumnIndex(1);
71 UI::ShiftCursor(7.0f, 0.0f);
75 if ((LabelSize > 0) && (Label[0] !=
'#'))
83 const bool Dragged = ImGui::DragScalar(LabelBuf.data(), ImGuiDataType_Float, Value, ValueSpeed, &ValueMin, &ValueMax, Format, Flags);
87 ImGui::TableNextRow();
93 FORCEINLINE
bool DragFloat3(
const char* Label,
95 float VecSpeed = 1.0f,
98 const char* Format =
"%.3f",
99 ImGuiSliderFlags Flags = 0)
101 ImGuiTable* CurrentTable = ImGui::GetCurrentTable();
102 const bool IsInTable = (CurrentTable !=
nullptr);
105 ImGui::TableSetColumnIndex(0);
108 const bool Changed = ImGui::DragFloat3(Label, Vec, VecSpeed, VecMin, VecMax, Format, Flags);
109 DrawItemActivityOutline();
114 FORCEINLINE
bool DragFloat4(
const char* Label,
116 float VecSpeed = 1.0f,
119 const char* Format =
"%.3f",
120 ImGuiSliderFlags Flags = 0)
122 ImGuiTable* CurrentTable = ImGui::GetCurrentTable();
123 const bool IsInTable = (CurrentTable !=
nullptr);
126 ImGui::TableSetColumnIndex(0);
129 const bool Changed = ImGui::DragFloat4(Label, Vec, VecSpeed, VecMin, VecMax, Format, Flags);
130 DrawItemActivityOutline();
136 FORCEINLINE
bool SliderFloat3(
const char* Label,
140 const char* Format =
"%.3f",
141 ImGuiSliderFlags Flags = 0)
143 const bool Changed = ImGui::SliderFloat3(Label, Vec, VecMin, VecMax, Format, Flags);
144 DrawItemActivityOutline();
164 template<EVectorSemantic VecSemantic = EVectorSemantic::XYZW,
typename VectorType = glm::vec3>
167 const float ResetValue = 0.0f,
168 const float ValueSpeed = 0.10f,
169 const float ValueMin = 0.0f,
170 const float ValueMax = 0.0f,
171 const float ColumnWidth = 100.0f,
172 uint32_t RenderMultiSelectAxes = 0,
173 const char* Format =
"%.2f")
175 static constexpr const char* V1 = (VecSemantic == EVectorSemantic::XYZW) ?
"X" :
"R";
176 static constexpr const char* V2 = (VecSemantic == EVectorSemantic::XYZW) ?
"Y" :
"G";
177 static constexpr const char* V3 = (VecSemantic == EVectorSemantic::XYZW) ?
"Z" :
"B";
179 bool Modified =
false;
180 bool ManuallyEdited =
false;
182 ImGui::TableSetColumnIndex(0);
183 UI::ShiftCursor(17.0f, 7.0f);
185 ImGui::Text(Label.c_str());
186 UI::Draw::Underline(
false, 0.0f, 2.0f);
188 ImGui::TableSetColumnIndex(1);
189 UI::ShiftCursor(7.0f, 0.0f);
191 static constexpr float SpacingX = 8.0f;
192 UI::FScopedStyle ItemSpacing(ImGuiStyleVar_ItemSpacing, ImVec2(SpacingX, 0.0f));
199 ImGui::GetID((Label +
"Subwindow").c_str()),
200 ImVec2((ImGui::GetContentRegionAvail().x - SpacingX), ImGui::GetFrameHeightWithSpacing() + 8.0f),
201 ImGuiChildFlags_None,
202 ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse
206 static constexpr float FramePadding = 4.0f;
207 static constexpr float OutlineSpacing = 1.0f;
208 const float LineHeight = GImGui->Font->FontSize + FramePadding * 2.0f;
209 const ImVec2 ButtonSize = { LineHeight + 2.0f, LineHeight };
210 const float InputItemWidth = (ImGui::GetContentRegionAvail().x - SpacingX) / 3.0f - ButtonSize.x;
212 UI::ShiftCursor(0.0f, FramePadding);
214 auto DrawControl = [&](
const std::string& InLabel,
216 const ImVec4& InColorNormal,
217 const ImVec4& InColorHover,
218 const ImVec4& InColorPressed,
219 bool RenderMultiSelect)
222 UI::FScopedStyle ButtonFrame(ImGuiStyleVar_FramePadding, ImVec2(FramePadding, 0.0f));
225 ImGuiCol_Button, InColorNormal,
226 ImGuiCol_ButtonHovered, InColorHover,
227 ImGuiCol_ButtonActive, InColorPressed
230 if (ImGui::Button(InLabel.c_str(), ButtonSize))
232 InValue = ResetValue;
234 LK_CORE_DEBUG(
"Pressed Button: {}", InLabel.c_str());
238 ImGui::SameLine(0.0f, OutlineSpacing);
239 ImGui::SetNextItemWidth(InputItemWidth);
241 ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, RenderMultiSelect);
242 const ImGuiID InputID = ImGui::GetID((
"##" + InLabel).c_str());
243 const bool WasTempInputActive = ImGui::TempInputIsActive(InputID);
244 Modified |= ImGui::DragFloat((
"##" + InLabel).c_str(), &InValue, ValueSpeed, ValueMin, ValueMax, Format, 0);
246 if (ImGui::TempInputIsActive(InputID))
251 ImGui::PopItemFlag();
253 if (WasTempInputActive)
255 ManuallyEdited |= ImGui::IsItemDeactivatedAfterEdit();
259 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
265 ImVec4(0.80f, 0.10f, 0.15f, 1.0f),
266 ImVec4(0.90f, 0.20f, 0.20f, 1.0f),
267 ImVec4(0.80f, 0.10f, 0.15f, 1.0f),
268 (RenderMultiSelectAxes & EVectorAxis::X)
272 ImGui::SameLine(0.0f, OutlineSpacing);
276 ImVec4(0.20f, 0.70f, 0.20f, 1.0f),
277 ImVec4(0.30f, 0.80f, 0.30f, 1.0f),
278 ImVec4(0.20f, 0.70f, 0.20f, 1.0f),
279 (RenderMultiSelectAxes & EVectorAxis::Y)
283 ImGui::SameLine(0.0f, OutlineSpacing);
287 ImVec4(0.10f, 0.25f, 0.80f, 1.0f),
288 ImVec4(0.20f, 0.35f, 0.90f, 1.0f),
289 ImVec4(0.10f, 0.25f, 0.80f, 1.0f),
290 (RenderMultiSelectAxes & EVectorAxis::Z)
293 ImGui::PopStyleVar(1);
301 ImGui::TableNextRow();
314 template<EVectorSemantic VecSemantic = EVectorSemantic::XYZW,
typename VectorType = ImVec4>
317 const float ValueSpeed = 0.10f,
318 const float ResetValue = 0.0f,
319 const float ValueMin = 0.0f,
320 const float ValueMax = 0.0f,
321 const float ColumnWidth = 100.0f,
322 const char* Format =
"%.2f",
323 uint32_t RenderMultiSelectAxes = 0)
325 static_assert((VecSemantic == EVectorSemantic::XYZW) || (VecSemantic == EVectorSemantic::RGBA),
326 "Invalid type of vector semantic, only vectors with 4 elements are allowed");
327 static_assert(std::disjunction_v<
328 std::is_same<VectorType, ImVec4>,
329 std::is_same<VectorType, glm::vec4>>,
330 "Invalid vector type");
332 static constexpr const char* V1 = (VecSemantic == EVectorSemantic::XYZW) ?
"X" :
"R";
333 static constexpr const char* V2 = (VecSemantic == EVectorSemantic::XYZW) ?
"Y" :
"G";
334 static constexpr const char* V3 = (VecSemantic == EVectorSemantic::XYZW) ?
"Z" :
"B";
335 static constexpr const char* V4 = (VecSemantic == EVectorSemantic::XYZW) ?
"W" :
"A";
337 bool Modified =
false;
338 bool ManuallyEdited =
false;
340 ImGuiTable* CurrentTable = ImGui::GetCurrentTable();
341 const bool IsInTable = (CurrentTable !=
nullptr);
343 if (UIContext.bInGrid)
345 ImGui::TableSetColumnIndex(0);
346 if (!Label.empty() && Label.at(0) !=
'#')
348 ImGui::Text(Label.c_str());
354 ImGui::TableSetColumnIndex(0);
355 UI::ShiftCursor(Slider::TablePaddingX, 7.0f);
357 ImGui::Text(Label.c_str());
358 UI::Draw::Underline(
false, 0.0f, 2.0f);
360 ImGui::TableSetColumnIndex(1);
361 UI::ShiftCursor(7.0f, 0.0f);
365 if (!Label.empty() && Label.at(0) !=
'#')
367 ImGui::Text(Label.c_str());
374 static constexpr float SpacingX = 8.0f;
375 UI::FScopedStyle ItemSpacing(ImGuiStyleVar_ItemSpacing, ImVec2(SpacingX, 0.0f));
376 UI::FScopedStyle WindowPadding(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 2.0f));
381 static constexpr float FrameHeightPadding = 4.0f;
384 ImGui::GetID((Label +
"Subwindow").c_str()),
385 ImVec2((ImGui::GetContentRegionAvail().x - SpacingX), ImGui::GetFrameHeightWithSpacing() + FrameHeightPadding),
386 (UI::Debug::GridBorders == (
int)EBorder::None) ? ImGuiChildFlags_None : ImGuiChildFlags_Border,
387 ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse
391 static constexpr float FramePadding = 4.0f;
392 static constexpr float OutlineSpacing = 1.0f;
394 const float LineHeight = GImGui->Font->FontSize + FramePadding * 2.0f;
395 const ImVec2 ButtonSize = { LineHeight + 2.0f, LineHeight };
396 const float InputItemWidth = (ImGui::GetContentRegionAvail().x - SpacingX) / 4.0f - ButtonSize.x;
398 UI::ShiftCursor(0.0f, FramePadding);
400 auto DrawControl = [&](
const char* InLabel,
402 const VectorType& InColorNormal,
403 const VectorType& InColorHover,
404 const VectorType& InColorPressed,
405 bool RenderMultiSelect)
407 const std::string LabelStr = LK_FMT_LIB::format(
"##{}", InLabel);
409 static constexpr ImVec2 ButtonFrameSize(2.0f * FramePadding, 0.0f);
411 UI::FScopedStyle ButtonFramePadding(ImGuiStyleVar_FramePadding, ButtonFrameSize);
414 ImGuiCol_Button, InColorNormal,
415 ImGuiCol_ButtonHovered, InColorHover,
416 ImGuiCol_ButtonActive, InColorPressed
419 if (ImGui::Button(InLabel, ButtonSize))
421 InValue = ResetValue;
423 LK_CORE_DEBUG(
"Pressed slider button: {}", InLabel);
427 ImGui::SameLine(0.0f, OutlineSpacing);
428 ImGui::SetNextItemWidth(InputItemWidth);
430 ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, RenderMultiSelect);
431 const ImGuiID InputID = ImGui::GetID(LabelStr.c_str());
432 const bool WasTempInputActive = ImGui::TempInputIsActive(InputID);
433 Modified |= ImGui::DragFloat(LabelStr.c_str(), &InValue, ValueSpeed, ValueMin, ValueMax, Format, 0);
435 if (ImGui::TempInputIsActive(InputID))
440 ImGui::PopItemFlag();
442 if (WasTempInputActive)
444 ManuallyEdited |= ImGui::IsItemDeactivatedAfterEdit();
448 if (UIContext.bInGrid || IsInTable)
450 ImGui::TableSetColumnIndex(1);
453 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
459 ImVec4(0.80f, 0.10f, 0.15f, 1.0f),
460 ImVec4(0.90f, 0.20f, 0.20f, 1.0f),
461 ImVec4(0.80f, 0.10f, 0.15f, 1.0f),
462 (RenderMultiSelectAxes & EVectorAxis::X)
466 ImGui::SameLine(0.0f, OutlineSpacing);
470 ImVec4(0.20f, 0.70f, 0.20f, 1.0f),
471 ImVec4(0.30f, 0.80f, 0.30f, 1.0f),
472 ImVec4(0.20f, 0.70f, 0.20f, 1.0f),
473 (RenderMultiSelectAxes & EVectorAxis::Y)
477 ImGui::SameLine(0.0f, OutlineSpacing);
481 ImVec4(0.10f, 0.25f, 0.80f, 1.0f),
482 ImVec4(0.20f, 0.35f, 0.90f, 1.0f),
483 ImVec4(0.10f, 0.25f, 0.80f, 1.0f),
484 (RenderMultiSelectAxes & EVectorAxis::Z)
488 ImGui::SameLine(0.0f, OutlineSpacing);
492 VectorType(0.50f, 0.40f, 0.70f, 1.0f),
493 VectorType(0.55f, 0.40f, 0.60f, 1.0f),
494 VectorType(0.50f, 0.40f, 0.70f, 1.0f),
495 (RenderMultiSelectAxes & EVectorAxis::Z)
498 ImGui::PopStyleVar(1);
502 if (UIContext.bInGrid)
504 ImGui::TableNextRow();
508 ImGui::TableNextRow();
511 return (Modified || ManuallyEdited);
520 FORCEINLINE
bool Vec4Control(
const std::string& Label,
522 const float ValueSpeed = 0.10f,
523 const float ResetValue = 0.0f,
524 const float ValueMin = 0.0f,
525 const float ValueMax = 0.0f,
526 const float ColumnWidth = 100.0f,
527 const char* Format =
"%.2f",
528 uint32_t RenderMultiSelectAxes = 0)
530 bool Modified =
false;
531 bool ManuallyEdited =
false;
533 ImGuiTable* CurrentTable = ImGui::GetCurrentTable();
534 const bool IsInTable = (CurrentTable !=
nullptr);
536 if (UIContext.bInGrid)
538 ImGui::TableSetColumnIndex(0);
539 if (!Label.empty() && Label.at(0) !=
'#')
541 ImGui::Text(Label.c_str());
547 ImGui::TableSetColumnIndex(0);
548 UI::ShiftCursor(Slider::TablePaddingX, 7.0f);
550 ImGui::Text(Label.c_str());
551 UI::Draw::Underline(
false, 0.0f, 2.0f);
553 ImGui::TableSetColumnIndex(1);
554 UI::ShiftCursor(7.0f, 0.0f);
558 if (!Label.empty() && Label.at(0) !=
'#')
560 ImGui::Text(Label.c_str());
567 static constexpr float SpacingX = 8.0f;
568 UI::FScopedStyle ItemSpacing(ImGuiStyleVar_ItemSpacing, ImVec2(SpacingX, 0.0f));
569 UI::FScopedStyle Padding(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 2.0f));
571 UI::FScopedColor Padding(ImGuiCol_Border, IM_COL32(0, 0, 0, 0));
572 UI::FScopedColor Frame(ImGuiCol_FrameBg, IM_COL32(0, 0, 0, 0));
575 ImGui::GetID((Label +
"Subwindow").c_str()),
576 ImVec2((ImGui::GetContentRegionAvail().x - SpacingX), ImGui::GetFrameHeightWithSpacing() + 8.0f),
577 ImGuiChildFlags_None,
578 ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse
582 static constexpr float FramePadding = 4.0f;
583 static constexpr float OutlineSpacing = 1.0f;
584 const float LineHeight = GImGui->Font->FontSize + FramePadding * 2.0f;
585 const ImVec2 ButtonSize = { LineHeight + 2.0f, LineHeight };
586 const float InputItemWidth = (ImGui::GetContentRegionAvail().x - SpacingX) / 4.0f - ButtonSize.x;
588 UI::ShiftCursor(0.0f, FramePadding);
590 auto DrawControl = [&](
const std::string& InLabel,
592 const ImVec4& InColorNormal,
593 const ImVec4& InColorHover,
594 const ImVec4& InColorPressed,
595 bool RenderMultiSelect)
598 UI::FScopedStyle ButtonFrame(ImGuiStyleVar_FramePadding, ImVec2(FramePadding, 0.0f));
599 UI::FScopedStyle ButtonRounding(ImGuiStyleVar_FrameRounding, 1.0f);
600 UI::FScopedColorStack ButtonColours(
601 ImGuiCol_Button, InColorNormal,
602 ImGuiCol_ButtonHovered, InColorHover,
603 ImGuiCol_ButtonActive, InColorPressed
606 if (ImGui::Button(InLabel.c_str(), ButtonSize))
608 InValue = ResetValue;
610 LK_CORE_DEBUG(
"Pressed Button: {}", InLabel.c_str());
614 ImGui::SameLine(0.0f, OutlineSpacing);
615 ImGui::SetNextItemWidth(InputItemWidth);
617 ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, RenderMultiSelect);
618 const ImGuiID InputID = ImGui::GetID((
"##" + InLabel).c_str());
619 const bool WasTempInputActive = ImGui::TempInputIsActive(InputID);
620 Modified |= ImGui::DragFloat((
"##" + InLabel).c_str(), &InValue, ValueSpeed, ValueMin, ValueMax, Format, 0);
622 if (ImGui::TempInputIsActive(InputID))
627 ImGui::PopItemFlag();
629 if (WasTempInputActive)
631 ManuallyEdited |= ImGui::IsItemDeactivatedAfterEdit();
637 ImGui::TableSetColumnIndex(1);
645 ImVec4(0.80f, 0.10f, 0.15f, 1.0f),
646 ImVec4(0.90f, 0.20f, 0.20f, 1.0f),
647 ImVec4(0.80f, 0.10f, 0.15f, 1.0f),
648 (RenderMultiSelectAxes & EVectorAxis::X)
652 ImGui::SameLine(0.0f, OutlineSpacing);
656 ImVec4(0.20f, 0.70f, 0.20f, 1.0f),
657 ImVec4(0.30f, 0.80f, 0.30f, 1.0f),
658 ImVec4(0.20f, 0.70f, 0.20f, 1.0f),
659 (RenderMultiSelectAxes & EVectorAxis::Y)
663 ImGui::SameLine(0.0f, OutlineSpacing);
667 ImVec4(0.10f, 0.25f, 0.80f, 1.0f),
668 ImVec4(0.20f, 0.35f, 0.90f, 1.0f),
669 ImVec4(0.10f, 0.25f, 0.80f, 1.0f),
670 (RenderMultiSelectAxes & EVectorAxis::Z)
674 ImGui::SameLine(0.0f, OutlineSpacing);
678 ImVec4(0.50f, 0.40f, 0.70f, 1.0f),
679 ImVec4(0.55f, 0.40f, 0.60f, 1.0f),
680 ImVec4(0.50f, 0.40f, 0.70f, 1.0f),
681 (RenderMultiSelectAxes & EVectorAxis::W)
687 if (UIContext.bInGrid)
689 ImGui::TableNextRow();
693 ImGui::TableNextRow();
696 return (Modified || ManuallyEdited);
FORCEINLINE bool Vec4Control(const std::string &Label, VectorType &Values, const float ValueSpeed=0.10f, const float ResetValue=0.0f, const float ValueMin=0.0f, const float ValueMax=0.0f, const float ColumnWidth=100.0f, const char *Format="%.2f", uint32_t RenderMultiSelectAxes=0)
Definition Slider.h:315
FORCEINLINE bool Vec3Control(const std::string &Label, VectorType &Values, const float ResetValue=0.0f, const float ValueSpeed=0.10f, const float ValueMin=0.0f, const float ValueMax=0.0f, const float ColumnWidth=100.0f, uint32_t RenderMultiSelectAxes=0, const char *Format="%.2f")
Slider widget for three-component vectors.
Definition Slider.h:165
EVectorSemantic
Definition Slider.h:29