6#include "entt/core/any.hpp"
7#include "imgui_widgets/utils.h"
12#include "imgui/imgui.h"
13#include "imgui/imgui_internal.h"
27#include <unordered_map>
39 auto base_inspector_type = entt::resolve<inspector>();
41 for(
auto& inspector_type : inspector_types)
44 if(inspected_type_var)
47 inspector_type.invoke(
"create_and_register"_hs, {}, inspected_type_var, entt::forward_as_meta(
type_map));
62 return debug_view > 0;
70 const entt::meta_any& old_var,
71 const entt::meta_any& new_var,
72 const entt::meta_custom& custom)
74 std::function<void()> on_success =
nullptr;
81 on_success = [
entity = override_ctx.
entity, component_type_name, component_type_pretty_name, prop_path]()
105 end_prefab_inspection();
107 auto prefab_root = find_prefab_root_entity(e);
115 prefab_root_entity = prefab_root;
119 is_path_overridden_callback =
120 [comp_copy = *prefab_comp, entity_copy = e](
const hpp::uuid& entity_uuid,
121 const std::string& component_path)
123 return comp_copy.has_override(entity_uuid, component_path);
127 auto entity_uuid = get_entity_prefab_uuid(e);
129 set_entity_uuid(entity_uuid);
149 if(!is_active || !prefab_root_entity)
158 auto entity_uuid = path_context.get_entity_uuid();
160 if(exists_in_prefab(prefab_scene,
163 path_context.get_component_type_name(),
164 path_context.get_current_path()))
167 std::string component_path = path_context.get_current_path_with_component_type();
169 std::string pretty_component_path = pretty_path_context.get_current_path_with_component_type();
171 prefab_comp->add_override(entity_uuid, component_path, pretty_component_path);
172 prefab_comp->changed =
true;
213 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
214 ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
227 ImGui::PopStyleColor(2);
247 auto current_entity =
entity;
250 while(current_entity)
254 return current_entity;
264 current_entity = transform->get_parent();
358 const entt::meta_type& component_type,
359 const std::string& property_path)
368 const std::string& component_type_name,
369 const std::string& component_pretty_type_name,
370 const std::string& property_path)
389 auto type = entt::resolve(entt::hashed_string(component_type_name.c_str()));
390 std::string current_path = component_type_name;
391 std::string current_pretty_path = component_pretty_type_name;
393 for(
auto& token : tokens)
395 auto prop =
type.data(entt::hashed_string(token.c_str()));
396 auto prop_type = prop.type();
398 current_path +=
"/" + token;
404 prefab_comp->add_override(entity_uuid, current_path, current_pretty_path);
409 if(component_type_name ==
"transform_component")
411 auto property_path_global =
string_utils::replace(property_path,
"global_transform",
"local_transform");
413 if(property_path_global != property_path)
429 if(entity_uuid.is_nil())
434 prefab_comp->remove_entity(entity_uuid);
441 hpp::uuid entity_uuid,
442 const std::string& component_type,
443 const std::string& property_path) ->
bool
450 if(entity_uuid.is_nil())
455 auto etype = entt::resolve(entt::hashed_string(component_type.c_str()));
460 auto method = etype.func(
"component_exists"_hs);
466 struct prefab_version_t
471 entt::handle instance;
472 auto view = cache_scene.registry->view<
prefab_component, prefab_version_t>();
474 [&](
auto e,
auto&& comp,
auto&&
version)
478 instance = cache_scene.create_handle(e);
483 cache_scene.unload();
484 instance = cache_scene.instantiate(
prefab);
485 instance.emplace<prefab_version_t>(
prefab.version());
494 auto result = method.invoke({},
entity);
496 bool exists = result.cast<
bool>();
502 if(etype == entt::resolve<script_component>())
508 if(tokens.size() > 1 && tokens[0] ==
"script_components")
510 auto script_name = tokens[1];
511 return script_comp->has_script_components(script_name);
558 if(predicate_meta.try_cast<
bool>())
560 auto pred = predicate_meta.cast<
bool>();
575 auto prop_var = prop.get(
object);
578 auto prop_old_var = prop.get(
object);
581 auto prop_type = prop_var.type();
584 bool is_array = prop_type.is_sequence_container();
585 bool is_associative_container = prop_type.is_associative_container();
586 bool is_container = is_array || is_associative_container;
587 bool is_enum = prop_type.is_enum();
605 prop_inspector->before_inspect(prop);
617 result |=
inspect_array(ctx, prop_var, prop_proxy, prop, info, prop.custom());
619 else if(is_associative_container)
626 result |=
inspect_enum(ctx, prop_var, prop_proxy, info);
632 result |=
inspect_var(ctx, prop_var, prop_proxy, info, prop.custom());
634 else if(!is_flattable)
636 ImGui::AlignTextToFramePadding();
637 ImGui::SetNextItemOpen(
true, ImGuiCond_Appearing);
641 bool open = ImGui::TreeNodeEx(pretty_name.c_str(), ImGuiTreeNodeFlags_SpanAvailWidth);
645 ImGui::TreePush(pretty_name.c_str());
647 result |=
inspect_var(ctx, prop_var, prop_proxy, info, prop.custom());
653 ImGui::SetItemFocusFrame(ImGui::GetColorU32(ImGuiCol_Separator), 1.0f);
663 ImGui::PushID(pretty_name.c_str());
665 result |=
inspect_var(ctx, prop_var, prop_proxy, info, prop.custom());
672 if(result.changed && !is_readonly)
674 prop.set(
object, prop_var);
675 add_property_action(ctx, override_ctx, result, prop_proxy, prop_old_var, prop_var, prop.custom());
684 prop_inspector->after_inspect(prop);
687 override_ctx.pop_segment();
695 const entt::meta_data& prop,
709 const std::string&
name,
714 auto view = var.as_sequence_container();
717 auto int_size =
static_cast<int>(
size);
726 bool resizeable = view.resize(
size);
729 ImGuiInputTextFlags flags = 0;
732 bool readonly = info.read_only || !resizeable;
737 flags |= ImGuiInputTextFlags_ReadOnly;
742 if(ImGui::InputInt(
"##array", &int_size, step, step_fast, flags))
744 int_size = std::max(readonly_count, int_size);
746 if(view.resize(
static_cast<std::size_t
>(int_size)))
748 size =
static_cast<std::size_t
>(int_size);
749 result.changed =
true;
751 result.edit_finished =
true;
755 ImGui::DrawItemActivityOutline();
762 ImGui::TreePush(
"array");
764 int index_to_remove = -1;
765 for(std::size_t i = 0; i <
size; ++i)
767 auto value = view[i];
768 std::string element =
"Element ";
769 element += std::to_string(i);
773 auto item_info = info;
774 item_info.read_only |= readonly_count > 0;
778 auto pos_before = ImGui::GetCursorPos();
795 value_proxy.
impl->get_name = [var_proxy, element]()
797 auto name = var_proxy.impl->get_name();
802 return fmt::format(
"{}/{}",
name, element);
804 value_proxy.
impl->getter = [parent_proxy = var_proxy, i](entt::meta_any& result)
807 if(parent_proxy.impl->getter(var) && var)
809 auto view = var.as_sequence_container();
810 if(view.size() >
static_cast<std::size_t
>(i))
812 auto value = view[i];
819 value_proxy.
impl->setter = [parent_proxy = var_proxy, i](
meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
822 if(parent_proxy.impl->getter(var) && var)
824 auto view = var.as_sequence_container();
825 if(view.size() >
static_cast<std::size_t
>(i))
828 auto it = view.begin();
829 std::advance(it,
static_cast<std::ptrdiff_t
>(i));
835 view.insert(it, value);
838 return parent_proxy.impl->setter(parent_proxy, var, execution_count);
845 result |=
inspect_var(ctx, value, value_proxy, item_info, custom);
856 auto pos_after = ImGui::GetCursorPos();
863 if(!item_info.read_only && !resizeable)
865 ImGui::SetCursorPos(pos_before);
868 ImGui::AlignTextToFramePadding();
869 if(ImGui::Button(
ICON_MDI_DELETE, ImVec2(0.0f, ImGui::GetFrameHeightWithSpacing())))
873 ImGui::SetItemTooltipEx(
"Remove element.");
875 ImGui::SetCursorPos(pos_after);
880 if(index_to_remove != -1)
882 auto it = view.begin();
883 std::advance(it, index_to_remove);
885 result.changed =
true;
886 result.edit_finished =
true;
892 ImGui::RenderFrameEx(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
900 const entt::meta_data& prop,
904 auto view = var.as_associative_container();
906 auto int_size =
static_cast<int>(
size);
999 if(!edited.allow_cast<int64_t>())
1003 auto current_value = edited.cast<int64_t>();
1005 int current_idx = 0;
1008 auto type = var.type();
1013 std::string pretty_name;
1017 std::vector<enum_value> names;
1018 for(
auto kvp :
type.data())
1020 const auto& data = kvp.second;
1023 auto value = data.get(var);
1025 int64_t value64 = 0;
1026 if(value.allow_cast<int64_t>())
1028 value64 = value.cast<int64_t>();
1034 names.emplace_back(enum_value{
name, pretty_name, value64});
1036 if(value64 == current_value)
1043 if(current_idx >=
static_cast<int>(names.size()))
1052 ImGui::LabelText(
"##enum",
"%s", names[current_idx].pretty_name.c_str());
1056 int listbox_item_size =
static_cast<int>(names.size());
1058 ImGuiComboFlags flags = 0;
1060 if(ImGui::BeginCombo(
"##enum", names[current_idx].pretty_name.c_str(), flags))
1062 for(
int n = 0; n < listbox_item_size; n++)
1064 const bool is_selected = (current_idx == n);
1066 if(ImGui::Selectable(names[n].pretty_name.c_str(), is_selected))
1069 result.changed =
true;
1070 result.edit_finished |=
true;
1072 edited = names[n].value;
1074 if(edited.allow_cast(var.type()))
1076 var = std::move(edited);
1080 ImGui::DrawItemActivityOutline();
1083 ImGui::SetItemDefaultFocus();
1088 ImGui::DrawItemActivityOutline();
1095 entt::meta_any& var,
1102 auto type = var.type();
1105 derived_var_proxy.
impl->get_name = [parent_proxy = var_proxy]()
1107 return parent_proxy.impl->get_name();
1109 derived_var_proxy.
impl->getter = [parent_proxy = var_proxy](entt::meta_any& result)
1111 if(parent_proxy.impl->getter(result) && result)
1118 derived_var_proxy.
impl->setter = [parent_proxy = var_proxy](
meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
1121 if(proxy.impl->getter(var) && var)
1124 return parent_proxy.impl->setter(parent_proxy, var, execution_count);
1129 entt::meta_any old_var;
1130 if(info.is_copyable)
1142 result |=
inspector->inspect(ctx, var, derived_var_proxy, info, custom);
1144 else if(
type.is_enum())
1146 result |=
inspect_enum(ctx, var, derived_var_proxy, info);
1154 if(result.changed && info.is_property)
1167 entt::meta_any& var,
1169 const entt::meta_type&
type,
1173 auto properties =
type.data();
1176 if(properties.begin() == properties.end())
1183 if(
type.is_sequence_container())
1185 result |=
inspect_array(ctx, var, var_proxy,
"",
"", info, custom);
1190 std::vector<std::pair<std::string, std::vector<entt::meta_data>>> grouped_props;
1191 for(
auto kvp : properties)
1193 const auto& prop = kvp.second;
1198 auto it = std::find_if(grouped_props.begin(),
1199 grouped_props.end(),
1202 return kv.first == group;
1205 if(it == grouped_props.end())
1208 grouped_props.emplace_back(group, std::vector<entt::meta_data>{prop});
1213 it->second.emplace_back(prop);
1217 for(
auto& kvp : grouped_props)
1219 auto& props = kvp.second;
1221 const auto& group_name = kvp.first;
1223 if(group_name.empty())
1225 for(
auto&& prop : props)
1235 ImGui::AlignTextToFramePadding();
1236 ImGui::SetNextItemOpen(
true, ImGuiCond_Appearing);
1237 ImGui::BeginGroup();
1238 if(ImGui::TreeNodeEx(kvp.first.c_str(), ImGuiTreeNodeFlags_SpanAvailWidth))
1240 ImGui::TreePush(kvp.first.c_str());
1241 ImGui::PushID(kvp.first.c_str());
1243 for(
auto& prop : props)
1256 ImGui::SetItemFocusFrame(ImGui::GetColorU32(ImGuiCol_Separator), 1.0f);
1270 entt::meta_any& var,
1276 for(
auto base : var.type().base())
Manages ImGui layout for property inspection in the editor.
void set_data(const entt::meta_data &prop, bool columns=true)
Updates layout data from meta property.
void pop_layout()
Cleans up ImGui state (IDs, tables, tree nodes)
auto push_tree_layout(ImGuiTreeNodeFlags flags=0) -> bool
Creates a collapsible tree node layout for nested properties.
void push_segment(const std::string &segment)
Push a new path segment onto the context stack.
void set_component_type(const std::string &type)
Set the component type for this context.
auto get_component_type_name() const -> std::string
Get the component type name.
void pop_segment()
Pop the last path segment from the context stack.
void set_entity_uuid(const hpp::uuid &entity_uuid)
Set the entity UUID for nested entity tracking.
auto get_current_path() const -> std::string
Get the current full property path.
Class that contains core data for audio listeners. There can only be one instance of it per scene.
void PushFont(Font::Enum _font)
void PushReadonly(bool _enabled)
auto get_derived_types(const meta_type &t) -> std::vector< meta_type >
auto get_pretty_name(const meta_type &t) -> std::string
auto as_derived(meta_any &obj) -> bool
auto get_attribute_as< std::string >(const meta_custom &custom, const char *name) -> std::string
auto get_attribute_as(const meta_custom &custom, const char *name) -> T
auto get_attribute(const meta_custom &custom, const char *name) -> const meta_any &
std::function< bool(const meta_any &)> property_predicate_t
auto get_name(const meta_type &t) -> std::string
Provides utilities for inspecting and converting sequence-related types to strings.
auto tokenize(const std::string &str, const std::string &delimiters) -> string_tokens_t
auto replace(const std::string &str, const std::string &search, const std::string &replace) -> std::string
auto inspect_property(rtti::context &ctx, entt::meta_any &object, const meta_any_proxy &var_proxy, const entt::meta_data &prop) -> inspect_result
void pop_debug_view()
Pops debug view mode (decreases debug view counter)
auto make_property_proxy(const meta_any_proxy &var_proxy, const entt::meta_data &prop) -> meta_any_proxy
auto is_property_readonly(const entt::meta_any &object, const entt::meta_data &prop) -> bool
auto is_property_visible(const entt::meta_any &object, const entt::meta_data &prop) -> bool
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 inspect_associative_container(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const entt::meta_data &prop, const var_info &info, const entt::meta_custom &custom) -> inspect_result
Inspects associative containers like maps and sets.
auto inspect_var_properties_impl(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const entt::meta_type &type, const var_info &info, const entt::meta_custom &custom) -> inspect_result
auto inspect_var_properties(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info, const entt::meta_custom &custom) -> inspect_result
Inspects all properties of a complex object recursively.
void push_debug_view()
Pushes debug view mode (increases debug view counter)
auto is_debug_view() -> bool
Checks if currently in debug view mode.
auto get_inspector(rtti::context &ctx, const entt::meta_type &type) -> std::shared_ptr< inspector >
auto inspect_array(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const entt::meta_data &prop, const var_info &info, const entt::meta_custom &custom) -> inspect_result
Inspects array-like containers with add/remove functionality.
auto inspect_enum(rtti::context &ctx, entt::meta_any &var, const meta_any_proxy &var_proxy, const var_info &info) -> inspect_result
Inspects enumeration types with dropdown selection.
auto is_property_flattable(const entt::meta_any &object, const entt::meta_data &prop) -> bool
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.
Represents a handle to an asset, providing access and management functions.
void do_action(const std::string &name, const std::function< void()> &action)
static auto context() -> rtti::context &
Result of an inspection operation indicating what changes occurred.
bool change_recorded
Whether the change was recorded for undo/redo system.
Registry for managing type-specific inspector instances.
inspector_registry()
Constructor that auto-discovers and registers all inspector types.
std::unordered_map< entt::id_type, std::shared_ptr< inspector > > type_map
Map from type ID to inspector instance for fast lookup.
Component that holds a reference to a prefab asset and tracks property overrides.
Component that provides a unique identifier (UUID) for a prefab.
hpp::uuid id
The unique identifier for the entity.
Global context for tracking prefab override changes during inspection.
void end_prefab_inspection()
End prefab inspection context and clean up state.
entt::handle prefab_root_entity
The prefab root entity that contains the prefab_component.
static auto exists_in_prefab(scene &cache_scene, const asset_handle< prefab > &prefab, hpp::uuid entity_uuid, const std::string &component_type, const std::string &property_path) -> bool
Checks if a property exists in the original prefab.
void set_entity_uuid(const hpp::uuid &uuid)
Sets the entity UUID for both path contexts.
property_path_context pretty_path_context
Current property path context for human-readable paths.
entt::handle entity
The specific entity currently being inspected.
auto is_path_overridden() const -> bool
Check if the current property path is already overridden.
static void mark_property_as_changed(entt::handle entity, const entt::meta_type &component_type, const std::string &property_path)
Marks a specific property as changed using component type.
static void mark_transform_global_as_changed(entt::handle entity, bool position, bool rotation, bool scale, bool skew)
static auto find_prefab_root_entity(entt::handle entity) -> entt::handle
Finds the prefab root entity by traversing up the parent hierarchy.
static void mark_material_as_changed(entt::handle entity)
Marks material as changed in prefab override system.
static void mark_text_area_as_changed(entt::handle entity)
Marks text area as changed in prefab override system.
property_path_context path_context
Current property path context for serialization paths.
void set_component_type(const std::string &type, const std::string &pretty_type)
Sets the component type for both path contexts.
auto record_override() -> bool
Record a property override when a change is detected.
static void mark_entity_as_removed(entt::handle entity)
Marks an entity as removed from the prefab instance.
bool is_active
Whether we're currently inspecting a prefab instance.
void push_segment(const std::string &segment, const std::string &pretty_segment)
Pushes a new path segment onto both contexts and applies override styling.
static void mark_active_as_changed(entt::handle entity)
Marks entity active state as changed in prefab override system.
static void mark_transform_as_changed(entt::handle entity, bool position, bool rotation, bool scale, bool skew)
Marks transform properties as changed in prefab override system.
void pop_segment()
Pops the last path segment and removes override styling if needed.
static auto get_entity_prefab_uuid(entt::handle entity) -> hpp::uuid
Gets the prefab UUID of an entity from its prefab_id_component.
auto begin_prefab_inspection(entt::handle entity) -> bool
Initialize context for inspecting a prefab instance.
Represents a generic prefab with a buffer for serialized data.
Represents a scene in the ACE framework, managing entities and their relationships.
static auto find_entity_by_prefab_uuid(entt::handle root_entity, const hpp::uuid &target_uuid) -> entt::handle
Finds an entity by UUID in the scene.
Metadata about a variable being inspected.
bool is_property
Whether this is a property that can be overridden in prefabs.
bool read_only
Whether the variable should be displayed as read-only.