36#include <imgui/imgui.h>
37#include <imgui/imgui_internal.h>
38#include <imgui_widgets/sequencer/imgui_neo_sequencer.h>
61 if(ImGui::IsDragDropPossibleTargetForType(
type.c_str()))
63 ImGui::SetItemFocusFrame(ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 0.0f, 1.0f)));
69 if(ImGui::BeginDragDropTarget())
71 if(ImGui::IsDragDropPayloadBeingAccepted())
73 ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
77 ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
82 auto payload = ImGui::AcceptDragDropPayload(
type.c_str());
85 std::string absolute_path(
reinterpret_cast<const char*
>(payload->Data), std::size_t(payload->DataSize));
88 const auto& entry_future = am.template find_asset<T>(key);
89 if(entry_future.is_ready())
101 ImGui::EndDragDropTarget();
107auto pick_asset(ImGuiTextFilter& filter,
109 thumbnail_manager& tm,
112 const std::string&
type) -> inspect_result
114 inspect_result result{};
116 auto fh = ImGui::GetFrameHeight();
117 ImVec2 item_size = ImVec2(fh, fh) * 4.0f;
121 const auto& thumbnail = tm.get_thumbnail(data);
125 ImGui::ContentItem citem{};
127 citem.texture_size = texture_size;
128 citem.image_size = item_size;
130 if(ImGui::ContentButtonItem(citem))
136 ImGui::DrawItemActivityOutline();
140 ImGui::Dummy(item_size);
141 ImGui::RenderFrameEx(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
144 bool drag_dropped = process_drag_drop_target(am, data);
145 result.changed |= drag_dropped;
146 result.edit_finished |= drag_dropped;
150 std::string item = data ? data.name() : fmt::format(
"None ({})",
type);
152 ImGui::AlignTextToFramePadding();
154 auto popup_name = fmt::format(
"Pick {}",
type);
155 bool clicked = ImGui::Button(item.c_str(), ImVec2(ImGui::GetContentRegionAvail().
x, ImGui::GetFrameHeight()));
156 ImGui::DrawItemActivityOutline();
158 ImGui::SetItemTooltipEx(
"%s\n\nPick an Asset", item.c_str());
162 ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size * 0.4f);
163 ImGui::OpenPopup(popup_name.c_str());
171 ImGui::DrawItemActivityOutline();
173 ImGui::SetItemTooltipEx(
"Locate the asset in the content browser.\n%s", data.id().c_str());
175 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
182 result.changed =
true;
183 result.edit_finished =
true;
186 ImGui::DrawItemActivityOutline();
188 ImGui::SetItemTooltipEx(
"Reset to default.");
193 ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, ImVec2(0.5f, 0.5f));
194 if(ImGui::BeginPopupModal(popup_name.c_str(), &open))
198 ImGui::CloseCurrentPopup();
201 if(ImGui::IsWindowAppearing())
203 ImGui::SetKeyboardFocusHere();
206 ImGui::DrawFilterWithHint(filter,
"Search...", ImGui::GetContentRegionAvail().
x);
207 ImGui::DrawItemActivityOutline();
209 auto assets = am.get_assets_with_predicate<T>(
210 [&](
const auto& asset)
212 const auto&
id = asset.
id();
213 hpp::string_view id_view(
id);
214 return !id_view.starts_with(
"editor:/") && filter.PassFilter(asset.
name().c_str());
217 const float size = 100.0f;
219 ImGui::BeginChild(
"##items", {-1.0f, -1.0f});
220 ImGui::ItemBrowser(
size,
224 auto& asset = assets[index];
225 const auto& thumbnail = tm.get_thumbnail(asset);
227 ImVec2 item_size = {size, size};
233 ImGui::ContentItem citem{};
235 citem.name =
name.c_str();
236 citem.texture_size = texture_size;
237 citem.image_size = item_size;
239 if(ImGui::ContentButtonItem(citem))
242 result.changed = true;
243 result.edit_finished = true;
244 ImGui::CloseCurrentPopup();
247 ImGui::SetItemTooltipEx(
"%s", asset.
name().c_str());
254 ImGui::PopStyleVar();
262auto make_asset_instance_proxy(entt::meta_any& var,
const meta_any_proxy& var_proxy) -> meta_any_proxy
264 meta_any_proxy data_var_proxy;
265 data_var_proxy.impl->get_name = [parent_proxy = var_proxy]()
267 return parent_proxy.impl->get_name();
269 data_var_proxy.impl->getter = [parent_proxy = var_proxy](entt::meta_any& result)
272 if(parent_proxy.impl->getter(var) && var)
274 auto data = var.cast<std::shared_ptr<T>>();
275 result = entt::forward_as_meta(*data);
280 data_var_proxy.impl->setter = [parent_proxy = var_proxy](meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
283 if(proxy.impl->getter(var) && var)
286 return parent_proxy.impl->setter(parent_proxy, var, execution_count);
290 return data_var_proxy;
294auto make_asset_proxy(entt::meta_any& var,
const meta_any_proxy& var_proxy) -> meta_any_proxy
297 meta_any_proxy data_var_proxy;
298 data_var_proxy.impl->get_name = [parent_proxy = var_proxy]()
300 return parent_proxy.impl->get_name();
302 data_var_proxy.impl->getter = [parent_proxy = var_proxy](entt::meta_any& result)
305 if(parent_proxy.impl->getter(var) && var)
311 auto mat = data.get(
false);
314 result = entt::forward_as_meta(*mat);
321 data_var_proxy.impl->setter = [parent_proxy = var_proxy](meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
332 return data_var_proxy;
336auto make_mutable_asset_proxy(entt::meta_any& var,
const meta_any_proxy& var_proxy) -> meta_any_proxy
339 meta_any_proxy data_var_proxy;
340 data_var_proxy.impl->get_name = [parent_proxy = var_proxy]()
342 return parent_proxy.impl->get_name();
344 data_var_proxy.impl->getter = [parent_proxy = var_proxy](entt::meta_any& result)
347 if(parent_proxy.impl->getter(var) && var)
352 auto mat = data.get(
false);
355 result = entt::forward_as_meta(*mat);
364 data_var_proxy.impl->setter = [data, parent_proxy = var_proxy](meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
367 if(proxy.impl->getter(var) && var)
370 parent_proxy.impl->setter(parent_proxy, var, execution_count);
373 auto data_asset = data.get(
true);
376 *data_asset = var.cast<T&>();
379 if(execution_count > 1)
383 auto& tm = ctx.get_cached<thumbnail_manager>();
384 tm.regenerate_thumbnail(data.uid());
394 return data_var_proxy;
407 const auto tex = data.
get(
false);
410 if(tex->info.numMips > 1)
412 ImGui::SliderInt(
"Mip", &inspected_mip_, 0, tex->info.numMips - 1);
419 ImGui::RenderFrameBorder(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
445 return inspect_as_property(ctx, data);
448 bool changed =
false;
449 if(inspected_asset_ != data || inspected_version_ != data.version())
451 inspected_asset_ = data;
452 inspected_version_ = data.version();
460 auto available = ImGui::GetContentRegionAvail();
462 if(ImGui::BeginTabBar(
"asset_handle_texture",
463 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
465 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
467 ImGui::BeginChild(
ex::get_type(data.extension()).c_str());
469 draw_image(data, available);
478 auto tex_var_proxy = make_asset_proxy<gfx::texture>(var, var_proxy);
480 entt::meta_any tex_var;
481 if(tex_var_proxy.impl->getter(tex_var))
490 if(ImGui::BeginTabItem(
"Import"))
492 auto meta = am.get_metadata(data.uid());
494 auto base_importer = meta.meta.importer;
496 auto importer = std::static_pointer_cast<texture_importer_meta>(base_importer);
503 importer_ = std::make_shared<texture_importer_meta>(*importer);
509 if(ImGui::Button(
"Revert"))
514 if(ImGui::Button(
"Apply"))
518 *importer = *importer_;
521 auto meta_absolute_path = asset_writer::resolve_meta_file(data);
522 asset_writer::atomic_save_to_file(meta_absolute_path.string(), meta.meta);
556 return inspect_as_property(ctx, data);
563 auto data_var_proxy = make_mutable_asset_proxy<material>(var, var_proxy);
565 entt::meta_any data_var;
566 if(data_var_proxy.impl->getter(data_var))
578 if(result.edit_finished)
580 asset_writer::atomic_save_to_file(data.id(), data);
592 auto& data = var.cast<std::shared_ptr<material>&>();
602 result.changed =
true;
603 result.edit_finished =
true;
606 if(ImGui::TreeNodeEx(
"Material Instance", ImGuiTreeNodeFlags_AllowOverlap))
608 auto data_var_proxy = make_asset_instance_proxy<material>(var, var_proxy);
609 auto data_var = entt::forward_as_meta(*data);
617 if(ImGui::Button(
"Create Instance"))
619 data = std::make_shared<pbr_material>();
620 result.changed =
true;
621 result.edit_finished =
true;
652 return inspect_as_property(ctx, data);
655 if(inspected_asset_ != data || inspected_version_ != data.version())
657 inspected_asset_ = data;
658 inspected_version_ = data.version();
665 if(ImGui::BeginTabBar(
"asset_handle_mesh",
666 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
668 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
670 ImGui::BeginChild(
ex::get_type(data.extension()).c_str());
678 auto mesh_var_proxy = make_asset_proxy<mesh>(var, var_proxy);
680 entt::meta_any mesh_var;
681 if(mesh_var_proxy.impl->getter(mesh_var))
692 if(ImGui::BeginTabItem(
"Import"))
694 auto meta = am.get_metadata(data.uid());
696 auto base_importer = meta.meta.importer;
698 auto importer = std::static_pointer_cast<mesh_importer_meta>(base_importer);
704 importer_ = std::make_shared<mesh_importer_meta>(*importer);
707 if(ImGui::BeginTabBar(
"asset_handle_mesh_import",
708 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton |
709 ImGuiTabBarFlags_FittingPolicyScroll))
711 if(ImGui::BeginTabItem(
"Model"))
718 if(ImGui::BeginTabItem(
"Rig"))
725 if(ImGui::BeginTabItem(
"Animations"))
732 if(ImGui::BeginTabItem(
"Materials"))
743 if(ImGui::Button(
"Revert"))
748 if(ImGui::Button(
"Apply"))
752 *importer = *importer_;
755 auto meta_absolute_path = asset_writer::resolve_meta_file(data);
756 asset_writer::atomic_save_to_file(meta_absolute_path.string(), meta.meta);
789 return inspect_as_property(ctx, data);
792 if(inspected_asset_ != data || inspected_version_ != data.version())
794 inspected_asset_ = data;
795 inspected_version_ = data.version();
802 if(ImGui::BeginTabBar(
"asset_handle_animation",
803 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
805 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
812 auto clip_var_proxy = make_asset_proxy<animation_clip>(var, var_proxy);
815 entt::meta_any clip_var;
816 if(clip_var_proxy.impl->getter(clip_var))
824 if(ImGui::BeginTabItem(
"Import"))
826 auto meta = am.get_metadata(data.uid());
827 auto base_importer = meta.meta.importer;
829 auto importer = std::static_pointer_cast<animation_importer_meta>(base_importer);
835 importer_ = std::make_shared<animation_importer_meta>(*importer);
838 if(ImGui::BeginTabBar(
"asset_handle_mesh_import",
839 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton |
840 ImGuiTabBarFlags_FittingPolicyScroll))
842 if(ImGui::BeginTabItem(
"Root Motion"))
853 if(ImGui::Button(
"Revert"))
858 if(ImGui::Button(
"Apply"))
862 *importer = *importer_;
865 auto meta_absolute_path = asset_writer::resolve_meta_file(data);
866 asset_writer::atomic_save_to_file(meta_absolute_path.string(), meta.meta);
878 entt::handle instance{};
879 auto view = inspected_scene_.registry->view<prefab_component>();
881 [&](
auto e,
auto&& comp)
883 if(comp.source == prefab && comp.source.version() == inspected_version_)
885 instance = inspected_scene_.create_handle(e);
890 inspected_scene_.unload();
891 instance = inspected_scene_.instantiate(prefab);
892 inspected_version_ = prefab.version();
921 return inspect_as_property(ctx, data);
924 auto prefab_entity = get_prefab_entity(ctx, data);
929 if(ImGui::BeginTabBar(
"asset_handle_prefab",
930 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
932 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
934 ImGui::BeginChild(
ex::get_type(data.extension()).c_str());
940 if(result.edit_finished)
943 asset_writer::atomic_save_to_file(absolute_key.string(), prefab_entity);
949 if(ImGui::BeginTabItem(
"Import"))
951 ImGui::TextUnformatted(
"Import options");
953 if(ImGui::Button(
"Reimport"))
989 return inspect_as_property(ctx, data);
995 if(ImGui::BeginTabBar(
"asset_handle_scene_prefab",
996 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
998 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
1001 ImGui::EndTabItem();
1003 if(ImGui::BeginTabItem(
"Import"))
1005 ImGui::BeginChild(
"Import");
1007 ImGui::TextUnformatted(
"Import options");
1009 if(ImGui::Button(
"Reimport"))
1015 ImGui::EndTabItem();
1022auto inspector_asset_handle_physics_material::inspect_as_property(
rtti::context& ctx,
1037 entt::meta_any& var,
1044 if(info.is_property)
1046 return inspect_as_property(ctx, data);
1052 auto data_var_proxy = make_mutable_asset_proxy<physics_material>(var, var_proxy);
1054 entt::meta_any data_var;
1055 if(data_var_proxy.impl->getter(data_var))
1060 if(result.edit_finished)
1062 asset_writer::atomic_save_to_file(data.id(), data);
1081void inspector_asset_handle_audio_clip::inspect_clip(
const std::shared_ptr<audio_clip>& var)
1085 source_ = std::make_shared<audio::source>();
1087 source_->update(audio::duration_t(0.0166));
1089 property_layout layout(
"clip",
1092 ImGui::BeginGroup();
1096 if(source_->is_playing())
1102 source_->bind(*var);
1119 auto duration = source_->has_bound_sound() ? source_->get_playback_duration() : var->get_info().duration;
1121 float total_time = floorf(
float(duration.count()) * 100.0f) / 100.0f;
1123 auto current_time = float(source_->get_playback_position().count());
1125 if(ImGui::SliderFloat(
"##playing_offset", ¤t_time, 0.0f, total_time))
1127 source_->set_playback_position(audio::duration_t(current_time));
1132 entt::meta_any& var,
1139 if(info.is_property)
1141 return inspect_as_property(ctx, data);
1144 if(inspected_asset_ != data || inspected_version_ != data.version())
1146 inspected_asset_ = data;
1147 inspected_version_ = data.version();
1148 importer_ =
nullptr;
1154 if(ImGui::BeginTabBar(
"asset_handle_audio_clip",
1155 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
1157 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
1159 ImGui::BeginChild(
ex::get_type(data.extension()).c_str());
1161 auto data_var = data.get(
false);
1168 auto data_var_proxy = make_asset_proxy<audio_clip>(var, var_proxy);
1170 entt::meta_any data_var;
1171 if(data_var_proxy.impl->getter(data_var))
1176 auto clip = data.get(
false);
1185 ImGui::EndTabItem();
1187 if(ImGui::BeginTabItem(
"Import"))
1189 auto meta = am.get_metadata(data.uid());
1190 auto base_importer = meta.meta.importer;
1192 auto importer = std::static_pointer_cast<audio_importer_meta>(base_importer);
1198 importer_ = std::make_shared<audio_importer_meta>(*importer);
1204 if(ImGui::Button(
"Revert"))
1209 if(ImGui::Button(
"Apply"))
1213 *importer = *importer_;
1216 auto meta_absolute_path = asset_writer::resolve_meta_file(data);
1217 asset_writer::atomic_save_to_file(meta_absolute_path.string(), meta.meta);
1220 ImGui::EndTabItem();
1244 entt::meta_any& var,
1251 if(info.is_property)
1253 return inspect_as_property(ctx, data);
1259 auto data_var = data.get(
false);
1266 auto data_var_proxy = make_asset_proxy<font>(var, var_proxy);
1267 entt::meta_any data_var;
1268 if(data_var_proxy.impl->getter(data_var))
1293 entt::meta_any& var,
1300 if(info.is_property)
1302 return inspect_as_property(ctx, data);
1308 auto data_var_proxy = make_mutable_asset_proxy<ui_tree>(var, var_proxy);
1310 entt::meta_any data_var;
1311 if(data_var_proxy.impl->getter(data_var))
1316 if(result.edit_finished)
1318 asset_writer::atomic_save_to_file(data.id(), data);
1338 entt::meta_any& var,
1345 if(info.is_property)
1347 return inspect_as_property(ctx, data);
1353 auto data_var_proxy = make_mutable_asset_proxy<style_sheet>(var, var_proxy);
1355 entt::meta_any data_var;
1356 if(data_var_proxy.impl->getter(data_var))
1361 if(result.edit_finished)
1363 asset_writer::atomic_save_to_file(data.id(), data);
static void touch(const fs::path &path, bool recursive, fs::file_time_type time=fs::now())
Sets the last modification time of a file or directory. by default sets the time to the current time.
Manages assets, including loading, unloading, and storage.
#define ICON_MDI_UNDO_VARIANT
#define ICON_MDI_FILE_FIND
ImTextureID ToId(gfx::texture_handle _handle, uint8_t _mip=0, uint8_t _flags=IMGUI_FLAGS_ALPHA_BLEND)
ImVec2 GetSize(const gfx::texture &tex, const ImVec2 &fallback={})
auto get_type() -> const std::string &
auto get_suported_formats() -> const std::vector< std::string > &
path resolve_protocol(const path &_path)
Given the specified path/filename, resolve the final full filename. This will be based on either the ...
path convert_to_protocol(const path &_path)
Oposite of the resolve_protocol this function tries to convert to protocol path from an absolute one.
auto resolve_path(const std::string &key) -> fs::path
auto atomic_save_to_file(const fs::path &key, const asset_handle< T > &obj) -> bool
auto inspect(rtti::context &ctx, T &obj) -> inspect_result
Convenience template function for inspecting objects of known type.
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.
static auto get_empty() -> const asset_handle &
Gets an empty asset handle.
auto get(bool wait=true) const -> std::shared_ptr< T >
Gets the shared pointer to the asset.
auto name() const -> std::string
Gets the name of the asset derived from its path.
auto is_ready() const -> bool
Checks if the task is ready.
auto id() const -> const std::string &
Gets the string identifier of the asset.
static auto context() -> rtti::context &
Result of an inspection operation indicating what changes occurred.
Represents a generic prefab with a buffer for serialized data.
void regenerate_thumbnail(const hpp::uuid &uid)
Metadata about a variable being inspected.
bool read_only
Whether the variable should be displayed as read-only.