add component from inspector

This commit is contained in:
2020-02-02 06:29:44 +07:00
parent bbc52def82
commit fefa2a135f
7 changed files with 180 additions and 25 deletions

View File

@@ -148,6 +148,41 @@ namespace e2d
};
}
//
// inspector_creator
//
namespace impl
{
class inspector_creator;
using inspector_creator_iptr = intrusive_ptr<inspector_creator>;
class inspector_creator
: private noncopyable
, public ref_counter<inspector_creator> {
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<str_hash, impl::inspector_drawer_iptr> drawers_;
flat_map<str, inspector_impl> inspector_impls_;
};
}

View File

@@ -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<Component>::operator()(
gobject& go) const
{
void typed_inspector_drawer<Component>::operator()(gobject& go) const {
if constexpr ( utils::is_detected<has_component_inspector, Component>() ) {
gcomponent<Component> co = go.component<Component>();
if ( !co ) {
@@ -79,7 +84,42 @@ namespace e2d::impl
ImGui::PushID(co.find());
E2D_DEFER([](){ ImGui::PopID(); });
if ( ImGui::CollapsingHeader(component_inspector<Component>::title) ) {
const bool inspector_opened = ImGui::CollapsingHeader(
component_inspector<Component>::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<disabled<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<disabled<Component>>() ) {
inspector_(co, ctx);
}
}
}
}
namespace e2d::impl
{
template < typename Component >
void typed_inspector_creator<Component>::ensure(gobject& go) const {
go.component<Component>().ensure();
}
template < typename Component >
bool typed_inspector_creator<Component>::exists(gobject& go) const noexcept {
return go.component<Component>().exists();
}
template < typename Component >
const char* typed_inspector_creator<Component>::title() const noexcept {
return component_inspector<Component>::title;
}
}
namespace e2d
{
template < typename Component >
inspector& inspector::register_component(str_hash type) {
inspector& inspector::register_component(str type) {
std::lock_guard<std::mutex> 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<Component>());
drawers_.emplace(type, std::move(drawer));
auto drawer = make_intrusive<impl::typed_inspector_drawer<Component>>();
auto creator = make_intrusive<impl::typed_inspector_creator<Component>>();
inspector_impls_.insert(std::make_pair(
std::move(type),
inspector_impl{
std::move(drawer),
std::move(creator)}));
return *this;
}
}

View File

@@ -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_;

View File

@@ -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
}
}
}]
}

View File

@@ -8,17 +8,42 @@
namespace e2d
{
void inspector::show_for(gobject& go) {
void inspector::show_for(gobject go) {
std::lock_guard<std::mutex> 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<std::mutex> guard(mutex_);
for ( auto& p : drawers_ ) {
(*p.second)(go, ctx);
for ( auto& p : inspector_impls_ ) {
(*p.second.drawer)(go, ctx);
}
}
}

View File

@@ -22,8 +22,9 @@ namespace e2d::dbgui_widgets
return false;
}
gobject go = the<editor>().selection();
the<inspector>().show_for(go);
if ( gobject go = the<editor>().selection() ) {
the<inspector>().show_for(go);
}
return true;
}

View File

@@ -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<gobject_state>(inst.internal_state())
: nullptr;