Files
godot-flecs-character-module/src/modules/character/animation_system.h
2023-09-23 10:34:25 +03:00

441 lines
12 KiB
C++

#ifndef ANIMATION_SYSTEM_H
#define ANIMATION_SYSTEM_H
class AnimationNode;
namespace ECS {
struct AnimationPlayer;
enum AnimationProcessMode {
ANIMATION_PROCESS_PHYSICS,
ANIMATION_PROCESS_IDLE,
ANIMATION_PROCESS_MANUAL,
};
enum AnimationMethodCallMode {
ANIMATION_METHOD_CALL_DEFERRED,
ANIMATION_METHOD_CALL_IMMEDIATE,
};
enum SpecialProperty {
SP_NONE,
SP_NODE2D_POS,
SP_NODE2D_ROT,
SP_NODE2D_SCALE,
};
struct TrackNodeCache {
bool used;
NodePath path;
flecs::entity_t id;
Ref<Resource> resource;
flecs::entity_t bone_idx;
// accumulated transforms
Vector3 loc_accum;
Quat rot_accum;
Vector3 scale_accum;
uint64_t accum_pass;
bool audio_playing;
float audio_start;
float audio_len;
bool animation_playing;
TrackNodeCache() :
used(false),
id(-1),
bone_idx(-1),
accum_pass(0),
audio_playing(false),
audio_start(0.0),
audio_len(0.0),
animation_playing(false)
{
}
};
struct Track {
Animation::TrackType type;
Animation::InterpolationType interpolation;
bool loop_wrap;
NodePath path; // path to something
bool imported;
bool enabled;
Track()
{
interpolation = Animation::INTERPOLATION_LINEAR;
imported = false;
loop_wrap = true;
enabled = true;
}
virtual ~Track() {}
};
struct Key {
float transition;
float time; // time in secs
Key() { transition = 1; }
};
// transform key holds either Vector3 or Quaternion
template <class T> struct TKey : public Key {
T value;
};
struct TransformKey {
Vector3 loc;
Quat rot;
Vector3 scale;
};
struct TransformTrack : public Track {
Vector<TKey<TransformKey>> transforms;
TransformTrack() { type = Animation::TYPE_TRANSFORM; }
};
struct ValueTrack : public Track {
Animation::UpdateMode update_mode;
bool update_on_seek;
Vector<TKey<Variant>> values;
ValueTrack()
{
type = Animation::TYPE_VALUE;
update_mode = Animation::UPDATE_CONTINUOUS;
}
};
struct MethodKey : public Key {
StringName method;
Vector<Variant> params;
};
struct MethodTrack : public Track {
Vector<MethodKey> methods;
MethodTrack() { type = Animation::TYPE_METHOD; }
};
struct BezierKey {
Vector2 in_handle; //relative (x always <0)
Vector2 out_handle; //relative (x always >0)
float value;
};
struct BezierTrack : public Track {
Vector<TKey<BezierKey>> values;
BezierTrack() { type = Animation::TYPE_BEZIER; }
};
struct AudioKey {
RES stream;
float start_offset; //offset from start
float end_offset; //offset from end, if 0 then full length or infinite
AudioKey()
{
start_offset = 0;
end_offset = 0;
}
};
struct AudioTrack : public Track {
Vector<TKey<AudioKey>> values;
AudioTrack() { type = Animation::TYPE_AUDIO; }
};
struct BasicTrack : public Track {
uint8_t data[256];
BasicTrack() { type = Animation::TYPE_TRANSFORM; }
};
struct AnimationData {
String name;
StringName next;
int node_cache_size;
struct TrackNodeCache *node_cache[128];
AnimationData(const Animation *anim) :
animation(anim), node_cache_size(0)
{
assert(animation);
animation = anim;
}
AnimationData() : animation(nullptr), node_cache_size(0) {}
AnimationData(const AnimationData &d)
{
int i;
name = d.name;
next = d.next;
assert(d.animation);
node_cache_size = d.node_cache_size;
for (i = 0; i < 128; i++)
node_cache[i] = d.node_cache[i];
animation = d.animation;
assert(animation);
}
AnimationData(AnimationData &&d)
{
int i;
name = d.name;
next = d.next;
assert(d.animation);
node_cache_size = d.node_cache_size;
for (i = 0; i < 128; i++)
node_cache[i] = d.node_cache[i];
animation = d.animation;
assert(animation.is_valid());
d.node_cache_size = 0;
d.name = "";
d.next = "";
d.animation = nullptr;
}
AnimationData &operator=(const AnimationData &d)
{
memnew_placement(this, AnimationData(d));
return *this;
}
const Animation *get_animation() const { return animation; }
~AnimationData() { animation = nullptr; }
private:
const Animation *animation;
};
struct PlaybackData {
AnimationData *from;
float pos;
float speed_scale;
};
struct Blend {
PlaybackData data;
float blend_time;
float blend_left;
};
struct Playback {
List<Blend> blend;
PlaybackData current;
StringName assigned;
bool seeked;
bool started;
Playback()
{
blend.clear();
seeked = false;
started = false;
}
};
struct BlendKey {
StringName from;
StringName to;
bool operator<(const BlendKey &bk) const
{
return from == bk.from ? String(to) < String(bk.to)
: String(from) < String(bk.from);
}
};
struct TrackNodeCacheKey {
flecs::entity_t id, bone_idx;
inline bool operator<(const TrackNodeCacheKey &p_right) const
{
if (id < p_right.id) {
return true;
} else if (id > p_right.id) {
return false;
} else {
return bone_idx < p_right.bone_idx;
}
}
};
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 {
int type_id;
TrackNodeCache *cache_update[NODE_CACHE_UPDATE_MAX];
int cache_update_size;
Set<TrackNodeCache *> playing_caches;
uint64_t accum_pass;
float speed_scale;
float default_blend_time;
static Map<StringName, AnimationData> animation_set[2];
Map<BlendKey, float> blend_times;
Playback playback;
List<StringName> queued;
bool end_reached;
bool end_notify;
String autoplay;
bool reset_on_save;
AnimationProcessMode animation_process_mode;
bool processing;
bool active;
bool playing;
AnimationPlayerData(int id)
{
type_id = id;
processing = false;
playing = false;
active = false;
cache_update_size = 0;
playing_caches.clear();
accum_pass = 0;
speed_scale = 1.0f;
default_blend_time = 0;
animation_set[id].clear();
blend_times.clear();
queued.clear();
end_reached = false;
end_notify = false;
autoplay = "";
reset_on_save = false;
animation_process_mode =
AnimationProcessMode::ANIMATION_PROCESS_MANUAL;
processing = false;
active = false;
}
AnimationPlayerData(const AnimationPlayerData &d)
{
int i;
type_id = d.type_id;
for (i = 0; i < NODE_CACHE_UPDATE_MAX; i++)
cache_update[i] = d.cache_update[i];
cache_update_size = d.cache_update_size;
playing_caches = d.playing_caches;
accum_pass = d.accum_pass;
speed_scale = d.speed_scale;
default_blend_time = d.default_blend_time;
blend_times = d.blend_times;
playback = d.playback;
queued = d.queued;
end_reached = d.end_reached;
end_notify = d.end_notify;
autoplay = d.autoplay;
reset_on_save = d.reset_on_save;
animation_process_mode = d.animation_process_mode;
processing = d.processing;
active = d.active;
playing = d.playing;
}
AnimationPlayerData(AnimationPlayerData &&d)
{
memnew_placement(this, AnimationPlayerData(d));
d.playing = playing;
d.cache_update_size = 0;
d.active = false;
}
AnimationPlayerData &operator=(const AnimationPlayerData &d)
{
memnew_placement(this, AnimationPlayerData(d));
return *this;
}
AnimationPlayerData &operator=(AnimationPlayerData &&d)
{
int i;
type_id = d.type_id;
for (i = 0; i < NODE_CACHE_UPDATE_MAX; i++)
cache_update[i] = d.cache_update[i];
cache_update_size = d.cache_update_size;
playing_caches = d.playing_caches;
accum_pass = d.accum_pass;
speed_scale = d.speed_scale;
default_blend_time = d.default_blend_time;
blend_times = d.blend_times;
playback = d.playback;
queued = d.queued;
end_reached = d.end_reached;
end_notify = d.end_notify;
autoplay = d.autoplay;
reset_on_save = d.reset_on_save;
animation_process_mode = d.animation_process_mode;
processing = d.processing;
active = d.active;
playing = d.playing;
d.playing = playing;
d.cache_update_size = 0;
d.active = false;
return *this;
}
~AnimationPlayerData() { playing = false; }
};
/* AnimationPlayer */
/* public functions */
StringName find_animation(
struct AnimationPlayerData *player, const Ref<Animation> &p_animation);
Error add_animation(flecs::entity_t entity, flecs::world &ecs,
struct AnimationPlayerData *player, const StringName &p_name,
const Animation *p_animation);
void remove_animation(flecs::entity_t entity, flecs::world &ecs,
struct AnimationPlayerData *player, const StringName &p_name);
void rename_animation(struct AnimationPlayerData *player,
const StringName &p_name, const StringName &p_new_name);
bool has_animation(
struct AnimationPlayerData *player, const StringName &p_name);
Ref<Animation> get_animation(
struct AnimationPlayerData *player, const StringName &p_name);
void get_animation_list(
struct AnimationPlayerData *player, List<StringName> *p_animations);
void set_blend_time(struct AnimationPlayerData *player,
const StringName &p_animation1, const StringName &p_animation2,
float p_time);
float get_blend_time(struct AnimationPlayerData *player,
const StringName &p_animation1, const StringName &p_animation2);
void animation_set_next(struct AnimationPlayerData *player,
const StringName &p_animation, const StringName &p_next);
StringName animation_get_next(
struct AnimationPlayerData *player, const StringName &p_animation);
void set_default_blend_time(
struct AnimationPlayerData *player, float p_default);
float get_default_blend_time(struct AnimationPlayerData *player);
void play(struct AnimationPlayerData *player,
const StringName &p_name = StringName(), float p_custom_blend = -1,
float p_custom_scale = 1.0, bool p_from_end = false);
void play_backwards(struct AnimationPlayerData *player,
const StringName &p_name = StringName(), float p_custom_blend = -1);
void queue(struct AnimationPlayerData *player, const StringName &p_name);
PoolVector<String> get_queue(struct AnimationPlayerData *player);
void clear_queue(struct AnimationPlayerData *player);
void stop(struct AnimationPlayerData *player, bool p_reset = true);
bool is_playing(struct AnimationPlayerData *player);
String get_current_animation(struct AnimationPlayerData *player);
void set_current_animation(
struct AnimationPlayerData *player, const String &p_anim);
String get_assigned_animation(struct AnimationPlayerData *player);
void set_assigned_animation(
struct AnimationPlayerData *player, const String &p_anim);
void set_active(struct AnimationPlayerData *player, bool p_active);
bool is_active(struct AnimationPlayerData *player);
bool is_valid(struct AnimationPlayerData *player);
void set_speed_scale(struct AnimationPlayerData *player, float p_speed);
float get_speed_scale(struct AnimationPlayerData *player);
float get_playing_speed(struct AnimationPlayerData *player);
void set_autoplay(struct AnimationPlayerData *player, const String &p_name);
String get_autoplay(struct AnimationPlayerData *player);
void set_reset_on_save_enabled(
struct AnimationPlayerData *player, bool p_enabled);
bool is_reset_on_save_enabled(struct AnimationPlayerData *player);
void set_animation_process_mode(
struct AnimationPlayerData *player, AnimationProcessMode p_mode);
AnimationProcessMode get_animation_process_mode(
struct AnimationPlayerData *player);
void set_method_call_mode(
struct AnimationPlayerData *player, AnimationMethodCallMode p_mode);
AnimationMethodCallMode get_method_call_mode(
struct AnimationPlayerData *player);
void seek(struct AnimationPlayerData *player, float p_time,
bool p_update = false);
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(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(flecs::entity_t entity, flecs::world &ecs,
struct AnimationPlayerData *player);
void get_argument_options(struct AnimationPlayerData *player,
const StringName &p_function, int p_idx, List<String> *r_options);
} //namespace ECS
#endif