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/scene.hpp"
#include "components/spine_player.hpp"
#include "components/spine_renderer.hpp"
#include "components/sprite_renderer.hpp"
#include "systems/flipbook_system.hpp"

View File

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

View File

@@ -12,16 +12,26 @@
#include "../assets/spine_model_asset.hpp"
struct spAnimationState;
struct spSkeleton;
struct spSkeletonClipping;
struct spVertexEffect;
namespace e2d
{
class spine_player final {
public:
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:
spine_player() = default;
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;
[[nodiscard]] float time_scale() const noexcept;
@@ -38,10 +48,16 @@ namespace e2d
spine_player& clear() 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;
private:
animation_ptr animation_;
spine_model_asset::ptr model_;
skeleton_ptr skeleton_;
clipping_ptr clipping_;
effect_ptr effect_;
};
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 <spine/AnimationState.h>
#include <spine/spine.h>
namespace
{
@@ -16,14 +15,53 @@ namespace
namespace e2d
{
spine_player::spine_player(const spine_model_asset::ptr& model)
: model_(model) {
E2D_ASSERT(model_);
E2D_ASSERT(model_->content().animation());
spine_player::spine_player(const spine_model_asset::ptr& model) {
this->model(model);
}
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 {
@@ -118,6 +156,11 @@ namespace e2d
"additionalProperties" : false,
"properties" : {
"model" : { "$ref": "#/common_definitions/address" },
"skin" : { "$ref": "#/common_definitions/name" },
"attachments" : {
"type" : "array",
"items" : { "$ref": "#/definitions/spine_attachment" }
},
"animations" : {
"type" : "array",
"items" : { "$ref": "#/definitions/spine_animation" }
@@ -134,6 +177,15 @@ namespace e2d
"loop" : { "type" : "boolean" },
"delay" : { "type" : "number" }
}
},
"spine_attachment" : {
"type" : "object",
"required" : [ "slot", "name" ],
"additionalProperties" : false,
"properties" : {
"slot" : { "$ref": "#/common_definitions/name" },
"name" : { "$ref": "#/common_definitions/name" }
}
}
}
})json";
@@ -159,6 +211,36 @@ namespace e2d
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") ) {
const auto& animations_json = ctx.root["animations"];
E2D_ASSERT(animations_json.IsArray());
@@ -179,21 +261,21 @@ namespace e2d
if ( item_json.HasMember("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;
}
}
if ( item_json.HasMember("delay") ) {
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;
}
}
if ( item_json.HasMember("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;
}
}
@@ -201,6 +283,7 @@ namespace e2d
component.add_animation(track, name, loop, delay);
}
}
return true;
}
@@ -208,7 +291,10 @@ namespace e2d
asset_dependencies& dependencies,
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;
}
}

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/scene.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/systems/flipbook_system.hpp>
@@ -143,7 +142,6 @@ namespace e2d
.register_component<renderer>("renderer")
.register_component<scene>("scene")
.register_component<spine_player>("spine_player")
.register_component<spine_renderer>("spine_renderer")
.register_component<sprite_renderer>("sprite_renderer");
safe_module_initialize<library>(params.library_root(), the<deferrer>());
safe_module_initialize<world>();

View File

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

View File

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

View File

@@ -22,12 +22,11 @@ namespace e2d
void spine_system::process(ecs::registry& owner) {
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&,
spine_player& player,
const spine_renderer& renderer)
spine_player& player)
{
spSkeleton* skeleton = renderer.skeleton().operator->();
spSkeleton* skeleton = player.skeleton().operator->();
spAnimationState* anim_state = player.animation().operator->();
if ( !skeleton || !anim_state ) {