mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-16 22:16:53 +07:00
two separated spine system for pre and post update
This commit is contained in:
@@ -43,7 +43,7 @@
|
|||||||
#include "systems/flipbook_system.hpp"
|
#include "systems/flipbook_system.hpp"
|
||||||
#include "systems/label_system.hpp"
|
#include "systems/label_system.hpp"
|
||||||
#include "systems/render_system.hpp"
|
#include "systems/render_system.hpp"
|
||||||
#include "systems/spine_system.hpp"
|
#include "systems/spine_systems.hpp"
|
||||||
|
|
||||||
#include "address.hpp"
|
#include "address.hpp"
|
||||||
#include "asset.hpp"
|
#include "asset.hpp"
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ namespace e2d
|
|||||||
class flipbook_system;
|
class flipbook_system;
|
||||||
class label_system;
|
class label_system;
|
||||||
class render_system;
|
class render_system;
|
||||||
class spine_system;
|
class spine_pre_system;
|
||||||
|
class spine_post_system;
|
||||||
|
|
||||||
template < typename Asset, typename Content >
|
template < typename Asset, typename Content >
|
||||||
class content_asset;
|
class content_asset;
|
||||||
|
|||||||
@@ -10,10 +10,20 @@
|
|||||||
|
|
||||||
namespace e2d
|
namespace e2d
|
||||||
{
|
{
|
||||||
class spine_system final : public ecs::system {
|
class spine_pre_system final : public ecs::system {
|
||||||
public:
|
public:
|
||||||
spine_system();
|
spine_pre_system();
|
||||||
~spine_system() noexcept final;
|
~spine_pre_system() noexcept final;
|
||||||
|
void process(ecs::registry& owner) override;
|
||||||
|
private:
|
||||||
|
class internal_state;
|
||||||
|
std::unique_ptr<internal_state> state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class spine_post_system final : public ecs::system {
|
||||||
|
public:
|
||||||
|
spine_post_system();
|
||||||
|
~spine_post_system() noexcept final;
|
||||||
void process(ecs::registry& owner) override;
|
void process(ecs::registry& owner) override;
|
||||||
private:
|
private:
|
||||||
class internal_state;
|
class internal_state;
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
#include <enduro2d/high/systems/flipbook_system.hpp>
|
#include <enduro2d/high/systems/flipbook_system.hpp>
|
||||||
#include <enduro2d/high/systems/label_system.hpp>
|
#include <enduro2d/high/systems/label_system.hpp>
|
||||||
#include <enduro2d/high/systems/render_system.hpp>
|
#include <enduro2d/high/systems/render_system.hpp>
|
||||||
#include <enduro2d/high/systems/spine_system.hpp>
|
#include <enduro2d/high/systems/spine_systems.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -46,10 +46,11 @@ namespace
|
|||||||
|
|
||||||
bool initialize() final {
|
bool initialize() final {
|
||||||
ecs::registry_filler(the<world>().registry())
|
ecs::registry_filler(the<world>().registry())
|
||||||
.system<flipbook_system>(world::priority_update)
|
.system<flipbook_system>(world::priority_pre_update)
|
||||||
.system<label_system>(world::priority_update)
|
.system<label_system>(world::priority_pre_update)
|
||||||
.system<render_system>(world::priority_render)
|
.system<spine_pre_system>(world::priority_pre_update)
|
||||||
.system<spine_system>(world::priority_update);
|
.system<spine_post_system>(world::priority_post_update)
|
||||||
|
.system<render_system>(world::priority_render);
|
||||||
return !application_ || application_->initialize();
|
return !application_ || application_->initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
237
sources/enduro2d/high/systems/spine_post_system.cpp
Normal file
237
sources/enduro2d/high/systems/spine_post_system.cpp
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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/systems/spine_systems.hpp>
|
||||||
|
|
||||||
|
#include <enduro2d/high/components/spine_player.hpp>
|
||||||
|
#include <enduro2d/high/components/spine_player_cmd.hpp>
|
||||||
|
#include <enduro2d/high/components/spine_player_evt.hpp>
|
||||||
|
|
||||||
|
#include <spine/spine.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using namespace e2d;
|
||||||
|
|
||||||
|
struct entry_internal_state {
|
||||||
|
ecs::entity target;
|
||||||
|
str end_message;
|
||||||
|
str complete_message;
|
||||||
|
|
||||||
|
entry_internal_state(ecs::entity target, str end_msg, str complete_msg)
|
||||||
|
: target(std::move(target))
|
||||||
|
, end_message(std::move(end_msg))
|
||||||
|
, complete_message(std::move(complete_msg)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void entry_listener(
|
||||||
|
spAnimationState*,
|
||||||
|
spEventType type,
|
||||||
|
spTrackEntry* entry,
|
||||||
|
spEvent* event)
|
||||||
|
{
|
||||||
|
if ( !entry->userData ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_internal_state& entry_state =
|
||||||
|
*static_cast<entry_internal_state*>(entry->userData);
|
||||||
|
|
||||||
|
if ( type == SP_ANIMATION_DISPOSE || !entry_state.target.valid() ) {
|
||||||
|
std::unique_ptr<entry_internal_state> entry_internal(&entry_state);
|
||||||
|
entry->userData = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type == SP_ANIMATION_EVENT ) {
|
||||||
|
if ( !event || !event->data ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry_state.target.ensure_component<spine_player_evt>()
|
||||||
|
.add_event(spine_player_evt::custom_evt(event->data->name ? event->data->name : "")
|
||||||
|
.int_value(event->intValue)
|
||||||
|
.float_value(event->floatValue)
|
||||||
|
.string_value(event->stringValue ? event->stringValue : ""));
|
||||||
|
} else if ( type == SP_ANIMATION_END ) {
|
||||||
|
if ( entry_state.end_message.empty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry_state.target.ensure_component<spine_player_evt>()
|
||||||
|
.add_event(spine_player_evt::end_evt(entry_state.end_message));
|
||||||
|
} else if ( type == SP_ANIMATION_COMPLETE ) {
|
||||||
|
if ( entry_state.complete_message.empty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry_state.target.ensure_component<spine_player_evt>()
|
||||||
|
.add_event(spine_player_evt::complete_evt(entry_state.complete_message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class command_visitor final : private noncopyable {
|
||||||
|
public:
|
||||||
|
command_visitor(
|
||||||
|
ecs::entity target,
|
||||||
|
spSkeletonData& skeleton_data,
|
||||||
|
spAnimationState& animation_state)
|
||||||
|
: target_(std::move(target))
|
||||||
|
, skeleton_data_(skeleton_data)
|
||||||
|
, animation_state_(animation_state) {}
|
||||||
|
|
||||||
|
void operator()(const spine_player_cmd::clear_track_cmd& cmd) const noexcept {
|
||||||
|
spAnimationState_clearTrack(
|
||||||
|
&animation_state_,
|
||||||
|
math::numeric_cast<int>(cmd.track()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const spine_player_cmd::set_anim_cmd& cmd) const noexcept {
|
||||||
|
spAnimation* animation = spSkeletonData_findAnimation(&skeleton_data_, cmd.name().c_str());
|
||||||
|
if ( !animation ) {
|
||||||
|
the<debug>().error("SPINE_POST_SYSTEM: animation '%0' is not found", cmd.name());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto entry_state = std::make_unique<entry_internal_state>(
|
||||||
|
target_,
|
||||||
|
cmd.end_message(),
|
||||||
|
cmd.complete_message());
|
||||||
|
|
||||||
|
spTrackEntry* entry = spAnimationState_setAnimation(
|
||||||
|
&animation_state_,
|
||||||
|
math::numeric_cast<int>(cmd.track()),
|
||||||
|
animation,
|
||||||
|
cmd.loop() ? 1 : 0);
|
||||||
|
|
||||||
|
entry->listener = &entry_listener;
|
||||||
|
entry->userData = entry_state.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const spine_player_cmd::add_anim_cmd& cmd) const noexcept {
|
||||||
|
spAnimation* animation = spSkeletonData_findAnimation(&skeleton_data_, cmd.name().c_str());
|
||||||
|
if ( !animation ) {
|
||||||
|
the<debug>().error("SPINE_POST_SYSTEM: animation '%0' is not found", cmd.name());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto entry_state = std::make_unique<entry_internal_state>(
|
||||||
|
target_,
|
||||||
|
cmd.end_message(),
|
||||||
|
cmd.complete_message());
|
||||||
|
|
||||||
|
spTrackEntry* entry = spAnimationState_addAnimation(
|
||||||
|
&animation_state_,
|
||||||
|
math::numeric_cast<int>(cmd.track()),
|
||||||
|
animation,
|
||||||
|
cmd.loop() ? 1 : 0,
|
||||||
|
cmd.delay().value);
|
||||||
|
|
||||||
|
entry->listener = &entry_listener;
|
||||||
|
entry->userData = entry_state.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const spine_player_cmd::set_empty_anim_cmd& cmd) const noexcept {
|
||||||
|
auto entry_state = std::make_unique<entry_internal_state>(
|
||||||
|
target_,
|
||||||
|
cmd.end_message(),
|
||||||
|
cmd.complete_message());
|
||||||
|
|
||||||
|
spTrackEntry* entry = spAnimationState_setEmptyAnimation(
|
||||||
|
&animation_state_,
|
||||||
|
math::numeric_cast<int>(cmd.track()),
|
||||||
|
cmd.mix_duration().value);
|
||||||
|
|
||||||
|
entry->listener = &entry_listener;
|
||||||
|
entry->userData = entry_state.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const spine_player_cmd::add_empty_anim_cmd& cmd) const noexcept {
|
||||||
|
auto entry_state = std::make_unique<entry_internal_state>(
|
||||||
|
target_,
|
||||||
|
cmd.end_message(),
|
||||||
|
cmd.complete_message());
|
||||||
|
|
||||||
|
spTrackEntry* entry = spAnimationState_addEmptyAnimation(
|
||||||
|
&animation_state_,
|
||||||
|
math::numeric_cast<int>(cmd.track()),
|
||||||
|
cmd.mix_duration().value,
|
||||||
|
cmd.delay().value);
|
||||||
|
|
||||||
|
entry->listener = &entry_listener;
|
||||||
|
entry->userData = entry_state.release();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ecs::entity target_;
|
||||||
|
spSkeletonData& skeleton_data_;
|
||||||
|
spAnimationState& animation_state_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace e2d
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// internal_state
|
||||||
|
//
|
||||||
|
|
||||||
|
class spine_post_system::internal_state final {
|
||||||
|
public:
|
||||||
|
internal_state() = default;
|
||||||
|
~internal_state() noexcept = default;
|
||||||
|
|
||||||
|
void process(ecs::registry& owner) {
|
||||||
|
process_commands(owner);
|
||||||
|
clear_commands(owner);
|
||||||
|
clear_events(owner);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void process_commands(ecs::registry& owner) {
|
||||||
|
owner.for_joined_components<spine_player_cmd, spine_player>([](
|
||||||
|
ecs::entity e,
|
||||||
|
const spine_player_cmd& pc,
|
||||||
|
spine_player& p)
|
||||||
|
{
|
||||||
|
spSkeleton* skeleton = p.skeleton().get();
|
||||||
|
spAnimationState* animation_state = p.animation().get();
|
||||||
|
|
||||||
|
if ( !skeleton || !skeleton->data || !animation_state ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
command_visitor v(e, *skeleton->data, *animation_state);
|
||||||
|
for ( const auto& cmd : pc.commands() ) {
|
||||||
|
stdex::visit(v, cmd);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_commands(ecs::registry& owner) {
|
||||||
|
owner.for_each_component<spine_player_cmd>([
|
||||||
|
](const ecs::const_entity&, spine_player_cmd& pc) {
|
||||||
|
pc.clear_commands();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_events(ecs::registry& owner) {
|
||||||
|
owner.for_each_component<spine_player_evt>([
|
||||||
|
](const ecs::const_entity&, spine_player_evt& pe) {
|
||||||
|
pe.clear_events();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// spine_post_system
|
||||||
|
//
|
||||||
|
|
||||||
|
spine_post_system::spine_post_system()
|
||||||
|
: state_(new internal_state()) {}
|
||||||
|
|
||||||
|
spine_post_system::~spine_post_system() noexcept {
|
||||||
|
spAnimationState_disposeStatics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spine_post_system::process(ecs::registry& owner) {
|
||||||
|
state_->process(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
sources/enduro2d/high/systems/spine_pre_system.cpp
Normal file
62
sources/enduro2d/high/systems/spine_pre_system.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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/systems/spine_systems.hpp>
|
||||||
|
|
||||||
|
#include <enduro2d/high/components/spine_player.hpp>
|
||||||
|
#include <enduro2d/high/components/spine_player_cmd.hpp>
|
||||||
|
#include <enduro2d/high/components/spine_player_evt.hpp>
|
||||||
|
|
||||||
|
#include <spine/spine.h>
|
||||||
|
|
||||||
|
namespace e2d
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// internal_state
|
||||||
|
//
|
||||||
|
|
||||||
|
class spine_pre_system::internal_state final {
|
||||||
|
public:
|
||||||
|
internal_state() = default;
|
||||||
|
~internal_state() noexcept = default;
|
||||||
|
|
||||||
|
void process(ecs::registry& owner) {
|
||||||
|
update_animations(owner);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void update_animations(ecs::registry& owner) {
|
||||||
|
const float dt = the<engine>().delta_time();
|
||||||
|
owner.for_each_component<spine_player>([dt](
|
||||||
|
const ecs::const_entity&,
|
||||||
|
spine_player& p)
|
||||||
|
{
|
||||||
|
spSkeleton* skeleton = p.skeleton().get();
|
||||||
|
spAnimationState* anim_state = p.animation().get();
|
||||||
|
|
||||||
|
if ( !skeleton || !anim_state ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spSkeleton_update(skeleton, dt);
|
||||||
|
spAnimationState_update(anim_state, dt);
|
||||||
|
spAnimationState_apply(anim_state, skeleton);
|
||||||
|
spSkeleton_updateWorldTransform(skeleton);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// spine_pre_system
|
||||||
|
//
|
||||||
|
|
||||||
|
spine_pre_system::spine_pre_system()
|
||||||
|
: state_(new internal_state()) {}
|
||||||
|
spine_pre_system::~spine_pre_system() noexcept = default;
|
||||||
|
|
||||||
|
void spine_pre_system::process(ecs::registry& owner) {
|
||||||
|
state_->process(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,199 +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/systems/spine_system.hpp>
|
|
||||||
|
|
||||||
#include <enduro2d/high/components/spine_player.hpp>
|
|
||||||
#include <enduro2d/high/components/spine_animation_event.hpp>
|
|
||||||
|
|
||||||
#include <spine/spine.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// spine will allocate storage for each track, so keep number of track as small as possible
|
|
||||||
constexpr e2d::u32 max_track_count = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace e2d
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// internal_state
|
|
||||||
//
|
|
||||||
|
|
||||||
class spine_system::internal_state final {
|
|
||||||
public:
|
|
||||||
void clear_events(ecs::registry& owner) const;
|
|
||||||
void process_new_animations(ecs::registry& owner);
|
|
||||||
void update_animations(ecs::registry& owner);
|
|
||||||
|
|
||||||
void add_event(spTrackEntry* entry, const str& ev_name);
|
|
||||||
private:
|
|
||||||
struct animation_visitor_;
|
|
||||||
static void event_listener_(spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event);
|
|
||||||
private:
|
|
||||||
flat_map<const spTrackEntry*, str> anim_events_;
|
|
||||||
ecs::registry* owner_ = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// animation_visitor_
|
|
||||||
//
|
|
||||||
|
|
||||||
struct spine_system::internal_state::animation_visitor_ {
|
|
||||||
animation_visitor_(
|
|
||||||
spSkeletonData* skeleton,
|
|
||||||
spAnimationState* anim_state,
|
|
||||||
internal_state& state)
|
|
||||||
: skeleton_(skeleton)
|
|
||||||
, anim_state_(anim_state)
|
|
||||||
, state_(state) {}
|
|
||||||
|
|
||||||
void operator()(const spine_animation_event::clear_track& cmd) const noexcept {
|
|
||||||
E2D_ASSERT(cmd.track < max_track_count);
|
|
||||||
spAnimationState_clearTrack(anim_state_, cmd.track);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(const spine_animation_event::set_anim& cmd) const noexcept {
|
|
||||||
E2D_ASSERT(cmd.track < max_track_count);
|
|
||||||
|
|
||||||
spAnimation* anim = spSkeletonData_findAnimation(skeleton_, cmd.name.c_str());
|
|
||||||
if ( !anim ) {
|
|
||||||
the<debug>().error("SPINE_PLAYER: animation '%0' is not found", cmd.name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
spTrackEntry* entry = spAnimationState_setAnimation(anim_state_, cmd.track, anim, cmd.loop);
|
|
||||||
if ( entry && !cmd.on_complete.empty() ) {
|
|
||||||
state_.add_event(entry, cmd.on_complete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(const spine_animation_event::add_anim& cmd) const noexcept {
|
|
||||||
E2D_ASSERT(cmd.track < max_track_count);
|
|
||||||
|
|
||||||
spAnimation* anim = spSkeletonData_findAnimation(skeleton_, cmd.name.c_str());
|
|
||||||
if ( !anim ) {
|
|
||||||
the<debug>().error("SPINE_PLAYER: animation '%0' is not found", cmd.name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
spTrackEntry* entry = spAnimationState_addAnimation(anim_state_, cmd.track, anim, cmd.loop, cmd.delay.value);
|
|
||||||
if ( entry && !cmd.on_complete.empty() ) {
|
|
||||||
state_.add_event(entry, cmd.on_complete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(const spine_animation_event::empty_anim& cmd) const noexcept {
|
|
||||||
E2D_ASSERT(cmd.track < max_track_count);
|
|
||||||
spTrackEntry* entry = spAnimationState_addEmptyAnimation(anim_state_, cmd.track, cmd.duration.value, cmd.delay.value);
|
|
||||||
if ( entry && !cmd.on_complete.empty() ) {
|
|
||||||
state_.add_event(entry, cmd.on_complete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
spSkeletonData* skeleton_;
|
|
||||||
spAnimationState* anim_state_;
|
|
||||||
internal_state& state_;
|
|
||||||
};
|
|
||||||
|
|
||||||
void spine_system::internal_state::add_event(spTrackEntry* entry, const str& ev_name) {
|
|
||||||
anim_events_.insert_or_assign(entry, ev_name);
|
|
||||||
entry->listener = &event_listener_;
|
|
||||||
entry->userData = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spine_system::internal_state::event_listener_(spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event) {
|
|
||||||
if ( !entry || !entry->userData || type == SP_ANIMATION_DISPOSE ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_state* self = reinterpret_cast<internal_state*>(entry->userData);
|
|
||||||
auto entry_to_event = self->anim_events_.find(entry);
|
|
||||||
if ( entry_to_event == self->anim_events_.end() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecs::entity_id id(size_t(state->userData));
|
|
||||||
ecs::entity ent(*self->owner_, id);
|
|
||||||
|
|
||||||
switch ( type ) {
|
|
||||||
case SP_ANIMATION_COMPLETE: {
|
|
||||||
auto* comp = ent.find_component<spine_player::on_complete_event>();
|
|
||||||
if ( !comp ) {
|
|
||||||
comp = &ent.assign_component<spine_player::on_complete_event>();
|
|
||||||
}
|
|
||||||
comp->completed().push_back(std::move(entry_to_event->second));
|
|
||||||
|
|
||||||
self->anim_events_.erase(entry_to_event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void spine_system::internal_state::clear_events(ecs::registry& owner) const {
|
|
||||||
owner.remove_all_components<spine_player::on_complete_event>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void spine_system::internal_state::process_new_animations(ecs::registry& owner) {
|
|
||||||
owner_ = &owner;
|
|
||||||
owner.for_joined_components<spine_animation_event, spine_player>(
|
|
||||||
[this, &owner](
|
|
||||||
ecs::entity_id id,
|
|
||||||
const spine_animation_event& events,
|
|
||||||
spine_player& player)
|
|
||||||
{
|
|
||||||
spSkeleton* skeleton = player.skeleton().get();
|
|
||||||
spAnimationState* anim_state = player.animation().get();
|
|
||||||
|
|
||||||
if ( !skeleton || !anim_state ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
anim_state->userData = reinterpret_cast<void*>(size_t(id));
|
|
||||||
|
|
||||||
animation_visitor_ vis(skeleton->data, anim_state, *this);
|
|
||||||
for ( auto& ev : events.commands() ) {
|
|
||||||
stdex::visit(vis, ev);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
owner.remove_all_components<spine_animation_event>();
|
|
||||||
owner_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spine_system::internal_state::update_animations(ecs::registry& owner) {
|
|
||||||
const float dt = the<engine>().delta_time();
|
|
||||||
owner_ = &owner;
|
|
||||||
owner.for_each_component<spine_player>(
|
|
||||||
[dt](
|
|
||||||
ecs::entity_id id,
|
|
||||||
spine_player& player)
|
|
||||||
{
|
|
||||||
spSkeleton* skeleton = player.skeleton().get();
|
|
||||||
spAnimationState* anim_state = player.animation().get();
|
|
||||||
|
|
||||||
if ( !skeleton || !anim_state ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spSkeleton_update(skeleton, dt);
|
|
||||||
spAnimationState_update(anim_state, dt);
|
|
||||||
spAnimationState_apply(anim_state, skeleton);
|
|
||||||
spSkeleton_updateWorldTransform(skeleton);
|
|
||||||
});
|
|
||||||
owner_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
spine_system::spine_system()
|
|
||||||
: state_(new internal_state()) {}
|
|
||||||
|
|
||||||
spine_system::~spine_system() noexcept {
|
|
||||||
spAnimationState_disposeStatics();
|
|
||||||
}
|
|
||||||
|
|
||||||
void spine_system::process(ecs::registry& owner) {
|
|
||||||
state_->clear_events(owner);
|
|
||||||
state_->process_new_animations(owner);
|
|
||||||
state_->update_animations(owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user