38#include <imgui/imgui.h>
39#include <imgui/imgui_internal.h>
40#include <imgui_widgets/sequencer/imgui_neo_sequencer.h>
52 if(ImGui::IsDragDropPossibleTargetForType(
type.c_str()))
54 ImGui::SetItemFocusFrame(ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 0.0f, 1.0f)));
60 if(ImGui::BeginDragDropTarget())
62 if(ImGui::IsDragDropPayloadBeingAccepted())
64 ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
68 ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
73 auto payload = ImGui::AcceptDragDropPayload(
type.c_str());
76 std::string absolute_path(
reinterpret_cast<const char*
>(payload->Data), std::size_t(payload->DataSize));
79 const auto& entry_future = am.template find_asset<T>(key);
80 if(entry_future.is_ready())
92 ImGui::EndDragDropTarget();
98auto pick_asset(ImGuiTextFilter& filter,
100 thumbnail_manager& tm,
103 const std::string&
type) -> inspect_result
105 inspect_result result{};
107 auto fh = ImGui::GetFrameHeight();
108 ImVec2 item_size = ImVec2(fh, fh) * 2.0f;
112 const auto& thumbnail = tm.get_thumbnail(data);
116 auto spinner_size = item_size.x;
117 ImSpinner::Spinner<ImSpinner::SpinnerTypeT::e_st_eclipse>(
"spinner",
118 ImSpinner::Radius{spinner_size * 0.5f},
119 ImSpinner::Thickness{6.0f},
120 ImSpinner::Color{ImSpinner::white},
121 ImSpinner::Speed{6.0f});
127 ImGui::ContentItem citem{};
129 citem.texture_size = texture_size;
130 citem.image_size = item_size;
132 if(ImGui::ContentButtonItem(citem))
134 em.foucs_asset(data);
136 ImGui::SetItemTooltipEx(
"Locate the asset in the content browser.\n%s", data.id().c_str());
138 ImGui::DrawItemActivityOutline();
143 ImGui::Button(
"##None", item_size);
145 ImGui::SetItemFocusFrame(ImGui::GetColorU32(ImGuiCol_TextDisabled), 1.0f);
148 bool drag_dropped = process_drag_drop_target(am, data);
149 result.changed |= drag_dropped;
150 result.edit_finished |= drag_dropped;
154 std::string item = data ? data.name() : fmt::format(
"None ({})",
type);
156 ImGui::AlignTextToFramePadding();
158 auto popup_name = fmt::format(
"Pick {}",
type);
159 bool clicked = ImGui::Button(item.c_str(), ImVec2(ImGui::GetContentRegionAvail().
x, ImGui::GetFrameHeight()));
160 ImGui::DrawItemActivityOutline();
162 ImGui::SetItemTooltipEx(
"%s\n\nPick an Asset", item.c_str());
166 ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size * 0.4f);
167 ImGui::OpenPopup(popup_name.c_str());
172 em.foucs_asset(data);
174 ImGui::DrawItemActivityOutline();
176 ImGui::SetItemTooltipEx(
"Locate the asset in the content browser.\n%s", data.id().c_str());
178 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
185 result.changed =
true;
186 result.edit_finished =
true;
189 ImGui::DrawItemActivityOutline();
191 ImGui::SetItemTooltipEx(
"Reset to default.");
196 ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, ImVec2(0.5f, 0.5f));
197 if(ImGui::BeginPopupModal(popup_name.c_str(), &open))
201 ImGui::CloseCurrentPopup();
204 if(ImGui::IsWindowAppearing())
206 ImGui::SetKeyboardFocusHere();
209 ImGui::DrawFilterWithHint(filter,
"Search...", ImGui::GetContentRegionAvail().
x);
210 ImGui::DrawItemActivityOutline();
212 auto assets = am.get_assets_with_predicate<T>(
213 [&](
const auto& asset)
215 const auto&
id = asset.id();
216 hpp::string_view id_view(
id);
217 return !id_view.starts_with(
"editor:/") && filter.PassFilter(asset.name().c_str());
220 const float size = 100.0f;
222 ImGui::BeginChild(
"##items", {-1.0f, -1.0f});
223 ImGui::ItemBrowser(
size,
227 auto& asset = assets[index];
228 const auto& thumbnail = tm.get_thumbnail(asset);
231 if(asset && !asset.is_ready())
233 auto spinner_size = size;
234 ImSpinner::Spinner<ImSpinner::SpinnerTypeT::e_st_eclipse>(
236 ImSpinner::Radius{spinner_size * 0.5f},
237 ImSpinner::Thickness{6.0f},
238 ImSpinner::Color{ImSpinner::white},
239 ImSpinner::Speed{6.0f});
243 ImVec2 texture_size = ImGui::GetSize(thumbnail, item_size);
244 ImVec2 item_size = {size, size};
247 auto name = asset.name();
249 ImGui::ContentItem citem{};
251 citem.name =
name.c_str();
253 citem.texture_size = texture_size;
254 citem.image_size = item_size;
256 if(ImGui::ContentButtonItem(citem))
259 result.changed = true;
260 result.edit_finished = true;
261 ImGui::CloseCurrentPopup();
264 ImGui::SetItemTooltipEx(
"%s", asset.name().c_str());
272 ImGui::PopStyleVar();
280auto make_asset_instance_proxy(entt::meta_any& var,
const meta_any_proxy& var_proxy) -> meta_any_proxy
282 meta_any_proxy data_var_proxy;
283 data_var_proxy.impl->parent = var_proxy.impl;
285 data_var_proxy.impl->name = var_proxy.impl->name;
286 data_var_proxy.impl->getter = [parent_proxy = var_proxy](entt::meta_any& result)
289 if(parent_proxy.impl->getter(var) && var)
291 auto data = var.cast<std::shared_ptr<T>>();
292 result = entt::forward_as_meta(*data);
297 data_var_proxy.impl->setter =
298 [parent_proxy = var_proxy](meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
301 if(proxy.impl->getter(var) && var)
304 return parent_proxy.impl->setter(parent_proxy, var, execution_count);
308 return data_var_proxy;
312auto make_asset_proxy(entt::meta_any& var,
const meta_any_proxy& var_proxy) -> meta_any_proxy
315 meta_any_proxy data_var_proxy;
316 data_var_proxy.impl->parent = var_proxy.impl;
318 data_var_proxy.impl->
name = var_proxy.impl->name;
319 data_var_proxy.impl->getter = [parent_proxy = var_proxy](entt::meta_any& result)
322 if(parent_proxy.impl->getter(var) && var)
327 auto mat = data.get(
false);
330 result = entt::forward_as_meta(*mat);
337 data_var_proxy.impl->setter =
338 [parent_proxy = var_proxy](meta_any_proxy& proxy,
const entt::meta_any& value, uint64_t execution_count)
mutable
349 return data_var_proxy;
353auto make_mutable_asset_proxy(entt::meta_any& var,
const meta_any_proxy& var_proxy) -> meta_any_proxy
356 meta_any_proxy data_var_proxy;
357 data_var_proxy.impl->parent = var_proxy.impl;
359 data_var_proxy.impl->
name = var_proxy.impl->name;
360 data_var_proxy.impl->getter = [parent_proxy = var_proxy](entt::meta_any& result)
363 if(parent_proxy.impl->getter(var) && var)
368 auto mat = data.get(
false);
371 result = entt::forward_as_meta(*mat);
379 data_var_proxy.impl->setter = [data, parent_proxy = var_proxy](meta_any_proxy& proxy,
380 const entt::meta_any& value,
381 uint64_t execution_count)
mutable
384 if(proxy.impl->getter(var) && var)
387 parent_proxy.impl->setter(parent_proxy, var, execution_count);
390 auto data_asset = data.get(
true);
393 *data_asset = var.cast<T&>();
396 if(execution_count > 1)
399 auto& ctx = engine::context();
400 auto& tm = ctx.get_cached<thumbnail_manager>();
401 tm.regenerate_thumbnail(data.uid());
402 asset_writer::atomic_save_to_file(data.id(), data);
410 return data_var_proxy;
422 const auto tex = data.
get(
false);
425 if(tex->info.numMips > 1)
427 ImGui::KnobSliderScalarT(
"Mip", &inspected_mip_, 0, tex->info.numMips - 1);
434 ImGui::RenderFrameBorder(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
460 return inspect_as_property(ctx, data);
463 bool changed =
false;
464 if(inspected_asset_ != data || inspected_version_ != data.version())
466 inspected_asset_ = data;
467 inspected_version_ = data.version();
475 auto available = ImGui::GetContentRegionAvail();
477 if(ImGui::BeginTabBar(
"asset_handle_texture",
478 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
480 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
482 ImGui::BeginChild(
ex::get_type(data.extension()).c_str());
484 draw_image(data, available);
492 auto tex_var_proxy = make_asset_proxy<gfx::texture>(var, var_proxy);
494 entt::meta_any tex_var;
495 if(tex_var_proxy.impl->getter(tex_var))
503 if(ImGui::BeginTabItem(
"Import"))
505 auto meta = am.get_metadata(data.uid());
507 auto base_importer = meta.meta.importer;
509 auto importer = std::static_pointer_cast<texture_importer_meta>(base_importer);
515 importer_ = std::make_shared<texture_importer_meta>(*importer);
521 if(ImGui::Button(
"Revert"))
526 if(ImGui::Button(
"Apply"))
530 *importer = *importer_;
533 auto meta_absolute_path = asset_writer::resolve_meta_file(data);
534 asset_writer::atomic_save_to_file(meta_absolute_path.string(), meta.meta);
568 return inspect_as_property(ctx, data);
575 auto data_var_proxy = make_mutable_asset_proxy<material>(var, var_proxy);
577 entt::meta_any data_var;
578 if(data_var_proxy.impl->getter(data_var))
589 if(result.edit_finished)
591 asset_writer::atomic_save_to_file(data.id(), data);
603 auto& data = var.cast<std::shared_ptr<material>&>();
612 result.changed =
true;
613 result.edit_finished =
true;
616 if(ImGui::TreeNodeEx(
"Material Instance", ImGuiTreeNodeFlags_AllowOverlap))
618 auto data_var_proxy = make_asset_instance_proxy<material>(var, var_proxy);
619 auto data_var = entt::forward_as_meta(*data);
627 if(ImGui::Button(
"Create Instance"))
629 data = std::make_shared<pbr_material>();
630 result.changed =
true;
631 result.edit_finished =
true;
661 return inspect_as_property(ctx, data);
664 if(inspected_asset_ != data || inspected_version_ != data.version())
666 inspected_asset_ = data;
667 inspected_version_ = data.version();
674 if(ImGui::BeginTabBar(
"asset_handle_mesh",
675 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
677 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
679 ImGui::BeginChild(
ex::get_type(data.extension()).c_str());
687 auto mesh_var_proxy = make_asset_proxy<mesh>(var, var_proxy);
689 entt::meta_any mesh_var;
690 if(mesh_var_proxy.impl->getter(mesh_var))
700 if(ImGui::BeginTabItem(
"Import"))
702 auto meta = am.get_metadata(data.uid());
704 auto base_importer = meta.meta.importer;
706 auto importer = std::static_pointer_cast<mesh_importer_meta>(base_importer);
712 importer_ = std::make_shared<mesh_importer_meta>(*importer);
715 if(ImGui::BeginTabBar(
"asset_handle_mesh_import",
716 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton |
717 ImGuiTabBarFlags_FittingPolicyScroll))
719 if(ImGui::BeginTabItem(
"Model"))
726 if(ImGui::BeginTabItem(
"Rig"))
733 if(ImGui::BeginTabItem(
"Animations"))
740 if(ImGui::BeginTabItem(
"Materials"))
751 if(ImGui::Button(
"Revert"))
756 if(ImGui::Button(
"Apply"))
760 *importer = *importer_;
763 auto meta_absolute_path = asset_writer::resolve_meta_file(data);
764 asset_writer::atomic_save_to_file(meta_absolute_path.string(), meta.meta);
797 return inspect_as_property(ctx, data);
800 if(inspected_asset_ != data || inspected_version_ != data.version())
802 inspected_asset_ = data;
803 inspected_version_ = data.version();
810 if(ImGui::BeginTabBar(
"asset_handle_animation",
811 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
813 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
820 auto clip_var_proxy = make_asset_proxy<animation_clip>(var, var_proxy);
822 entt::meta_any clip_var;
823 if(clip_var_proxy.impl->getter(clip_var))
830 if(ImGui::BeginTabItem(
"Import"))
832 auto meta = am.get_metadata(data.uid());
833 auto base_importer = meta.meta.importer;
835 auto importer = std::static_pointer_cast<animation_importer_meta>(base_importer);
841 importer_ = std::make_shared<animation_importer_meta>(*importer);
844 if(ImGui::BeginTabBar(
"asset_handle_mesh_import",
845 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton |
846 ImGuiTabBarFlags_FittingPolicyScroll))
848 if(ImGui::BeginTabItem(
"Root Motion"))
859 if(ImGui::Button(
"Revert"))
864 if(ImGui::Button(
"Apply"))
868 *importer = *importer_;
871 auto meta_absolute_path = asset_writer::resolve_meta_file(data);
872 asset_writer::atomic_save_to_file(meta_absolute_path.string(), meta.meta);
885 entt::handle instance{};
886 auto view = inspected_scene_.registry->view<prefab_component>();
888 [&](
auto e,
auto&& comp)
890 if(comp.source == prefab && comp.source.version() == inspected_version_)
892 instance = inspected_scene_.create_handle(e);
897 inspected_scene_.unload();
898 instance = inspected_scene_.instantiate(prefab,
false);
899 inspected_version_ = prefab.version();
928 return inspect_as_property(ctx, data);
931 auto prefab_entity = get_prefab_entity(ctx, data);
936 if(ImGui::BeginTabBar(
"asset_handle_prefab",
937 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
939 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
941 ImGui::BeginChild(
ex::get_type(data.extension()).c_str());
947 if(result.edit_finished)
950 asset_writer::atomic_save_to_file(absolute_key.string(), prefab_entity);
956 if(ImGui::BeginTabItem(
"Import"))
958 ImGui::TextUnformatted(
"Import options");
960 if(ImGui::Button(
"Reimport"))
962 asset_actions::reimport(data);
996 return inspect_as_property(ctx, data);
1002 if(ImGui::BeginTabBar(
"asset_handle_scene_prefab",
1003 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
1005 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
1007 ImGui::EndTabItem();
1009 if(ImGui::BeginTabItem(
"Import"))
1011 ImGui::BeginChild(
"Import");
1013 ImGui::TextUnformatted(
"Import options");
1015 if(ImGui::Button(
"Reimport"))
1017 asset_actions::reimport(data);
1021 ImGui::EndTabItem();
1028auto inspector_asset_handle_physics_material::inspect_as_property(
rtti::context& ctx,
1043 entt::meta_any& var,
1050 if(info.is_property)
1052 return inspect_as_property(ctx, data);
1058 auto data_var_proxy = make_mutable_asset_proxy<physics_material>(var, var_proxy);
1060 entt::meta_any data_var;
1061 if(data_var_proxy.impl->getter(data_var))
1066 if(result.edit_finished)
1068 asset_writer::atomic_save_to_file(data.id(), data);
1087void inspector_asset_handle_audio_clip::inspect_clip(
const std::shared_ptr<audio_clip>& var)
1091 source_ = std::make_shared<audio::source>();
1093 source_->update(audio::duration_t(0.0166));
1095 property_layout layout(
"clip",
1098 ImGui::BeginGroup();
1102 if(source_->is_playing())
1108 source_->bind(*var);
1125 auto duration = source_->has_bound_sound() ? source_->get_playback_duration() : var->get_info().duration;
1127 float total_time = floorf(
float(duration.count()) * 100.0f) / 100.0f;
1129 auto current_time = float(source_->get_playback_position().count());
1131 if(ImGui::KnobSliderScalarT(
"##playing_offset", ¤t_time, 0.0f, total_time))
1133 source_->set_playback_position(audio::duration_t(current_time));
1138 entt::meta_any& var,
1145 if(info.is_property)
1147 return inspect_as_property(ctx, data);
1150 if(inspected_asset_ != data || inspected_version_ != data.version())
1152 inspected_asset_ = data;
1153 inspected_version_ = data.version();
1154 importer_ =
nullptr;
1160 if(ImGui::BeginTabBar(
"asset_handle_audio_clip",
1161 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_FittingPolicyScroll))
1163 if(ImGui::BeginTabItem(
ex::get_type(data.extension()).c_str()))
1165 ImGui::BeginChild(
ex::get_type(data.extension()).c_str());
1167 auto data_var = data.get(
false);
1174 auto data_var_proxy = make_asset_proxy<audio_clip>(var, var_proxy);
1176 entt::meta_any data_var;
1177 if(data_var_proxy.impl->getter(data_var))
1182 auto clip = data.get(
false);
1191 ImGui::EndTabItem();
1193 if(ImGui::BeginTabItem(
"Import"))
1195 auto meta = am.get_metadata(data.uid());
1196 auto base_importer = meta.meta.importer;
1198 auto importer = std::static_pointer_cast<audio_importer_meta>(base_importer);
1204 importer_ = std::make_shared<audio_importer_meta>(*importer);
1210 if(ImGui::Button(
"Revert"))
1215 if(ImGui::Button(
"Apply"))
1219 *importer = *importer_;
1222 auto meta_absolute_path = asset_writer::resolve_meta_file(data);
1223 asset_writer::atomic_save_to_file(meta_absolute_path.string(), meta.meta);
1226 ImGui::EndTabItem();
1247 entt::meta_any& var,
1254 if(info.is_property)
1256 return inspect_as_property(ctx, data);
1262 auto data_var = data.get(
false);
1269 auto data_var_proxy = make_asset_proxy<font>(var, var_proxy);
1270 entt::meta_any data_var;
1271 if(data_var_proxy.impl->getter(data_var))
1295 entt::meta_any& var,
1302 if(info.is_property)
1304 return inspect_as_property(ctx, data);
1310 auto data_var_proxy = make_mutable_asset_proxy<ui_tree>(var, var_proxy);
1312 entt::meta_any data_var;
1313 if(data_var_proxy.impl->getter(data_var))
1318 if(result.edit_finished)
1320 asset_writer::atomic_save_to_file(data.id(), data);
1340 entt::meta_any& var,
1347 if(info.is_property)
1349 return inspect_as_property(ctx, data);
1355 auto data_var_proxy = make_mutable_asset_proxy<style_sheet>(var, var_proxy);
1357 entt::meta_any data_var;
1358 if(data_var_proxy.impl->getter(data_var))
1363 if(result.edit_finished)
1365 asset_writer::atomic_save_to_file(data.id(), data);
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_pretty_name(const meta_type &t) -> std::string
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 inspect(rtti::context &ctx, T &obj, const std::string &name={}) -> 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.
Thread-safe handle to an asset.
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.
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.
std::vector< GitHubAsset > assets