From fefa2a135fa7a24c399166c06a83c9141edb81fa Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 2 Feb 2020 06:29:44 +0700 Subject: [PATCH] add component from inspector --- headers/enduro2d/high/inspector.hpp | 48 +++++++++- headers/enduro2d/high/inspector.inl | 91 ++++++++++++++++--- headers/enduro2d/high/world.hpp | 2 +- samples/bin/library/scenes/sample_08.json | 20 ++++ sources/enduro2d/high/inspector.cpp | 37 ++++++-- .../high/widgets/inspector_widget.cpp | 5 +- sources/enduro2d/high/world.cpp | 2 +- 7 files changed, 180 insertions(+), 25 deletions(-) diff --git a/headers/enduro2d/high/inspector.hpp b/headers/enduro2d/high/inspector.hpp index 7cd9b614..c4d183a6 100644 --- a/headers/enduro2d/high/inspector.hpp +++ b/headers/enduro2d/high/inspector.hpp @@ -148,6 +148,41 @@ namespace e2d }; } + // + // inspector_creator + // + + namespace impl + { + class inspector_creator; + using inspector_creator_iptr = intrusive_ptr; + + class inspector_creator + : private noncopyable + , public ref_counter { + public: + inspector_creator() = default; + virtual ~inspector_creator() noexcept = default; + + virtual void ensure(gobject& go) const = 0; + virtual bool exists(gobject& go) const noexcept = 0; + + virtual const char* title() const noexcept = 0; + }; + + template < typename Component > + class typed_inspector_creator final : public inspector_creator { + public: + typed_inspector_creator() = default; + ~typed_inspector_creator() noexcept final = default; + + void ensure(gobject& go) const final; + bool exists(gobject& go) const noexcept final; + + const char* title() const noexcept final; + }; + } + // // inspector // @@ -158,17 +193,22 @@ namespace e2d ~inspector() noexcept final = default; template < typename Component > - inspector& register_component(str_hash type); + inspector& register_component(str type); void show_for( - gobject& go); + gobject go); void show_for( - gobject& go, + gobject go, component_inspector<>::gizmos_context& ctx); + private: + struct inspector_impl { + impl::inspector_drawer_iptr drawer; + impl::inspector_creator_iptr creator; + }; private: mutable std::mutex mutex_; - hash_map drawers_; + flat_map inspector_impls_; }; } diff --git a/headers/enduro2d/high/inspector.inl b/headers/enduro2d/high/inspector.inl index 270bc568..a2d9e45b 100644 --- a/headers/enduro2d/high/inspector.inl +++ b/headers/enduro2d/high/inspector.inl @@ -50,7 +50,10 @@ namespace e2d for ( Iter iter = begin; iter != end; ) { const v2f p1 = *iter++; const v2f p2 = (iter != end) ? *iter : *begin; - draw_line(center + p1, center + p2, color); + draw_line( + center + p1, + center + p2, + color); } } @@ -60,16 +63,18 @@ namespace e2d const v2f& center, const color32& color) { - draw_wire_polygon(std::begin(container), std::end(container), center, color); + draw_wire_polygon( + std::begin(container), + std::end(container), + center, + color); } } namespace e2d::impl { template < typename Component > - void typed_inspector_drawer::operator()( - gobject& go) const - { + void typed_inspector_drawer::operator()(gobject& go) const { if constexpr ( utils::is_detected() ) { gcomponent co = go.component(); if ( !co ) { @@ -79,7 +84,42 @@ namespace e2d::impl ImGui::PushID(co.find()); E2D_DEFER([](){ ImGui::PopID(); }); - if ( ImGui::CollapsingHeader(component_inspector::title) ) { + const bool inspector_opened = ImGui::CollapsingHeader( + component_inspector::title, + ImGuiTreeNodeFlags_AllowItemOverlap); + + const char* component_popup_context_str_id = "e2d_component_popup_context"; + if ( ImGui::BeginPopupContextItem(component_popup_context_str_id) ) { + E2D_DEFER([](){ ImGui::EndPopup(); }); + + auto disabled_co = co.owner().template component>(); + if ( bool enabled = !disabled_co; ImGui::Checkbox("Enabled", &enabled) ) { + if ( enabled ) { + disabled_co.remove(); + } else { + disabled_co.ensure(); + } + } + + ImGui::Separator(); + + if ( ImGui::Button("Remove") ) { + co.remove(); + return; + } + } + + { + ImGui::SameLine( + ImGui::GetWindowContentRegionMax().x - + ImGui::GetFrameHeight()); + + if ( ImGui::Button(ICON_FA_COG) ) { + ImGui::OpenPopup(component_popup_context_str_id); + } + } + + if ( inspector_opened ) { inspector_(co); } } @@ -99,21 +139,50 @@ namespace e2d::impl ImGui::PushID(co.find()); E2D_DEFER([](){ ImGui::PopID(); }); - inspector_(co, ctx); + if ( !co.owner().template component>() ) { + inspector_(co, ctx); + } } } } +namespace e2d::impl +{ + template < typename Component > + void typed_inspector_creator::ensure(gobject& go) const { + go.component().ensure(); + } + + template < typename Component > + bool typed_inspector_creator::exists(gobject& go) const noexcept { + return go.component().exists(); + } + + template < typename Component > + const char* typed_inspector_creator::title() const noexcept { + return component_inspector::title; + } +} + namespace e2d { template < typename Component > - inspector& inspector::register_component(str_hash type) { + inspector& inspector::register_component(str type) { std::lock_guard guard(mutex_); - if ( drawers_.count(type) > 0 ) { + + if ( inspector_impls_.count(type) > 0 ) { throw bad_inspector_operation(); } - impl::inspector_drawer_iptr drawer(new impl::typed_inspector_drawer()); - drawers_.emplace(type, std::move(drawer)); + + auto drawer = make_intrusive>(); + auto creator = make_intrusive>(); + + inspector_impls_.insert(std::make_pair( + std::move(type), + inspector_impl{ + std::move(drawer), + std::move(creator)})); + return *this; } } diff --git a/headers/enduro2d/high/world.hpp b/headers/enduro2d/high/world.hpp index 1d12599e..7b90e9f6 100644 --- a/headers/enduro2d/high/world.hpp +++ b/headers/enduro2d/high/world.hpp @@ -31,7 +31,7 @@ namespace e2d gobject instantiate(const node_iptr& parent, const t2f& transform); gobject instantiate(const prefab& prefab, const node_iptr& parent, const t2f& transform); - void destroy_instance(gobject& inst) noexcept; + void destroy_instance(gobject inst) noexcept; void finalize_instances() noexcept; private: ecs::registry registry_; diff --git a/samples/bin/library/scenes/sample_08.json b/samples/bin/library/scenes/sample_08.json index 5c1de842..78aba80c 100644 --- a/samples/bin/library/scenes/sample_08.json +++ b/samples/bin/library/scenes/sample_08.json @@ -1,5 +1,8 @@ { "components" : { + "named" : { + "name" : "scene" + }, "scene" : {}, "behaviour" : { "script" : "../scripts/sample_08/sample_08.lua" @@ -102,5 +105,22 @@ "size" : [320, 50] } } + },{ + "prototype" : "../prefabs/label_sdf_prefab.json", + "components" : { + "named" : { + "name" : "label" + }, + "label" : { + "text" : "Hello!", + "halign" : "center", + "outline_width" : 0.5, + "outline_color" : [0,0,0,255] + }, + "actor" : { + "translation" : [-80,-140], + "scale" : 1 + } + } }] } diff --git a/sources/enduro2d/high/inspector.cpp b/sources/enduro2d/high/inspector.cpp index 988ac616..f279368a 100644 --- a/sources/enduro2d/high/inspector.cpp +++ b/sources/enduro2d/high/inspector.cpp @@ -8,17 +8,42 @@ namespace e2d { - void inspector::show_for(gobject& go) { + void inspector::show_for(gobject go) { std::lock_guard guard(mutex_); - for ( auto& p : drawers_ ) { - (*p.second)(go); + + for ( const auto& p : inspector_impls_ ) { + (*p.second.drawer)(go); + } + + ImGui::Separator(); + + { + const char* add_component_popup_str_id = "e2d_add_component_popup"; + + if ( ImGui::Button("+ Add Component") ) { + ImGui::OpenPopup(add_component_popup_str_id); + } + + if ( ImGui::BeginPopup(add_component_popup_str_id) ) { + E2D_DEFER([](){ ImGui::EndPopup(); }); + + for ( const auto& p : inspector_impls_ ) { + if ( ImGui::Button(p.second.creator->title()) ) { + p.second.creator->ensure(go); + ImGui::CloseCurrentPopup(); + } + } + } } } - void inspector::show_for(gobject& go, component_inspector<>::gizmos_context& ctx) { + void inspector::show_for( + gobject go, + component_inspector<>::gizmos_context& ctx) + { std::lock_guard guard(mutex_); - for ( auto& p : drawers_ ) { - (*p.second)(go, ctx); + for ( auto& p : inspector_impls_ ) { + (*p.second.drawer)(go, ctx); } } } diff --git a/sources/enduro2d/high/widgets/inspector_widget.cpp b/sources/enduro2d/high/widgets/inspector_widget.cpp index d61ee8c8..fdced362 100644 --- a/sources/enduro2d/high/widgets/inspector_widget.cpp +++ b/sources/enduro2d/high/widgets/inspector_widget.cpp @@ -22,8 +22,9 @@ namespace e2d::dbgui_widgets return false; } - gobject go = the().selection(); - the().show_for(go); + if ( gobject go = the().selection() ) { + the().show_for(go); + } return true; } diff --git a/sources/enduro2d/high/world.cpp b/sources/enduro2d/high/world.cpp index 3d8313ce..033a96dd 100644 --- a/sources/enduro2d/high/world.cpp +++ b/sources/enduro2d/high/world.cpp @@ -237,7 +237,7 @@ namespace e2d return inst; } - void world::destroy_instance(gobject& inst) noexcept { + void world::destroy_instance(gobject inst) noexcept { auto gstate = inst ? dynamic_pointer_cast(inst.internal_state()) : nullptr;