Animations work now

This commit is contained in:
2023-09-19 02:17:12 +03:00
parent b553b8ca1d
commit 49b11221a6
4 changed files with 169 additions and 117 deletions

View File

@@ -6,6 +6,10 @@
"future": "cpp",
"istream": "cpp",
"functional": "cpp",
"numbers": "cpp"
"numbers": "cpp",
"*.inc": "cpp",
"*.tcc": "cpp",
"ranges": "cpp",
"streambuf": "cpp"
}
}

View File

@@ -5,23 +5,27 @@
#include <flecs.h>
#include "animation_system.h"
#include "character.h"
/* private functions */
namespace ECS {
static void _animation_process_animation(struct AnimationPlayerData *player,
static void _animation_process_animation(flecs::entity_t entity,
flecs::world &ecs, struct AnimationPlayerData *player,
AnimationData *p_anim, float p_time, float p_delta, float p_interp,
bool p_is_current = true, bool p_seeked = false,
bool p_started = false);
static void _ensure_node_caches(struct AnimationPlayerData *player,
AnimationData *p_anim, Node *p_root_override = NULL);
static void _animation_process_data(struct AnimationPlayerData *player,
PlaybackData &cd, float p_delta, float p_blend, bool p_seeked,
bool p_started);
static void _animation_process2(
flecs::entity_t entity, flecs::world &ecs, AnimationData *p_anim,
Node *p_root_override = NULL);
static void _animation_process_data(flecs::entity_t entity, flecs::world &ecs,
struct AnimationPlayerData *player, PlaybackData &cd, float p_delta,
float p_blend, bool p_seeked, bool p_started);
static void _animation_process2(flecs::entity_t entity, flecs::world &ecs,
struct AnimationPlayerData *player, float p_delta, bool p_started);
static void _animation_update_transforms(struct AnimationPlayerData *player);
static void _animation_process(
struct AnimationPlayerData *player, float p_delta);
static void _animation_update_transforms(flecs::entity_t entity,
flecs::world &ecs, struct AnimationPlayerData *player);
static void _animation_process(flecs::entity_t entity, flecs::world &ecs,
struct AnimationPlayerData *player, float p_time);
// static void _node_removed(struct AnimationPlayerData *player,
// Node *p_node);
static void _stop_playing_caches(struct AnimationPlayerData *player);
@@ -145,7 +149,8 @@ void ECS::play(struct ECS::AnimationPlayerData *player,
}
}
static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player,
AnimationData *p_anim, Node *p_root_override)
flecs::entity_t entity, flecs::world &ecs, AnimationData *p_anim,
Node *p_root_override)
{
// Already cached?
assert(p_anim->animation.is_valid());
@@ -205,12 +210,16 @@ static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player,
#endif
ECS::TrackNodeCacheKey key;
key.id = id;
key.bone_idx = bone_idx;
String path = a->track_get_path(i);
key.id = entity;
flecs::entity e = ecs.entity(entity);
flecs::entity bone_e =
e.lookup(String(np.get_subname(0)).ascii().get_data());
flecs::entity_t bone_id = bone_e.id();
key.bone_idx = bone_id;
String path = np.get_subname(0);
print_line("TRACK: " + itos(i) +
" BONE IDX: " + itos(bone_idx) + " ID: " + itos(id) +
" PATH: " + path);
" BONE IDX: " + itos(bone_id) +
" ID: " + itos(entity) + " PATH: " + path);
if (!player->node_cache_map.has(key))
player->node_cache_map[key] = ECS::TrackNodeCache();
@@ -240,17 +249,18 @@ static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player,
.get_subname(0);
/* use entities */
p_anim->node_cache[i]->bone_idx =
key.bone_idx;
#if 0
p_anim->node_cache[i]->bone_idx = p_anim->node_cache[i]->skeleton->find_bone(bone_name);
#endif
#if 0
if (p_anim->node_cache[i]->bone_idx <
0) {
// broken track (nonexistent
// bone)
#if 0
p_anim->node_cache[i]->skeleton = nullptr;
p_anim->node_cache[i]->spatial = nullptr;
#endif
ERR_CONTINUE(
p_anim->node_cache[i]
->bone_idx <
@@ -260,55 +270,58 @@ static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player,
#if 0
// no property, just use spatialnode
p_anim->node_cache[i]->skeleton = nullptr;
#endif
}
#endif
}
}
}
if (a->track_get_type(i) == Animation::TYPE_VALUE) {
if (!p_anim->node_cache[i]->property_anim.has(
a->track_get_path(i)
.get_concatenated_subnames())) {
TrackNodeCache::PropertyAnim pa;
pa.subpath = leftover_path;
#if 0
if (a->track_get_type(i) == Animation::TYPE_VALUE) {
if (!p_anim->node_cache[i]->property_anim.has(
a->track_get_path(i)
.get_concatenated_subnames())) {
TrackNodeCache::PropertyAnim pa;
pa.subpath = leftover_path;
#if 0
pa.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child;
#endif
pa.special = SP_NONE;
pa.owner = p_anim->node_cache[i];
p_anim->node_cache[i]->property_anim
[a->track_get_path(i)
.get_concatenated_subnames()] =
pa;
pa.special = SP_NONE;
pa.owner = p_anim->node_cache[i];
p_anim->node_cache[i]->property_anim
[a->track_get_path(i)
.get_concatenated_subnames()] =
pa;
}
}
}
if (a->track_get_type(i) == Animation::TYPE_BEZIER &&
leftover_path.size()) {
if (!p_anim->node_cache[i]->bezier_anim.has(
a->track_get_path(i)
.get_concatenated_subnames())) {
TrackNodeCache::BezierAnim ba;
ba.bezier_property = leftover_path;
if (a->track_get_type(i) == Animation::TYPE_BEZIER &&
leftover_path.size()) {
if (!p_anim->node_cache[i]->bezier_anim.has(
a->track_get_path(i)
.get_concatenated_subnames())) {
TrackNodeCache::BezierAnim ba;
ba.bezier_property = leftover_path;
#if 0
ba.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child;
#endif
ba.owner = p_anim->node_cache[i];
ba.owner = p_anim->node_cache[i];
p_anim->node_cache[i]->bezier_anim
[a->track_get_path(i)
.get_concatenated_subnames()] =
ba;
}
p_anim->node_cache[i]->bezier_anim
[a->track_get_path(i)
.get_concatenated_subnames()] =
ba;
}
#endif
}
}
}
static void ECS::_animation_process_animation(
struct ECS::AnimationPlayerData *player, ECS::AnimationData *p_anim,
float p_time, float p_delta, float p_interp, bool p_is_current,
bool p_seeked, bool p_started)
static void ECS::_animation_process_animation(flecs::entity_t entity,
flecs::world &ecs, struct ECS::AnimationPlayerData *player,
ECS::AnimationData *p_anim, float p_time, float p_delta,
float p_interp, bool p_is_current, bool p_seeked, bool p_started)
{
_ensure_node_caches(player, p_anim);
_ensure_node_caches(player, entity, ecs, p_anim);
ERR_FAIL_COND(p_anim->node_cache_size !=
p_anim->animation->get_track_count());
@@ -318,20 +331,23 @@ static void ECS::_animation_process_animation(
#endif
for (int i = 0; i < a->get_track_count(); i++) {
// If an animation changes this animation (or it animates
// itself) we need to recreate our animation cache
// If an animation changes this animation (or it
// animates itself) we need to recreate our animation
// cache
if (p_anim->node_cache_size != a->get_track_count()) {
_ensure_node_caches(player, p_anim);
_ensure_node_caches(player, entity, ecs, p_anim);
}
TrackNodeCache *nc = p_anim->node_cache[i];
if (!nc) {
continue; // no node cache for this track, skip it
continue; // no node cache for this track, skip
// it
}
if (!a->track_is_enabled(i)) {
continue; // do nothing if the track is disabled
continue; // do nothing if the track is
// disabled
}
flecs::log::trace("track keys: %d", i);
if (a->track_get_key_count(i) == 0) {
@@ -351,8 +367,8 @@ static void ECS::_animation_process_animation(
Error err = a->transform_track_interpolate(
i, p_time, &loc, &rot, &scale);
//ERR_CONTINUE(err!=OK); //used for testing,
//should be removed
//ERR_CONTINUE(err!=OK); //used for
//testing, should be removed
if (err != OK) {
continue;
@@ -369,6 +385,8 @@ static void ECS::_animation_process_animation(
nc->loc_accum = loc;
nc->rot_accum = rot;
nc->scale_accum = scale;
print_line("cache update: " +
itos(nc->bone_idx));
} else {
nc->loc_accum =
@@ -382,6 +400,8 @@ static void ECS::_animation_process_animation(
.linear_interpolate(
scale,
p_interp);
print_line("cache update2: " +
itos(nc->bone_idx));
}
} break;
@@ -418,7 +438,8 @@ static void ECS::_animation_process_animation(
int key_count =
a->track_get_key_count(i);
if (key_count == 0) {
continue; //eeh not worth it
continue; //eeh not
//worth it
}
float first_key_time =
@@ -427,11 +448,15 @@ static void ECS::_animation_process_animation(
int first_key = 0;
if (first_key_time == 0.0) {
//ignore, use for transition
//ignore, use for
//transition
if (key_count == 1) {
continue; //with one
//key we
//can't do
continue; //with
//one
//key
//we
//can't
//do
//anything
}
transition =
@@ -497,14 +522,14 @@ static void ECS::_animation_process_animation(
continue;
}
//thanks to trigger mode, this should
//be solved now..
//thanks to trigger mode, this
//should be solved now..
/*
if (p_delta==0 &&
value.get_type()==Variant::STRING)
continue; // doing this with
strings is messy, should find another
way
continue; // doing this
with strings is messy, should
find another way
*/
if (pa->accum_pass !=
player->accum_pass) {
@@ -623,8 +648,10 @@ static void ECS::_animation_process_animation(
#endif
static_assert(VARIANT_ARG_MAX == 8,
"This code needs to be "
"updated if VARIANT_ARG_MAX "
"This code needs to "
"be "
"updated if "
"VARIANT_ARG_MAX "
"!= 8");
#if 0
if (player->can_call) {
@@ -703,7 +730,8 @@ static void ECS::_animation_process_animation(
}
if (p_seeked) {
//find whatever should be playing
//find whatever should be
//playing
int idx = a->track_find_key(i, p_time);
if (idx < 0) {
continue;
@@ -863,7 +891,8 @@ static void ECS::_animation_process_animation(
} break;
case Animation::TYPE_ANIMATION: {
/* animations of animations - need rework */
/* animations of animations - need
* rework */
#if 0
AnimationPlayer *player = Object::cast_to<AnimationPlayer>(nc->node);
if (!player) {
@@ -930,9 +959,10 @@ static void ECS::_animation_process_animation(
}
}
}
static void ECS::_animation_process_data(
struct ECS::AnimationPlayerData *player, PlaybackData &cd,
float p_delta, float p_blend, bool p_seeked, bool p_started)
static void ECS::_animation_process_data(flecs::entity_t entity,
flecs::world &ecs, struct ECS::AnimationPlayerData *player,
PlaybackData &cd, float p_delta, float p_blend, bool p_seeked,
bool p_started)
{
float delta = p_delta * player->speed_scale * cd.speed_scale;
float next_pos = cd.pos + delta;
@@ -953,36 +983,39 @@ static void ECS::_animation_process_data(
bool backwards =
signbit(delta); // Negative zero means playing backwards too
delta = next_pos -
cd.pos; // Fix delta (after determination of backwards because
// negative zero is lost here)
cd.pos; // Fix delta (after determination of backwards
// because negative zero is lost here)
if (&cd == &player->playback.current) {
if (!backwards && cd.pos <= len && next_pos == len) {
//playback finished
player->end_reached = true;
player->end_notify = cd.pos <
len; // Notify only if not already at the end
player->end_notify =
cd.pos < len; // Notify only if not
// already at the end
}
if (backwards && cd.pos >= 0 && next_pos == 0) {
//playback finished
player->end_reached = true;
player->end_notify =
cd.pos > 0; // Notify only if not already at
// the beginning
cd.pos > 0; // Notify only if not
// already at the beginning
}
} else {
float looped_next_pos = Math::fposmod(next_pos, len);
if (looped_next_pos == 0 && next_pos != 0)
// Loop multiples of the length to it, rather than 0
// so state at time=length is previewable in the editor
// Loop multiples of the length to it, rather
// than 0 so state at time=length is
// previewable in the editor
next_pos = len;
else
next_pos = looped_next_pos;
}
cd.pos = next_pos;
_animation_process_animation(player, cd.from, cd.pos, delta, p_blend,
&cd == &player->playback.current, p_seeked, p_started);
_animation_process_animation(entity, ecs, player, cd.from, cd.pos,
delta, p_blend, &cd == &player->playback.current, p_seeked,
p_started);
}
static void ECS::_animation_process2(
static void ECS::_animation_process2(flecs::entity_t entity, flecs::world &ecs,
struct ECS::AnimationPlayerData *player, float p_delta, bool p_started)
{
ECS::Playback &c = player->playback;
@@ -994,7 +1027,7 @@ static void ECS::_animation_process2(
}
flecs::log::trace("length: %d",
player->playback.current.from->animation->get_length());
_animation_process_data(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);
if (p_delta != 0)
c.seeked = false;
@@ -1011,16 +1044,17 @@ static void ECS::_animation_process2(
c.blend.erase(E);
continue;
}
_animation_process_data(
player, b.data, p_delta, blend, false, false);
_animation_process_data(entity, ecs, player, b.data, p_delta,
blend, false, false);
b.blend_left -= Math::absf(player->speed_scale * p_delta);
prev = E->prev();
if (b.blend_left < 0)
c.blend.erase(E);
}
}
static void ECS::_animation_update_transforms(
struct ECS::AnimationPlayerData *player)
/* transforms are set here */
static void ECS::_animation_update_transforms(flecs::entity_t entity,
flecs::world &ecs, struct ECS::AnimationPlayerData *player)
{
int i;
{
@@ -1029,6 +1063,15 @@ static void ECS::_animation_update_transforms(
TrackNodeCache *nc = player->cache_update[i];
t.origin = nc->loc_accum;
t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum);
flecs::entity bone_entity = ecs.entity(nc->bone_idx);
if (bone_entity) {
ECS::BonePose *bone =
bone_entity.get_mut<ECS::BonePose>();
bone->pose = t;
bone_entity.modified<ECS::BonePose>();
flecs::log::err("good bone %d", nc->bone_idx);
} else
flecs::log::err("bad bone %d", nc->bone_idx);
#if 0
/* update transform on skeleton or node */
if (nc->skeleton && nc->bone_idx >= 0)
@@ -1049,14 +1092,17 @@ static void ECS::_animation_update_transforms(
pa->subpath, pa->value_accum, &valid);
if (!valid) {
/* error setting key
ERR_PRINT("Failed setting key at time "
+ rtos(playback.current.pos) + " in
Animation '" + get_current_animation()
+ "' at Node '" + get_path() + "',
Track '" + String(pa->owner->path) +
"'. Check if property exists or the
type of key is right for the
property");
ERR_PRINT("Failed setting key
at time "
+ rtos(playback.current.pos) +
" in Animation '" +
get_current_animation()
+ "' at Node '" + get_path() +
"', Track '" +
String(pa->owner->path) +
"'. Check if property exists or
the type of key is right for
the property");
*/
}
} break;
@@ -1087,7 +1133,7 @@ static void ECS::_set_process(
{
/* Nothing */
}
static void ECS::_animation_process(
static void ECS::_animation_process(flecs::entity_t entity, flecs::world &ecs,
struct ECS::AnimationPlayerData *player, float p_time)
{
if (player->playback.current.from) {
@@ -1096,10 +1142,11 @@ static void ECS::_animation_process(
->get_length());
player->end_reached = false;
player->end_notify = false;
_animation_process2(player, p_time, player->playback.started);
_animation_process2(
entity, ecs, player, p_time, player->playback.started);
if (player->playback.started)
player->playback.started = false;
_animation_update_transforms(player);
_animation_update_transforms(entity, ecs, player);
if (player->end_reached) {
if (player->queued.size()) {
String old = player->playback.assigned;
@@ -1222,13 +1269,14 @@ void ECS::clear_caches(struct ECS::AnimationPlayerData *player)
player->cache_update_bezier_size = 0;
}
void ECS::advance(struct ECS::AnimationPlayerData *player, float p_time)
void ECS::advance(flecs::entity_t entity, flecs::world &ecs,
ECS::AnimationPlayerData *player, float p_time)
{
if (player->playback.current.from) {
flecs::log::trace("length: %f",
player->playback.current.from->animation
->get_length());
}
ECS::_animation_process(player, p_time);
ECS::_animation_process(entity, ecs, player, p_time);
player->playback.current.from = nullptr;
}

View File

@@ -28,7 +28,7 @@ struct TrackNodeCache {
Node2D *node_2d;
Skeleton *skeleton;
#endif
int bone_idx;
flecs::entity_t bone_idx;
// accumulated transforms
Vector3 loc_accum;
Quat rot_accum;
@@ -234,8 +234,7 @@ struct BlendKey {
}
};
struct TrackNodeCacheKey {
uint32_t id;
int bone_idx;
flecs::entity_t id, bone_idx;
inline bool operator<(const TrackNodeCacheKey &p_right) const
{
@@ -348,7 +347,8 @@ void seek_delta(
struct AnimationPlayerData *player, float p_time, float p_delta);
float get_current_animation_position(struct AnimationPlayerData *player);
float get_current_animation_length(struct AnimationPlayerData *player);
void advance(struct AnimationPlayerData *player, float p_time);
void advance(flecs::entity_t entity, flecs::world &ecs,
AnimationPlayerData *player, float p_time);
void set_root(struct AnimationPlayerData *player, const NodePath &p_root);
NodePath get_root(struct AnimationPlayerData *player);
void clear_caches(struct AnimationPlayerData *player);

View File

@@ -124,15 +124,14 @@ int Character::create_character(int id)
}
for (i = 0; i < scene_data[id].meshes.size(); i++) {
// flecs::log::trace("creating slot -");
flecs::entity entity =
ecs.entity(scene_data[id]
.meshes[i]
.slot_name.ascii()
.get_data())
.child_of(root)
.emplace<ECS::CharacterSlot>(
scene_data[id].meshes[i].mesh,
scene_data[id].meshes[i].skin);
ecs.entity(scene_data[id]
.meshes[i]
.slot_name.ascii()
.get_data())
.child_of(root)
.emplace<ECS::CharacterSlot>(
scene_data[id].meshes[i].mesh,
scene_data[id].meshes[i].skin);
}
// print_line("character created");
int xid = entities.size();
@@ -383,7 +382,8 @@ void Character::animation_system_init()
.each([](flecs::entity e, ECS::AnimationPlayerData &player) {
if (!player.playing)
ECS::play(&player, "stand1-loop");
ECS::advance(&player,
flecs::world w = e.world();
ECS::advance(e.id(), w, &player,
SceneTree::get_singleton()
->get_physics_process_time());
});