mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 00:11:55 +07:00
first impl component creator
This commit is contained in:
@@ -27,9 +27,39 @@ namespace e2d
|
||||
// component_loader
|
||||
//
|
||||
|
||||
template < typename Component >
|
||||
template < typename Component = void >
|
||||
class component_loader;
|
||||
|
||||
template <>
|
||||
class component_loader<> {
|
||||
public:
|
||||
struct fill_context {
|
||||
const str parent_address;
|
||||
const rapidjson::Value& root;
|
||||
const asset_group& dependencies;
|
||||
|
||||
fill_context(
|
||||
str nparent_address,
|
||||
const rapidjson::Value& nroot,
|
||||
const asset_group& ndependencies)
|
||||
: parent_address(std::move(nparent_address))
|
||||
, root(nroot)
|
||||
, dependencies(ndependencies) {}
|
||||
};
|
||||
|
||||
struct collect_context {
|
||||
const str parent_address;
|
||||
const rapidjson::Value& root;
|
||||
|
||||
collect_context(
|
||||
str nparent_address,
|
||||
const rapidjson::Value& nroot)
|
||||
: parent_address(std::move(nparent_address))
|
||||
, root(nroot) {}
|
||||
};
|
||||
public:
|
||||
};
|
||||
|
||||
//
|
||||
// component_creator_base
|
||||
//
|
||||
@@ -43,6 +73,14 @@ namespace e2d
|
||||
public:
|
||||
component_creator_base() = default;
|
||||
virtual ~component_creator_base() noexcept = default;
|
||||
|
||||
virtual bool fill_prototype(
|
||||
ecs::prototype& prototype,
|
||||
const component_loader<>::fill_context& ctx) const = 0;
|
||||
|
||||
virtual bool collect_dependencies(
|
||||
asset_dependencies& dependencies,
|
||||
const component_loader<>::collect_context& ctx) const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -54,6 +92,16 @@ namespace e2d
|
||||
public:
|
||||
component_creator() = default;
|
||||
~component_creator() noexcept override = default;
|
||||
|
||||
bool fill_prototype(
|
||||
ecs::prototype& prototype,
|
||||
const component_loader<>::fill_context& ctx) const override;
|
||||
|
||||
bool collect_dependencies(
|
||||
asset_dependencies& dependencies,
|
||||
const component_loader<>::collect_context& ctx) const override;
|
||||
private:
|
||||
component_loader<Component> loader_;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -67,8 +115,20 @@ namespace e2d
|
||||
|
||||
template < typename Component >
|
||||
component_factory& register_component(str_hash type);
|
||||
|
||||
bool fill_prototype(
|
||||
str_hash type,
|
||||
ecs::prototype& prototype,
|
||||
const component_loader<>::fill_context& ctx) const;
|
||||
|
||||
bool collect_dependencies(
|
||||
str_hash type,
|
||||
asset_dependencies& dependencies,
|
||||
const component_loader<>::collect_context& ctx) const;
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
component_creator_base_iptr find_creator(str_hash type) const;
|
||||
private:
|
||||
mutable std::mutex mutex_;
|
||||
hash_map<str_hash, component_creator_base_iptr> creators_;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,6 +13,35 @@
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
// component_creator
|
||||
//
|
||||
|
||||
template < typename Component >
|
||||
bool component_creator<Component>::fill_prototype(
|
||||
ecs::prototype& prototype,
|
||||
const component_loader<>::fill_context& ctx) const
|
||||
{
|
||||
Component component;
|
||||
if ( !loader_(ctx.parent_address, ctx.root, ctx.dependencies, component) ) {
|
||||
return false;
|
||||
}
|
||||
prototype.component<Component>(component);
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename Component >
|
||||
bool component_creator<Component>::collect_dependencies(
|
||||
asset_dependencies& dependencies,
|
||||
const component_loader<>::collect_context& ctx) const
|
||||
{
|
||||
return loader_(ctx.parent_address, ctx.root, dependencies);
|
||||
}
|
||||
|
||||
//
|
||||
// component_factory
|
||||
//
|
||||
|
||||
template < typename Component >
|
||||
component_factory& component_factory::register_component(str_hash type) {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <enduro2d/high/assets/prefab_asset.hpp>
|
||||
|
||||
#include <enduro2d/high/component.hpp>
|
||||
#include <enduro2d/high/assets/json_asset.hpp>
|
||||
|
||||
namespace
|
||||
@@ -65,13 +66,98 @@ namespace
|
||||
return *schema;
|
||||
}
|
||||
|
||||
stdex::promise<prefab> parse_prefab(
|
||||
void collect_dependencies(
|
||||
str_view parent_address,
|
||||
const rapidjson::Value& root,
|
||||
asset_dependencies& dependencies)
|
||||
{
|
||||
if ( root.HasMember("prototype") ) {
|
||||
dependencies.add_dependency<prefab_asset>(
|
||||
path::combine(parent_address, root["prototype"].GetString()));
|
||||
}
|
||||
|
||||
if ( root.HasMember("components") ) {
|
||||
const rapidjson::Value& components_root = root["components"];
|
||||
for ( rapidjson::Value::ConstMemberIterator component_root = components_root.MemberBegin();
|
||||
component_root != components_root.MemberEnd();
|
||||
++component_root )
|
||||
{
|
||||
component_loader<>::collect_context ctx(
|
||||
parent_address,
|
||||
component_root->value);
|
||||
the<component_factory>().collect_dependencies(
|
||||
component_root->name.GetString(),
|
||||
dependencies,
|
||||
ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if ( root.HasMember("children") ) {
|
||||
const rapidjson::Value& children_root = root["children"];
|
||||
for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) {
|
||||
collect_dependencies(parent_address, children_root[i], dependencies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stdex::promise<asset_group> collect_dependencies(
|
||||
const library& library,
|
||||
str_view parent_address,
|
||||
const rapidjson::Value& root)
|
||||
{
|
||||
E2D_UNUSED(library, parent_address, root);
|
||||
return stdex::make_resolved_promise(prefab());
|
||||
asset_dependencies dependencies;
|
||||
collect_dependencies(parent_address, root, dependencies);
|
||||
return dependencies.load_async(library);
|
||||
}
|
||||
|
||||
prefab parse_prefab(
|
||||
str_view parent_address,
|
||||
const rapidjson::Value& root,
|
||||
const asset_group& dependencies)
|
||||
{
|
||||
prefab content;
|
||||
|
||||
if ( root.HasMember("prototype") ) {
|
||||
auto proto_res = dependencies.find_asset<prefab_asset>(
|
||||
path::combine(parent_address, root["prototype"].GetString()));
|
||||
if ( !proto_res ) {
|
||||
throw prefab_asset_loading_exception();
|
||||
}
|
||||
content = proto_res->content();
|
||||
}
|
||||
|
||||
if ( root.HasMember("components") ) {
|
||||
const rapidjson::Value& components_root = root["components"];
|
||||
for ( rapidjson::Value::ConstMemberIterator component_root = components_root.MemberBegin();
|
||||
component_root != components_root.MemberEnd();
|
||||
++component_root )
|
||||
{
|
||||
component_loader<>::fill_context ctx(
|
||||
parent_address,
|
||||
component_root->value,
|
||||
dependencies);
|
||||
the<component_factory>().fill_prototype(
|
||||
component_root->name.GetString(),
|
||||
content.prototype(),
|
||||
ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if ( root.HasMember("children") ) {
|
||||
const rapidjson::Value& children_root = root["children"];
|
||||
|
||||
vector<prefab> children;
|
||||
children.reserve(children_root.Size());
|
||||
|
||||
for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) {
|
||||
children.emplace_back(parse_prefab(
|
||||
parent_address, children_root[i], dependencies));
|
||||
}
|
||||
|
||||
content.set_children(std::move(children));
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,12 +179,12 @@ namespace e2d
|
||||
}
|
||||
})
|
||||
.then([&library, parent_address, prefab_data](){
|
||||
return parse_prefab(
|
||||
return collect_dependencies(
|
||||
library, parent_address, prefab_data->content());
|
||||
})
|
||||
.then([](auto&& content){
|
||||
return prefab_asset::create(
|
||||
std::forward<decltype(content)>(content));
|
||||
.then([parent_address, prefab_data](const asset_group& dependencies){
|
||||
return prefab_asset::create(parse_prefab(
|
||||
parent_address, prefab_data->content(), dependencies));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
40
sources/enduro2d/high/component.cpp
Normal file
40
sources/enduro2d/high/component.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include <enduro2d/high/component.hpp>
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
bool component_factory::fill_prototype(
|
||||
str_hash type,
|
||||
ecs::prototype& prototype,
|
||||
const component_loader<>::fill_context& ctx) const
|
||||
{
|
||||
auto creator = find_creator(type);
|
||||
return creator
|
||||
? creator->fill_prototype(prototype, ctx)
|
||||
: false;
|
||||
}
|
||||
|
||||
bool component_factory::collect_dependencies(
|
||||
str_hash type,
|
||||
asset_dependencies& dependencies,
|
||||
const component_loader<>::collect_context& ctx) const
|
||||
{
|
||||
auto creator = find_creator(type);
|
||||
return creator
|
||||
? creator->collect_dependencies(dependencies, ctx)
|
||||
: false;
|
||||
}
|
||||
|
||||
component_creator_base_iptr component_factory::find_creator(str_hash type) const {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
const auto iter = creators_.find(type);
|
||||
return iter != creators_.end()
|
||||
? iter->second
|
||||
: nullptr;
|
||||
}
|
||||
}
|
||||
@@ -30,16 +30,12 @@ namespace e2d
|
||||
gobjects_.emplace(inst->entity().id(), inst);
|
||||
|
||||
try {
|
||||
auto inst_n = node::create(inst);
|
||||
auto inst_a = inst->get_component<actor>();
|
||||
if ( !inst_a.exists() ) {
|
||||
inst_a.assign(node::create(inst));
|
||||
}
|
||||
if ( !inst_a.get().node() ) {
|
||||
inst_a.get().node(node::create(inst));
|
||||
}
|
||||
if ( inst_a.get().node()->owner() != inst ) {
|
||||
inst_a.get().node()->owner(inst);
|
||||
if ( inst_a && inst_a->node() ) {
|
||||
inst_n->transform(inst_a->node()->transform());
|
||||
}
|
||||
inst_a.assign(inst_n);
|
||||
} catch (...) {
|
||||
destroy_instance(inst, true);
|
||||
throw;
|
||||
@@ -53,16 +49,12 @@ namespace e2d
|
||||
gobjects_.emplace(inst->entity().id(), inst);
|
||||
|
||||
try {
|
||||
auto inst_n = node::create(inst);
|
||||
auto inst_a = inst->get_component<actor>();
|
||||
if ( !inst_a.exists() ) {
|
||||
inst_a.assign(node::create(inst));
|
||||
}
|
||||
if ( !inst_a.get().node() ) {
|
||||
inst_a.get().node(node::create(inst));
|
||||
}
|
||||
if ( inst_a.get().node()->owner() != inst ) {
|
||||
inst_a.get().node()->owner(inst);
|
||||
if ( inst_a && inst_a->node() ) {
|
||||
inst_n->transform(inst_a->node()->transform());
|
||||
}
|
||||
inst_a.assign(inst_n);
|
||||
} catch (...) {
|
||||
destroy_instance(inst, true);
|
||||
throw;
|
||||
@@ -74,7 +66,7 @@ namespace e2d
|
||||
try {
|
||||
auto inst_a = inst->get_component<actor>();
|
||||
auto child_a = child->get_component<actor>();
|
||||
inst_a.get().node()->add_child(child_a.get().node());
|
||||
inst_a->node()->add_child(child_a->node());
|
||||
} catch (...) {
|
||||
destroy_instance(child, true);
|
||||
throw;
|
||||
@@ -90,8 +82,8 @@ namespace e2d
|
||||
|
||||
void world::destroy_instance(const gobject_iptr& inst, bool recursive) noexcept {
|
||||
if ( recursive ) {
|
||||
node_iptr inst_n = inst && inst->get_component<actor>().exists()
|
||||
? inst->get_component<actor>().get().node()
|
||||
node_iptr inst_n = inst && inst->get_component<actor>()
|
||||
? inst->get_component<actor>()->node()
|
||||
: nullptr;
|
||||
if ( inst_n ) {
|
||||
inst_n->for_each_child([this](const node_iptr& child_n){
|
||||
|
||||
Reference in New Issue
Block a user