Unravel Engine C++ Reference
Loading...
Searching...
No Matches
inspector_script.cpp
Go to the documentation of this file.
1#include "inspector_script.h"
2#include "inspectors.h"
5#include <monopp/mono_field_invoker.h>
6#include <monopp/mono_property_invoker.h>
7
8#include <graphics/texture.h>
9
14
15
18#include <engine/ecs/prefab.h>
20
21namespace unravel
22{
23
24auto find_attribute(const std::string& name, const std::vector<mono::mono_object>& attribs) -> mono::mono_object
25{
26 auto it = std::find_if(std::begin(attribs),
27 std::end(attribs),
28 [&](const mono::mono_object& obj)
29 {
30 return obj.get_type().get_name() == name;
31 });
32
33 if(it != std::end(attribs))
34 {
35 return *it;
36 }
37
38 return {};
39}
40
47template<typename T>
49{
50 mono::mono_field field;
51 std::string field_name;
52
53 mono_field_proxy(mono::mono_field f) : field(f), field_name(f.get_name()) {}
54
55 auto get_name() const -> std::string { return field_name; }
56
57 auto get_value(mono::mono_object& obj) const -> T
58 {
59 auto invoker = mono::make_field_invoker<T>(field);
60 return invoker.get_value(obj);
61 }
62
63 void set_value(mono::mono_object& obj, const T& value) const
64 {
65 auto invoker = mono::make_field_invoker<T>(field);
66 invoker.set_value(obj, value);
67 }
68
69 auto get_attributes() const
70 {
71 return field.get_attributes();
72 }
73
74 auto get_type() const
75 {
76 return field.get_type();
77 }
78
79 auto is_readonly() const { return field.is_readonly(); }
80 auto is_const() const { return field.is_const(); }
81};
82
89template<typename T>
91{
92 mono::mono_property property;
93 std::string property_name;
94
95 mono_property_proxy(mono::mono_property p) : property(p), property_name(p.get_name()) {}
96
97 auto get_name() const -> std::string { return property_name; }
98
99 auto get_value(mono::mono_object& obj) const -> T
100 {
101 auto invoker = mono::make_property_invoker<T>(property);
102 return invoker.get_value(obj);
103 }
104
105 void set_value(mono::mono_object& obj, const T& value) const
106 {
107 auto invoker = mono::make_property_invoker<T>(property);
108 invoker.set_value(obj, value);
109 }
110
111 auto get_attributes() const
112 {
113 return property.get_attributes();
114 }
115
116 auto get_type() const
117 {
118 return property.get_type();
119 }
120
121 auto is_readonly() const { return property.is_readonly(); }
122};
123
130template<typename T, typename ProxyType>
131auto make_script_proxy(const meta_any_proxy& obj_proxy, const ProxyType& script_proxy) -> meta_any_proxy
132{
133 meta_any_proxy field_proxy;
134
135 field_proxy.impl->get_name = [obj_proxy, script_proxy]()
136 {
137 auto parent_name = obj_proxy.impl->get_name();
138 if(parent_name.empty())
139 {
140 return script_proxy.get_name();
141 }
142 return fmt::format("{}/{}", parent_name, script_proxy.get_name());
143 };
144
145 field_proxy.impl->getter = [obj_proxy, script_proxy](entt::meta_any& result) mutable
146 {
147 entt::meta_any obj_var;
148 if(obj_proxy.impl->getter(obj_var) && obj_var)
149 {
150 auto& mono_obj = obj_var.cast<mono::mono_object&>();
151 auto field_value = script_proxy.get_value(mono_obj);
152 // Create an owned copy to avoid dangling references
153 result = entt::meta_any{std::in_place_type<T>, field_value};
154 return true;
155 }
156 return false;
157 };
158
159 field_proxy.impl->setter = [obj_proxy, script_proxy](meta_any_proxy& proxy, const entt::meta_any& value, uint64_t execution_count) mutable
160 {
161 entt::meta_any obj_var;
162 if(obj_proxy.impl->getter(obj_var) && obj_var)
163 {
164 auto& mono_obj = obj_var.cast<mono::mono_object&>();
165 if(value.allow_cast<T>())
166 {
167 script_proxy.set_value(mono_obj, value.cast<T>());
168 return obj_proxy.impl->setter(proxy, obj_var, execution_count);
169 }
170 }
171 return false;
172 };
173
174 return field_proxy;
175}
176
183 template<typename Invoker>
184auto make_entity_handle_proxy(const meta_any_proxy& obj_proxy, const Invoker& mutable_field, rtti::context& ctx) -> meta_any_proxy
185{
186 meta_any_proxy handle_proxy;
187 auto field_name = mutable_field.get_name();
188
189 handle_proxy.impl->get_name = [obj_proxy, field_name]()
190 {
191 auto parent_name = obj_proxy.impl->get_name();
192 if(parent_name.empty())
193 {
194 return field_name;
195 }
196 return fmt::format("{}/{}", parent_name, field_name);
197 };
198
199 handle_proxy.impl->getter = [obj_proxy, field_name, &ctx](entt::meta_any& result) mutable
200 {
201 entt::meta_any obj_var;
202 if(obj_proxy.impl->getter(obj_var) && obj_var)
203 {
204 auto& mono_obj = obj_var.cast<mono::mono_object&>();
205
206 // Recreate the invoker from the field name
207 auto obj_type = mono_obj.get_type();
208 auto field = obj_type.get_field(field_name);
209 auto invoker = mono::make_field_invoker<entt::entity>(field);
210
211 auto entity = invoker.get_value(mono_obj);
212 auto& ec = ctx.get_cached<ecs>();
213 auto& scene = ec.get_scene();
215 // Create an owned copy to avoid dangling references
216 result = entt::meta_any{std::in_place_type<entt::handle>, handle};
217 return true;
218 }
219 return false;
220 };
221
222 handle_proxy.impl->setter = [obj_proxy, field_name](meta_any_proxy& proxy, const entt::meta_any& value, uint64_t execution_count) mutable
223 {
224 entt::meta_any obj_var;
225 if(obj_proxy.impl->getter(obj_var) && obj_var)
226 {
227 auto& mono_obj = obj_var.cast<mono::mono_object&>();
228 if(value.allow_cast<entt::handle>())
229 {
230 // Recreate the invoker from the field name
231 auto obj_type = mono_obj.get_type();
232 auto field = obj_type.get_field(field_name);
233 auto invoker = mono::make_field_invoker<entt::entity>(field);
234
235 auto handle = value.cast<entt::handle>();
236 invoker.set_value(mono_obj, handle.entity());
237 return obj_proxy.impl->setter(proxy, obj_var, execution_count);
238 }
239 }
240 return false;
241 };
242
243 return handle_proxy;
244}
245
252template<typename T, typename Invoker>
253auto make_asset_handle_proxy(const meta_any_proxy& obj_proxy, const Invoker& mutable_field, rtti::context& ctx) -> meta_any_proxy
254{
255 meta_any_proxy asset_proxy;
256 auto field_name = mutable_field.get_name();
257
258 asset_proxy.impl->get_name = [obj_proxy, field_name]()
259 {
260 auto parent_name = obj_proxy.impl->get_name();
261 if(parent_name.empty())
262 {
263 return field_name;
264 }
265 return fmt::format("{}/{}", parent_name, field_name);
266 };
267
268 asset_proxy.impl->getter = [obj_proxy, field_name, &ctx](entt::meta_any& result) mutable
269 {
270 entt::meta_any obj_var;
271 if(obj_proxy.impl->getter(obj_var) && obj_var)
272 {
273 auto& mono_obj = obj_var.cast<mono::mono_object&>();
274
275 // Recreate the invoker from the field name
276 auto obj_type = mono_obj.get_type();
277 auto field = obj_type.get_field(field_name);
278 auto invoker = mono::make_field_invoker<mono::mono_object>(field);
279
280 auto val = invoker.get_value(mono_obj);
281
282 // Convert mono asset handle to engine asset handle
283 asset_handle<T> asset;
284 if(val)
285 {
286 const auto& field_type = invoker.get_type();
287 auto prop = field_type.get_property("uid");
288 auto mutable_prop = mono::make_property_invoker<hpp::uuid>(prop);
289 auto uid = mutable_prop.get_value(val);
290
291 auto& am = ctx.get_cached<asset_manager>();
292 asset = am.get_asset<T>(uid);
293 }
294
295 // Create an owned copy to avoid dangling references
296 result = entt::meta_any{std::in_place_type<asset_handle<T>>, asset};
297 return true;
298 }
299 return false;
300 };
301
302 asset_proxy.impl->setter = [obj_proxy, field_name](meta_any_proxy& proxy, const entt::meta_any& value, uint64_t execution_count) mutable
303 {
304 entt::meta_any obj_var;
305 if(obj_proxy.impl->getter(obj_var) && obj_var)
306 {
307 auto& mono_obj = obj_var.cast<mono::mono_object&>();
308 if(value.allow_cast<asset_handle<T>>())
309 {
310 // Recreate the invoker from the field name
311 auto obj_type = mono_obj.get_type();
312 auto field = obj_type.get_field(field_name);
313 auto invoker = mono::make_field_invoker<mono::mono_object>(field);
314
315 auto asset = value.cast<asset_handle<T>>();
316 const auto& field_type = invoker.get_type();
317
318 auto val = invoker.get_value(mono_obj);
319 if(asset && !val)
320 {
321 val = field_type.new_instance();
322 invoker.set_value(mono_obj, val);
323 }
324
325 if(val)
326 {
327 auto prop = field_type.get_property("uid");
328 auto mutable_prop = mono::make_property_invoker<hpp::uuid>(prop);
329 mutable_prop.set_value(val, asset.uid());
330 }
331
332 return obj_proxy.impl->setter(proxy, obj_var, execution_count);
333 }
334 }
335 return false;
336 };
337
338 return asset_proxy;
339}
340
347template<typename T, typename Invoker>
348auto make_array_element_proxy(const meta_any_proxy& obj_proxy, const Invoker& mutable_field, size_t index) -> meta_any_proxy
349{
350 meta_any_proxy element_proxy;
351 auto field_name = mutable_field.get_name();
352
353 element_proxy.impl->get_name = [obj_proxy, field_name, index]()
354 {
355 auto parent_name = obj_proxy.impl->get_name();
356 auto element_name = fmt::format("{}[{}]", field_name, index);
357 if(parent_name.empty())
358 {
359 return element_name;
360 }
361 return fmt::format("{}/{}", parent_name, element_name);
362 };
363
364 element_proxy.impl->getter = [obj_proxy, field_name, index](entt::meta_any& result) mutable
365 {
366 entt::meta_any obj_var;
367 if(obj_proxy.impl->getter(obj_var) && obj_var)
368 {
369 auto& mono_obj = obj_var.cast<mono::mono_object&>();
370
371 // Recreate the invoker from the field name
372 auto obj_type = mono_obj.get_type();
373 auto field = obj_type.get_field(field_name);
374 auto invoker = mono::make_field_invoker<mono::mono_object>(field);
375
376 auto val = invoker.get_value(mono_obj);
377 mono::mono_array<T> array(val);
378
379 if(index < array.size())
380 {
381 auto element_value = array.get(index);
382 // Create an owned copy to avoid dangling references
383 result = entt::meta_any{std::in_place_type<T>, element_value};
384 return true;
385 }
386 }
387 return false;
388 };
389
390 element_proxy.impl->setter = [obj_proxy, field_name, index](meta_any_proxy& proxy, const entt::meta_any& value, uint64_t execution_count) mutable
391 {
392 entt::meta_any obj_var;
393 if(obj_proxy.impl->getter(obj_var) && obj_var)
394 {
395 auto& mono_obj = obj_var.cast<mono::mono_object&>();
396 if(value.allow_cast<T>())
397 {
398 // Recreate the invoker from the field name
399 auto obj_type = mono_obj.get_type();
400 auto field = obj_type.get_field(field_name);
401 auto invoker = mono::make_field_invoker<mono::mono_object>(field);
402
403 auto val = invoker.get_value(mono_obj);
404 mono::mono_array<T> array(val);
405
406 if(index < array.size())
407 {
408 array.set(index, value.cast<T>());
409 // Note: mono arrays are reference types, so the change is already applied
410 return obj_proxy.impl->setter(proxy, obj_var, execution_count);
411 }
412 }
413 }
414 return false;
415 };
416
417 return element_proxy;
418}
419
420template<typename T>
422{
423
424 static auto inspect_field(rtti::context& ctx,
425 mono::mono_object& obj,
426 const meta_any_proxy& obj_proxy,
427 mono::mono_field& field,
428 const var_info& info) -> inspect_result
429 {
430 auto invoker = mono::make_field_invoker<T>(field);
431
432 var_info field_info;
433 field_info.is_property = true;
434 field_info.read_only = ImGui::IsReadonly() || info.read_only || field.is_readonly() || field.is_const();
435
436 // Use the new proxy system to enable undo/redo for script fields
437 return inspect_invoker_with_proxy(ctx, obj, obj_proxy, field, field_info);
438 }
439
440 // New method that uses the proxy system for proper undo/redo support
442 mono::mono_object& obj,
443 const meta_any_proxy& obj_proxy,
444 mono::mono_field& field,
445 const var_info& info) -> inspect_result
446 {
447 // Create script proxy wrapper
448 mono_field_proxy<T> script_proxy(field);
449
450 // Create meta_any_proxy that bridges to the script system
451 auto field_proxy = make_script_proxy<T>(obj_proxy, script_proxy);
452
453 // Get current value through the proxy for inspection
454 entt::meta_any var;
455 if(!field_proxy.impl->getter(var))
456 {
457 return {};
458 }
459
460 inspect_result result;
461
462 // Extract attributes for custom metadata
463 auto attribs = script_proxy.get_attributes();
464 auto range_attrib = find_attribute("RangeAttribute", attribs);
465 auto min_attrib = find_attribute("MinAttribute", attribs);
466 auto max_attrib = find_attribute("MaxAttribute", attribs);
467 auto step_attrib = find_attribute("StepAttribute", attribs);
468 auto tooltip_attrib = find_attribute("TooltipAttribute", attribs);
469
470 std::string tooltip;
471 if(tooltip_attrib.valid())
472 {
473 auto invoker = mono::make_field_invoker<std::string>(tooltip_attrib.get_type(), "tooltip");
474 tooltip = invoker.get_value(tooltip_attrib);
475 }
476
477 entt::attributes meta_attribs;
478
479 if(min_attrib.valid())
480 {
481 auto invoker = mono::make_field_invoker<float>(min_attrib.get_type(), "min");
482 float min_value = invoker.get_value(min_attrib);
483 meta_attribs["min"] = min_value;
484 }
485
486 if(range_attrib.valid())
487 {
488 auto invoker = mono::make_field_invoker<float>(range_attrib.get_type(), "min");
489 float min_value = invoker.get_value(range_attrib);
490 meta_attribs["min"] = min_value;
491
492 auto max_invoker = mono::make_field_invoker<float>(range_attrib.get_type(), "max");
493 float max_value = max_invoker.get_value(range_attrib);
494 meta_attribs["max"] = max_value;
495 }
496
497 if(max_attrib.valid())
498 {
499 auto invoker = mono::make_field_invoker<float>(max_attrib.get_type(), "max");
500 float max_value = invoker.get_value(max_attrib);
501 meta_attribs["max"] = max_value;
502 }
503
504 if(step_attrib.valid())
505 {
506 auto invoker = mono::make_field_invoker<float>(step_attrib.get_type(), "step");
507 float step_value = invoker.get_value(step_attrib);
508 meta_attribs["step"] = step_value;
509 }
510
511 auto custom = entt::make_custom<entt::attributes>(meta_attribs);
512
513 {
514 property_layout layout(script_proxy.get_name(), tooltip);
515 result |= inspect_var(ctx, var, field_proxy, info, custom);
516 }
517
518 return result;
519 }
520
522 mono::mono_object& obj,
523 const meta_any_proxy& obj_proxy,
524 mono::mono_property& property,
525 const var_info& info) -> inspect_result
526 {
527 auto invoker = mono::make_property_invoker<T>(property);
528
529 var_info field_info;
530 field_info.is_property = true;
531 field_info.read_only = ImGui::IsReadonly() || info.read_only || property.is_readonly();
532
533 // Use the new proxy system to enable undo/redo for script properties
534 return inspect_property_with_proxy(ctx, obj, obj_proxy, property, field_info);
535 }
536
537 // New method that uses the proxy system for proper undo/redo support
539 mono::mono_object& obj,
540 const meta_any_proxy& obj_proxy,
541 mono::mono_property& property,
542 const var_info& info) -> inspect_result
543 {
544 // Create script proxy wrapper
545 mono_property_proxy<T> script_proxy(property);
546
547 // Create meta_any_proxy that bridges to the script system
548 auto prop_proxy = make_script_proxy<T>(obj_proxy, script_proxy);
549
550 // Get current value through the proxy for inspection
551 entt::meta_any var;
552 if(!prop_proxy.impl->getter(var))
553 {
554 return {};
555 }
556
557 inspect_result result;
558
559 // Extract attributes for custom metadata
560 auto attribs = script_proxy.get_attributes();
561 auto range_attrib = find_attribute("RangeAttribute", attribs);
562 auto min_attrib = find_attribute("MinAttribute", attribs);
563 auto max_attrib = find_attribute("MaxAttribute", attribs);
564 auto step_attrib = find_attribute("StepAttribute", attribs);
565 auto tooltip_attrib = find_attribute("TooltipAttribute", attribs);
566
567 std::string tooltip;
568 if(tooltip_attrib.valid())
569 {
570 auto invoker = mono::make_field_invoker<std::string>(tooltip_attrib.get_type(), "tooltip");
571 tooltip = invoker.get_value(tooltip_attrib);
572 }
573
574 entt::attributes meta_attribs;
575
576 if(min_attrib.valid())
577 {
578 auto invoker = mono::make_field_invoker<float>(min_attrib.get_type(), "min");
579 float min_value = invoker.get_value(min_attrib);
580 meta_attribs["min"] = min_value;
581 }
582
583 if(range_attrib.valid())
584 {
585 auto invoker = mono::make_field_invoker<float>(range_attrib.get_type(), "min");
586 float min_value = invoker.get_value(range_attrib);
587 meta_attribs["min"] = min_value;
588
589 auto max_invoker = mono::make_field_invoker<float>(range_attrib.get_type(), "max");
590 float max_value = max_invoker.get_value(range_attrib);
591 meta_attribs["max"] = max_value;
592 }
593
594 if(max_attrib.valid())
595 {
596 auto invoker = mono::make_field_invoker<float>(max_attrib.get_type(), "max");
597 float max_value = invoker.get_value(max_attrib);
598 meta_attribs["max"] = max_value;
599 }
600
601 if(step_attrib.valid())
602 {
603 auto invoker = mono::make_field_invoker<float>(step_attrib.get_type(), "step");
604 float step_value = invoker.get_value(step_attrib);
605 meta_attribs["step"] = step_value;
606 }
607
608 auto custom = entt::make_custom<entt::attributes>(meta_attribs);
609
610 {
611 property_layout layout(script_proxy.get_name(), tooltip);
612 result |= inspect_var(ctx, var, prop_proxy, info, custom);
613 }
614
615 return result;
616 }
617};
618
619template<typename T>
621{
622 static auto value_to_name(T value, const std::vector<std::pair<T, std::string>>& mapping) -> const std::string&
623 {
624 for(const auto& kvp : mapping)
625 {
626 if(kvp.first == value)
627 {
628 return kvp.second;
629 }
630 }
631
632 static const std::string empty;
633 return empty;
634 }
635
636 static auto name_to_value(const std::string& name, const std::vector<std::pair<T, std::string>>& mapping) -> T
637 {
638 for(const auto& kvp : mapping)
639 {
640 if(kvp.second == name)
641 {
642 return kvp.first;
643 }
644 }
645
646 return std::numeric_limits<T>::max();
647 }
648
649 template<typename Invoker>
651 mono::mono_object& obj,
652 const meta_any_proxy& obj_proxy,
653 const Invoker& mutable_field,
654 const std::vector<std::pair<T, std::string>>& mapping,
655 const var_info& info) -> inspect_result
656 {
657 auto val = mutable_field.get_value(obj);
658
659 inspect_result result;
660
661 auto attribs = mutable_field.get_attributes();
662 auto tooltip_attrib = find_attribute("TooltipAttribute", attribs);
663
664 std::string tooltip;
665 if(tooltip_attrib.valid())
666 {
667 auto invoker = mono::make_field_invoker<std::string>(tooltip_attrib.get_type(), "tooltip");
668 tooltip = invoker.get_value(tooltip_attrib);
669 }
670
671 auto current_name = value_to_name(val, mapping);
672
673 std::vector<const char*> cstrings{};
674 cstrings.reserve(mapping.size());
675
676 int current_idx = 0;
677 int i = 0;
678 for(const auto& pair : mapping)
679 {
680 cstrings.push_back(pair.second.c_str());
681
682 if(current_name == pair.second)
683 {
684 current_idx = i;
685 }
686 i++;
687 }
688
689 property_layout layout(mutable_field.get_name(), tooltip);
690
691 if(info.read_only)
692 {
693 ImGui::LabelText("##enum", "%s", cstrings[current_idx]);
694 }
695 else
696 {
697 int listbox_item_size = static_cast<int>(cstrings.size());
698
699 ImGuiComboFlags flags = 0;
700
701 if(ImGui::BeginCombo("##enum", cstrings[current_idx], flags))
702 {
703 for(int n = 0; n < listbox_item_size; n++)
704 {
705 const bool is_selected = (current_idx == n);
706
707 if(ImGui::Selectable(cstrings[n], is_selected))
708 {
709 current_idx = n;
710 result.changed = true;
711 result.edit_finished |= true;
712 val = name_to_value(cstrings[current_idx], mapping);
713 }
714
715 ImGui::DrawItemActivityOutline();
716
717 if(is_selected)
718 {
719 ImGui::SetItemDefaultFocus();
720 }
721 }
722
723 ImGui::EndCombo();
724 }
725 ImGui::DrawItemActivityOutline();
726 }
727
728 if(result.changed)
729 {
730 mutable_field.set_value(obj, val);
731 }
732
733 return result;
734 }
735
736 static auto inspect_field(rtti::context& ctx,
737 mono::mono_object& obj,
738 const meta_any_proxy& obj_proxy,
739 mono::mono_field& field,
740 const var_info& info) -> inspect_result
741 {
742 var_info field_info;
743 field_info.is_property = true;
744 field_info.read_only = ImGui::IsReadonly() || info.read_only || field.is_readonly() || field.is_const();
745
746 const auto& field_type = field.get_type();
747
748 auto invoker = mono::make_field_invoker<T>(field);
749 auto mapping = field_type.get_enum_values<T>();
750
751 // Use the new proxy system to enable undo/redo for enum script fields
752 return inspect_enum_field_with_proxy(ctx, obj, obj_proxy, field, mapping, field_info);
753 }
754
755 // New method that uses the proxy system for proper undo/redo support for enum fields
757 mono::mono_object& obj,
758 const meta_any_proxy& obj_proxy,
759 mono::mono_field& field,
760 const std::vector<std::pair<T, std::string>>& mapping,
761 const var_info& info) -> inspect_result
762 {
763 // Create script proxy wrapper
764 mono_field_proxy<T> script_proxy(field);
765
766 // Create meta_any_proxy that bridges to the script system
767 auto field_proxy = make_script_proxy<T>(obj_proxy, script_proxy);
768
769 // Get current value for display
770 auto val = script_proxy.get_value(obj);
771
772 inspect_result result;
773
774 auto attribs = script_proxy.get_attributes();
775 auto tooltip_attrib = find_attribute("TooltipAttribute", attribs);
776
777 std::string tooltip;
778 if(tooltip_attrib.valid())
779 {
780 auto invoker = mono::make_field_invoker<std::string>(tooltip_attrib.get_type(), "tooltip");
781 tooltip = invoker.get_value(tooltip_attrib);
782 }
783
784 auto current_name = value_to_name(val, mapping);
785
786 std::vector<const char*> cstrings{};
787 cstrings.reserve(mapping.size());
788
789 int current_idx = 0;
790 int i = 0;
791 for(const auto& pair : mapping)
792 {
793 cstrings.push_back(pair.second.c_str());
794
795 if(current_name == pair.second)
796 {
797 current_idx = i;
798 }
799 i++;
800 }
801
802 property_layout layout(script_proxy.get_name(), tooltip);
803
804 if(info.read_only)
805 {
806 ImGui::LabelText("##enum", "%s", cstrings[current_idx]);
807 }
808 else
809 {
810 int listbox_item_size = static_cast<int>(cstrings.size());
811
812 ImGuiComboFlags flags = 0;
813
814 if(ImGui::BeginCombo("##enum", cstrings[current_idx], flags))
815 {
816 for(int n = 0; n < listbox_item_size; n++)
817 {
818 const bool is_selected = (current_idx == n);
819
820 if(ImGui::Selectable(cstrings[n], is_selected))
821 {
822 current_idx = n;
823 result.changed = true;
824 result.edit_finished |= true;
825 val = name_to_value(cstrings[current_idx], mapping);
826
827 // Record the change using the proxy
828 entt::meta_any new_value = entt::forward_as_meta(val);
829 entt::meta_any old_value;
830 field_proxy.impl->getter(old_value);
831
832 auto& override_ctx = ctx.get_cached<prefab_override_context>();
833 add_property_action(ctx, override_ctx, result, field_proxy, old_value, new_value, {});
834 }
835
836 ImGui::DrawItemActivityOutline();
837
838 if(is_selected)
839 {
840 ImGui::SetItemDefaultFocus();
841 }
842 }
843
844 ImGui::EndCombo();
845 }
846 ImGui::DrawItemActivityOutline();
847 }
848
849 return result;
850 }
851
853 mono::mono_object& obj,
854 const meta_any_proxy& obj_proxy,
855 mono::mono_property& property,
856 const var_info& info) -> inspect_result
857 {
858 var_info field_info;
859 field_info.is_property = true;
860 field_info.read_only = ImGui::IsReadonly() || info.read_only || property.is_readonly();
861
862 const auto& field_type = property.get_type();
863
864 auto invoker = mono::make_property_invoker<T>(property);
865 auto mapping = field_type.get_enum_values<T>();
866
867 // Use the new proxy system to enable undo/redo for enum script properties
868 return inspect_enum_property_with_proxy(ctx, obj, obj_proxy, property, mapping, field_info);
869 }
870
871 // New method that uses the proxy system for proper undo/redo support for enum properties
873 mono::mono_object& obj,
874 const meta_any_proxy& obj_proxy,
875 mono::mono_property& property,
876 const std::vector<std::pair<T, std::string>>& mapping,
877 const var_info& info) -> inspect_result
878 {
879 // Create script proxy wrapper
880 mono_property_proxy<T> script_proxy(property);
881
882 // Create meta_any_proxy that bridges to the script system
883 auto prop_proxy = make_script_proxy<T>(obj_proxy, script_proxy);
884
885 // Get current value for display
886 auto val = script_proxy.get_value(obj);
887
888 inspect_result result;
889
890 auto attribs = script_proxy.get_attributes();
891 auto tooltip_attrib = find_attribute("TooltipAttribute", attribs);
892
893 std::string tooltip;
894 if(tooltip_attrib.valid())
895 {
896 auto invoker = mono::make_field_invoker<std::string>(tooltip_attrib.get_type(), "tooltip");
897 tooltip = invoker.get_value(tooltip_attrib);
898 }
899
900 auto current_name = value_to_name(val, mapping);
901
902 std::vector<const char*> cstrings{};
903 cstrings.reserve(mapping.size());
904
905 int current_idx = 0;
906 int i = 0;
907 for(const auto& pair : mapping)
908 {
909 cstrings.push_back(pair.second.c_str());
910
911 if(current_name == pair.second)
912 {
913 current_idx = i;
914 }
915 i++;
916 }
917
918 property_layout layout(script_proxy.get_name(), tooltip);
919
920 if(info.read_only)
921 {
922 ImGui::LabelText("##enum", "%s", cstrings[current_idx]);
923 }
924 else
925 {
926 int listbox_item_size = static_cast<int>(cstrings.size());
927
928 ImGuiComboFlags flags = 0;
929
930 if(ImGui::BeginCombo("##enum", cstrings[current_idx], flags))
931 {
932 for(int n = 0; n < listbox_item_size; n++)
933 {
934 const bool is_selected = (current_idx == n);
935
936 if(ImGui::Selectable(cstrings[n], is_selected))
937 {
938 current_idx = n;
939 result.changed = true;
940 result.edit_finished |= true;
941 val = name_to_value(cstrings[current_idx], mapping);
942
943 // Record the change using the proxy
944 entt::meta_any new_value = entt::forward_as_meta(val);
945 entt::meta_any old_value;
946 prop_proxy.impl->getter(old_value);
947
948 auto& override_ctx = ctx.get_cached<prefab_override_context>();
949 add_property_action(ctx, override_ctx, result, prop_proxy, old_value, new_value, {});
950 }
951
952 ImGui::DrawItemActivityOutline();
953
954 if(is_selected)
955 {
956 ImGui::SetItemDefaultFocus();
957 }
958 }
959
960 ImGui::EndCombo();
961 }
962 ImGui::DrawItemActivityOutline();
963 }
964
965 return result;
966 }
967};
968
969template<>
971{
972 template<typename Invoker>
974 mono::mono_object& obj,
975 const meta_any_proxy& obj_proxy,
976 const Invoker& mutable_field,
977 const var_info& info) -> inspect_result
978 {
979 inspect_result result;
980
981 auto attribs = mutable_field.get_attributes();
982 auto tooltip_attrib = find_attribute("TooltipAttribute", attribs);
983
984 std::string tooltip;
985 if(tooltip_attrib.valid())
986 {
987 auto invoker = mono::make_field_invoker<std::string>(tooltip_attrib.get_type(), "tooltip");
988 tooltip = invoker.get_value(tooltip_attrib);
989 }
990
991 // Use the helper function to create a clean entity handle proxy
992 auto handle_proxy = make_entity_handle_proxy(obj_proxy, mutable_field, ctx);
993
994 // Get current value through the proxy for inspection
995 entt::meta_any var;
996 if(!handle_proxy.impl->getter(var))
997 {
998 return {};
999 }
1000
1001 {
1002 property_layout layout(mutable_field.get_name(), tooltip);
1003 result |= inspect_var(ctx, var, handle_proxy, info);
1004 }
1005
1006 return result;
1007 }
1008
1010 mono::mono_object& obj,
1011 const meta_any_proxy& obj_proxy,
1012 mono::mono_field& field,
1013 const var_info& info) -> inspect_result
1014 {
1015 auto invoker = mono::make_field_invoker<entt::entity>(field);
1016
1017 var_info field_info;
1018 field_info.is_property = true;
1019 field_info.read_only = ImGui::IsReadonly() || info.read_only || field.is_readonly() || field.is_const();
1020
1021 return inspect_invoker(ctx, obj, obj_proxy, invoker, field_info);
1022 }
1023
1025 mono::mono_object& obj,
1026 const meta_any_proxy& obj_proxy,
1027 mono::mono_property& field,
1028 const var_info& info) -> inspect_result
1029 {
1030 auto invoker = mono::make_property_invoker<entt::entity>(field);
1031
1032 var_info field_info;
1033 field_info.is_property = true;
1034 field_info.read_only = ImGui::IsReadonly() || info.read_only || field.is_readonly();
1035
1036 return inspect_invoker(ctx, obj, obj_proxy, invoker, field_info);
1037 }
1038};
1039
1040template<typename T>
1042{
1043 template<typename Invoker>
1045 mono::mono_object& obj,
1046 const meta_any_proxy& obj_proxy,
1047 const Invoker& mutable_field,
1048 const var_info& info) -> inspect_result
1049 {
1050 inspect_result result;
1051
1052 auto attribs = mutable_field.get_attributes();
1053 auto tooltip_attrib = find_attribute("TooltipAttribute", attribs);
1054
1055 std::string tooltip;
1056 if(tooltip_attrib.valid())
1057 {
1058 auto invoker = mono::make_field_invoker<std::string>(tooltip_attrib.get_type(), "tooltip");
1059 tooltip = invoker.get_value(tooltip_attrib);
1060 }
1061
1062 // Use the helper function to create a clean asset handle proxy
1063 auto asset_proxy = make_asset_handle_proxy<T>(obj_proxy, mutable_field, ctx);
1064
1065 // Get current value through the proxy for inspection
1066 entt::meta_any var;
1067 if(!asset_proxy.impl->getter(var))
1068 {
1069 return {};
1070 }
1071
1072 {
1073 property_layout layout(mutable_field.get_name(), tooltip);
1074 result |= inspect_var(ctx, var, asset_proxy, info);
1075 }
1076
1077 return result;
1078 }
1079
1081 mono::mono_object& obj,
1082 const meta_any_proxy& obj_proxy,
1083 mono::mono_field& field,
1084 const var_info& info) -> inspect_result
1085 {
1086 auto invoker = mono::make_field_invoker<mono::mono_object>(field);
1087
1088 var_info field_info;
1089 field_info.is_property = true;
1090 field_info.read_only = ImGui::IsReadonly() || info.read_only || field.is_readonly() || field.is_const();
1091
1092 return inspect_invoker(ctx, obj, obj_proxy, invoker, field_info);
1093 }
1094
1096 mono::mono_object& obj,
1097 const meta_any_proxy& obj_proxy,
1098 mono::mono_property& field,
1099 const var_info& info) -> inspect_result
1100 {
1101 auto invoker = mono::make_property_invoker<mono::mono_object>(field);
1102
1103 var_info field_info;
1104 field_info.is_property = true;
1105 field_info.read_only = ImGui::IsReadonly() || info.read_only || field.is_readonly();
1106
1107 return inspect_invoker(ctx, obj, obj_proxy, invoker, field_info);
1108 }
1109};
1110
1111template<typename T>
1112struct mono_inspector<mono::mono_array<T>>
1113{
1114 template<typename Invoker>
1116 mono::mono_object& obj,
1117 const meta_any_proxy& obj_proxy,
1118 const Invoker& mutable_field,
1119 const var_info& info) -> inspect_result
1120 {
1121 inspect_result result;
1122
1123 auto val = mutable_field.get_value(obj);
1124 mono::mono_array<T> array(val);
1125
1126 for(size_t i = 0; i < array.size(); ++i)
1127 {
1128 // Use the helper function to create a clean array element proxy
1129 auto element_proxy = make_array_element_proxy<T>(obj_proxy, mutable_field, i);
1130
1131 // Get current value through the proxy for inspection
1132 entt::meta_any element;
1133 if(element_proxy.impl->getter(element))
1134 {
1135 result |= unravel::inspect_var(ctx, element, element_proxy, info);
1136 }
1137 }
1138 return result;
1139 }
1140
1142 mono::mono_object& obj,
1143 const meta_any_proxy& obj_proxy,
1144 mono::mono_field& field,
1145 const var_info& info) -> inspect_result
1146 {
1147 auto invoker = mono::make_field_invoker<mono::mono_object>(field);
1148
1149 var_info field_info;
1150 field_info.is_property = true;
1151 field_info.read_only = ImGui::IsReadonly() || info.read_only || field.is_readonly() || field.is_const();
1152
1153 return inspect_invoker(ctx, obj, obj_proxy, invoker, field_info);
1154 }
1155
1157 mono::mono_object& obj,
1158 const meta_any_proxy& obj_proxy,
1159 mono::mono_property& field,
1160 const var_info& info) -> inspect_result
1161 {
1162 auto invoker = mono::make_property_invoker<mono::mono_object>(field);
1163
1164 var_info field_info;
1165 field_info.is_property = true;
1166 field_info.read_only = ImGui::IsReadonly() || info.read_only || field.is_readonly();
1167
1168 return inspect_invoker(ctx, obj, obj_proxy, invoker, field_info);
1169 }
1170};
1171
1173 entt::meta_any& var,
1174 const meta_any_proxy& var_proxy,
1175 const var_info& info,
1176 const entt::meta_custom& custom) -> inspect_result
1177{
1178 auto& data = var.cast<mono::mono_object&>();
1179
1180 inspect_result result{};
1181
1182 const auto& type = data.get_type();
1183
1184 using mono_field_inspector = std::function<inspect_result(rtti::context&,
1185 mono::mono_object&,
1186 const meta_any_proxy& obj_proxy,
1187 mono::mono_field&,
1188 const var_info&)>;
1189
1190 auto get_field_inspector = [](const std::string& type_name) -> const mono_field_inspector&
1191 {
1192 // clang-format off
1193 static std::map<std::string, mono_field_inspector> reg = {
1214 {"Texture", &mono_inspector<asset_handle<gfx::texture>>::inspect_field},
1215 {"Material", &mono_inspector<asset_handle<material>>::inspect_field},
1216 {"Mesh", &mono_inspector<asset_handle<mesh>>::inspect_field},
1217 {"AnimationClip", &mono_inspector<asset_handle<animation_clip>>::inspect_field},
1218 {"Prefab", &mono_inspector<asset_handle<prefab>>::inspect_field},
1219 {"Scene", &mono_inspector<asset_handle<scene_prefab>>::inspect_field},
1220 {"PhysicsMaterial", &mono_inspector<asset_handle<physics_material>>::inspect_field},
1221 {"AudioClip", &mono_inspector<asset_handle<audio_clip>>::inspect_field},
1222 {"Font", &mono_inspector<asset_handle<font>>::inspect_field},
1223 // {"Color[]", &mono_inspector<mono::mono_array<math::color>>::inspect_field},
1224
1225 };
1226 // clang-format on
1227
1228 auto it = reg.find(type_name);
1229 if(it != reg.end())
1230 {
1231 return it->second;
1232 }
1233 static const mono_field_inspector empty;
1234 return empty;
1235 };
1236
1237 auto get_enum_field_inspector = [](const std::string& type_name) -> const mono_field_inspector&
1238 {
1239 // clang-format off
1240 static std::map<std::string, mono_field_inspector> reg = {
1249 };
1250 // clang-format on
1251
1252 auto it = reg.find(type_name);
1253 if(it != reg.end())
1254 {
1255 return it->second;
1256 }
1257 static const mono_field_inspector empty;
1258 return empty;
1259 };
1260
1261 auto fields = type.get_fields();
1262 for(auto& field : fields)
1263 {
1264 bool inspect_predicate = field.get_visibility() == mono::visibility::vis_public;
1265
1266 ImGui::PushReadonly(!inspect_predicate);
1267
1268 if(is_debug_view())
1269 {
1270 inspect_predicate = !field.is_backing_field();
1271 }
1272 if(inspect_predicate)
1273 {
1274 const auto& field_type = field.get_type();
1275
1276 auto field_inspector = get_field_inspector(field_type.get_name());
1277
1278 auto& override_ctx = ctx.get_cached<prefab_override_context>();
1279 override_ctx.push_segment(field.get_name(), field.get_name());
1280
1281 if(field_inspector)
1282 {
1283 result |= field_inspector(ctx, data, var_proxy, field, info);
1284 }
1285 else if(field_type.is_enum())
1286 {
1287 auto enum_type = field_type.get_enum_base_type();
1288 auto enum_inspector = get_enum_field_inspector(enum_type.get_name());
1289 if(enum_inspector)
1290 {
1291 result |= enum_inspector(ctx, data, var_proxy, field, info);
1292 }
1293 }
1294 else
1295 {
1296 var_info field_info;
1297 field_info.is_property = true;
1298 field_info.read_only = true;
1299
1300 std::string unknown = field.get_type().get_name();
1301 entt::meta_any unknown_var = entt::forward_as_meta(unknown);
1302
1303 auto unknown_var_proxy = make_proxy(unknown_var);
1304 {
1305 property_layout layout(field.get_name());
1306 result |= inspect_var(ctx, unknown_var, unknown_var_proxy, field_info);
1307 }
1308 }
1309
1310 override_ctx.pop_segment();
1311 }
1313 }
1314
1315 using mono_property_inspector = std::function<inspect_result(rtti::context&,
1316 mono::mono_object&,
1317 const meta_any_proxy& obj_proxy,
1318 mono::mono_property&,
1319 const var_info&)>;
1320
1321 auto get_property_inspector = [](const std::string& type_name) -> const mono_property_inspector&
1322 {
1323 // clang-format off
1324 static std::map<std::string, mono_property_inspector> reg = {
1354
1355 };
1356 // clang-format on
1357
1358 auto it = reg.find(type_name);
1359 if(it != reg.end())
1360 {
1361 return it->second;
1362 }
1363 static const mono_property_inspector empty;
1364 return empty;
1365 };
1366
1367 auto get_enum_property_inspector = [](const std::string& type_name) -> const mono_property_inspector&
1368 {
1369 // clang-format off
1370 static std::map<std::string, mono_property_inspector> reg = {
1379 };
1380 // clang-format on
1381
1382 auto it = reg.find(type_name);
1383 if(it != reg.end())
1384 {
1385 return it->second;
1386 }
1387 static const mono_property_inspector empty;
1388 return empty;
1389 };
1390
1391 auto properties = type.get_properties();
1392 for(auto& prop : properties)
1393 {
1394 bool inspect_predicate = prop.get_visibility() == mono::visibility::vis_public;
1395 ImGui::PushReadonly(!inspect_predicate);
1396
1397 if(is_debug_view())
1398 {
1399 inspect_predicate = true;
1400 }
1401
1402 if(inspect_predicate)
1403 {
1404 const auto& prop_type = prop.get_type();
1405
1406 auto property_inspector = get_property_inspector(prop_type.get_name());
1407
1408 auto& override_ctx = ctx.get_cached<prefab_override_context>();
1409 override_ctx.push_segment(prop.get_name(), prop.get_name());
1410
1411 if(property_inspector)
1412 {
1413 result |= property_inspector(ctx, data, var_proxy, prop, info);
1414 }
1415 else if(prop_type.is_enum())
1416 {
1417 auto enum_type = prop_type.get_enum_base_type();
1418 auto enum_inspector = get_enum_property_inspector(enum_type.get_name());
1419 if(enum_inspector)
1420 {
1421 result |= enum_inspector(ctx, data, var_proxy, prop, info);
1422 }
1423 }
1424 else
1425 {
1426 var_info field_info;
1427 field_info.is_property = true;
1428 field_info.read_only = true;
1429
1430 std::string unknown = prop.get_type().get_name();
1431 entt::meta_any unknown_var = entt::forward_as_meta(unknown);
1432
1433 auto unknown_var_proxy = make_proxy(unknown_var);
1434
1435 {
1436 property_layout layout(prop.get_name());
1437 result |= inspect_var(ctx, unknown_var, unknown_var_proxy, field_info);
1438 }
1439 }
1440
1441 override_ctx.pop_segment();
1442 }
1444 }
1445
1446 return result;
1447}
1448
1450 entt::meta_any& var,
1451 const meta_any_proxy& var_proxy,
1452 const var_info& info,
1453 const entt::meta_custom& custom) -> inspect_result
1454{
1455 meta_any_proxy obj_proxy;
1456 obj_proxy.impl->get_name = [parent_proxy = var_proxy]()
1457 {
1458 return parent_proxy.impl->get_name();
1459 };
1460 obj_proxy.impl->getter = [parent_proxy = var_proxy](entt::meta_any& result)
1461 {
1462 entt::meta_any var;
1463 if(parent_proxy.impl->getter(var) && var)
1464 {
1465 auto& data = var.cast<mono::mono_scoped_object&>();
1466 auto& mono_obj = static_cast<mono::mono_object&>(data.object);
1467 result = entt::forward_as_meta(mono_obj);
1468 return true;
1469 }
1470 return false;
1471 };
1472 obj_proxy.impl->setter = [parent_proxy = var_proxy](meta_any_proxy& proxy, const entt::meta_any& value, uint64_t execution_count) mutable
1473 {
1474 entt::meta_any var;
1475 if(proxy.impl->getter(var) && var)
1476 {
1477 var.assign(value);
1478 return parent_proxy.impl->setter(parent_proxy, var, execution_count);
1479 }
1480 return false;
1481 };
1482
1483
1484 auto& data = var.cast<mono::mono_scoped_object&>();
1485 auto& mono_obj = static_cast<mono::mono_object&>(data.object);
1486 auto obj_var = entt::forward_as_meta(mono_obj);
1487
1488 return inspector_mono_object::inspect(ctx, obj_var, obj_proxy, info, custom);
1489}
1490
1491} // namespace unravel
manifold_type type
Manages assets, including loading, unloading, and storage.
Manages ImGui layout for property inspection in the editor.
Definition inspector.h:19
std::string name
Definition hub.cpp:27
const char * tooltip
bool IsReadonly()
Definition imgui.cpp:643
void PopReadonly()
Definition imgui.cpp:658
void PushReadonly(bool _enabled)
Definition imgui.cpp:649
std::map< std::string, meta_any > attributes
Definition reflection.h:18
auto make_custom(Args &&...args) -> entt::meta_custom
Definition reflection.h:91
auto inspect_property(rtti::context &ctx, entt::meta_any &object, const meta_any_proxy &var_proxy, const entt::meta_data &prop) -> inspect_result
auto make_array_element_proxy(const meta_any_proxy &obj_proxy, const Invoker &mutable_field, size_t index) -> meta_any_proxy
Creates a specialized proxy for individual array elements in script objects.
auto find_attribute(const std::string &name, const std::vector< mono::mono_object > &attribs) -> mono::mono_object
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_entity_handle_proxy(const meta_any_proxy &obj_proxy, const Invoker &mutable_field, rtti::context &ctx) -> meta_any_proxy
Creates a specialized proxy for entity handle fields in script objects.
auto make_asset_handle_proxy(const meta_any_proxy &obj_proxy, const Invoker &mutable_field, rtti::context &ctx) -> meta_any_proxy
Creates a specialized proxy for asset handle fields in script objects.
auto make_script_proxy(const meta_any_proxy &obj_proxy, const ProxyType &script_proxy) -> meta_any_proxy
Creates a meta_any_proxy that can access script fields through the proxy wrapper.
auto is_debug_view() -> bool
Checks if currently in debug view mode.
auto make_proxy(entt::meta_any &var, const std::string &name) -> meta_any_proxy
Creates a simple proxy for direct variable access.
auto inspect_var(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result
Main entry point for inspecting any variable with automatic type resolution.
entt::entity entity
Represents a handle to an asset, providing access and management functions.
Manages the entity-component-system (ECS) operations for the ACE framework.
Definition ecs.h:12
Result of an inspection operation indicating what changes occurred.
Definition inspector.h:146
bool changed
Whether the value was modified during inspection.
Definition inspector.h:148
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
Safe deferred property access proxy for arbitrary object properties.
Definition inspector.h:198
std::shared_ptr< meta_any_proxy_impl > impl
Definition inspector.h:221
Proxy wrapper for mono field access that integrates with meta_any_proxy system.
auto get_name() const -> std::string
auto get_value(mono::mono_object &obj) const -> T
mono_field_proxy(mono::mono_field f)
void set_value(mono::mono_object &obj, const T &value) const
static auto inspect_field(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_field &field, const var_info &info) -> inspect_result
static auto inspect_invoker(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, const Invoker &mutable_field, const var_info &info) -> inspect_result
static auto inspect_property(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_property &field, const var_info &info) -> inspect_result
static auto inspect_invoker(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, const Invoker &mutable_field, const var_info &info) -> inspect_result
static auto inspect_field(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_field &field, const var_info &info) -> inspect_result
static auto inspect_property(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_property &field, const var_info &info) -> inspect_result
static auto inspect_property(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_property &field, const var_info &info) -> inspect_result
static auto inspect_invoker(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, const Invoker &mutable_field, const var_info &info) -> inspect_result
static auto inspect_field(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_field &field, const var_info &info) -> inspect_result
static auto inspect_field(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_field &field, const var_info &info) -> inspect_result
static auto name_to_value(const std::string &name, const std::vector< std::pair< T, std::string > > &mapping) -> T
static auto inspect_enum_property_with_proxy(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_property &property, const std::vector< std::pair< T, std::string > > &mapping, const var_info &info) -> inspect_result
static auto inspect_invoker(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, const Invoker &mutable_field, const std::vector< std::pair< T, std::string > > &mapping, const var_info &info) -> inspect_result
static auto inspect_property(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_property &property, const var_info &info) -> inspect_result
static auto inspect_enum_field_with_proxy(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_field &field, const std::vector< std::pair< T, std::string > > &mapping, const var_info &info) -> inspect_result
static auto value_to_name(T value, const std::vector< std::pair< T, std::string > > &mapping) -> const std::string &
static auto inspect_property(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_property &property, const var_info &info) -> inspect_result
static auto inspect_field(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_field &field, const var_info &info) -> inspect_result
static auto inspect_invoker_with_proxy(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_field &field, const var_info &info) -> inspect_result
static auto inspect_property_with_proxy(rtti::context &ctx, mono::mono_object &obj, const meta_any_proxy &obj_proxy, mono::mono_property &property, const var_info &info) -> inspect_result
Proxy wrapper for mono property access that integrates with meta_any_proxy system.
mono_property_proxy(mono::mono_property p)
void set_value(mono::mono_object &obj, const T &value) const
auto get_name() const -> std::string
auto get_value(mono::mono_object &obj) const -> T
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.
Represents a scene in the ACE framework, managing entities and their relationships.
Definition scene.h:21
auto create_handle(entt::entity e) -> entt::handle
Creates an entity in the scene.
Definition scene.cpp:304
Metadata about a variable being inspected.
Definition inspector.h:133
bool is_property
Whether this is a property that can be overridden in prefabs.
Definition inspector.h:137
bool read_only
Whether the variable should be displayed as read-only.
Definition inspector.h:135
gfx::uniform_handle handle
Definition uniform.cpp:9