summaryrefslogtreecommitdiff
path: root/scene/animation/animation_player.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/animation/animation_player.cpp')
-rw-r--r--scene/animation/animation_player.cpp187
1 files changed, 130 insertions, 57 deletions
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 2afe9ac35f..59930a3fbb 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -37,6 +37,7 @@
#ifdef TOOLS_ENABLED
#include "editor/editor_node.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/2d/skeleton_2d.h"
void AnimatedValuesBackup::update_skeletons() {
@@ -64,7 +65,7 @@ void AnimatedValuesBackup::restore() const {
if (arr.size() == 3) {
Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_position(entry->bone_idx, arr[0]);
Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_rotation(entry->bone_idx, arr[1]);
- Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[0]);
+ Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[2]);
}
}
}
@@ -108,7 +109,7 @@ bool AnimationPlayer::_set(const StringName &p_name, const Variant &p_value) {
Ref<AnimationLibrary> lib = d[lib_name];
add_animation_library(lib_name, lib);
}
-
+ emit_signal("animation_libraries_updated");
} else if (name.begins_with("next/")) {
String which = name.get_slicec('/', 1);
animation_set_next(which, p_value);
@@ -155,7 +156,7 @@ bool AnimationPlayer::_get(const StringName &p_name, Variant &r_ret) const {
} else if (name == "blend_times") {
Vector<BlendKey> keys;
- for (const KeyValue<BlendKey, float> &E : blend_times) {
+ for (const KeyValue<BlendKey, double> &E : blend_times) {
keys.ordered_insert(E.key);
}
@@ -174,8 +175,8 @@ bool AnimationPlayer::_get(const StringName &p_name, Variant &r_ret) const {
return true;
}
-void AnimationPlayer::_validate_property(PropertyInfo &property) const {
- if (property.name == "current_animation") {
+void AnimationPlayer::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "current_animation") {
List<String> names;
for (const KeyValue<StringName, AnimationData> &E : animation_set) {
@@ -191,10 +192,8 @@ void AnimationPlayer::_validate_property(PropertyInfo &property) const {
hint += E->get();
}
- property.hint_string = hint;
+ p_property.hint_string = hint;
}
-
- Node::_validate_property(property);
}
void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const {
@@ -217,7 +216,7 @@ void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::ARRAY, "blend_times", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
}
-void AnimationPlayer::advance(float p_time) {
+void AnimationPlayer::advance(double p_time) {
_animation_process(p_time);
}
@@ -283,10 +282,12 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
setup_pass++;
for (int i = 0; i < a->get_track_count(); i++) {
+ p_anim->node_cache.write[i] = nullptr;
+
if (!a->track_is_enabled(i)) {
continue;
}
- p_anim->node_cache.write[i] = nullptr;
+
Ref<Resource> resource;
Vector<StringName> leftover_path;
Node *child = parent->get_node_and_resource(a->track_get_path(i), resource, leftover_path);
@@ -321,10 +322,8 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
#endif // _3D_DISABLED
- {
- if (!child->is_connected("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed))) {
- child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed), make_binds(child), CONNECT_ONESHOT);
- }
+ if (!child->is_connected("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed))) {
+ child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed).bind(child), CONNECT_ONE_SHOT);
}
TrackNodeCacheKey key;
@@ -368,8 +367,12 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
node_cache->node_3d = nullptr;
ERR_CONTINUE(node_cache->bone_idx < 0);
}
+ Transform3D rest = node_cache->skeleton->get_bone_rest(bone_idx);
+ node_cache->init_loc = rest.origin;
+ node_cache->init_rot = rest.basis.get_rotation_quaternion();
+ node_cache->init_scale = rest.basis.get_scale();
} else {
- // no property, just use spatialnode
+ // Not a skeleton, the node can be accessed with the node_3d member.
node_cache->skeleton = nullptr;
}
}
@@ -448,6 +451,23 @@ static void _call_object(Object *p_object, const StringName &p_method, const Vec
}
}
+Variant AnimationPlayer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) {
+ switch (p_anim->track_get_type(p_track)) {
+#ifndef _3D_DISABLED
+ case Animation::TYPE_POSITION_3D: {
+ if (p_object_idx >= 0) {
+ const Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_object);
+ return Vector3(p_value) * skel->get_motion_scale();
+ }
+ return p_value;
+ } break;
+#endif // _3D_DISABLED
+ default: {
+ } break;
+ }
+ return p_value;
+}
+
void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) {
_ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
@@ -492,14 +512,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (err != OK) {
continue;
}
+ loc = _post_process_key_value(a, i, loc, nc->node_3d, nc->bone_idx);
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
cache_update[cache_update_size++] = nc;
nc->accum_pass = accum_pass;
nc->loc_accum = loc;
- nc->rot_accum = Quaternion();
- nc->scale_accum = Vector3();
+ nc->rot_accum = nc->init_rot;
+ nc->scale_accum = nc->init_scale;
} else {
nc->loc_accum = nc->loc_accum.lerp(loc, p_interp);
}
@@ -519,14 +540,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (err != OK) {
continue;
}
+ rot = _post_process_key_value(a, i, rot, nc->node_3d, nc->bone_idx);
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
cache_update[cache_update_size++] = nc;
nc->accum_pass = accum_pass;
- nc->loc_accum = Vector3();
+ nc->loc_accum = nc->init_loc;
nc->rot_accum = rot;
- nc->scale_accum = Vector3();
+ nc->scale_accum = nc->init_scale;
} else {
nc->rot_accum = nc->rot_accum.slerp(rot, p_interp);
}
@@ -546,13 +568,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (err != OK) {
continue;
}
+ scale = _post_process_key_value(a, i, scale, nc->node_3d, nc->bone_idx);
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
cache_update[cache_update_size++] = nc;
nc->accum_pass = accum_pass;
- nc->loc_accum = Vector3();
- nc->rot_accum = Quaternion();
+ nc->loc_accum = nc->init_loc;
+ nc->rot_accum = nc->init_rot;
nc->scale_accum = scale;
} else {
nc->scale_accum = nc->scale_accum.lerp(scale, p_interp);
@@ -573,6 +596,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (err != OK) {
continue;
}
+ blend = _post_process_key_value(a, i, blend, nc->node_blend_shape, nc->blend_shape_idx);
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
@@ -625,16 +649,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (p_time < first_key_time) {
double c = Math::ease(p_time / first_key_time, transition);
Variant first_value = a->track_get_key_value(i, first_key);
- Variant interp_value;
- Variant::interpolate(pa->capture, first_value, c, interp_value);
-
+ first_value = _post_process_key_value(a, i, first_value, nc->node);
+ Variant interp_value = Animation::interpolate_variant(pa->capture, first_value, c);
if (pa->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX);
cache_update_prop[cache_update_prop_size++] = pa;
pa->value_accum = interp_value;
pa->accum_pass = accum_pass;
} else {
- Variant::interpolate(pa->value_accum, interp_value, p_interp, pa->value_accum);
+ pa->value_accum = Animation::interpolate_variant(pa->value_accum, interp_value, p_interp);
}
continue; //handled
@@ -647,6 +670,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (value == Variant()) {
continue;
}
+ value = _post_process_key_value(a, i, value, nc->node);
if (pa->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX);
@@ -654,7 +678,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
pa->value_accum = value;
pa->accum_pass = accum_pass;
} else {
- Variant::interpolate(pa->value_accum, value, p_interp, pa->value_accum);
+ pa->value_accum = Animation::interpolate_variant(pa->value_accum, value, p_interp);
}
} else if (p_is_current && p_delta != 0) {
@@ -663,6 +687,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
for (int &F : indices) {
Variant value = a->track_get_key_value(i, F);
+ value = _post_process_key_value(a, i, value, nc->node);
switch (pa->special) {
case SP_NONE: {
bool valid;
@@ -747,6 +772,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
TrackNodeCache::BezierAnim *ba = &E->value;
real_t bezier = a->bezier_track_interpolate(i, p_time);
+ bezier = _post_process_key_value(a, i, bezier, nc->node);
if (ba->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_bezier_size >= NODE_CACHE_UPDATE_MAX);
cache_update_bezier[cache_update_bezier_size++] = ba;
@@ -1124,7 +1150,7 @@ void AnimationPlayer::_animation_update_transforms() {
}
#endif
- static_cast<Node2D *>(pa->object)->set_rotation(Math::deg2rad((double)pa->value_accum));
+ static_cast<Node2D *>(pa->object)->set_rotation(Math::deg_to_rad((double)pa->value_accum));
} break;
case SP_NODE2D_SCALE: {
#ifdef DEBUG_ENABLED
@@ -1171,11 +1197,15 @@ void AnimationPlayer::_animation_process(double p_delta) {
emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name);
}
} else {
- //stop();
playing = false;
_set_process(false);
if (end_notify) {
emit_signal(SceneStringNames::get_singleton()->animation_finished, playback.assigned);
+
+ if (movie_quit_on_finish && OS::get_singleton()->has_feature("movie")) {
+ print_line(vformat("Movie Maker mode is enabled. Quitting on animation finish as requested by: %s", get_path()));
+ get_tree()->quit();
+ }
}
}
end_reached = false;
@@ -1239,9 +1269,28 @@ void AnimationPlayer::_animation_set_cache_update() {
// If something was modified or removed, caches need to be cleared
clear_caches();
}
+
+ emit_signal(SNAME("animation_list_changed"));
}
void AnimationPlayer::_animation_added(const StringName &p_name, const StringName &p_library) {
+ {
+ int at_pos = -1;
+
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ if (animation_libraries[i].name == p_library) {
+ at_pos = i;
+ break;
+ }
+ }
+
+ ERR_FAIL_COND(at_pos == -1);
+
+ ERR_FAIL_COND(!animation_libraries[at_pos].library->animations.has(p_name));
+
+ _ref_anim(animation_libraries[at_pos].library->animations[p_name]);
+ }
+
_animation_set_cache_update();
}
@@ -1251,11 +1300,17 @@ void AnimationPlayer::_animation_removed(const StringName &p_name, const StringN
if (!animation_set.has(name)) {
return; // No need to update because not the one from the library being used.
}
+
+ AnimationData animation_data = animation_set[name];
+ if (animation_data.animation_library == p_library) {
+ _unref_anim(animation_data.animation);
+ }
+
_animation_set_cache_update();
// Erase blends if needed
List<BlendKey> to_erase;
- for (const KeyValue<BlendKey, float> &E : blend_times) {
+ for (const KeyValue<BlendKey, double> &E : blend_times) {
BlendKey bk = E.key;
if (bk.from == name || bk.to == name) {
to_erase.push_back(bk);
@@ -1271,8 +1326,8 @@ void AnimationPlayer::_animation_removed(const StringName &p_name, const StringN
void AnimationPlayer::_rename_animation(const StringName &p_from_name, const StringName &p_to_name) {
// Rename autoplay or blends if needed.
List<BlendKey> to_erase;
- HashMap<BlendKey, float, BlendKey> to_insert;
- for (const KeyValue<BlendKey, float> &E : blend_times) {
+ HashMap<BlendKey, double, BlendKey> to_insert;
+ for (const KeyValue<BlendKey, double> &E : blend_times) {
BlendKey bk = E.key;
BlendKey new_bk = bk;
bool erase = false;
@@ -1343,9 +1398,13 @@ Error AnimationPlayer::add_animation_library(const StringName &p_name, const Ref
animation_libraries.insert(insert_pos, ald);
- ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name));
- ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name));
- ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_name));
+ ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name));
+ ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed).bind(p_name));
+ ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_name));
+
+ for (const KeyValue<StringName, Ref<Animation>> &K : ald.library->animations) {
+ _ref_anim(K.value);
+ }
_animation_set_cache_update();
@@ -1367,7 +1426,7 @@ void AnimationPlayer::remove_animation_library(const StringName &p_name) {
ERR_FAIL_COND(at_pos == -1);
animation_libraries[at_pos].library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added));
- animation_libraries[at_pos].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added));
+ animation_libraries[at_pos].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed));
animation_libraries[at_pos].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed));
stop();
@@ -1383,7 +1442,7 @@ void AnimationPlayer::remove_animation_library(const StringName &p_name) {
}
void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) {
- Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), CONNECT_REFERENCE_COUNTED);
}
void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) {
@@ -1406,12 +1465,12 @@ void AnimationPlayer::rename_animation_library(const StringName &p_name, const S
animation_libraries[i].name = p_new_name;
// rename connections
animation_libraries[i].library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added));
- animation_libraries[i].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added));
+ animation_libraries[i].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed));
animation_libraries[i].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed));
- animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name));
- animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name));
- animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_new_name));
+ animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name));
+ animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed).bind(p_new_name));
+ animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_new_name));
for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[i].library->animations) {
StringName old_name = p_name == StringName() ? K.key : StringName(String(p_name) + "/" + String(K.key));
@@ -1470,11 +1529,11 @@ bool AnimationPlayer::has_animation(const StringName &p_name) const {
}
Ref<Animation> AnimationPlayer::get_animation(const StringName &p_name) const {
- ERR_FAIL_COND_V_MSG(!animation_set.has(p_name), Ref<Animation>(), vformat("Animation not found: %s.", p_name));
+ ERR_FAIL_COND_V_MSG(!animation_set.has(p_name), Ref<Animation>(), vformat("Animation not found: \"%s\".", p_name));
- const AnimationData &data = animation_set[p_name];
+ const AnimationData &anim_data = animation_set[p_name];
- return data.animation;
+ return anim_data.animation;
}
void AnimationPlayer::get_animation_list(List<StringName> *p_animations) const {
@@ -1491,7 +1550,7 @@ void AnimationPlayer::get_animation_list(List<StringName> *p_animations) const {
}
}
-void AnimationPlayer::set_blend_time(const StringName &p_animation1, const StringName &p_animation2, float p_time) {
+void AnimationPlayer::set_blend_time(const StringName &p_animation1, const StringName &p_animation2, double p_time) {
ERR_FAIL_COND_MSG(!animation_set.has(p_animation1), vformat("Animation not found: %s.", p_animation1));
ERR_FAIL_COND_MSG(!animation_set.has(p_animation2), vformat("Animation not found: %s.", p_animation2));
ERR_FAIL_COND_MSG(p_time < 0, "Blend time cannot be smaller than 0.");
@@ -1506,7 +1565,7 @@ void AnimationPlayer::set_blend_time(const StringName &p_animation1, const Strin
}
}
-float AnimationPlayer::get_blend_time(const StringName &p_animation1, const StringName &p_animation2) const {
+double AnimationPlayer::get_blend_time(const StringName &p_animation1, const StringName &p_animation2) const {
BlendKey bk;
bk.from = p_animation1;
bk.to = p_animation2;
@@ -1539,11 +1598,11 @@ void AnimationPlayer::clear_queue() {
queued.clear();
}
-void AnimationPlayer::play_backwards(const StringName &p_name, float p_custom_blend) {
+void AnimationPlayer::play_backwards(const StringName &p_name, double p_custom_blend) {
play(p_name, p_custom_blend, -1, true);
}
-void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float p_custom_scale, bool p_from_end) {
+void AnimationPlayer::play(const StringName &p_name, double p_custom_blend, float p_custom_scale, bool p_from_end) {
StringName name = p_name;
if (String(name) == "") {
@@ -1555,7 +1614,7 @@ void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float
Playback &c = playback;
if (c.current.from) {
- float blend_time = 0.0;
+ double blend_time = 0.0;
// find if it can blend
BlendKey bk;
bk.from = c.current.from->name;
@@ -1709,7 +1768,7 @@ void AnimationPlayer::seek(double p_time, bool p_update) {
}
}
-void AnimationPlayer::seek_delta(double p_time, float p_delta) {
+void AnimationPlayer::seek_delta(double p_time, double p_delta) {
if (!playback.current.from) {
if (playback.assigned) {
ERR_FAIL_COND_MSG(!animation_set.has(playback.assigned), vformat("Animation not found: %s.", playback.assigned));
@@ -1730,12 +1789,12 @@ bool AnimationPlayer::is_valid() const {
return (playback.current.from);
}
-float AnimationPlayer::get_current_animation_position() const {
+double AnimationPlayer::get_current_animation_position() const {
ERR_FAIL_COND_V_MSG(!playback.current.from, 0, "AnimationPlayer has no current animation");
return playback.current.pos;
}
-float AnimationPlayer::get_current_animation_length() const {
+double AnimationPlayer::get_current_animation_length() const {
ERR_FAIL_COND_V_MSG(!playback.current.from, 0, "AnimationPlayer has no current animation");
return playback.current.from->animation->get_length();
}
@@ -1862,6 +1921,14 @@ AnimationPlayer::AnimationMethodCallMode AnimationPlayer::get_method_call_mode()
return method_call_mode;
}
+void AnimationPlayer::set_movie_quit_on_finish_enabled(bool p_enabled) {
+ movie_quit_on_finish = p_enabled;
+}
+
+bool AnimationPlayer::is_movie_quit_on_finish_enabled() const {
+ return movie_quit_on_finish;
+}
+
void AnimationPlayer::_set_process(bool p_process, bool p_force) {
if (processing == p_process && !p_force) {
return;
@@ -1893,11 +1960,11 @@ StringName AnimationPlayer::animation_get_next(const StringName &p_animation) co
return animation_set[p_animation].next;
}
-void AnimationPlayer::set_default_blend_time(float p_default) {
+void AnimationPlayer::set_default_blend_time(double p_default) {
default_blend_time = p_default;
}
-float AnimationPlayer::get_default_blend_time() const {
+double AnimationPlayer::get_default_blend_time() const {
return default_blend_time;
}
@@ -1997,16 +2064,15 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
aux_player->add_animation_library("", al);
aux_player->set_assigned_animation(SceneStringNames::get_singleton()->RESET);
// Forcing the use of the original root because the scene where original player belongs may be not the active one
- Node *root = get_node(get_root());
- Ref<AnimatedValuesBackup> old_values = aux_player->backup_animated_values(root);
+ Ref<AnimatedValuesBackup> old_values = aux_player->backup_animated_values(get_node(get_root()));
aux_player->seek(0.0f, true);
- aux_player->queue_delete();
+ aux_player->queue_free();
if (p_user_initiated) {
Ref<AnimatedValuesBackup> new_values = aux_player->backup_animated_values();
old_values->restore();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Anim Apply Reset"));
ur->add_do_method(new_values.ptr(), "restore");
ur->add_undo_method(old_values.ptr(), "restore");
@@ -2082,6 +2148,9 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_method_call_mode", "mode"), &AnimationPlayer::set_method_call_mode);
ClassDB::bind_method(D_METHOD("get_method_call_mode"), &AnimationPlayer::get_method_call_mode);
+ ClassDB::bind_method(D_METHOD("set_movie_quit_on_finish_enabled", "enabled"), &AnimationPlayer::set_movie_quit_on_finish_enabled);
+ ClassDB::bind_method(D_METHOD("is_movie_quit_on_finish_enabled"), &AnimationPlayer::is_movie_quit_on_finish_enabled);
+
ClassDB::bind_method(D_METHOD("get_current_animation_position"), &AnimationPlayer::get_current_animation_position);
ClassDB::bind_method(D_METHOD("get_current_animation_length"), &AnimationPlayer::get_current_animation_length);
@@ -2103,9 +2172,13 @@ void AnimationPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed", PROPERTY_HINT_RANGE, "-64,64,0.01"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::INT, "method_call_mode", PROPERTY_HINT_ENUM, "Deferred,Immediate"), "set_method_call_mode", "get_method_call_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "movie_quit_on_finish"), "set_movie_quit_on_finish_enabled", "is_movie_quit_on_finish_enabled");
+
ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING_NAME, "anim_name")));
ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING_NAME, "old_name"), PropertyInfo(Variant::STRING_NAME, "new_name")));
ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING_NAME, "anim_name")));
+ ADD_SIGNAL(MethodInfo("animation_list_changed"));
+ ADD_SIGNAL(MethodInfo("animation_libraries_updated"));
ADD_SIGNAL(MethodInfo("caches_cleared"));
BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS);