6#include "entt/core/any.hpp"
7#include "imgui_widgets/utils.h"
12#include "imgui/imgui.h"
13#include "imgui/imgui_internal.h"
28#include <unordered_map>
35 auto color = ImGui::GetStyleColorVec4(idx);
36 color.x *= multiplier;
37 color.y *= multiplier;
38 color.z *= multiplier;
52 auto base_inspector_type = entt::resolve<inspector>();
54 for(
auto& inspector_type : inspector_types)
57 if(inspected_type_var)
60 inspector_type.invoke(
"create_and_register"_hs, {}, inspected_type_var, entt::forward_as_meta(
type_map));
75 return debug_view > 0;
81 if(!var_proxy.
impl->name.empty())
90 ImGui::DrawItemActivityOutline(ImGui::OutlineFlags_WhenCalled | ImGui::OutlineFlags_HighlightActive);
94 ImGui::SetScrollHereY();
104 const entt::meta_any& old_var,
105 const entt::meta_any& new_var,
106 const entt::meta_custom& custom) ->
bool
108 std::function<void()> on_success =
nullptr;
109 if(override_ctx.record_override())
111 auto component_type_name = override_ctx.path_context.get_component_type_name();
112 auto component_type_pretty_name = override_ctx.pretty_path_context.get_component_type_name();
113 auto prop_path = override_ctx.path_context.get_current_path();
114 auto prop_pretty_path = override_ctx.pretty_path_context.get_current_path();
115 on_success = [
entity = override_ctx.entity, component_type_name, component_type_pretty_name, prop_path, prop_pretty_path]()
122 if(!result.change_recorded)
132 result.change_recorded =
true;
135 return result.change_recorded;
140 end_prefab_inspection();
142 auto prefab_root = find_prefab_root_entity(e);
150 prefab_root_entity = prefab_root;
154 is_path_overridden_callback =
155 [comp_copy = *prefab_comp, entity_copy = e](
const hpp::uuid& entity_uuid,
156 const std::string& component_path)
158 return comp_copy.has_override(entity_uuid, component_path);
162 auto entity_uuid = get_entity_prefab_uuid(e);
164 set_entity_uuid(entity_uuid);
184 if(!is_active || !prefab_root_entity)
193 auto entity_uuid = path_context.get_entity_uuid();
195 if(exists_in_prefab(prefab_scene,
198 path_context.get_component_type_name(),
199 path_context.get_current_path()))
202 std::string component_path = path_context.get_current_path_with_component_type();
204 std::string pretty_component_path = pretty_path_context.get_current_path_with_component_type();
206 prefab_comp->add_override(entity_uuid, component_path, pretty_component_path);
207 prefab_comp->changed =
true;
216 if(!is_active || !prefab_root_entity)
224 prefab_comp->remove_override(path_context.get_entity_uuid(), path_context.get_current_path_with_component_type());
225 prefab_comp->changed =
true;
269 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
270 ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
283 ImGui::PopStyleColor(2);
303 auto current_entity =
entity;
306 while(current_entity)
310 return current_entity;
320 current_entity = transform->get_parent();
419 const entt::meta_type& component_type,
420 const std::string& property_path,
421 const std::string& property_pretty_path)
430 const std::string& component_type_name,
431 const std::string& component_pretty_type_name,
432 const std::string& property_path,
433 const std::string& property_pretty_path)
452 auto type = entt::resolve(entt::hashed_string(component_type_name.c_str()));
453 std::string current_path = component_type_name;
454 std::string current_pretty_path = component_pretty_type_name;
456 for(
auto&
token : tokens)
458 current_path +=
"/" +
token;
461 auto pretty_tokens = tokens;
462 if(!property_pretty_path.empty())
465 for(
auto&
token : pretty_tokens)
467 current_pretty_path +=
"/" +
token;
472 for(
auto&
token : tokens)
474 auto prop =
type.data(entt::hashed_string(
token.c_str()));
475 auto prop_type = prop.type();
477 if(
token.starts_with(
"script_components["))
491 prefab_comp->add_override(entity_uuid, current_path, current_pretty_path);
496 if(component_type_name ==
"transform_component")
498 auto property_path_global =
string_utils::replace(property_path,
"global_transform",
"local_transform");
500 if(property_path_global != property_path)
516 if(entity_uuid.is_nil())
521 prefab_comp->remove_entity(entity_uuid);
528 hpp::uuid entity_uuid,
529 const std::string& component_type,
530 const std::string& property_path) ->
bool
537 if(entity_uuid.is_nil())
542 auto etype = entt::resolve(entt::hashed_string(component_type.c_str()));
547 auto method = etype.func(
"component_exists"_hs);
553 struct prefab_version_t
558 entt::handle instance;
561 [&](
auto e,
auto&& comp,
auto&&
version)
565 instance = cache_scene.create_handle(e);
570 cache_scene.unload();
571 instance = cache_scene.instantiate(
prefab);
572 instance.emplace<prefab_version_t>(
prefab.version());
581 auto result = method.invoke({},
entity);
583 bool exists = result.cast<
bool>();
589 if(etype == entt::resolve<script_component>())
595 if(tokens.size() > 1 && tokens[0] ==
"script_components")
597 auto script_name = tokens[1];
598 return script_comp->has_script_components(script_name);
627 auto prop_var = prop.get(
object);
630 auto prop_old_var = prop.get(
object);
633 auto prop_type = prop_var.type();
636 bool is_array = prop_type.is_sequence_container();
637 bool is_associative_container = prop_type.is_associative_container();
638 bool is_container = is_array || is_associative_container;
639 bool is_enum = prop_type.is_enum();
659 prop_inspector->before_inspect(prop,
object);
668 result |=
inspect_array(ctx, prop_var, prop_proxy, prop, info, prop.custom());
670 else if(is_associative_container)
677 result |=
inspect_enum(ctx, prop_var, prop_proxy, info);
683 result |=
inspect_var(ctx, prop_var, prop_proxy, info, prop.custom());
685 else if(!is_flattable)
690 ImGui::SetNextItemOpen(
true, ImGuiCond_Appearing);
691 ImGui::AlignTextToFramePadding();
695 bool open = ImGui::TreeNodeEx(pretty_name.c_str(), ImGuiTreeNodeFlags_SpanAvailWidth);
700 ImGui::TreePush(pretty_name.c_str());
701 ImGui::PushID(pretty_name.c_str());
703 result |=
inspect_var(ctx, prop_var, prop_proxy, info, prop.custom());
714 ImGui::SetItemFocusFrame(ImGui::GetColorU32(ImGuiCol_Separator), 1.0f);
719 ImGui::PushID(pretty_name.c_str());
721 result |=
inspect_var(ctx, prop_var, prop_proxy, info, prop.custom());
733 add_property_action(ctx, override_ctx, result, prop_proxy, prop_old_var, prop_var, prop.custom());
744 prop_inspector->after_inspect(prop,
object);
747 override_ctx.pop_segment();
755 const entt::meta_data& prop,
770 const std::string&
name,
775 auto view = var.as_sequence_container();
778 auto int_size =
static_cast<int>(
size);
793 bool resizeable = !is_fixed_size_array &&
view.resize(
size);
796 ImGuiInputTextFlags flags = 0;
799 bool readonly = info.read_only || !resizeable;
804 flags |= ImGuiInputTextFlags_ReadOnly;
809 if(ImGui::InputInt(
"##array", &int_size, step, step_fast, flags))
811 int_size = std::max(readonly_count, int_size);
813 if(
view.resize(
static_cast<std::size_t
>(int_size)))
815 size =
static_cast<std::size_t
>(int_size);
816 result.changed =
true;
818 result.edit_finished =
true;
822 ImGui::DrawItemActivityOutline();
840 int index_to_remove = -1;
841 for(std::size_t i = 0; i <
size; ++i)
843 auto value =
view[i];
844 std::string element =
"Item ";
845 element += std::to_string(i);
849 auto item_info = info;
850 item_info.read_only |= readonly_count > 0;
854 auto pos_before = ImGui::GetCursorPos();
859 auto array_index_segment =
"[" + std::to_string(i) +
"]";
860 override_ctx.
push_segment(array_index_segment, array_index_segment);
869 value_proxy.
impl->parent = var_proxy.impl;
871 value_proxy.
impl->name = [&]()
873 const auto&
name = var_proxy.impl->name;
876 return fmt::format(
"[{}]", i);
878 return fmt::format(
"{}[{}]",
name, i);
880 value_proxy.
impl->getter = [parent_proxy = var_proxy, i](entt::meta_any& result)
883 if(parent_proxy.impl->getter(var) && var)
885 auto view = var.as_sequence_container();
886 if(
view.size() >
static_cast<std::size_t
>(i))
888 auto value =
view[i];
895 value_proxy.
impl->setter = [parent_proxy = var_proxy, i](
meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
898 if(parent_proxy.impl->getter(var) && var)
900 auto view = var.as_sequence_container();
901 if(
view.size() >
static_cast<std::size_t
>(i))
904 auto it =
view.begin();
905 std::advance(it,
static_cast<std::ptrdiff_t
>(i));
911 view.insert(it, value);
914 return parent_proxy.impl->setter(parent_proxy, var, execution_count);
922 result |=
inspect_var(ctx, value, value_proxy, item_info, custom);
924 override_ctx.pop_segment();
928 auto pos_after = ImGui::GetCursorPos();
931 if(!item_info.read_only && resizeable)
933 ImGui::SetCursorPos(pos_before);
936 ImGui::AlignTextToFramePadding();
937 if(ImGui::Button(
ICON_MDI_DELETE, ImVec2(0.0f, ImGui::GetFrameHeightWithSpacing())))
941 ImGui::SetItemTooltipEx(
"Remove element.");
943 ImGui::SetCursorPos(pos_after);
962 if(index_to_remove != -1)
964 auto it =
view.begin();
965 std::advance(it, index_to_remove);
967 result.changed =
true;
968 result.edit_finished =
true;
976 ImGui::SetItemFocusFrame(ImGui::GetColorU32(ImGuiCol_Separator), 1.0f);
985 const entt::meta_data& prop,
989 auto view = var.as_associative_container();
991 auto int_size =
static_cast<int>(
size);
1084 if(!edited.allow_cast<int64_t>())
1088 auto current_value = edited.cast<int64_t>();
1090 int current_idx = 0;
1093 auto type = var.type();
1098 std::string pretty_name;
1102 std::vector<enum_value> names;
1103 for(
auto kvp :
type.data())
1105 const auto& data = kvp.second;
1108 auto value = data.get(var);
1110 int64_t value64 = 0;
1111 if(value.allow_cast<int64_t>())
1113 value64 = value.cast<int64_t>();
1119 names.emplace_back(enum_value{
name, pretty_name, value64});
1121 if(value64 == current_value)
1128 if(current_idx >=
static_cast<int>(names.size()))
1137 ImGui::LabelText(
"##enum",
"%s", names[current_idx].pretty_name.c_str());
1141 int listbox_item_size =
static_cast<int>(names.size());
1143 ImGuiComboFlags flags = 0;
1145 if(ImGui::BeginCombo(
"##enum", names[current_idx].pretty_name.c_str(), flags))
1147 for(
int n = 0; n < listbox_item_size; n++)
1149 const bool is_selected = (current_idx == n);
1151 if(ImGui::Selectable(names[n].pretty_name.c_str(), is_selected))
1154 result.changed =
true;
1155 result.edit_finished |=
true;
1157 edited = names[n].value;
1159 if(edited.allow_cast(var.type()))
1161 var = std::move(edited);
1165 ImGui::DrawItemActivityOutline();
1168 ImGui::SetItemDefaultFocus();
1173 ImGui::DrawItemActivityOutline();
1180 entt::meta_any& var,
1187 auto type = var.type();
1190 derived_var_proxy.
impl->parent = var_proxy.impl;
1192 derived_var_proxy.
impl->name = var_proxy.impl->name;
1193 derived_var_proxy.
impl->getter = [parent_proxy = var_proxy](entt::meta_any& result) ->
bool
1195 if(parent_proxy.impl->getter(result) && result)
1202 derived_var_proxy.
impl->setter = [parent_proxy = var_proxy](
meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
1205 if(proxy.impl->getter(var) && var)
1208 return parent_proxy.impl->setter(parent_proxy, var, execution_count);
1213 entt::meta_any old_var;
1214 if(info.is_copyable)
1227 result |=
inspector->inspect(ctx, var, derived_var_proxy, info, custom);
1229 else if(
type.is_enum())
1231 result |=
inspect_enum(ctx, var, derived_var_proxy, info);
1239 if(info.is_property)
1256 entt::meta_any& var,
1258 const entt::meta_type&
type,
1262 auto properties =
type.data();
1265 if(properties.begin() == properties.end())
1272 if(
type.is_sequence_container())
1281 std::vector<std::pair<std::string, std::vector<entt::meta_data>>> grouped_props;
1282 for(
auto kvp : properties)
1284 const auto& prop = kvp.second;
1293 auto it = std::find_if(grouped_props.begin(),
1294 grouped_props.end(),
1297 return kv.first == group;
1300 if(it == grouped_props.end())
1303 grouped_props.emplace_back(group, std::vector<entt::meta_data>{prop});
1308 it->second.emplace_back(prop);
1312 for(
auto& kvp : grouped_props)
1314 auto& props = kvp.second;
1316 const auto& group_name = kvp.first;
1318 if(group_name.empty())
1320 for(
auto&& prop : props)
1331 ImGui::SetNextItemOpen(
true, ImGuiCond_Appearing);
1332 ImGui::BeginGroup();
1333 ImGui::AlignTextToFramePadding();
1335 bool open = ImGui::TreeNodeEx(group_name.c_str(), ImGuiTreeNodeFlags_SpanAvailWidth);
1340 ImGui::TreePush(group_name.c_str());
1341 ImGui::PushID(group_name.c_str());
1343 for(
auto& prop : props)
1359 ImGui::SetItemFocusFrame(ImGui::GetColorU32(ImGuiCol_Separator), 1.0f);
1370 entt::meta_any& var,
1376 for(
auto base : var.type().base())
Manages ImGui layout for property inspection in the editor.
auto push_tree_layout(ImGuiTreeNodeFlags flags=0, bool default_open=true) -> bool
Creates a collapsible tree node layout for nested properties.
void set_data(const entt::meta_data &prop, const entt::meta_any &object, bool columns=true)
Updates layout data from meta property.
void pop_layout()
Cleans up ImGui state (IDs, tables, tree nodes)
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.
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.
Class that contains core data for audio listeners. There can only be one instance of it per scene.
std::chrono::duration< float > delta_t
auto GetStyleColor(ImGuiCol idx, float multiplier=1.0f) -> ImVec4
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 is_property_visible(const entt::meta_any &object, const entt::meta_data &prop) -> bool
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 &
auto is_property_readonly(const entt::meta_any &object, const entt::meta_data &prop) -> bool
auto is_property_flattable(const entt::meta_any &object, const entt::meta_data &prop) -> bool
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
auto add_property_action(rtti::context &ctx, prefab_override_context &override_ctx, inspect_result &result, meta_any_proxy &var_proxy, const entt::meta_any &old_var, const entt::meta_any &new_var, const entt::meta_custom &custom) -> bool
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 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 focus_property_on_undo_redo(rtti::context &ctx, const meta_any_proxy &var_proxy)
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 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.
std::vector< math::color > color
std::vector< float > scale
std::vector< math::quat > rotation
Thread-safe handle to an asset.
void sync_prefab_entity(rtti::context &ctx, entt::handle entity, const asset_handle< prefab > &pfb)
void do_action(const std::string &name, const std::function< void()> &action)
static auto context() -> rtti::context &
hpp::uuid id
The unique identifier for the entity.
Result of an inspection operation indicating what changes occurred.
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.
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_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.
auto reset_override() -> bool
bool is_active
Whether we're currently inspecting a prefab instance.
static void mark_ui_document_size_as_changed(entt::handle entity)
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_property_as_changed(entt::handle entity, const entt::meta_type &component_type, const std::string &property_path, const std::string &property_pretty_path={})
Marks a specific property as changed using component type.
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.
std::string last_action_name
delta_t last_action_elapsed_time
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.