mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-14 16:09:06 +07:00
spine_renderer united with spine_player
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace e2d
|
||||
class renderer;
|
||||
class scene;
|
||||
class spine_player;
|
||||
class spine_renderer;
|
||||
class sprite_renderer;
|
||||
|
||||
class flipbook_system;
|
||||
|
||||
@@ -12,15 +12,25 @@
|
||||
#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 <>
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -5,8 +5,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include <enduro2d/high/components/spine_player.hpp>
|
||||
|
||||
#include <spine/AnimationState.h>
|
||||
#include <spine/spine.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -16,16 +15,55 @@ namespace
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
spine_player::spine_player(const spine_model_asset::ptr& model)
|
||||
: 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(const spine_model_asset::ptr& model) {
|
||||
this->model(model);
|
||||
}
|
||||
|
||||
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 {
|
||||
E2D_ASSERT(animation_);
|
||||
animation_->timeScale = value;
|
||||
@@ -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";
|
||||
@@ -158,6 +210,36 @@ namespace e2d
|
||||
the<debug>().error("SPINE_PLAYER: Property 'model' is not found");
|
||||
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"];
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
Reference in New Issue
Block a user