spine_renderer united with spine_player

This commit is contained in:
andrey.zhirnov
2019-08-27 10:04:42 +03:00
parent a53060f423
commit 79bd643b55
10 changed files with 122 additions and 216 deletions

View File

@@ -36,7 +36,6 @@
#include "components/renderer.hpp" #include "components/renderer.hpp"
#include "components/scene.hpp" #include "components/scene.hpp"
#include "components/spine_player.hpp" #include "components/spine_player.hpp"
#include "components/spine_renderer.hpp"
#include "components/sprite_renderer.hpp" #include "components/sprite_renderer.hpp"
#include "systems/flipbook_system.hpp" #include "systems/flipbook_system.hpp"

View File

@@ -48,7 +48,6 @@ namespace e2d
class renderer; class renderer;
class scene; class scene;
class spine_player; class spine_player;
class spine_renderer;
class sprite_renderer; class sprite_renderer;
class flipbook_system; class flipbook_system;

View File

@@ -12,15 +12,25 @@
#include "../assets/spine_model_asset.hpp" #include "../assets/spine_model_asset.hpp"
struct spAnimationState; struct spAnimationState;
struct spSkeleton;
struct spSkeletonClipping;
struct spVertexEffect;
namespace e2d namespace e2d
{ {
class spine_player final { class spine_player final {
public: public:
using animation_ptr = std::shared_ptr<spAnimationState>; using animation_ptr = std::shared_ptr<spAnimationState>;
using skeleton_ptr = std::shared_ptr<spSkeleton>;
using clipping_ptr = std::shared_ptr<spSkeletonClipping>;
using effect_ptr = std::shared_ptr<spVertexEffect>;
public: public:
spine_player() = default; spine_player() = default;
spine_player(const spine_model_asset::ptr& model); spine_player(const spine_model_asset::ptr& model);
spine_player& model(const spine_model_asset::ptr& value) noexcept;
spine_player& skin(const str& value) noexcept;
spine_player& attachment(const str& slot, const str& name) noexcept;
spine_player& time_scale(float value) noexcept; spine_player& time_scale(float value) noexcept;
[[nodiscard]] float time_scale() const noexcept; [[nodiscard]] float time_scale() const noexcept;
@@ -38,10 +48,16 @@ namespace e2d
spine_player& clear() noexcept; spine_player& clear() noexcept;
const animation_ptr& animation() const noexcept; const animation_ptr& animation() const noexcept;
const skeleton_ptr& skeleton() const noexcept;
const clipping_ptr& clipper() const noexcept;
const effect_ptr& effect() const noexcept;
const spine_model_asset::ptr& model() const noexcept; const spine_model_asset::ptr& model() const noexcept;
private: private:
animation_ptr animation_; animation_ptr animation_;
spine_model_asset::ptr model_; spine_model_asset::ptr model_;
skeleton_ptr skeleton_;
clipping_ptr clipping_;
effect_ptr effect_;
}; };
template <> template <>

View File

@@ -1,58 +0,0 @@
/*******************************************************************************
* 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)
******************************************************************************/
#pragma once
#include "../_high.hpp"
#include "../factory.hpp"
#include "../assets/spine_model_asset.hpp"
struct spSkeleton;
struct spSkeletonClipping;
struct spVertexEffect;
namespace e2d
{
class spine_renderer final {
public:
using skeleton_ptr = std::shared_ptr<spSkeleton>;
using clipping_ptr = std::shared_ptr<spSkeletonClipping>;
using effect_ptr = std::shared_ptr<spVertexEffect>;
public:
spine_renderer() = default;
spine_renderer(const spine_model_asset::ptr& model);
spine_renderer& model(const spine_model_asset::ptr& value) noexcept;
spine_renderer& skin(const str& value) noexcept;
spine_renderer& attachment(const str& slot, const str& name) noexcept;
const skeleton_ptr& skeleton() const noexcept;
const clipping_ptr& clipper() const noexcept;
const effect_ptr& effect() const noexcept;
const spine_model_asset::ptr& model() const noexcept;
private:
skeleton_ptr skeleton_;
clipping_ptr clipping_;
effect_ptr effect_;
spine_model_asset::ptr model_;
};
template <>
class factory_loader<spine_renderer> final : factory_loader<> {
public:
static const char* schema_source;
bool operator()(
spine_renderer& component,
const fill_context& ctx) const;
bool operator()(
asset_dependencies& dependencies,
const collect_context& ctx) const;
};
}

View File

@@ -5,8 +5,7 @@
******************************************************************************/ ******************************************************************************/
#include <enduro2d/high/components/spine_player.hpp> #include <enduro2d/high/components/spine_player.hpp>
#include <spine/spine.h>
#include <spine/AnimationState.h>
namespace namespace
{ {
@@ -16,16 +15,55 @@ namespace
namespace e2d namespace e2d
{ {
spine_player::spine_player(const spine_model_asset::ptr& model) spine_player::spine_player(const spine_model_asset::ptr& model) {
: model_(model) { this->model(model);
E2D_ASSERT(model_);
E2D_ASSERT(model_->content().animation());
animation_ = animation_ptr(
spAnimationState_create(model_->content().animation().get()),
spAnimationState_dispose);
} }
spine_player& spine_player::model(const spine_model_asset::ptr& value) noexcept {
E2D_ASSERT(value);
E2D_ASSERT(value->content().skeleton());
E2D_ASSERT(value->content().atlas());
model_ = value;
skeleton_ = skeleton_ptr(spSkeleton_create(model_->content().skeleton().get()), spSkeleton_dispose);
clipping_ = clipping_ptr(spSkeletonClipping_create(), spSkeletonClipping_dispose);
if ( model_->content().animation() ) {
animation_ = animation_ptr(
spAnimationState_create(model_->content().animation().get()),
spAnimationState_dispose);
} else {
animation_.reset();
}
return *this;
}
spine_player& spine_player::skin(const str& value) noexcept {
spSkeleton_setSkinByName(skeleton_.get(), value.empty() ? nullptr : value.c_str());
return *this;
}
spine_player& spine_player::attachment(const str& slot, const str& name) noexcept {
E2D_ASSERT(!slot.empty());
E2D_ASSERT(!name.empty());
if ( !spSkeleton_setAttachment(skeleton_.get(), slot.c_str(), name.c_str()) ) {
the<debug>().error("SPINE_RENDERER: can't set attachment '%0' to slot '%1'", name, slot);
}
return *this;
}
const spine_player::skeleton_ptr& spine_player::skeleton() const noexcept {
return skeleton_;
}
const spine_player::clipping_ptr& spine_player::clipper() const noexcept {
return clipping_;
}
const spine_player::effect_ptr& spine_player::effect() const noexcept {
return effect_;
}
spine_player& spine_player::time_scale(float value) noexcept { spine_player& spine_player::time_scale(float value) noexcept {
E2D_ASSERT(animation_); E2D_ASSERT(animation_);
animation_->timeScale = value; animation_->timeScale = value;
@@ -118,6 +156,11 @@ namespace e2d
"additionalProperties" : false, "additionalProperties" : false,
"properties" : { "properties" : {
"model" : { "$ref": "#/common_definitions/address" }, "model" : { "$ref": "#/common_definitions/address" },
"skin" : { "$ref": "#/common_definitions/name" },
"attachments" : {
"type" : "array",
"items" : { "$ref": "#/definitions/spine_attachment" }
},
"animations" : { "animations" : {
"type" : "array", "type" : "array",
"items" : { "$ref": "#/definitions/spine_animation" } "items" : { "$ref": "#/definitions/spine_animation" }
@@ -134,6 +177,15 @@ namespace e2d
"loop" : { "type" : "boolean" }, "loop" : { "type" : "boolean" },
"delay" : { "type" : "number" } "delay" : { "type" : "number" }
} }
},
"spine_attachment" : {
"type" : "object",
"required" : [ "slot", "name" ],
"additionalProperties" : false,
"properties" : {
"slot" : { "$ref": "#/common_definitions/name" },
"name" : { "$ref": "#/common_definitions/name" }
}
} }
} }
})json"; })json";
@@ -158,6 +210,36 @@ namespace e2d
the<debug>().error("SPINE_PLAYER: Property 'model' is not found"); the<debug>().error("SPINE_PLAYER: Property 'model' is not found");
return false; return false;
} }
if ( ctx.root.HasMember("skin") ) {
str skin;
if ( !json_utils::try_parse_value(ctx.root["skin"], skin) ) {
the<debug>().error("SPINE RENDERER: Incorrect formatting of 'skin' property");
return false;
}
component.skin(skin);
}
if ( ctx.root.HasMember("attachments") ) {
const auto& attachments_json = ctx.root["attachments"];
E2D_ASSERT(attachments_json.IsArray());
for ( rapidjson::SizeType i = 0; i < attachments_json.Size(); ++i ) {
E2D_ASSERT(attachments_json[i].IsObject());
const auto& item_json = attachments_json[i];
if ( !item_json.HasMember("slot") ) {
the<debug>().error("SPINE_PLAYER: Incorrect formatting of 'attachments.slot' property");
return false;
}
if ( !item_json.HasMember("name") ) {
the<debug>().error("SPINE_PLAYER: Incorrect formatting of 'attachments.name' property");
return false;
}
component.attachment(item_json["slot"].GetString(), item_json["name"].GetString());
}
}
if ( ctx.root.HasMember("animations") ) { if ( ctx.root.HasMember("animations") ) {
const auto& animations_json = ctx.root["animations"]; const auto& animations_json = ctx.root["animations"];
@@ -179,21 +261,21 @@ namespace e2d
if ( item_json.HasMember("track") ) { if ( item_json.HasMember("track") ) {
if ( !json_utils::try_parse_value(item_json["track"], track) ) { if ( !json_utils::try_parse_value(item_json["track"], track) ) {
the<debug>().error("SPINE_PLAYER: Incorrect formatting of 'track' property"); the<debug>().error("SPINE_PLAYER: Incorrect formatting of 'animations.track' property");
return false; return false;
} }
} }
if ( item_json.HasMember("delay") ) { if ( item_json.HasMember("delay") ) {
if ( !json_utils::try_parse_value(item_json["delay"], delay.value) ) { if ( !json_utils::try_parse_value(item_json["delay"], delay.value) ) {
the<debug>().error("SPINE_PLAYER: Incorrect formatting of 'delay' property"); the<debug>().error("SPINE_PLAYER: Incorrect formatting of 'animations.delay' property");
return false; return false;
} }
} }
if ( item_json.HasMember("loop") ) { if ( item_json.HasMember("loop") ) {
if ( !json_utils::try_parse_value(item_json["loop"], loop) ) { if ( !json_utils::try_parse_value(item_json["loop"], loop) ) {
the<debug>().error("SPINE_PLAYER: Incorrect formatting of 'loop' property"); the<debug>().error("SPINE_PLAYER: Incorrect formatting of 'animations.loop' property");
return false; return false;
} }
} }
@@ -201,6 +283,7 @@ namespace e2d
component.add_animation(track, name, loop, delay); component.add_animation(track, name, loop, delay);
} }
} }
return true; return true;
} }
@@ -208,7 +291,10 @@ namespace e2d
asset_dependencies& dependencies, asset_dependencies& dependencies,
const collect_context& ctx) const const collect_context& ctx) const
{ {
E2D_UNUSED(dependencies, ctx); if ( ctx.root.HasMember("model") ) {
dependencies.add_dependency<spine_model_asset>(
path::combine(ctx.parent_address, ctx.root["model"].GetString()));
}
return true; return true;
} }
} }

