mirror of
https://github.com/enduro2d/enduro2d.git
synced 2026-03-22 04:44:09 +07:00
add component from inspector
This commit is contained in:
@@ -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_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user