Unravel Engine C++ Reference
Loading...
Searching...
No Matches
inspector_math.cpp
Go to the documentation of this file.
1#include "inspector_math.h"
2#include "entt/meta/meta.hpp"
3#include "imgui_widgets/tooltips.h"
6#include "inspectors.h"
7#include "entt/meta/resolve.hpp"
8#include "imgui/imgui.h"
9#include "math/gradient.h"
10#include <imgui/imgui_internal.h>
11#include <imgui_widgets/imgradient.h>
13
14namespace unravel
15{
16namespace
17{
18 namespace utils
19 {
20
21 template<typename T>
22 auto get_gradient_element_color(const typename math::gradient<T>::point_t& element,
23 float alphaMult = 1.0f) -> ImU32
24 {
25 return ImGui::ColorConvertFloat4ToU32({1.0f, 1.0f, 1.0f, alphaMult});
26 }
27
28 template<>
29 inline auto get_gradient_element_color<math::color>(const typename math::gradient<math::color>::point_t& element,
30 float alphaMult) -> ImU32
31 {
32 return ImGui::ColorConvertFloat4ToU32({element.element.value.x,
33 element.element.value.y,
34 element.element.value.z,
35 (element.element.value.w) * alphaMult});
36 }
37
38 template<typename T>
39 void draw_gradient_background(ImDrawList* drawList,
40 const math::gradient<T>& gradient,
41 ImVec2 barOriginPos,
42 ImVec2 size)
43 {
44
45 ImGui::Dummy(size);
46
47 ImGui::RenderFrame(barOriginPos, barOriginPos + size, ImGui::GetColorU32(ImGuiCol_FrameBg), true, ImGui::GetStyle().FrameRounding);
48
49 }
50
51 template<>
52 void draw_gradient_background<math::color>(ImDrawList* drawList,
53 const math::gradient<math::color>& gradient,
54 ImVec2 barOriginPos,
55 ImVec2 size)
56 {
57
58 ImGui::Dummy(size);
59
60 const float gridStep = size.y / 2.0f;
61
62 ImGui::RenderColorRectWithAlphaCheckerboard(drawList,
63 barOriginPos,
64 barOriginPos + size,
65 IM_COL32(50, 50, 50, 128), gridStep, ImVec2(0, 0));
66
67 }
68
69
70 template<typename T>
71 void draw_gradient_combined_element(ImDrawList* drawList,
72 const math::gradient<T>& gradient,
73 const T& default_value,
74 const std::vector<float>& xkeys,
75 const std::vector<size_t>& ind,
76 ImVec2 barOriginPos,
77 ImVec2 size)
78 {
79
80 }
81
82 template<>
83 inline void draw_gradient_combined_element<math::color>(ImDrawList* drawList,
84 const math::gradient<math::color>& gradient,
85 const math::color& deault_value,
86 const std::vector<float>& xkeys,
87 const std::vector<size_t>& ind,
88 ImVec2 barOriginPos, ImVec2 size)
89 {
90 if(ind.size() == 1)
91 {
92 auto i = ind.front();
93 auto c1 = deault_value;
94
95 if(gradient.is_valid())
96 {
97 c1 = gradient.sample(xkeys[i]);
98 }
99 const uint32_t colorAU32 = c1;
100
101 static constexpr auto rounding{1.f};
102 drawList->AddRectFilled(ImVec2(barOriginPos.x + xkeys[i] * size.x, barOriginPos.y),
103 ImVec2(barOriginPos.x + xkeys[i + 1] * size.x, barOriginPos.y + size.y),
104 colorAU32,
105 rounding);
106 }
107 else if(ind.size() == 2)
108 {
109
110 auto c1 = deault_value;
111 auto c2 = deault_value;
112
113 if(gradient.is_valid())
114 {
115 c1 = gradient.sample(xkeys[ind[0]]);
116 c2 = gradient.sample(xkeys[ind[1]]);
117 }
118
119 const uint32_t colorAU32 = c1;
120 const uint32_t colorBU32 = c2;
121
122 drawList->AddRectFilledMultiColor(
123 ImVec2(barOriginPos.x + xkeys[ind[0]] * size.x, barOriginPos.y),
124 ImVec2(barOriginPos.x + xkeys[ind[1]] * size.x, barOriginPos.y + size.y),
125 colorAU32,
126 colorBU32,
127 colorBU32,
128 colorAU32);
129
130 }
131 }
132
133
134 template<typename T>
135 void draw_gradient_combined_elements(ImDrawList* drawList,
136 const math::gradient<T>& gradient,
137 const T& default_value,
138 const std::vector<float>& xkeys,
139 ImVec2 barOriginPos,
140 ImVec2 size)
141 {
143 {
144 for(size_t i = 0; i < xkeys.size() - 1; i++)
145 {
146 std::vector<size_t> ind = {i, i+1};
147 draw_gradient_combined_element<T>(drawList,
148 gradient,
149 default_value,
150 xkeys,
151 ind,
152 barOriginPos,
153 size);
154
155 }
156 }
157 else
158 {
159 for(size_t i = 0; i < xkeys.size() - 1; i++)
160 {
161 std::vector<size_t> ind = {i};
162
163 draw_gradient_combined_element<T>(drawList,
164 gradient,
165 default_value,
166 xkeys,
167 ind,
168 barOriginPos,
169 size);
170
171 }
172 }
173 }
174
175 template<>
176 inline void draw_gradient_combined_elements<float>(ImDrawList* drawList,
177 const math::gradient<float>& gradient,
178 const float& deault_value,
179 const std::vector<float>& xkeys,
180 ImVec2 barOriginPos, ImVec2 size)
181 {
182 ImGui::SetCursorScreenPos(barOriginPos);
183
184 size_t sample_count = std::max(size_t(64), xkeys.size());
185 std::vector<float> ykeys;
186 ykeys.reserve(sample_count);
187 float min_y = std::numeric_limits<float>::max();
188 float max_y = std::numeric_limits<float>::min();
189
190 for(size_t i = 0; i < sample_count; i++)
191 {
192 float progress = static_cast<float>(i) / static_cast<float>(sample_count - 1);
193 float y = gradient.sample(progress);
194 ykeys.emplace_back(y);
195 min_y = std::min(min_y, y);
196 max_y = std::max(max_y, y);
197 }
198
199 ImGui::PlotLines("##", ykeys.data(), ykeys.size(), 0, "", min_y, max_y, ImVec2(size.x, size.y));
200
201 }
202
203 template<>
204 inline void draw_gradient_combined_elements<frange_t>(ImDrawList* drawList,
205 const math::gradient<frange_t>& gradient,
206 const frange_t& deault_value,
207 const std::vector<float>& xkeys,
208 ImVec2 barOriginPos, ImVec2 size)
209 {
210 ImGui::SetCursorScreenPos(barOriginPos);
211
212 size_t sample_count = std::max(size_t(64), xkeys.size());
213 // std::vector<float> ykeys;
214 // ykeys.reserve(sample_count);
215 // float min_y = std::numeric_limits<float>::max();
216 // float max_y = std::numeric_limits<float>::min();
217
218 // for(size_t i = 0; i < sample_count; i++)
219 // {
220 // float progress = static_cast<float>(i) / static_cast<float>(sample_count - 1);
221 // frange_t ry = gradient.sample(progress);
222 // float y = ry.min +(ry.max - ry.min) * 0.5f;
223 // ykeys.emplace_back(y);
224 // min_y = std::min(min_y, y);
225 // max_y = std::max(max_y, y);
226 // }
227
228 // ImGui::PlotLines("##", ykeys.data(), ykeys.size(), 0, "", min_y, max_y, ImVec2(size.x, size.y));
229 // ImGui::PlotHistogram("##", ykeys.data(), ykeys.size(), 0, "", min_y, max_y, ImVec2(size.x, size.y));
230
231 std::vector<ImGui::ImRange> ykeys;
232 ykeys.reserve(sample_count);
233 float min_y = std::numeric_limits<float>::max();
234 float max_y = std::numeric_limits<float>::min();
235
236 for(size_t i = 0; i < sample_count; i++)
237 {
238 float progress = static_cast<float>(i) / static_cast<float>(sample_count - 1);
239 frange_t ry = gradient.sample(progress);
240 ykeys.emplace_back(ImGui::ImRange{ry.min, ry.max});
241 min_y = std::min(min_y, ry.min);
242 max_y = std::max(max_y, ry.max);
243 }
244
245 ImGui::PlotEx(ImGuiPlotType_Histogram, "##", [](void* data, int idx) -> ImGui::ImRange {
246 auto& ykeys = *static_cast<std::vector<ImGui::ImRange>*>(data);
247 return ykeys[idx];
248 }, &ykeys, ykeys.size(), 0, "", min_y, max_y, ImVec2(size.x, size.y));
249 }
250
251
252 template<typename T>
253 bool draw_gradient_impl(const std::string& title, math::gradient<T>& gradient,
254 const std::function<bool(T&)>& edit_element,
255 const T& default_value)
256 {
257 struct TemporaryState
258 {
259 ImGuiID activeId{};
260 int selectedIndex = -1;
261 int draggingIndex = -1;
262 };
263
264 enum class DrawMarkerMode
265 {
266 Selected,
267 Unselected,
268 None,
269 };
270
271 auto DrawMarker = [](const ImVec2& pmin, const ImVec2& pmax, const ImU32& color, DrawMarkerMode mode)
272 {
273 auto drawList = ImGui::GetWindowDrawList();
274 const auto w = static_cast<int32_t>(pmax.x - pmin.x);
275 const auto h = static_cast<int32_t>(pmax.y - pmin.y);
276 const auto sign = std::signbit(static_cast<float>(h)) ? -1 : 1;
277
278 const auto margin = 2;
279 const auto marginh = margin * sign;
280
281 if(mode != DrawMarkerMode::None)
282 {
283 const auto outlineColor = mode == DrawMarkerMode::Selected
284 ? ImGui::ColorConvertFloat4ToU32({0.0f, 0.0f, 1.0f, 1.0f})
285 : ImGui::ColorConvertFloat4ToU32({0.2f, 0.2f, 0.2f, 1.0f});
286
287 drawList->AddTriangleFilled({pmin.x + w / 2, pmin.y},
288 {pmin.x + 0, pmin.y + h / 2},
289 {pmin.x + w, pmin.y + h / 2},
290 outlineColor);
291
292 drawList->AddRectFilled({pmin.x + 0, pmin.y + h / 2}, {pmin.x + w, pmin.y + h}, outlineColor);
293 }
294
295 drawList->AddTriangleFilled({pmin.x + w / 2, pmin.y + marginh},
296 {pmin.x + 0 + margin, pmin.y + h / 2},
297 {pmin.x + w - margin, pmin.y + h / 2},
298 color);
299
300 drawList->AddRectFilled({pmin.x + 0 + margin, pmin.y + h / 2}, {pmin.x + w - margin, pmin.y + h - marginh}, color);
301 };
302
303
304 auto SortMarkers = [&](typename math::gradient<T>::points_t& a,
305 int32_t& selectedIndex, int32_t& draggingIndex)
306 {
307 struct SortedMarker
308 {
309 size_t index;
310 typename math::gradient<T>::point_t marker;
311 };
312
313 std::vector<SortedMarker> sortedMarker;
314
315 for(size_t i = 0; i < a.size(); i++)
316 {
317 sortedMarker.emplace_back(SortedMarker{i, a[i]});
318 }
319
320 std::sort(sortedMarker.begin(),
321 sortedMarker.end(),
322 [](const SortedMarker& a, const SortedMarker& b)
323 {
324 return a.marker < b.marker;
325 });
326
327 for(size_t i = 0; i < a.size(); i++)
328 {
329 a[i] = sortedMarker[i].marker;
330 }
331
332 if(selectedIndex != -1)
333 {
334 for(size_t i = 0; i < a.size(); i++)
335 {
336 if(selectedIndex >= 0 && sortedMarker[i].index == size_t(selectedIndex))
337 {
338 selectedIndex = i;
339 break;
340 }
341 }
342 }
343
344 if(draggingIndex != -1)
345 {
346 for(size_t i = 0; i < a.size(); i++)
347 {
348 if(draggingIndex >= 0 && sortedMarker[i].index == size_t(draggingIndex))
349 {
350 draggingIndex = i;
351 break;
352 }
353 }
354 }
355 };
356
357
358
359 enum class MarkerDirection
360 {
361 ToUpper,
362 ToLower,
363 };
364
365 struct UpdateMarkerResult
366 {
367 bool isChanged;
368 bool isHovered;
369 };
370
371 auto UpdateMarker = [&](TemporaryState& temporaryState,
372 typename math::gradient<T>::points_t& points,
373 const char* keyStr,
374 ImVec2 originPos,
375 float width,
376 float markerWidth,
377 float markerHeight,
378 MarkerDirection markerDir) -> UpdateMarkerResult
379 {
380 UpdateMarkerResult ret;
381 ret.isChanged = false;
382 ret.isHovered = false;
383
384 float markerOffset = markerWidth * 0.5f;
385 for(size_t i = 0; i < points.size(); i++)
386 {
387 const auto x = (int)(points[i].progress * width);
388
389 DrawMarkerMode mode;
390 if(temporaryState.selectedIndex >= 0 && size_t(temporaryState.selectedIndex) == i)
391 {
392 mode = DrawMarkerMode::Selected;
393 }
394 else
395 {
396 mode = DrawMarkerMode::Unselected;
397 }
398
399 if(markerDir == MarkerDirection::ToLower)
400 {
401 DrawMarker({originPos.x + x - markerOffset, originPos.y + markerHeight},
402 {originPos.x + x + markerOffset, originPos.y + 0},
403 get_gradient_element_color<T>(points[i]),
404 mode);
405 }
406 else
407 {
408 DrawMarker({originPos.x + x - markerOffset, originPos.y + 0},
409 {originPos.x + x + markerOffset, originPos.y + markerHeight},
410 get_gradient_element_color<T>(points[i]),
411 mode);
412 }
413
414 float pick_padding = 4.0f;
415 ImGui::SetCursorScreenPos({originPos.x + x - (markerOffset + pick_padding), originPos.y});
416
417 ImGui::InvisibleButton((keyStr + std::to_string(i)).c_str(), {markerWidth + pick_padding * 2.0f, markerHeight + pick_padding * 2.0f});
418
419 ret.isHovered |= ImGui::IsItemHovered();
420
421 if(temporaryState.draggingIndex == -1 && ImGui::IsItemHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Left))
422 {
423 temporaryState.selectedIndex = i;
424 temporaryState.draggingIndex = i;
425 }
426
427 if(!ImGui::IsMouseDown(ImGuiMouseButton_Left))
428 {
429 temporaryState.draggingIndex = -1;
430 }
431
432 if(temporaryState.draggingIndex >= 0 && size_t(temporaryState.draggingIndex) == i && ImGui::IsMouseDragging(ImGuiMouseButton_Left, 6.0f))
433 {
434 const auto diff = ImGui::GetIO().MouseDelta.x / width;
435 points[i].progress += diff;
436 points[i].progress = std::max(std::min(points[i].progress, 1.0f), 0.0f);
437
438 ret.isChanged |= diff != 0.0f;
439 }
440 }
441
442 return ret;
443 };
444
445
446 bool changed = false;
447
448 static TemporaryState temporaryState{};
449 auto widgetId = ImGui::GetID(title.c_str());
450 ImGui::PushID(widgetId);
451 TemporaryState tempState{};
452 tempState.activeId = widgetId;
453
454 if(widgetId == temporaryState.activeId)
455 {
456 tempState = temporaryState;
457 }
458
459 auto drawList = ImGui::GetWindowDrawList();
460
461 const float width = int(ImGui::CalcItemWidth());
462 const auto barHeight = ImGui::GetFrameHeight() * 1.5f;
463 const auto markerWidth = 16;
464 const auto markerHeight = 16;
465
466 const auto barOriginPos = ImGui::GetCursorScreenPos();
467 draw_gradient_background(drawList, gradient, barOriginPos, {width, barHeight});
468
469 {
470 std::vector<float> xkeys;
471 xkeys.reserve(16);
472
473 const auto& points = gradient.get_points();
474 for(size_t i = 0; i < points.size(); i++)
475 {
476 xkeys.emplace_back(points[i].progress);
477 }
478
479 xkeys.emplace_back(0.0f);
480 xkeys.emplace_back(1.0f);
481
482 std::sort(xkeys.begin(), xkeys.end());
483 auto result = std::unique(xkeys.begin(), xkeys.end());
484 xkeys.erase(result, xkeys.end());
485
486
487 draw_gradient_combined_elements<T>(drawList,
488 gradient,
489 default_value,
490 xkeys,
491 barOriginPos,
492 ImVec2(width, barHeight));
493
494 }
495
496 {
497 auto originPosBelowBar = ImGui::GetCursorScreenPos();
498
499 auto points = gradient.get_points();
500 const auto resultColor = UpdateMarker(tempState,
501 points,
502 "c",
503 originPosBelowBar,
504 width,
505 markerWidth,
506 markerHeight,
507 MarkerDirection::ToUpper);
508
509 changed |= resultColor.isChanged;
510
511 if(tempState.draggingIndex != -1)
512 {
513 SortMarkers(points, tempState.selectedIndex, tempState.draggingIndex);
514 }
515
516
517 if(resultColor.isChanged)
518 {
519 gradient.set_points(points);
520 }
521
522
523 ImGui::SetCursorScreenPos(barOriginPos);
524
525 ImGui::InvisibleButton("MarkerArea", {width, static_cast<float>(markerHeight * 1.5f + barHeight)});
526
527 if(ImGui::IsItemHovered())
528 {
529 const float x = (ImGui::GetIO().MousePos.x - (barOriginPos.x));
530 const float xn = x / width;
531
532 auto element = typename math::gradient<T>::point_t{xn, default_value};
533
534 if(gradient.is_valid())
535 {
536 element.element = gradient.sample(xn);
537 }
538
539 if(!resultColor.isHovered)
540 {
541 auto c = get_gradient_element_color<T>(element, 0.5f);
542 DrawMarker({originPosBelowBar.x + x - markerWidth * 0.5f, originPosBelowBar.y + 0},
543 {originPosBelowBar.x + x + markerWidth * 0.5f, originPosBelowBar.y + markerHeight},
544 c,
545 DrawMarkerMode::None);
546 }
547
548 if(ImGui::IsMouseClicked(ImGuiMouseButton_Left))
549 {
550 auto index = gradient.add_point(element.element, xn);
551 changed |= index >= 0;
552 tempState.selectedIndex = index;
553 }
554 }
555 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
556 if(ImGui::Button(ICON_MDI_WINDOW_CLOSE))
557 {
558 gradient.set_points({});
559 changed = true;
560 }
561 ImGui::SetItemTooltipEx("%s", "Clear the gradient's elements");
562 }
563
564 int indexToRemove = -1;
565 auto points = gradient.get_points();
566 for(size_t i = 0; i < points.size(); ++i)
567 {
568 ImGui::PushID(i);
569 ImGui::BeginGroup();
570 if(ImGui::Button(ICON_MDI_WINDOW_CLOSE))
571 {
572 indexToRemove = i;
573
574 }
575 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
576
577 changed |= edit_element(points[i].element);
578
579 ImGui::EndGroup();
580 if(tempState.selectedIndex >= 0 && i == size_t(tempState.selectedIndex))
581 {
582 ImGui::SetItemFocusFrame();
583 }
584
585 ImGui::PopID();
586 }
587
588 if(changed)
589 {
590 gradient.set_points(points);
591 }
592
593
594 if(indexToRemove != -1)
595 {
596 gradient.remove_point(indexToRemove);
597 tempState = {};
598 changed = true;
599 }
600
601 if(tempState.selectedIndex != -1)
602 {
603 temporaryState = tempState;
604 }
605
606 ImGui::PopID();
607
608 return changed;
609 }
610
611 inline void draw_title(const std::string& title)
612 {
613 if(title.empty())
614 {
615 return;
616 }
617 ImGui::TextUnformatted(title.c_str());
618 }
619
620 template<typename T>
621 auto draw_interpolation_mode(math::gradient<T>& gradient) -> bool
622 {
623 ImGui::PushID("InterpolationMode");
624 size_t interpolation_index = size_t(gradient.get_interpolation_mode());
625 std::vector<std::string> interpolation_modes = {"Linear", "Constant"};
626
627 bool changed = false;
628
629 if(ImGui::BeginCombo("##", interpolation_modes[interpolation_index].c_str()))
630 {
631 for(size_t i = 0; i < interpolation_modes.size(); i++)
632 {
633 if(ImGui::Selectable(interpolation_modes[i].c_str()))
634 {
635 interpolation_index = i;
636 changed = true;
637 }
638 }
639 ImGui::EndCombo();
640 }
641
642
643 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
644 ImGui::TextUnformatted("Interpolation");
645
646 if(changed)
647 {
648 gradient.set_interpolation_mode(math::gradient_interpolation_mode_t(interpolation_index));
649 }
650 ImGui::PopID();
651 return changed;
652 }
653
654 template<typename T>
655 bool draw_gradient(const std::string& title, math::gradient<T>& gradient,
656 const std::function<bool(T&)>& edit_element,
657 const T& default_value)
658 {
659 bool changed = false;
660
661 ImGui::PushID(title.c_str());
662 ImGui::BeginGroup();
663 changed |= draw_interpolation_mode(gradient);
664 changed |= draw_gradient_impl<T>(title, gradient, edit_element, default_value);
665 ImGui::EndGroup();
666 ImGui::PopID();
667
668 return changed;
669 }
670
671} // namespace utils
672
673
674float DRAG_SPEED = 0.01f;
675
676auto quat_to_vec4(math::quat q) -> math::vec4
677{
678 math::vec4 v;
679 v.x = q.x;
680 v.y = q.y;
681 v.z = q.z;
682 v.w = q.w;
683 return v;
684}
685auto vec4_to_quat(math::vec4 v) -> math::quat
686{
687 math::quat q;
688 q.x = v.x;
689 q.y = v.y;
690 q.z = v.z;
691 q.w = v.w;
692 return q;
693}
694
695bool DragFloat2(math::vec2& data, const var_info& info, std::array<const char*, 2> formats = {{"X:%.2f", "Y:%.2f"}})
696{
697 bool result = ImGui::DragMultiFormatScalarN("##",
698 ImGuiDataType_Float,
699 math::value_ptr(data),
700 2,
701 DRAG_SPEED,
702 nullptr,
703 nullptr,
704 formats.data());
705 ImGui::ActiveItemWrapMousePos();
706
707 return result;
708}
709
710bool DragFloat3(math::vec3& data,
711 const var_info& info,
712 std::array<const char*, 3> formats = {{"X:%.3f", "Y:%.3f", "Z:%.3f"}})
713{
714 bool result = ImGui::DragMultiFormatScalarN("##",
715 ImGuiDataType_Float,
716 math::value_ptr(data),
717 3,
718 DRAG_SPEED,
719 nullptr,
720 nullptr,
721 formats.data());
722 ImGui::ActiveItemWrapMousePos();
723
724 return result;
725}
726
727bool DragFloat4(math::vec4& data,
728 const var_info& info,
729 std::array<const char*, 4> formats = {{"X:%.3f", "Y:%.3f", "Z:%.3f", "W:%.3f"}})
730{
731 bool result = ImGui::DragMultiFormatScalarN("##",
732 ImGuiDataType_Float,
733 math::value_ptr(data),
734 4,
735 DRAG_SPEED,
736 nullptr,
737 nullptr,
738 formats.data());
739 ImGui::ActiveItemWrapMousePos();
740
741 return result;
742}
743
744bool DragVec2(math::vec2& data, const var_info& info, const math::vec2* reset = nullptr, const char* format = "%.3f")
745{
746 bool result = ImGui::DragVecN("##",
747 ImGuiDataType_Float,
748 math::value_ptr(data),
749 data.length(),
750 DRAG_SPEED,
751 nullptr,
752 nullptr,
753 reset ? math::value_ptr(*reset) : nullptr,
754 format);
755 ImGui::ActiveItemWrapMousePos();
756
757 return result;
758}
759
760bool DragVec3(math::vec3& data, const var_info& info, const math::vec3* reset = nullptr, const char* format = "%.3f")
761{
762 bool result = ImGui::DragVecN("##",
763 ImGuiDataType_Float,
764 math::value_ptr(data),
765 data.length(),
766 DRAG_SPEED,
767 nullptr,
768 nullptr,
769 reset ? math::value_ptr(*reset) : nullptr,
770 format);
771
772 ImGui::ActiveItemWrapMousePos();
773
774 return result;
775}
776
777bool DragVec4(math::vec4& data, const var_info& info, const math::vec4* reset = nullptr, const char* format = "%.3f")
778{
779 bool result = ImGui::DragVecN("##",
780 ImGuiDataType_Float,
781 math::value_ptr(data),
782 data.length(),
783 DRAG_SPEED,
784 nullptr,
785 nullptr,
786 reset ? math::value_ptr(*reset) : nullptr,
787 format);
788
789 ImGui::ActiveItemWrapMousePos();
790
791 return result;
792}
793
794} // namespace
795
797 entt::meta_any& var,
798 const meta_any_proxy& var_proxy,
799 const var_info& info,
800 const entt::meta_custom& custom) -> inspect_result
801{
802 auto& data = var.cast<math::bvec2&>();
803 inspect_result result{};
804
805 enum bflags
806 {
807 none = 0,
808 x = 1 << 0,
809 y = 1 << 1,
810 };
811
812 int flags = 0;
813 flags |= data.x ? bflags::x : 0;
814 flags |= data.y ? bflags::y : 0;
815
816 bool mod = false;
817 ImGui::BeginGroup();
818 mod |= ImGui::CheckboxFlags("X", &flags, bflags::x);
819 ImGui::SameLine();
820 mod |= ImGui::CheckboxFlags("Y", &flags, bflags::y);
821 ImGui::EndGroup();
822 if(mod)
823 {
824 data.x = flags & bflags::x;
825 data.y = flags & bflags::y;
826 result.changed = true;
827 }
828 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
829
830 return result;
831}
832
834 entt::meta_any& var,
835 const meta_any_proxy& var_proxy,
836 const var_info& info,
837 const entt::meta_custom& custom) -> inspect_result
838{
839 auto& data = var.cast<math::bvec3&>();
840 inspect_result result{};
841
842 enum bflags
843 {
844 none = 0,
845 x = 1 << 0,
846 y = 1 << 1,
847 z = 1 << 2,
848 };
849
850 int flags = 0;
851 flags |= data.x ? bflags::x : 0;
852 flags |= data.y ? bflags::y : 0;
853 flags |= data.z ? bflags::z : 0;
854
855 bool mod = false;
856 ImGui::BeginGroup();
857 mod |= ImGui::CheckboxFlags("X", &flags, bflags::x);
858 ImGui::SameLine();
859 mod |= ImGui::CheckboxFlags("Y", &flags, bflags::y);
860 ImGui::SameLine();
861 mod |= ImGui::CheckboxFlags("Z", &flags, bflags::z);
862 ImGui::EndGroup();
863
864 if(mod)
865 {
866 data.x = flags & bflags::x;
867 data.y = flags & bflags::y;
868 data.z = flags & bflags::z;
869 result.changed = true;
870 }
871 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
872
873 return result;
874}
875
877 entt::meta_any& var,
878 const meta_any_proxy& var_proxy,
879 const var_info& info,
880 const entt::meta_custom& custom) -> inspect_result
881{
882 auto& data = var.cast<math::bvec4&>();
883 inspect_result result{};
884
885 enum bflags
886 {
887 none = 0,
888 x = 1 << 0,
889 y = 1 << 1,
890 z = 1 << 2,
891 w = 1 << 3,
892 };
893
894 int flags = 0;
895 flags |= data.x ? bflags::x : 0;
896 flags |= data.y ? bflags::y : 0;
897 flags |= data.z ? bflags::z : 0;
898 flags |= data.w ? bflags::w : 0;
899
900 bool mod = false;
901 ImGui::BeginGroup();
902 mod |= ImGui::CheckboxFlags("X", &flags, bflags::x);
903 ImGui::SameLine();
904 mod |= ImGui::CheckboxFlags("Y", &flags, bflags::y);
905 ImGui::SameLine();
906 mod |= ImGui::CheckboxFlags("Z", &flags, bflags::z);
907 ImGui::SameLine();
908 mod |= ImGui::CheckboxFlags("W", &flags, bflags::w);
909 ImGui::EndGroup();
910
911 if(mod)
912 {
913 data.x = flags & bflags::x;
914 data.y = flags & bflags::y;
915 data.z = flags & bflags::z;
916 data.w = flags & bflags::w;
917
918 result.changed = true;
919 }
920 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
921
922 return result;
923}
924
926 entt::meta_any& var,
927 const meta_any_proxy& var_proxy,
928 const var_info& info,
929 const entt::meta_custom& custom) -> inspect_result
930{
931 auto& data = var.cast<math::vec2&>();
932 inspect_result result{};
933
934 static const auto reset = math::zero<math::vec2>();
935
936 if(DragVec2(data, info, &reset))
937 {
938 result.changed = true;
939 }
940 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
941
942 return result;
943}
944
946 entt::meta_any& var,
947 const meta_any_proxy& var_proxy,
948 const var_info& info,
949 const entt::meta_custom& custom) -> inspect_result
950{
951 auto& data = var.cast<math::vec3&>();
952 inspect_result result{};
953
954 static const auto reset = math::zero<math::vec3>();
955
956 if(DragVec3(data, info, &reset))
957 {
958 result.changed = true;
959 }
960 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
961
962 return result;
963}
964
966 entt::meta_any& var,
967 const meta_any_proxy& var_proxy,
968 const var_info& info,
969 const entt::meta_custom& custom) -> inspect_result
970{
971 auto& data = var.cast<math::vec4&>();
972 inspect_result result{};
973
974 static const auto reset = math::zero<math::vec4>();
975
976 if(DragVec4(data, info, &reset))
977 {
978 result.changed = true;
979 }
980 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
981
982 return result;
983}
984
986 entt::meta_any& var,
987 const meta_any_proxy& var_proxy,
988 const var_info& info,
989 const entt::meta_custom& custom) -> inspect_result
990{
991 auto& data = var.cast<math::color&>();
992 inspect_result result{};
993
994 if(ImGui::ColorEdit4("##",
995 math::value_ptr(data.value),
996 ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_AlphaPreviewHalf))
997 {
998 result.changed = true;
999 }
1000
1001 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
1002
1003 ImGui::DrawItemActivityOutline();
1004
1005 return result;
1006}
1007
1009 entt::meta_any& var,
1010 const meta_any_proxy& var_proxy,
1011 const var_info& info,
1012 const entt::meta_custom& custom) -> inspect_result
1013{
1014 auto& data = var.cast<math::gradient<float>&>();
1015 inspect_result result{};
1016
1017
1018 std::function<bool(float&)> draw_element = [&](float& c)
1019 {
1021 entt::meta_any var_proxy_any = entt::forward_as_meta(c);
1022 auto var_proxy_proxy = make_proxy(var_proxy_any);
1023 return inspector.inspect(ctx, var_proxy_any, var_proxy_proxy, info, custom).changed;
1024 };
1025
1026 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.7f);
1027
1028 if(utils::draw_gradient("##", data, draw_element, 0.0f))
1029 {
1030 result.changed = true;
1031
1032 }
1033 ImGui::PopItemWidth();
1034
1035 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
1036
1037 ImGui::DrawItemActivityOutline();
1038
1039 return result;
1040}
1041
1043 entt::meta_any& var,
1044 const meta_any_proxy& var_proxy,
1045 const var_info& info,
1046 const entt::meta_custom& custom) -> inspect_result
1047{
1048 auto& data = var.cast<math::gradient<math::color>&>();
1049 inspect_result result{};
1050
1051
1052 std::function<bool(math::color&)> draw_element = [](math::color& c)
1053 {
1054 ImColor color(c.value.x, c.value.y, c.value.z, c.value.w);
1055 if(ImGui::ColorEdit4("##", &color.Value.x,
1056 ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_AlphaPreviewHalf))
1057 {
1058 c.value.x = color.Value.x;
1059 c.value.y = color.Value.y;
1060 c.value.z = color.Value.z;
1061 c.value.w = color.Value.w;
1062 return true;
1063 }
1064 return false;
1065 };
1066
1067 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.7f);
1068
1069 if(utils::draw_gradient("##", data, draw_element, math::color::white()))
1070 {
1071 result.changed = true;
1072
1073 }
1074 ImGui::PopItemWidth();
1075
1076 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
1077
1078 ImGui::DrawItemActivityOutline();
1079
1080 return result;
1081}
1082
1084 entt::meta_any& var,
1085 const meta_any_proxy& var_proxy,
1086 const var_info& info,
1087 const entt::meta_custom& custom) -> inspect_result
1088{
1089 auto& data = var.cast<math::gradient<frange_t>&>();
1090 inspect_result result{};
1091
1092
1093 std::function<bool(frange_t&)> draw_element = [&](frange_t& c) -> bool
1094 {
1096 entt::meta_any var_proxy_any = entt::forward_as_meta(c);
1097 auto var_proxy_proxy = make_proxy(var_proxy_any);
1098 return inspector.inspect(ctx, var_proxy_any, var_proxy_proxy, info, custom).changed;
1099 };
1100
1101 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.7f);
1102
1103 if(utils::draw_gradient("##", data, draw_element, frange_t(0.0f, 1.0f)))
1104 {
1105 result.changed = true;
1106
1107 }
1108 ImGui::PopItemWidth();
1109
1110 result.edit_finished = ImGui::IsItemDeactivatedAfterEdit();
1111
1112 ImGui::DrawItemActivityOutline();
1113
1114 return result;
1115}
1116
1118 entt::meta_any& var,
1119 const meta_any_proxy& var_proxy,
1120 const var_info& info,
1121 const entt::meta_custom& custom) -> inspect_result
1122{
1123 auto& data = var.cast<math::quat&>();
1124 inspect_result result{};
1125
1126 auto val = math::degrees(math::eulerAngles(data));
1127
1128 static const auto reset = math::zero<math::vec3>();
1129
1130 // auto val = quat_to_vec4(data);
1131 if(DragVec3(val, info, &reset, "%.2f°"))
1132 {
1133 // data = vec4_to_quat(val);
1134 data = math::quat(math::radians(val));
1135 result.changed = true;
1136 }
1137 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1138
1139 ImGui::DrawItemActivityOutline();
1140
1141 return result;
1142}
1143
1145 entt::meta_any& var,
1146 const meta_any_proxy& var_proxy,
1147 const var_info& info,
1148 const entt::meta_custom& custom) -> inspect_result
1149{
1150 auto& data = var.cast<math::bbox&>();
1151 inspect_result result{};
1152
1153
1154 static const auto reset = math::zero<math::vec3>();
1155
1156 ImGui::BeginGroup();
1157 ImGui::PushID("Min");
1158 if(DragVec3(data.min, info, &reset, "Min %.2f"))
1159 {
1160 result.changed = true;
1161 }
1162 ImGui::PopID();
1163 ImGui::PushID("Max");
1164 if(DragVec3(data.max, info, &reset, "Max %.2f"))
1165 {
1166 result.changed = true;
1167 }
1168 ImGui::PopID();
1169 ImGui::EndGroup();
1170 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1171
1172 ImGui::DrawItemActivityOutline();
1173
1174 return result;
1175}
1176
1177
1178void inspector_transform::before_inspect(const entt::meta_data& prop)
1179{
1180 layout_ = std::make_unique<property_layout>();
1181 layout_->set_data(prop, false);
1182 open_ = layout_->push_tree_layout(ImGuiTreeNodeFlags_SpanFullWidth);
1183}
1184
1186 entt::meta_any& var,
1187 const meta_any_proxy& var_proxy,
1188 const var_info& info,
1189 const entt::meta_custom& custom) -> inspect_result
1190{
1191 if(!open_)
1192 {
1193 return {};
1194 }
1195 inspect_result result{};
1196
1197 auto& data = var.cast<math::transform&>();
1198 auto position = data.get_translation();
1199 auto rotation = data.get_rotation();
1200 auto scale = data.get_scale();
1201 auto skew = data.get_skew();
1202 // auto perspective = data.get_perspective();
1203
1204 auto type = entt::resolve<math::transform>();
1205
1206 static math::vec3 euler_angles(0.0f, 0.0f, 0.0f);
1207
1208 math::quat old_quat(math::radians(euler_angles));
1209
1210 float dot_product = math::dot(old_quat, rotation);
1211 bool equal = (dot_product > (1.0f - math::epsilon<float>()));
1212 if(!equal && (!ImGui::IsMouseDragging(ImGuiMouseButton_Left) || ImGuizmo::IsUsing()))
1213 {
1214 euler_angles = data.get_rotation_euler_degrees();
1215 }
1216
1217
1218
1219 ImGui::PushID("Position");
1220 {
1221 auto prop = type.data("position"_hs);
1222 auto prop_name = entt::get_name(prop);
1223 auto prop_pretty_name = entt::get_pretty_name(prop);
1224
1225 auto& override_ctx = ctx.get_cached<prefab_override_context>();
1226 override_ctx.push_segment(prop_name, prop_pretty_name);
1227
1228 property_layout layout;
1229 layout.set_data(prop_pretty_name, "");
1230 layout.push_layout(false);
1231
1232 ImGui::SameLine();
1233
1234 ImGui::AlignedItem(
1235 1.0f,
1236 ImGui::GetContentRegionAvail().x,
1237 ImGui::GetFrameHeight(),
1238 [&]()
1239 {
1240 if(ImGui::Button(ICON_MDI_UNDO_VARIANT, ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight())))
1241 {
1242 data.reset_position();
1243 result.changed = true;
1244 result.edit_finished = true;
1245
1246 auto prop_proxy = make_property_proxy(var_proxy, prop);
1247 add_property_action(ctx, override_ctx, result, prop_proxy, position, data.get_position(), prop.custom());
1248 }
1249 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1250 ImGui::SetItemTooltipEx("Reset %s", prop_pretty_name.c_str());
1251 });
1252 layout.prepare_for_item();
1253
1254 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
1255 {
1256 static const auto reset = math::zero<math::vec3>();
1257 if(DragVec3(position, info, &reset))
1258 {
1259 data.set_position(position);
1260 result.changed |= true;
1261
1262 auto prop_proxy = make_property_proxy(var_proxy, prop);
1263 add_property_action(ctx, override_ctx, result, prop_proxy, position, data.get_position(), prop.custom());
1264 }
1265 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1266 }
1267 ImGui::PopItemWidth();
1268
1269 override_ctx.pop_segment();
1270 }
1271 ImGui::PopID();
1272
1273 ImGui::PushID("Rotation");
1274 {
1275 auto prop = type.data("rotation"_hs);
1276 auto prop_name = entt::get_name(prop);
1277 auto prop_pretty_name = entt::get_pretty_name(prop);
1278
1279 auto& override_ctx = ctx.get_cached<prefab_override_context>();
1280 override_ctx.push_segment(prop_name, prop_pretty_name);
1281
1282 property_layout layout;
1283 layout.set_data(prop_pretty_name, "");
1284 layout.push_layout(false);
1285
1286 ImGui::SameLine();
1287
1288 ImGui::AlignedItem(
1289 1.0f,
1290 ImGui::GetContentRegionAvail().x,
1291 ImGui::GetFrameHeight(),
1292 [&]()
1293 {
1294 if(ImGui::Button(ICON_MDI_UNDO_VARIANT, ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight())))
1295 {
1296 data.reset_rotation();
1297 result.changed = true;
1298 result.edit_finished = true;
1299
1300 auto prop_proxy = make_property_proxy(var_proxy, prop);
1301 add_property_action(ctx, override_ctx, result, prop_proxy, rotation, data.get_rotation(), prop.custom());
1302 }
1303 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1304
1305 ImGui::SetItemTooltipEx("Reset %s", prop_pretty_name.c_str());
1306 });
1307 layout.prepare_for_item();
1308
1309 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
1310 {
1311 auto old_euler = euler_angles;
1312 static const auto reset = math::zero<math::vec3>();
1313 if(DragVec3(euler_angles, info, &reset, "%.2f°"))
1314 {
1315 data.rotate_local(math::radians(euler_angles - old_euler));
1316 result.changed |= true;
1317
1318 auto prop_proxy = make_property_proxy(var_proxy, prop);
1319 add_property_action(ctx, override_ctx, result, prop_proxy, rotation, data.get_rotation(), prop.custom());
1320 }
1321 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1322 }
1323
1324 ImGui::PopItemWidth();
1325
1326 override_ctx.pop_segment();
1327 }
1328 ImGui::PopID();
1329
1330 ImGui::PushID("Scale");
1331 {
1332 auto prop = type.data("scale"_hs);
1333 auto prop_name = entt::get_name(prop);
1334 auto prop_pretty_name = entt::get_pretty_name(prop);
1335
1336 auto& override_ctx = ctx.get_cached<prefab_override_context>();
1337 override_ctx.push_segment(prop_name, prop_pretty_name);
1338
1339 property_layout layout;
1340 layout.set_data(prop_pretty_name, "");
1341 layout.push_layout(false);
1342
1343 ImGui::SameLine();
1344 static bool locked_scale = false;
1345 auto label = locked_scale ? ICON_MDI_LOCK : ICON_MDI_LOCK_OPEN_VARIANT;
1346 ImGui::AlignedItem(
1347 1.0f,
1348 ImGui::GetContentRegionAvail().x,
1349 ImGui::CalcItemSize(label).x + ImGui::GetFrameHeight() + ImGui::GetStyle().ItemSpacing.x,
1350 [&]()
1351 {
1352 if(ImGui::Button(label))
1353 {
1354 locked_scale = !locked_scale;
1355 }
1356
1357 ImGui::SetItemTooltipEx("Enable/Disable Constrained Proportions");
1358
1359 ImGui::SameLine();
1360
1361 if(ImGui::Button(ICON_MDI_UNDO_VARIANT, ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight())))
1362 {
1363 data.reset_scale();
1364 result.changed = true;
1365 result.edit_finished = true;
1366
1367 auto prop_proxy = make_property_proxy(var_proxy, prop);
1368 add_property_action(ctx, override_ctx, result, prop_proxy, scale, data.get_scale(), prop.custom());
1369 }
1370 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1371
1372 ImGui::SetItemTooltipEx("Reset %s", prop_pretty_name.c_str());
1373 });
1374
1375 layout.prepare_for_item();
1376
1377 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
1378 {
1379 static const auto reset = math::one<math::vec3>();
1380 auto before_scale = scale;
1381 if(DragVec3(scale, info, &reset))
1382 {
1383 auto delta = scale - before_scale;
1384
1385 if(locked_scale)
1386 {
1387 before_scale += math::vec3(delta.x);
1388 before_scale += math::vec3(delta.y);
1389 before_scale += math::vec3(delta.z);
1390 scale = before_scale;
1391 }
1392
1393 data.set_scale(scale);
1394 result.changed |= true;
1395
1396 auto prop_proxy = make_property_proxy(var_proxy, prop);
1397 add_property_action(ctx, override_ctx, result, prop_proxy, scale, data.get_scale(), prop.custom());
1398 }
1399
1400 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1401 }
1402 ImGui::PopItemWidth();
1403
1404 override_ctx.pop_segment();
1405 }
1406 ImGui::PopID();
1407
1408 ImGui::PushID("Skew");
1409 {
1410 auto prop = type.data("skew"_hs);
1411 auto prop_name = entt::get_name(prop);
1412 auto prop_pretty_name = entt::get_pretty_name(prop);
1413
1414 auto& override_ctx = ctx.get_cached<prefab_override_context>();
1415 override_ctx.push_segment(prop_name, prop_pretty_name);
1416
1417 property_layout layout;
1418 layout.set_data(prop_pretty_name, "");
1419 layout.push_layout(false);
1420
1421 ImGui::SameLine();
1422
1423 ImGui::AlignedItem(
1424 1.0f,
1425 ImGui::GetContentRegionAvail().x,
1426 ImGui::GetFrameHeight(),
1427 [&]()
1428 {
1429 if(ImGui::Button(ICON_MDI_UNDO_VARIANT, ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight())))
1430 {
1431 data.reset_skew();
1432 result.changed = true;
1433 result.edit_finished = true;
1434
1435 auto prop_proxy = make_property_proxy(var_proxy, prop);
1436 add_property_action(ctx, override_ctx, result, prop_proxy, skew, data.get_skew(), prop.custom());
1437 }
1438 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1439 ImGui::SetItemTooltipEx("Reset %s", prop_pretty_name.c_str());
1440 });
1441 layout.prepare_for_item();
1442
1443 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
1444 {
1445 static const auto reset = math::zero<math::vec3>();
1446 if(DragVec3(skew, info, &reset))
1447 {
1448 data.set_skew(skew);
1449 result.changed |= true;
1450 auto prop_proxy = make_property_proxy(var_proxy, prop);
1451 add_property_action(ctx, override_ctx, result, prop_proxy, skew, data.get_skew(), prop.custom());
1452 }
1453
1454 result.edit_finished |= ImGui::IsItemDeactivatedAfterEdit();
1455 }
1456 ImGui::PopItemWidth();
1457
1458 override_ctx.pop_segment();
1459 }
1460 ImGui::PopID();
1461
1462 return result;
1463}
1464} // namespace unravel
entt::handle b
manifold_type type
entt::handle a
auto get_points() const noexcept -> const points_t &
Definition gradient.hpp:45
auto is_valid() const noexcept -> bool
Definition gradient.hpp:109
auto add_point(const T &element, float progress) -> size_t
Definition gradient.hpp:8
std::vector< point_t > points_t
Definition gradient.h:52
auto get_interpolation_mode() const noexcept -> gradient_interpolation_mode_t
Definition gradient.hpp:204
void set_interpolation_mode(gradient_interpolation_mode_t mode)
Definition gradient.hpp:197
void set_points(const points_t &points)
Definition gradient.hpp:37
void remove_point(int index)
Definition gradient.hpp:24
auto sample(float progress) const -> T
Definition gradient.hpp:115
General purpose transformation class designed to maintain each component of the transformation separa...
Definition transform.hpp:27
auto get_position() const noexcept -> const vec3_t &
Get the position component.
auto get_translation() const noexcept -> const vec3_t &
Get the translation component.
Manages ImGui layout for property inspection in the editor.
Definition inspector.h:19
void set_data(const entt::meta_data &prop, bool columns=true)
Updates layout data from meta property.
Definition inspector.cpp:76
void push_layout(bool auto_proceed_to_next_column=true)
Initializes ImGui layout with tables and property label.
Definition inspector.cpp:93
void prepare_for_item()
Prepares ImGui for rendering the property value widget.
range< float > frange_t
float scale
Definition hub.cpp:25
#define ICON_MDI_LOCK_OPEN_VARIANT
#define ICON_MDI_UNDO_VARIANT
#define ICON_MDI_LOCK
#define ICON_MDI_WINDOW_CLOSE
auto get_pretty_name(const meta_type &t) -> std::string
auto get_name(const meta_type &t) -> std::string
void reset(uint32_t _width, uint32_t _height, uint32_t _flags)
Definition graphics.cpp:261
Provides utilities for inspecting and converting sequence-related types to strings.
gradient_interpolation_mode_t
Definition gradient.h:22
auto make_property_proxy(const meta_any_proxy &var_proxy, const entt::meta_data &prop) -> meta_any_proxy
void add_property_action(rtti::context &ctx, prefab_override_context &override_ctx, inspect_result &result, const meta_any_proxy &var_proxy, const entt::meta_any &old_var, const entt::meta_any &new_var, const entt::meta_custom &custom)
auto make_proxy(entt::meta_any &var, const std::string &name) -> meta_any_proxy
Creates a simple proxy for direct variable access.
Definition hash.hpp:6
float y
float x
float z
Storage for box vector values and wraps up common functionality.
Definition bbox.h:21
static color white()
Definition color.h:13
Result of an inspection operation indicating what changes occurred.
Definition inspector.h:146
bool edit_finished
Whether user finished editing (e.g., released mouse or pressed enter)
Definition inspector.h:150
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
void before_inspect(const entt::meta_data &prop) override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
auto inspect(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result override
Safe deferred property access proxy for arbitrary object properties.
Definition inspector.h:198
Global context for tracking prefab override changes during inspection.
Definition inspectors.h:94
void push_segment(const std::string &segment, const std::string &pretty_segment)
Pushes a new path segment onto both contexts and applies override styling.
Metadata about a variable being inspected.
Definition inspector.h:133