View File

@@ -1,132 +0,0 @@
/*******************************************************************************
* 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/components/spine_renderer.hpp>
#include <spine/Skeleton.h>
#include <spine/VertexEffect.h>
#include <spine/SkeletonClipping.h>
namespace e2d
{
spine_renderer::spine_renderer(const spine_model_asset::ptr& model) {
this->model(model);
}
spine_renderer& spine_renderer::model(const spine_model_asset::ptr& value) noexcept {
E2D_ASSERT(value);
E2D_ASSERT(value->content().skeleton());
E2D_ASSERT(value->content().atlas());
model_ = value;
skeleton_ = skeleton_ptr(spSkeleton_create(model_->content().skeleton().get()), spSkeleton_dispose);
clipping_ = clipping_ptr(spSkeletonClipping_create(), spSkeletonClipping_dispose);
return *this;
}
spine_renderer& spine_renderer::skin(const str& value) noexcept {
spSkeleton_setSkinByName(skeleton_.get(), value.empty() ? nullptr : value.c_str());
return *this;
}
spine_renderer& spine_renderer::attachment(const str& slot, const str& name) noexcept {
E2D_ASSERT(!slot.empty());
E2D_ASSERT(!name.empty());
if ( !spSkeleton_setAttachment(skeleton_.get(), slot.c_str(), name.c_str()) ) {
the<debug>().error("SPINE_RENDERER: can't set attachment '%0' to slot '%1'", name, slot);
}
return *this;
}
const spine_renderer::skeleton_ptr& spine_renderer::skeleton() const noexcept {
return skeleton_;
}
const spine_renderer::clipping_ptr& spine_renderer::clipper() const noexcept {
return clipping_;
}
const spine_renderer::effect_ptr& spine_renderer::effect() const noexcept {
return effect_;
}
const spine_model_asset::ptr& spine_renderer::model() const noexcept {
return model_;
}
}
namespace e2d
{
const char* factory_loader<spine_renderer>::schema_source = R"json({
"type" : "object",
"required" : [ "model" ],
"additionalProperties" : false,
"properties" : {
"model" : { "$ref": "#/common_definitions/address" },
"skin" : { "$ref": "#/common_definitions/name" },
"attachments" : {
"type" : "array",
"items" : { "$ref": "#/definitions/spine_attachment_array" }
}
},
"definitions" : {
"spine_attachment_array" : {
"type" : "array",
"items" : { "$ref": "#/definitions/spine_attachment" }
},
"spine_attachment" : {
"type" : "object",
"required" : [ "slot", "name" ],
"additionalProperties" : false,
"properties" : {
"slot" : { "$ref": "#/common_definitions/name" },
"name" : { "$ref": "#/common_definitions/name" }
}
}
}
})json";
bool factory_loader<spine_renderer>::operator()(
spine_renderer& component,
const fill_context& ctx) const
{
if ( ctx.root.HasMember("model") ) {
auto model = ctx.dependencies.find_asset<spine_model_asset>(
path::combine(ctx.parent_address, ctx.root["model"].GetString()));
if ( !model ) {
the<debug>().error("SPINE RENDERER: Dependency 'model' is not found:\n"
"--> Parent address: %0\n"
"--> Dependency address: %1",
ctx.parent_address,
ctx.root["model"].GetString());
return false;
}
component.model(model);
}
if ( ctx.root.HasMember("skin") ) {
str skin;
if ( !json_utils::try_parse_value(ctx.root["skin"], skin) ) {
the<debug>().error("SPINE RENDERER: Incorrect formatting of 'skin' property");
return false;
}
component.skin(skin);
}
return true;
}
bool factory_loader<spine_renderer>::operator()(
asset_dependencies& dependencies,
const collect_context& ctx) const
{
if ( ctx.root.HasMember("model") ) {
dependencies.add_dependency<spine_model_asset>(
path::combine(ctx.parent_address, ctx.root["model"].GetString()));
}
return true;
}
}

View File

@@ -19,7 +19,6 @@
#include <enduro2d/high/components/renderer.hpp> #include <enduro2d/high/components/renderer.hpp>
#include <enduro2d/high/components/scene.hpp> #include <enduro2d/high/components/scene.hpp>
#include <enduro2d/high/components/spine_player.hpp> #include <enduro2d/high/components/spine_player.hpp>
#include <enduro2d/high/components/spine_renderer.hpp>
#include <enduro2d/high/components/sprite_renderer.hpp> #include <enduro2d/high/components/sprite_renderer.hpp>
#include <enduro2d/high/systems/flipbook_system.hpp> #include <enduro2d/high/systems/flipbook_system.hpp>
@@ -143,7 +142,6 @@ namespace e2d
.register_component<renderer>("renderer") .register_component<renderer>("renderer")
.register_component<scene>("scene") .register_component<scene>("scene")
.register_component<spine_player>("spine_player") .register_component<spine_player>("spine_player")
.register_component<spine_renderer>("spine_renderer")
.register_component<sprite_renderer>("sprite_renderer"); .register_component<sprite_renderer>("sprite_renderer");
safe_module_initialize<library>(params.library_root(), the<deferrer>()); safe_module_initialize<library>(params.library_root(), the<deferrer>());
safe_module_initialize<world>(); safe_module_initialize<world>();

View File

@@ -9,7 +9,6 @@
#include <enduro2d/high/components/renderer.hpp> #include <enduro2d/high/components/renderer.hpp>
#include <enduro2d/high/components/model_renderer.hpp> #include <enduro2d/high/components/model_renderer.hpp>
#include <enduro2d/high/components/sprite_renderer.hpp> #include <enduro2d/high/components/sprite_renderer.hpp>
#include <enduro2d/high/components/spine_renderer.hpp>
#include <enduro2d/high/components/spine_player.hpp> #include <enduro2d/high/components/spine_player.hpp>
#include <spine/AnimationState.h> #include <spine/AnimationState.h>
@@ -116,7 +115,7 @@ namespace e2d::render_system_impl
if ( spr_r ) { if ( spr_r ) {
draw(node, *node_r, *spr_r); draw(node, *node_r, *spr_r);
} }
const spine_renderer* spine_r = node_e.find_component<spine_renderer>(); const spine_player* spine_r = node_e.find_component<spine_player>();
if ( spine_r ) { if ( spine_r ) {
draw(node, *node_r, *spine_r); draw(node, *node_r, *spine_r);
} }
@@ -251,7 +250,7 @@ namespace e2d::render_system_impl
void drawer::context::draw( void drawer::context::draw(
const const_node_iptr& node, const const_node_iptr& node,
const renderer& node_r, const renderer& node_r,
const spine_renderer& spine_r) const spine_player& spine_r)
{ {
constexpr int stride = 2; constexpr int stride = 2;
std::vector<batcher_type::vertex_type> batch_vertices; // TODO: optimize std::vector<batcher_type::vertex_type> batch_vertices; // TODO: optimize

View File

@@ -56,7 +56,7 @@ namespace e2d::render_system_impl
void draw( void draw(
const const_node_iptr& node, const const_node_iptr& node,
const renderer& node_r, const renderer& node_r,
const spine_renderer& spine_r); const spine_player& spine_r);
void flush(); void flush();
private: private:

View File

@@ -22,12 +22,11 @@ namespace e2d
void spine_system::process(ecs::registry& owner) { void spine_system::process(ecs::registry& owner) {
float dt = the<engine>().delta_time(); float dt = the<engine>().delta_time();
owner.for_joined_components<spine_player, spine_renderer>([dt]( owner.for_each_component<spine_player>([dt](
const ecs::const_entity&, const ecs::const_entity&,
spine_player& player, spine_player& player)
const spine_renderer& renderer)
{ {
spSkeleton* skeleton = renderer.skeleton().operator->(); spSkeleton* skeleton = player.skeleton().operator->();
spAnimationState* anim_state = player.animation().operator->(); spAnimationState* anim_state = player.animation().operator->();
if ( !skeleton || !anim_state ) { if ( !skeleton || !anim_state ) {