441 lines
12 KiB
C++
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
|