Fixed looping animations

This commit is contained in:
2023-09-22 03:35:11 +03:00
parent 44f2b9b47b
commit 27fd225e90
3 changed files with 126 additions and 233 deletions

View File

@@ -1,3 +1,5 @@
#include <map>
#include <cassert> #include <cassert>
#include <scene/resources/animation.h> #include <scene/resources/animation.h>
#include <servers/audio/audio_stream.h> #include <servers/audio/audio_stream.h>
@@ -31,6 +33,7 @@ static void _animation_process(flecs::entity_t entity, flecs::world &ecs,
static void _stop_playing_caches(struct AnimationPlayerData *player); static void _stop_playing_caches(struct AnimationPlayerData *player);
static void _set_process(struct AnimationPlayerData *player, bool p_process, static void _set_process(struct AnimationPlayerData *player, bool p_process,
bool p_force = false); bool p_force = false);
Map<StringName, AnimationData> AnimationPlayerData::animation_set[2];
} //namespace ECS } //namespace ECS
void ECS::play(struct ECS::AnimationPlayerData *player, void ECS::play(struct ECS::AnimationPlayerData *player,
const StringName &p_name, float p_custom_blend, float p_custom_scale, const StringName &p_name, float p_custom_blend, float p_custom_scale,
@@ -41,8 +44,9 @@ void ECS::play(struct ECS::AnimationPlayerData *player,
if (String(name) == "") { if (String(name) == "") {
name = player->playback.assigned; name = player->playback.assigned;
} }
int type_id = player->type_id;
ERR_FAIL_COND_MSG(!player->animation_set.has(name), ERR_FAIL_COND_MSG(!player->animation_set[type_id].has(name),
"Animation not found: " + name + "."); "Animation not found: " + name + ".");
Playback &c = player->playback; Playback &c = player->playback;
@@ -51,6 +55,7 @@ void ECS::play(struct ECS::AnimationPlayerData *player,
float blend_time = 0; float blend_time = 0;
// find if it can blend // find if it can blend
ECS::BlendKey bk; ECS::BlendKey bk;
flecs::log::trace("%s: %p", __func__, c.current.from);
bk.from = c.current.from->name; bk.from = c.current.from->name;
bk.to = name; bk.to = name;
@@ -88,7 +93,7 @@ void ECS::play(struct ECS::AnimationPlayerData *player,
_stop_playing_caches(player); _stop_playing_caches(player);
} }
c.current.from = &player->animation_set[name]; c.current.from = &player->animation_set[type_id][name];
flecs::log::trace("setting animation from %p", c.current.from); flecs::log::trace("setting animation from %p", c.current.from);
if (c.assigned != name) { // reset if (c.assigned != name) { // reset
@@ -132,24 +137,24 @@ void ECS::play(struct ECS::AnimationPlayerData *player,
#endif #endif
StringName next = animation_get_next(player, p_name); StringName next = animation_get_next(player, p_name);
if (next != StringName() && player->animation_set.has(next)) { if (next != StringName() && player->animation_set[type_id].has(next)) {
queue(player, next); queue(player, next);
} }
flecs::log::trace("%s(): %d animation %p", __func__, __LINE__, flecs::log::trace("%s(): %d animation %p", __func__, __LINE__,
c.current.from->get_animation().ptr()); c.current.from->get_animation());
} }
static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player, static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player,
flecs::entity_t entity, flecs::world &ecs, AnimationData *p_anim, flecs::entity_t entity, flecs::world &ecs, AnimationData *p_anim,
Node *p_root_override) Node *p_root_override)
{ {
// Already cached? // Already cached?
assert(p_anim->get_animation().is_valid()); assert(p_anim->get_animation() != nullptr);
if (p_anim->node_cache_size == if (p_anim->node_cache_size ==
p_anim->get_animation()->get_track_count()) { p_anim->get_animation()->get_track_count()) {
return; return;
} }
const Animation *a = p_anim->get_animation().operator->(); const Animation *a = p_anim->get_animation();
p_anim->node_cache_size = a->get_track_count(); p_anim->node_cache_size = a->get_track_count();
@@ -178,10 +183,22 @@ static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player,
key.bone_idx = bone_id; key.bone_idx = bone_id;
String path = np.get_subname(0); String path = np.get_subname(0);
if (!player->node_cache_map.has(key)) AnimationCache *cache = e.get_mut<AnimationCache>();
player->node_cache_map[key] = ECS::TrackNodeCache();
p_anim->node_cache[i] = &player->node_cache_map[key]; if (!cache->node_cache_map.has(key)) {
int j, idx = -1;
for (j = 0; j < NODE_CACHE_UPDATE_MAX; j++)
if (!cache->node_cache_data[j].used) {
idx = j;
break;
}
assert(idx >= 0);
cache->node_cache_data[idx] = ECS::TrackNodeCache();
cache->node_cache_data[idx].used = true;
cache->node_cache_map[key] = idx;
}
p_anim->node_cache[i] = &cache->node_cache_data[cache->node_cache_map[key]];
p_anim->node_cache[i]->path = a->track_get_path(i); p_anim->node_cache[i]->path = a->track_get_path(i);
p_anim->node_cache[i]->resource = resource; p_anim->node_cache[i]->resource = resource;
if (a->track_get_type(i) == Animation::TYPE_TRANSFORM) { if (a->track_get_type(i) == Animation::TYPE_TRANSFORM) {
@@ -245,7 +262,7 @@ static void ECS::_animation_process_animation(flecs::entity_t entity,
ERR_FAIL_COND(p_anim->node_cache_size != ERR_FAIL_COND(p_anim->node_cache_size !=
p_anim->get_animation()->get_track_count()); p_anim->get_animation()->get_track_count());
const Animation *a = p_anim->get_animation().ptr(); const Animation *a = p_anim->get_animation();
for (int i = 0; i < a->get_track_count(); i++) { for (int i = 0; i < a->get_track_count(); i++) {
// If an animation changes this animation (or it // If an animation changes this animation (or it
@@ -876,13 +893,11 @@ static void ECS::_animation_process_data(flecs::entity_t entity,
{ {
float delta = p_delta * player->speed_scale * cd.speed_scale; float delta = p_delta * player->speed_scale * cd.speed_scale;
float next_pos = cd.pos + delta; float next_pos = cd.pos + delta;
if (cd.from->get_animation().is_null()) { if (cd.from->get_animation() == nullptr) {
ERR_PRINT("bad animation"); ERR_PRINT("bad animation");
return; return;
} }
assert(cd.from->get_animation().is_valid()); assert(cd.from->get_animation() != nullptr);
flecs::log::trace("%s(): %d animation %p", __func__, __LINE__,
cd.from->get_animation().ptr());
float len = cd.from->get_animation()->get_length(); float len = cd.from->get_animation()->get_length();
bool loop = cd.from->get_animation()->has_loop(); bool loop = cd.from->get_animation()->has_loop();
if (!loop) { if (!loop) {
@@ -890,7 +905,6 @@ static void ECS::_animation_process_data(flecs::entity_t entity,
next_pos = 0; next_pos = 0;
else if (next_pos > len) else if (next_pos > len)
next_pos = len; next_pos = len;
}
bool backwards = bool backwards =
signbit(delta); // Negative zero means playing backwards too signbit(delta); // Negative zero means playing backwards too
delta = next_pos - delta = next_pos -
@@ -900,17 +914,19 @@ static void ECS::_animation_process_data(flecs::entity_t entity,
if (!backwards && cd.pos <= len && next_pos == len) { if (!backwards && cd.pos <= len && next_pos == len) {
//playback finished //playback finished
player->end_reached = true; player->end_reached = true;
flecs::log::trace("AT END!!!");
player->end_notify = player->end_notify =
cd.pos < len; // Notify only if not cd.pos < len; // Notify only if not
// already at the end // already at the end
} }
if (backwards && cd.pos >= 0 && next_pos == 0) { if (backwards && cd.pos >= 0 && next_pos <= 0) {
//playback finished //playback finished
player->end_reached = true; player->end_reached = true;
player->end_notify = player->end_notify =
cd.pos > 0; // Notify only if not cd.pos > 0; // Notify only if not
// already at the beginning // already at the beginning
} }
}
} else { } else {
float looped_next_pos = Math::fposmod(next_pos, len); float looped_next_pos = Math::fposmod(next_pos, len);
if (looped_next_pos == 0 && next_pos != 0) if (looped_next_pos == 0 && next_pos != 0)
@@ -930,14 +946,12 @@ static void ECS::_animation_process2(flecs::entity_t entity, flecs::world &ecs,
struct ECS::AnimationPlayerData *player, float p_delta, bool p_started) struct ECS::AnimationPlayerData *player, float p_delta, bool p_started)
{ {
ECS::Playback &c = player->playback; ECS::Playback &c = player->playback;
player->accum_pass++;
if (c.current.from->get_animation().is_null()) { if (c.current.from->get_animation() == nullptr) {
ERR_PRINT("bad animation2"); ERR_PRINT("bad animation2");
return; return;
} }
flecs::log::trace("%s(): %d animation %p", __func__, __LINE__, player->accum_pass++;
c.current.from->get_animation().ptr());
_animation_process_data(entity, ecs, player, c.current, p_delta, 1.0f, _animation_process_data(entity, ecs, player, c.current, p_delta, 1.0f,
c.seeked && p_delta != 0, p_started); c.seeked && p_delta != 0, p_started);
if (p_delta != 0) if (p_delta != 0)
@@ -946,7 +960,7 @@ static void ECS::_animation_process2(flecs::entity_t entity, flecs::world &ecs,
for (List<Blend>::Element *E = c.blend.back(); E; E = prev) { for (List<Blend>::Element *E = c.blend.back(); E; E = prev) {
Blend &b = E->get(); Blend &b = E->get();
float blend = b.blend_left / b.blend_time; float blend = b.blend_left / b.blend_time;
if (b.data.from->get_animation().is_null()) { if (b.data.from->get_animation() == nullptr) {
ERR_PRINT("bad animation3"); ERR_PRINT("bad animation3");
b.blend_left -= b.blend_left -=
Math::absf(player->speed_scale * p_delta); Math::absf(player->speed_scale * p_delta);
@@ -962,8 +976,6 @@ static void ECS::_animation_process2(flecs::entity_t entity, flecs::world &ecs,
if (b.blend_left < 0) if (b.blend_left < 0)
c.blend.erase(E); c.blend.erase(E);
} }
flecs::log::trace("%s(): %d animation %p", __func__, __LINE__,
c.current.from->get_animation().ptr());
} }
/* transforms are set here */ /* transforms are set here */
static void ECS::_animation_update_transforms(flecs::entity_t entity, static void ECS::_animation_update_transforms(flecs::entity_t entity,
@@ -977,15 +989,13 @@ static void ECS::_animation_update_transforms(flecs::entity_t entity,
t.origin = nc->loc_accum; t.origin = nc->loc_accum;
t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum); t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum);
flecs::entity bone_entity = ecs.entity(nc->bone_idx); flecs::entity bone_entity = ecs.entity(nc->bone_idx);
if (bone_entity) { if (bone_entity.is_alive()) {
ECS::BonePose *bone = ECS::BonePose *bone =
bone_entity.get_mut<ECS::BonePose>(); bone_entity.get_mut<ECS::BonePose>();
bone->pose = t; bone->pose = t;
bone_entity.modified<ECS::BonePose>(); bone_entity.modified<ECS::BonePose>();
} }
} }
flecs::log::trace("update bones %f %f %f\n", t.origin.x,
t.origin.y, t.origin.z);
} }
player->cache_update_size = 0; player->cache_update_size = 0;
#ifdef VALUE_TRACK_SUPPORT #ifdef VALUE_TRACK_SUPPORT
@@ -1046,14 +1056,7 @@ static void ECS::_set_process(
static void ECS::_animation_process(flecs::entity_t entity, flecs::world &ecs, static void ECS::_animation_process(flecs::entity_t entity, flecs::world &ecs,
struct ECS::AnimationPlayerData *player, float p_time) struct ECS::AnimationPlayerData *player, float p_time)
{ {
flecs::log::trace("animation_pocess: %f", p_time);
if (player->playback.current.from) { if (player->playback.current.from) {
flecs::log::trace("animation at start: %p %p",
player->playback.current.from,
player->playback.current.from->get_animation().ptr());
flecs::log::trace("length: %f",
player->playback.current.from->get_animation()
->get_length());
player->end_reached = false; player->end_reached = false;
player->end_notify = false; player->end_notify = false;
_animation_process2( _animation_process2(
@@ -1079,8 +1082,6 @@ static void ECS::_animation_process(flecs::entity_t entity, flecs::world &ecs,
} }
player->end_reached = false; player->end_reached = false;
} }
flecs::log::trace("animation at end: %p",
player->playback.current.from->get_animation().ptr());
} else } else
_set_process(player, false); _set_process(player, false);
} }
@@ -1101,52 +1102,61 @@ void ECS::queue(
StringName ECS::animation_get_next( StringName ECS::animation_get_next(
struct ECS::AnimationPlayerData *player, const StringName &p_animation) struct ECS::AnimationPlayerData *player, const StringName &p_animation)
{ {
if (!player->animation_set.has(p_animation)) { int type_id = player->type_id;
if (!player->animation_set[type_id].has(p_animation)) {
return StringName(); return StringName();
} }
return player->animation_set[p_animation].next; return player->animation_set[type_id][p_animation].next;
} }
String ECS::get_current_animation(struct ECS::AnimationPlayerData *player) String ECS::get_current_animation(struct ECS::AnimationPlayerData *player)
{ {
return player->playing ? player->playback.assigned : ""; return player->playing ? player->playback.assigned : "";
} }
Error ECS::add_animation(struct ECS::AnimationPlayerData *player, Error ECS::add_animation(flecs::entity_t entity, flecs::world &ecs, struct ECS::AnimationPlayerData *player,
const StringName &p_name, const Ref<Animation> &p_animation) const StringName &p_name, const Animation *p_animation)
{ {
ERR_FAIL_COND_V(p_animation.is_null(), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_animation == nullptr, ERR_INVALID_PARAMETER);
int type_id = player->type_id;
if (player->animation_set.has(p_name)) { if (player->animation_set[type_id].has(p_name)) {
AnimationData ad(p_animation); AnimationData ad(p_animation);
ad.name = p_name; ad.name = p_name;
player->animation_set[p_name] = ad; player->animation_set[type_id][p_name] = ad;
// player->animation_set[p_name].animation = // player->animation_set[p_name].animation =
//p_animation; //p_animation;
clear_caches(player); clear_caches(entity, ecs, player);
} else { } else {
AnimationData ad(p_animation); AnimationData ad(p_animation);
ad.name = p_name; ad.name = p_name;
player->animation_set[p_name] = ad; player->animation_set[type_id][p_name] = ad;
} }
return OK; return OK;
} }
void ECS::remove_animation( void ECS::remove_animation(flecs::entity_t entity, flecs::world &ecs,
struct ECS::AnimationPlayerData *player, const StringName &p_name) struct ECS::AnimationPlayerData *player, const StringName &p_name)
{ {
ERR_FAIL_COND(!player->animation_set.has(p_name)); int type_id = player->type_id;
ERR_FAIL_COND(!player->animation_set[type_id].has(p_name));
stop(player); stop(player);
player->animation_set.erase(p_name); player->animation_set[type_id].erase(p_name);
clear_caches(player); clear_caches(entity, ecs, player);
} }
void ECS::clear_caches(struct ECS::AnimationPlayerData *player) void ECS::clear_caches(flecs::entity_t entity, flecs::world &ecs, struct ECS::AnimationPlayerData *player)
{ {
int type_id = player->type_id, i;
flecs::entity e = ecs.entity(entity);
ECS::AnimationCache *cache = e.get_mut<ECS::AnimationCache>();
_stop_playing_caches(player); _stop_playing_caches(player);
player->node_cache_map.clear(); cache->node_cache_map.clear();
for (i = 0; i < NODE_CACHE_UPDATE_MAX; i++)
cache->node_cache_data[i].used = false;
for (Map<StringName, AnimationData>::Element *E = for (Map<StringName, AnimationData>::Element *E =
player->animation_set.front(); player->animation_set[type_id].front();
E; E = E->next()) E; E = E->next())
E->get().node_cache_size = 0; E->get().node_cache_size = 0;
player->cache_update_size = 0; player->cache_update_size = 0;
@@ -1154,23 +1164,13 @@ void ECS::clear_caches(struct ECS::AnimationPlayerData *player)
player->cache_update_prop_size = 0; player->cache_update_prop_size = 0;
player->cache_update_bezier_size = 0; player->cache_update_bezier_size = 0;
#endif #endif
e.modified<ECS::AnimationCache>();
} }
void ECS::advance(flecs::entity_t entity, flecs::world &ecs, void ECS::advance(flecs::entity_t entity, flecs::world &ecs,
ECS::AnimationPlayerData *player, float p_time) ECS::AnimationPlayerData *player, float p_time)
{ {
flecs::log::trace(
"start current.from %p", player->playback.current.from);
flecs::log::trace("advance animation at start: %p %p",
player->playback.current.from,
player->playback.current.from->get_animation().ptr());
ECS::_animation_process(entity, ecs, player, p_time); ECS::_animation_process(entity, ecs, player, p_time);
// player->playback.current.from = nullptr;
flecs::log::trace("advance animation at end: %p %p",
player->playback.current.from,
player->playback.current.from->get_animation().ptr());
flecs::log::trace(
"end current.from %p", player->playback.current.from);
} }
void ECS::stop(struct ECS::AnimationPlayerData *player, bool p_reset) void ECS::stop(struct ECS::AnimationPlayerData *player, bool p_reset)
{ {

View File

@@ -19,8 +19,9 @@ enum SpecialProperty {
SP_NODE2D_SCALE, SP_NODE2D_SCALE,
}; };
struct TrackNodeCache { struct TrackNodeCache {
bool used;
NodePath path; NodePath path;
uint32_t id; flecs::entity_t id;
Ref<Resource> resource; Ref<Resource> resource;
#if 0 #if 0
Node *node; Node *node;
@@ -38,6 +39,7 @@ struct TrackNodeCache {
float audio_start; float audio_start;
float audio_len; float audio_len;
bool animation_playing; bool animation_playing;
#if 0
struct PropertyAnim { struct PropertyAnim {
TrackNodeCache *owner; TrackNodeCache *owner;
SpecialProperty special; SpecialProperty special;
@@ -55,6 +57,8 @@ struct TrackNodeCache {
} }
}; };
Map<StringName, PropertyAnim> property_anim; Map<StringName, PropertyAnim> property_anim;
#endif
#if 0
struct BezierAnim { struct BezierAnim {
Vector<StringName> bezier_property; Vector<StringName> bezier_property;
TrackNodeCache *owner; TrackNodeCache *owner;
@@ -71,8 +75,9 @@ struct TrackNodeCache {
} }
}; };
Map<StringName, BezierAnim> bezier_anim; Map<StringName, BezierAnim> bezier_anim;
#endif
TrackNodeCache() : TrackNodeCache() :
id(0), used(false), id(-1),
#if 0 #if 0
node(nullptr), node(nullptr),
spatial(nullptr), spatial(nullptr),
@@ -188,13 +193,14 @@ struct AnimationData {
StringName next; StringName next;
int node_cache_size; int node_cache_size;
struct TrackNodeCache *node_cache[128]; struct TrackNodeCache *node_cache[128];
AnimationData(Ref<Animation> anim) : AnimationData(const Animation *anim) :
animation(anim), node_cache_size(0) animation(anim), node_cache_size(0)
{ {
assert(animation.is_valid()); assert(animation);
animation = anim;
} }
AnimationData() : AnimationData() :
animation(Ref<Animation>(nullptr)), node_cache_size(0) animation(nullptr), node_cache_size(0)
{ {
} }
AnimationData(const AnimationData &d) AnimationData(const AnimationData &d)
@@ -202,19 +208,19 @@ struct AnimationData {
int i; int i;
name = d.name; name = d.name;
next = d.next; next = d.next;
assert(d.animation);
node_cache_size = d.node_cache_size; node_cache_size = d.node_cache_size;
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
node_cache[i] = d.node_cache[i]; node_cache[i] = d.node_cache[i];
animation = d.animation; animation = d.animation;
assert(animation.is_valid()); assert(animation);
flecs::log::trace("%s copy-constructed normally %p: %p",
__func__, this, animation.ptr());
} }
AnimationData(AnimationData &&d) AnimationData(AnimationData &&d)
{ {
int i; int i;
name = d.name; name = d.name;
next = d.next; next = d.next;
assert(d.animation);
node_cache_size = d.node_cache_size; node_cache_size = d.node_cache_size;
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
node_cache[i] = d.node_cache[i]; node_cache[i] = d.node_cache[i];
@@ -223,97 +229,32 @@ struct AnimationData {
d.node_cache_size = 0; d.node_cache_size = 0;
d.name = ""; d.name = "";
d.next = ""; d.next = "";
d.animation = Ref<Animation>(nullptr); d.animation = nullptr;
flecs::log::trace("%s move-constructed normally %p: %p",
__func__, this, animation.ptr());
} }
AnimationData &operator=(const AnimationData &d) AnimationData &operator=(const AnimationData &d)
{ {
memnew_placement(this, AnimationData(d)); memnew_placement(this, AnimationData(d));
return *this; return *this;
} }
const Ref<Animation> &get_animation() const const Animation *get_animation() const
{ {
assert(animation.is_valid());
flecs::log::trace("animation ptr %p", animation.ptr());
return animation; return animation;
} }
~AnimationData() { animation = Ref<Animation>(nullptr); } ~AnimationData() { animation = nullptr; }
private: private:
Ref<Animation> animation; const Animation *animation;
}; };
struct PlaybackData { struct PlaybackData {
AnimationData *from; AnimationData *from;
float pos; float pos;
float speed_scale; float speed_scale;
PlaybackData()
{
pos = 0;
speed_scale = 1.0;
from = nullptr;
}
PlaybackData(const PlaybackData &d)
{
pos = d.pos;
speed_scale = d.speed_scale;
from = d.from;
flecs::log::trace(
"%s copy-constructed normally %p", __func__, this);
}
PlaybackData(PlaybackData &&d)
{
pos = d.pos;
speed_scale = d.speed_scale;
from = d.from;
d.pos = 0;
d.speed_scale = 1.0f;
d.from = nullptr;
flecs::log::trace(
"%s move-constructed normally %p", __func__, this);
}
PlaybackData &operator=(const PlaybackData &d)
{
from = d.from;
pos = d.pos;
speed_scale = d.speed_scale;
return *this;
}
}; };
struct Blend { struct Blend {
PlaybackData data; PlaybackData data;
float blend_time; float blend_time;
float blend_left; float blend_left;
Blend()
{
blend_left = 0.0f;
blend_time = 0.0f;
}
Blend(const Blend &d)
{
data = PlaybackData(d.data);
blend_time = d.blend_time;
blend_left = d.blend_left;
flecs::log::trace(
"%s copy-constructed normally %p", __func__, this);
}
Blend(Blend &&d)
{
data = std::move(d.data);
blend_time = d.blend_time;
blend_left = d.blend_left;
d.blend_left = 0.0f;
d.blend_time = 0.0f;
flecs::log::trace(
"%s move-constructed normally %p", __func__, this);
}
Blend &operator=(const Blend &d)
{
memnew_placement(this, Blend(d));
return *this;
}
}; };
struct Playback { struct Playback {
List<Blend> blend; List<Blend> blend;
@@ -326,39 +267,6 @@ struct Playback {
blend.clear(); blend.clear();
seeked = false; seeked = false;
started = false; started = false;
flecs::log::trace(
"%s constructed normally %p", __func__, this);
}
Playback(const Playback &d)
{
blend = List<Blend>();
const List<Blend>::Element *e = d.blend.front();
/* copy construct blends */
while (e) {
blend.push_back(Blend(e->get()));
e = e->next();
}
current = PlaybackData(d.current);
StringName assigned = d.assigned;
seeked = d.seeked;
started = d.started;
flecs::log::trace(
"%s copy-constructed normally %p", __func__, this);
}
Playback(Playback &&d)
{
blend = std::move(d.blend);
current = std::move(d.current);
StringName assigned = d.assigned;
seeked = d.seeked;
started = d.started;
flecs::log::trace(
"%s move-constructed normally %p", __func__, this);
}
Playback &operator=(const Playback &d)
{
memnew_placement(this, Playback(d));
return *this;
} }
}; };
struct BlendKey { struct BlendKey {
@@ -385,8 +293,15 @@ struct TrackNodeCacheKey {
} }
}; };
enum { NODE_CACHE_UPDATE_MAX = 1024, BLEND_FROM_MAX = 3 }; enum { NODE_CACHE_UPDATE_MAX = 1024, BLEND_FROM_MAX = 3 };
struct AnimationCache {
Map<TrackNodeCacheKey, int> node_cache_map;
TrackNodeCache node_cache_data[NODE_CACHE_UPDATE_MAX];
};
struct AnimationPlayerData { struct AnimationPlayerData {
Map<TrackNodeCacheKey, TrackNodeCache> node_cache_map; int type_id;
TrackNodeCache *cache_update[NODE_CACHE_UPDATE_MAX]; TrackNodeCache *cache_update[NODE_CACHE_UPDATE_MAX];
int cache_update_size; int cache_update_size;
@@ -400,7 +315,7 @@ struct AnimationPlayerData {
uint64_t accum_pass; uint64_t accum_pass;
float speed_scale; float speed_scale;
float default_blend_time; float default_blend_time;
Map<StringName, AnimationData> animation_set; static Map<StringName, AnimationData> animation_set[2];
Map<BlendKey, float> blend_times; Map<BlendKey, float> blend_times;
Playback playback; Playback playback;
@@ -416,18 +331,18 @@ struct AnimationPlayerData {
NodePath root; NodePath root;
#endif #endif
bool playing; bool playing;
AnimationPlayerData() AnimationPlayerData(int id)
{ {
type_id = id;
processing = false; processing = false;
playing = false; playing = false;
active = false; active = false;
node_cache_map.clear();
cache_update_size = 0; cache_update_size = 0;
playing_caches.clear(); playing_caches.clear();
accum_pass = 0; accum_pass = 0;
speed_scale = 1.0f; speed_scale = 1.0f;
default_blend_time = 0; default_blend_time = 0;
animation_set.clear(); animation_set[id].clear();
blend_times.clear(); blend_times.clear();
queued.clear(); queued.clear();
end_reached = false; end_reached = false;
@@ -438,13 +353,11 @@ struct AnimationPlayerData {
AnimationProcessMode::ANIMATION_PROCESS_MANUAL; AnimationProcessMode::ANIMATION_PROCESS_MANUAL;
processing = false; processing = false;
active = false; active = false;
flecs::log::trace(
"%s constructed normally %p", __func__, this);
} }
AnimationPlayerData(const AnimationPlayerData &d) AnimationPlayerData(const AnimationPlayerData &d)
{ {
int i; int i;
node_cache_map = d.node_cache_map; type_id = d.type_id;
for (i = 0; i < NODE_CACHE_UPDATE_MAX; i++) for (i = 0; i < NODE_CACHE_UPDATE_MAX; i++)
cache_update[i] = d.cache_update[i]; cache_update[i] = d.cache_update[i];
cache_update_size = d.cache_update_size; cache_update_size = d.cache_update_size;
@@ -452,7 +365,6 @@ struct AnimationPlayerData {
accum_pass = d.accum_pass; accum_pass = d.accum_pass;
speed_scale = d.speed_scale; speed_scale = d.speed_scale;
default_blend_time = d.default_blend_time; default_blend_time = d.default_blend_time;
animation_set = d.animation_set;
blend_times = d.blend_times; blend_times = d.blend_times;
playback = d.playback; playback = d.playback;
queued = d.queued; queued = d.queued;
@@ -464,8 +376,6 @@ struct AnimationPlayerData {
processing = d.processing; processing = d.processing;
active = d.active; active = d.active;
playing = d.playing; playing = d.playing;
flecs::log::trace(
"%s copy-constructed normally %p", __func__, this);
} }
AnimationPlayerData(AnimationPlayerData &&d) AnimationPlayerData(AnimationPlayerData &&d)
{ {
@@ -496,8 +406,6 @@ struct AnimationPlayerData {
d.playing = playing; d.playing = playing;
d.cache_update_size = 0; d.cache_update_size = 0;
d.active = false; d.active = false;
flecs::log::trace(
"%s move-constructed normally %p", __func__, this);
} }
AnimationPlayerData &operator=(const AnimationPlayerData &d) AnimationPlayerData &operator=(const AnimationPlayerData &d)
{ {
@@ -525,15 +433,12 @@ struct AnimationPlayerData {
active = d.active; active = d.active;
playing = d.playing; playing = d.playing;
#endif #endif
flecs::log::trace(
"%s copy-assigned normally %p", __func__, this);
return *this; return *this;
} }
AnimationPlayerData &operator=(AnimationPlayerData &&d) AnimationPlayerData &operator=(AnimationPlayerData &&d)
{ {
int i; int i;
node_cache_map = d.node_cache_map; type_id = d.type_id;
for (i = 0; i < NODE_CACHE_UPDATE_MAX; i++) for (i = 0; i < NODE_CACHE_UPDATE_MAX; i++)
cache_update[i] = d.cache_update[i]; cache_update[i] = d.cache_update[i];
cache_update_size = d.cache_update_size; cache_update_size = d.cache_update_size;
@@ -541,7 +446,6 @@ struct AnimationPlayerData {
accum_pass = d.accum_pass; accum_pass = d.accum_pass;
speed_scale = d.speed_scale; speed_scale = d.speed_scale;
default_blend_time = d.default_blend_time; default_blend_time = d.default_blend_time;
animation_set = d.animation_set;
blend_times = d.blend_times; blend_times = d.blend_times;
playback = d.playback; playback = d.playback;
queued = d.queued; queued = d.queued;
@@ -556,9 +460,6 @@ struct AnimationPlayerData {
d.playing = playing; d.playing = playing;
d.cache_update_size = 0; d.cache_update_size = 0;
d.active = false; d.active = false;
flecs::log::trace(
"%s move-assigned normally %p", __func__, this);
return *this; return *this;
} }
~AnimationPlayerData() { playing = false; } ~AnimationPlayerData() { playing = false; }
@@ -566,9 +467,9 @@ struct AnimationPlayerData {
/* public functions */ /* public functions */
StringName find_animation( StringName find_animation(
struct AnimationPlayerData *player, const Ref<Animation> &p_animation); struct AnimationPlayerData *player, const Ref<Animation> &p_animation);
Error add_animation(struct AnimationPlayerData *player, Error add_animation(flecs::entity_t entity, flecs::world &ecs, struct AnimationPlayerData *player,
const StringName &p_name, const Ref<Animation> &p_animation); const StringName &p_name, const Animation *p_animation);
void remove_animation( void remove_animation(flecs::entity_t entity, flecs::world &ecs,
struct AnimationPlayerData *player, const StringName &p_name); struct AnimationPlayerData *player, const StringName &p_name);
void rename_animation(struct AnimationPlayerData *player, void rename_animation(struct AnimationPlayerData *player,
const StringName &p_name, const StringName &p_new_name); const StringName &p_name, const StringName &p_new_name);
@@ -636,7 +537,7 @@ void advance(flecs::entity_t entity, flecs::world &ecs,
AnimationPlayerData *player, float p_time); AnimationPlayerData *player, float p_time);
void set_root(struct AnimationPlayerData *player, const NodePath &p_root); void set_root(struct AnimationPlayerData *player, const NodePath &p_root);
NodePath get_root(struct AnimationPlayerData *player); NodePath get_root(struct AnimationPlayerData *player);
void clear_caches(struct AnimationPlayerData *player); void clear_caches(flecs::entity_t entity, flecs::world &ecs, struct AnimationPlayerData *player);
void get_argument_options(struct AnimationPlayerData *player, void get_argument_options(struct AnimationPlayerData *player,
const StringName &p_function, int p_idx, List<String> *r_options); const StringName &p_function, int p_idx, List<String> *r_options);
} //namespace ECS } //namespace ECS

View File

@@ -88,15 +88,17 @@ int Character::create_character(int id)
root.emplace<Transform>(); root.emplace<Transform>();
root.emplace<ECS::RigidBody>(body, ECS::RigidBody::TYPE_KINEMATIC); root.emplace<ECS::RigidBody>(body, ECS::RigidBody::TYPE_KINEMATIC);
root.emplace<ECS::Skeleton>(); root.emplace<ECS::Skeleton>();
root.emplace<ECS::AnimationPlayerData>(); root.emplace<ECS::AnimationCache>();
root.emplace<ECS::AnimationPlayerData>(id);
List<StringName> anim_list; List<StringName> anim_list;
scene_data[id].animations.get_key_list(&anim_list); scene_data[id].animations.get_key_list(&anim_list);
List<StringName>::Element *e = anim_list.front(); List<StringName>::Element *e = anim_list.front();
ECS::AnimationPlayerData *player = ECS::AnimationPlayerData *player =
root.get_mut<ECS::AnimationPlayerData>(); root.get_mut<ECS::AnimationPlayerData>();
while (e) { while (e) {
ECS::add_animation( assert(scene_data[id].animations[e->get()].is_valid());
player, e->get(), scene_data[id].animations[e->get()]); ECS::add_animation(root, ecs,
player, e->get(), scene_data[id].animations[e->get()].ptr());
flecs::log::trace("added animation %s", flecs::log::trace("added animation %s",
String(e->get()).ascii().get_data()); String(e->get()).ascii().get_data());
e = e->next(); e = e->next();
@@ -360,27 +362,17 @@ void Character::animation_system_init()
ecs.system<ECS::AnimationPlayerData>("UpdateAnimation") ecs.system<ECS::AnimationPlayerData>("UpdateAnimation")
.kind(flecs::OnUpdate) .kind(flecs::OnUpdate)
.each([](flecs::entity e, ECS::AnimationPlayerData &player) { .each([](flecs::entity e, ECS::AnimationPlayerData &player) {
flecs::log::trace("== start of animation frame %p",
player.playback.current.from);
if (player.playback.current.from)
flecs::log::trace("start animation %p",
player.playback.current.from
->get_animation()
.ptr());
if (!player.playing)
flecs::log::trace("not playing any animation");
if (!player.playing) if (!player.playing)
ECS::play(&player, "male-mx-walk-loop"); ECS::play(&player, "male-mx-walk-loop");
if (player.playing && player.end_reached) {
ECS::stop(&player, true);
if (!player.playing)
flecs::log::trace("stopped: not playing any animation");
}
flecs::world w = e.world(); flecs::world w = e.world();
ECS::advance(e.id(), w, &player, ECS::advance(e.id(), w, &player,
SceneTree::get_singleton() SceneTree::get_singleton()
->get_physics_process_time()); ->get_physics_process_time());
if (player.playback.current.from)
flecs::log::trace("end animation %p",
player.playback.current.from
->get_animation()
.ptr());
flecs::log::trace("== end of animation frame");
}); });
} }
void Character::initialize() void Character::initialize()