LkEngine 0.1.2
 
Loading...
Searching...
No Matches
Property.h
1#pragma once
2
5
6
7namespace LkEngine::UI {
8
9 FORCEINLINE bool Property(const char* Label, bool& Value, const char* HelpText = "")
10 {
11 bool Modified = false;
12
13 const bool IsCurrentlyInTable = InTable();
14 if (IsCurrentlyInTable)
15 {
16 ImGui::TableSetColumnIndex(0);
17 ShiftCursor(10.0f, 9.0f);
18 }
19
20 /* Skip rendering text for '#' and '##' identifier labels. */
21 if (Label && Label[0] != '#')
22 {
23 ImGui::Text(Label);
24 if (std::strlen(HelpText) != 0)
25 {
26 ImGui::SameLine();
27 HelpMarker(HelpText);
28 }
29 }
30
31 if (IsCurrentlyInTable)
32 {
33 ImGui::TableSetColumnIndex(1);
34 }
35 else
36 {
37 ImGui::SameLine();
38 }
39
40 ShiftCursorY(4.0f);
41
42 ImGui::PushItemWidth(-1);
43 Modified = ImGui::Checkbox(LK_FMT_LIB::format("##{0}", Label).c_str(), &Value);
44 ImGui::PopItemWidth();
45
46 if (IsCurrentlyInTable)
47 {
48 ImGui::TableNextRow();
49 }
50
51 return Modified;
52 }
53
54 FORCEINLINE bool Property(const char* Label,
55 float& Value,
56 float Delta = 0.10f,
57 float Min = 0.0f,
58 float Max = 0.0f,
59 const char* HelpText = "",
60 const char* HelpSymbol = "(?)")
61 {
62 const bool IsCurrentlyInTable = InTable();
63 if (IsCurrentlyInTable)
64 {
65 ImGui::TableSetColumnIndex(0);
66 ShiftCursor(10.0f, 9.0f);
67 }
68
69 /* Skip rendering text for '#' and '##' identifier labels. */
70 if (Label && Label[0] != '#')
71 {
72 ImGui::Text(Label);
73 if (std::strlen(HelpText) != 0)
74 {
75 ImGui::SameLine();
76 HelpMarker(HelpText, HelpSymbol);
77 }
78 }
79
80 if (IsCurrentlyInTable)
81 {
82 ImGui::TableSetColumnIndex(1);
83 ShiftCursorY(4.0f);
84 }
85
86 ImGui::PushItemWidth(-1);
87 const bool Modified = UI::Draw::DragFloat(LK_FMT_LIB::format("##{}", Label).c_str(), &Value, Delta, Min, Max);
88 ImGui::PopItemWidth();
89
90 if (IsCurrentlyInTable)
91 {
92 ImGui::TableNextRow();
93 }
94
95 return Modified;
96 }
97
101 FORCEINLINE bool Property(const char* Label,
102 glm::vec3& Value,
103 float Delta = 0.10f,
104 float Min = 0.0f,
105 float Max = 0.0f,
106 const char* HelpText = "")
107 {
108 ImGui::TableSetColumnIndex(0);
109
110 ShiftCursor(10.0f, 9.0f);
111 ImGui::Text(Label);
112
113 if (std::strlen(HelpText) != 0)
114 {
115 ImGui::SameLine();
116 HelpMarker(HelpText);
117 }
118
119 ImGui::TableSetColumnIndex(1);
120 ShiftCursorY(4.0f);
121
122 ImGui::PushItemWidth(-1);
123 const bool Modified = UI::Draw::DragFloat3(LK_FMT_LIB::format("##{0}", Label).c_str(), glm::value_ptr(Value), Delta, Min, Max);
124 ImGui::PopItemWidth();
125
126 ImGui::TableNextRow();
127
128 return Modified;
129 }
130
134 template<typename T>
135 FORCEINLINE bool PropertyLabel(const char* Label, const T Value, const char* HelpText = "")
136 {
137 if (!Label)
138 {
139 return false;
140 }
141
142 const ImVec2 LabelSize = ImGui::CalcTextSize(Label);
143 const ImVec2 ValueSize = ImGui::CalcTextSize(LK_FMT_LIB::format("{}", Value).c_str());
144
145 ImGuiContext& G = *GImGui;
146 ImGuiTable* CurrentTable = ImGui::GetCurrentTable();
147 const bool IsInTable = (CurrentTable != nullptr);
148
149 if (IsInTable)
150 {
151 ImGui::TableSetColumnIndex(0);
152
153 const float CenterPosX = (ImGui::GetContentRegionAvail().x * 0.50f);
154 ShiftCursorX(CenterPosX - (LabelSize.x * 0.50f));
155 ImGui::Text(Label);
156 }
157 else
158 {
159 ShiftCursor(10.0f, 0.0f);
160 ImGui::Text(Label);
161 }
162
163 if (std::strlen(HelpText) != 0)
164 {
165 ImGui::SameLine();
166 HelpMarker(HelpText);
167 }
168
169 if (IsInTable)
170 {
171 ImGui::TableSetColumnIndex(1);
172
173 /* Left align for StretchProp weights. */
174 if (CurrentTable->Flags & ImGuiTableFlags_SizingStretchProp)
175 {
176 ShiftCursorX(G.Style.FramePadding.x * 2.0f);
177 }
178 else
179 {
180 const float CenterPosX = (ImGui::GetContentRegionAvail().x * 0.50f);
181 ShiftCursorX(CenterPosX - (ValueSize.x * 0.50f));
182 }
183
184 ImGui::PushItemWidth(-1);
185 ImGui::Text("%s", LK_FMT_LIB::format("{}", Value).c_str());
186 ImGui::PopItemWidth();
187
188 ImGui::TableNextRow();
189 }
190 else
191 {
192 ShiftCursor(10.0f, 0.0f);
193 ImGui::PushItemWidth(-1);
194 ImGui::Text("%s", LK_FMT_LIB::format("{}", Value).c_str());
195 ImGui::PopItemWidth();
196 }
197
198 return false; /* Modified */
199 }
200
201 FORCEINLINE bool BeginCombo(const char* Label, const char* PreviewValue, ImGuiComboFlags Flags = ImGuiComboFlags_None)
202 {
203 const bool Opened = ImGui::BeginCombo(Label, PreviewValue, Flags);
204 DrawItemActivityOutline();
205
206 return Opened;
207 }
208
209 FORCEINLINE void EndCombo()
210 {
211 ImGui::EndCombo();
212 UIContext.NextItemData.ComboFlags = ImGuiComboFlags_None;
213 }
214
215 template<typename TEnum>
216 FORCEINLINE bool PropertyDropdown(const char* Label,
217 const char** Options,
218 const uint16_t ArrSize,
219 TEnum& Selected,
220 const char* HelpText = "")
221 {
222 using T = std::underlying_type_t<TEnum>;
223 const T SelectedIndex = static_cast<std::underlying_type_t<TEnum>>(Selected);
224
225 const char* CurrentOption = Options[SelectedIndex];
226 ShiftCursor(10.0f, 9.0f);
227 ImGui::Text(Label);
228
229 if (std::strlen(HelpText) != 0)
230 {
231 ImGui::SameLine();
232 HelpMarker(HelpText);
233 }
234
235 ImGui::NextColumn();
236 ShiftCursorY(4.0f);
237 ImGui::PushItemWidth(-1);
238
239 bool Modified = false;
240
241 const std::string ID = LK_FMT_LIB::format("##{}", Label);
242 if (UI::BeginCombo(ID.c_str(), CurrentOption))
243 {
244 for (uint16_t Idx = 0; Idx < ArrSize; Idx++)
245 {
246 const bool IsSelected = (CurrentOption == Options[Idx]);
247 if (ImGui::Selectable(Options[Idx], IsSelected))
248 {
249 CurrentOption = Options[Idx];
250 Selected = static_cast<TEnum>(Idx);
251 Modified = true;
252 }
253
254 if (IsSelected)
255 {
256 ImGui::SetItemDefaultFocus();
257 }
258 }
259
260 UI::EndCombo();
261 }
262
263 ImGui::PopItemWidth();
264 ImGui::NextColumn();
265 Draw::Underline();
266
267 return Modified;
268 }
269
270 template<std::size_t ArrSize, typename T, typename TEnum>
271 FORCEINLINE bool PropertyDropdown(const char* Label,
272 const std::array<T, ArrSize>& Options,
273 TEnum& Selected,
274 const char* HelpText = "",
275 const int ComboWidth = -1)
276 {
277 using ValueType = std::remove_cvref_t<T>;
278 static_assert((std::is_same_v<ValueType, const char*> || Core::IsPair<ValueType>), "Unsupported type");
279
280 using PrimitiveType = std::underlying_type_t<TEnum>;
281 const PrimitiveType SelectedIndex = static_cast<PrimitiveType>(Selected);
282
283 const char* CurrentOption = nullptr;
284 if constexpr (std::is_same_v<ValueType, const char*>)
285 {
286 CurrentOption = Options.at(SelectedIndex);
287 }
288 else if constexpr (Core::IsPair<ValueType>)
289 {
290 static_assert(Core::IsPairWithFirstArgConstChar<ValueType>, "The first pair argument (the label) is not const char*, which is required");
291 /* Select the label from the std::pair (first argument). */
292 CurrentOption = Options.at(SelectedIndex).first;
293 }
294
295 ImGuiContext& G = *GImGui;
296 const float NextItemWidth = G.NextItemData.Width;
297
298 ImGuiTable* CurrentTable = ImGui::GetCurrentTable();
299 const bool IsInTable = (CurrentTable != nullptr);
300
301 if (UIContext.bInGrid)
302 {
303 ImGui::TableSetColumnIndex(0);
304 ImGui::Text(Label);
305 if (std::strlen(HelpText) != 0)
306 {
307 ImGui::SameLine();
308 HelpMarker(HelpText);
309 }
310 }
311 else if (IsInTable)
312 {
313 ImGui::Text(Label);
314 if (std::strlen(HelpText) != 0)
315 {
316 ImGui::SameLine();
317 HelpMarker(HelpText);
318 }
319 }
320 else
321 {
322 ShiftCursor((2.0f + G.Style.FramePadding.x), (G.Style.FramePadding.y * 1.0f));
323 ImGui::Text(Label);
324 if (std::strlen(HelpText) != 0)
325 {
326 ImGui::SameLine();
327 HelpMarker(HelpText);
328 }
329 }
330
331 if (UIContext.bInGrid)
332 {
333 ImGui::TableSetColumnIndex(1);
334 }
335 else if (IsInTable)
336 {
337 }
338 else
339 {
340 ImGui::SameLine();
341 ShiftCursorY(-G.Style.FramePadding.y * 0.50f);
342 }
343
344 if (NextItemWidth > 0.0f)
345 {
346 ImGui::PushItemWidth(NextItemWidth);
347 }
348 else
349 {
350 ImGui::PushItemWidth(ComboWidth);
351 }
352
353 /* Dropdown modification flag. */
354 bool Modified = false;
355
356 ImGuiComboFlags ComboFlags = ImGuiComboFlags_None;
357 if (Options.size() > 30)
358 {
359 ComboFlags |= ImGuiComboFlags_HeightLarge;
360 }
361 ComboFlags |= UIContext.NextItemData.ComboFlags;
362
363 const std::string ID = LK_FMT_LIB::format("##{}", Label);
364 if (UI::BeginCombo(ID.c_str(), CurrentOption, ComboFlags))
365 {
366 for (uint16_t Idx = 0; Idx < ArrSize; Idx++)
367 {
368 const char* Option = nullptr;
369 if constexpr (std::is_same_v<ValueType, const char*>)
370 {
371 Option = Options[Idx];
372 }
373 else if constexpr (Core::IsPair<ValueType>)
374 {
375 Option = Options.at(Idx).first;
376 }
377
378 const bool IsSelected = (Option == CurrentOption);
379 if (ImGui::Selectable(Option, IsSelected))
380 {
381 CurrentOption = Options[Idx];
382 Selected = static_cast<TEnum>(Idx);
383 Modified = true;
384 }
385
386 if (IsSelected)
387 {
388 ImGui::SetItemDefaultFocus();
389 }
390 }
391
392 UI::EndCombo();
393 }
394
395 ImGui::PopItemWidth();
396
397 return Modified;
398 }
399
400 FORCEINLINE bool PropertyDropdown(const char* Label,
401 const char* const* Options,
402 const uint16_t ArrSize,
403 int32_t* Selected,
404 const char* HelpText = "",
405 const int ComboWidth = -1)
406 {
407 ImGuiContext& G = *GImGui;
408 const float NextItemWidth = G.NextItemData.Width;
409
410 ImGuiTable* CurrentTable = ImGui::GetCurrentTable();
411 const bool IsInTable = (CurrentTable != nullptr);
412
413 if (UIContext.bInGrid)
414 {
415 ImGui::TableSetColumnIndex(0);
416 }
417 else if (IsInTable)
418 {
419 }
420 else
421 {
422 ImGui::SameLine();
423 }
424
425 const char* CurrentOption = Options[*Selected];
426
427 /* Skip rendering text for '#' and '##' identifier labels. */
428 if (Label && Label[0] != '#')
429 {
430 ImGui::Text(Label);
431 if (std::strlen(HelpText) != 0)
432 {
433 ImGui::SameLine();
434 HelpMarker(HelpText);
435 }
436 }
437
438 if (UIContext.bInGrid)
439 {
440 ImGui::TableSetColumnIndex(1);
441 }
442 else if (IsInTable)
443 {
444 }
445 else
446 {
447 ImGui::SameLine(0.0f, 4.0f);
448 }
449
450 if (NextItemWidth > 0.0f)
451 {
452 ImGui::PushItemWidth(NextItemWidth);
453 }
454 else
455 {
456 ImGui::PushItemWidth(ComboWidth);
457 }
458
459 bool Modified = false;
460
461 ImGuiComboFlags ComboFlags = ImGuiComboFlags_None;
462 if (ArrSize > 30)
463 {
464 ComboFlags |= ImGuiComboFlags_HeightLarge;
465 }
466 ComboFlags |= UIContext.NextItemData.ComboFlags;
467
468 const std::string ID = LK_FMT_LIB::format("##{}", Label);
469 if (UI::BeginCombo(ID.c_str(), CurrentOption, ComboFlags))
470 {
471 for (uint16_t Idx = 0; Idx < ArrSize; Idx++)
472 {
473 const bool IsSelected = (CurrentOption == Options[Idx]);
474 if (ImGui::Selectable(Options[Idx], IsSelected))
475 {
476 CurrentOption = Options[Idx];
477 *Selected = Idx;
478 Modified = true;
479 }
480
481 if (IsSelected)
482 {
483 ImGui::SetItemDefaultFocus();
484 }
485 }
486
487 UI::EndCombo();
488 }
489
490 ImGui::PopItemWidth();
491
492 if (UIContext.bInGrid)
493 {
494 ImGui::TableNextRow();
495 }
496 if (IsInTable)
497 {
498 }
499 else
500 {
501 Draw::Underline();
502 }
503
504 return Modified;
505 }
506
507 template<std::size_t ArrSize, typename T>
508 FORCEINLINE bool PropertyDropdown(const char* Label,
509 const std::array<T, ArrSize>& Options,
510 int32_t* Selected,
511 const char* HelpText = "",
512 const int ComboWidth = -1)
513 {
514 using ValueType = std::remove_cvref_t<T>;
515 static_assert((std::is_same_v<ValueType, const char*> || Core::IsPair<ValueType>), "The type used in the array is not supported");
516
517 ImGuiContext& G = *GImGui;
518 const float NextItemWidth = G.NextItemData.Width;
519
520 ImGuiTable* CurrentTable = ImGui::GetCurrentTable();
521 const bool IsInTable = (CurrentTable != nullptr);
522
523 if (UIContext.bInGrid)
524 {
525 ImGui::TableSetColumnIndex(0);
526 UI::ShiftCursorX(Slider::TablePaddingX);
527 }
528 else if (IsInTable)
529 {
530 }
531 else
532 {
533 }
534
535 const char* CurrentOption = nullptr;
536 if constexpr (std::is_same_v<ValueType, const char*>)
537 {
538 CurrentOption = Options.at(*Selected);
539 }
540 else if constexpr (Core::IsPair<ValueType>)
541 {
542 static_assert(Core::IsPairWithFirstArgConstChar<ValueType>, "The first pair argument (the label) is not const char*, which is required");
543 /* Select the label from the std::pair (first argument). */
544 CurrentOption = Options.at(*Selected).first;
545 }
546
547 /* Skip rendering text for '#' and '##' identifier labels. */
548 if (Label && Label[0] != '#')
549 {
550 ImGui::Text(Label);
551 if (std::strlen(HelpText) != 0)
552 {
553 ImGui::SameLine();
554 HelpMarker(HelpText);
555 }
556 }
557
558 if (UIContext.bInGrid)
559 {
560 ImGui::TableSetColumnIndex(1);
561 }
562 else if (IsInTable)
563 {
564 }
565 else
566 {
567 ImGui::SameLine(0.0f, 4.0f);
568 }
569
570 if (NextItemWidth > 0.0f)
571 {
572 ImGui::PushItemWidth(NextItemWidth);
573 }
574 else
575 {
576 ImGui::PushItemWidth(ComboWidth);
577 }
578
579 bool Modified = false;
580
581 ImGuiComboFlags ComboFlags = ImGuiComboFlags_None;
582 if (Options.size() > 30)
583 {
584 ComboFlags |= ImGuiComboFlags_HeightLarge;
585 }
586 ComboFlags |= UIContext.NextItemData.ComboFlags;
587
588 const std::string ID = LK_FMT_LIB::format("##{}", Label);
589 if (UI::BeginCombo(ID.c_str(), CurrentOption, ComboFlags))
590 {
591 for (uint16_t Idx = 0; Idx < ArrSize; Idx++)
592 {
593 const char* Option = nullptr;
594 if constexpr (std::is_same_v<ValueType, const char*>)
595 {
596 Option = Options[Idx];
597 }
598 else if constexpr (Core::IsPair<ValueType>)
599 {
600 Option = Options.at(Idx).first;
601 }
602
603 const ImVec2 LabelSize = ImGui::CalcTextSize(Option);
604
605 const bool IsSelected = (Option == CurrentOption);
606 if (ImGui::Selectable(Option, IsSelected, ImGuiSelectableFlags_None, ImVec2(0.0f, LabelSize.y + G.Style.FramePadding.y * 1.50f)))
607 {
608 CurrentOption = Option;
609 *Selected = Idx;
610 Modified = true;
611 }
612
613 if (IsSelected)
614 {
615 ImGui::SetItemDefaultFocus();
616 }
617 }
618
619 UI::EndCombo();
620 }
621
622 ImGui::PopItemWidth();
623
624 if (UIContext.bInGrid)
625 {
626 ImGui::TableNextRow();
627 }
628 else if (IsInTable)
629 {
630 }
631 else
632 {
633 }
634
635 return Modified;
636 }
637
638}
Slider widgets.
Core UI.