AnimatedSprite{2D,3D} improvements

* Add support for individual frame duration to `SpriteFrames`.
* Various minor improvements.
This commit is contained in:
Danil Alexeev 2022-11-26 17:00:38 +03:00
parent dc3175e4cd
commit 0d25d8e7fc
No known key found for this signature in database
GPG key ID: 124453E157DA8DC7
13 changed files with 379 additions and 230 deletions

View file

@ -32,19 +32,40 @@
#include "scene/scene_string_names.h"
void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos) {
void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture2D> &p_texture, float p_duration, int p_at_pos) {
HashMap<StringName, Anim>::Iterator E = animations.find(p_anim);
ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
p_duration = MAX(0.0, p_duration);
Frame frame = { p_texture, p_duration };
if (p_at_pos >= 0 && p_at_pos < E->value.frames.size()) {
E->value.frames.insert(p_at_pos, p_frame);
E->value.frames.insert(p_at_pos, frame);
} else {
E->value.frames.push_back(p_frame);
E->value.frames.push_back(frame);
}
emit_changed();
}
void SpriteFrames::set_frame(const StringName &p_anim, int p_idx, const Ref<Texture2D> &p_texture, float p_duration) {
HashMap<StringName, Anim>::Iterator E = animations.find(p_anim);
ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
ERR_FAIL_COND(p_idx < 0);
if (p_idx >= E->value.frames.size()) {
return;
}
p_duration = MAX(0.0, p_duration);
Frame frame = { p_texture, p_duration };
E->value.frames.write[p_idx] = frame;
emit_changed();
}
int SpriteFrames::get_frame_count(const StringName &p_anim) const {
HashMap<StringName, Anim>::ConstIterator E = animations.find(p_anim);
ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist.");
@ -57,6 +78,7 @@ void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) {
ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
E->value.frames.remove_at(p_idx);
emit_changed();
}
@ -65,6 +87,7 @@ void SpriteFrames::clear(const StringName &p_anim) {
ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
E->value.frames.clear();
emit_changed();
}
@ -151,7 +174,10 @@ Array SpriteFrames::_get_animations() const {
d["loop"] = anim.loop;
Array frames;
for (int i = 0; i < anim.frames.size(); i++) {
frames.push_back(anim.frames[i]);
Dictionary f;
f["texture"] = anim.frames[i].texture;
f["duration"] = anim.frames[i].duration;
frames.push_back(f);
}
d["frames"] = frames;
anims.push_back(d);
@ -175,8 +201,21 @@ void SpriteFrames::_set_animations(const Array &p_animations) {
anim.loop = d["loop"];
Array frames = d["frames"];
for (int j = 0; j < frames.size(); j++) {
// For compatibility.
Ref<Resource> res = frames[j];
anim.frames.push_back(res);
if (res.is_valid()) {
Frame frame = { res, 1.0 };
anim.frames.push_back(frame);
continue;
}
Dictionary f = frames[j];
ERR_CONTINUE(!f.has("texture"));
ERR_CONTINUE(!f.has("duration"));
Frame frame = { f["texture"], f["duration"] };
anim.frames.push_back(frame);
}
animations[d["name"]] = anim;
@ -191,17 +230,20 @@ void SpriteFrames::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_animation_names"), &SpriteFrames::get_animation_names);
ClassDB::bind_method(D_METHOD("set_animation_speed", "anim", "speed"), &SpriteFrames::set_animation_speed);
ClassDB::bind_method(D_METHOD("set_animation_speed", "anim", "fps"), &SpriteFrames::set_animation_speed);
ClassDB::bind_method(D_METHOD("get_animation_speed", "anim"), &SpriteFrames::get_animation_speed);
ClassDB::bind_method(D_METHOD("set_animation_loop", "anim", "loop"), &SpriteFrames::set_animation_loop);
ClassDB::bind_method(D_METHOD("get_animation_loop", "anim"), &SpriteFrames::get_animation_loop);
ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "at_position"), &SpriteFrames::add_frame, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count);
ClassDB::bind_method(D_METHOD("get_frame", "anim", "idx"), &SpriteFrames::get_frame);
ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt"), &SpriteFrames::set_frame);
ClassDB::bind_method(D_METHOD("add_frame", "anim", "texture", "duration", "at_position"), &SpriteFrames::add_frame, DEFVAL(1.0), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "texture", "duration"), &SpriteFrames::set_frame, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("remove_frame", "anim", "idx"), &SpriteFrames::remove_frame);
ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count);
ClassDB::bind_method(D_METHOD("get_frame_texture", "anim", "idx"), &SpriteFrames::get_frame_texture);
ClassDB::bind_method(D_METHOD("get_frame_duration", "anim", "idx"), &SpriteFrames::get_frame_duration);
ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear);
ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all);