diff options
Diffstat (limited to 'scene/animation/animation_player.cpp')
-rw-r--r-- | scene/animation/animation_player.cpp | 288 |
1 files changed, 170 insertions, 118 deletions
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 4e56f1acf0..f6091f224c 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,12 +30,13 @@ #include "animation_player.h" -#include "core/engine.h" -#include "core/message_queue.h" +#include "core/config/engine.h" +#include "core/object/message_queue.h" #include "scene/scene_string_names.h" #include "servers/audio/audio_stream.h" #ifdef TOOLS_ENABLED +#include "editor/editor_node.h" #include "editor/editor_settings.h" #include "scene/2d/skeleton_2d.h" @@ -53,6 +54,21 @@ void AnimatedValuesBackup::update_skeletons() { } } } + +void AnimatedValuesBackup::restore() const { + for (int i = 0; i < entries.size(); i++) { + const AnimatedValuesBackup::Entry *entry = &entries[i]; + if (entry->bone_idx == -1) { + entry->object->set_indexed(entry->subpath, entry->value); + } else { + Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose(entry->bone_idx, entry->value); + } + } +} + +void AnimatedValuesBackup::_bind_methods() { + ClassDB::bind_method(D_METHOD("restore"), &AnimatedValuesBackup::restore); +} #endif bool AnimationPlayer::_set(const StringName &p_name, const Variant &p_value) { @@ -160,8 +176,8 @@ void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const { anim_names.sort(); - for (List<PropertyInfo>::Element *E = anim_names.front(); E; E = E->next()) { - p_list->push_back(E->get()); + for (const PropertyInfo &E : anim_names) { + p_list->push_back(E); } p_list->push_back(PropertyInfo(Variant::ARRAY, "blend_times", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); @@ -190,7 +206,7 @@ void AnimationPlayer::_notification(int p_what) { } } break; case NOTIFICATION_INTERNAL_PROCESS: { - if (animation_process_mode == ANIMATION_PROCESS_PHYSICS) { + if (process_callback == ANIMATION_PROCESS_PHYSICS) { break; } @@ -199,7 +215,7 @@ void AnimationPlayer::_notification(int p_what) { } } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - if (animation_process_mode == ANIMATION_PROCESS_IDLE) { + if (process_callback == ANIMATION_PROCESS_IDLE) { break; } @@ -213,13 +229,13 @@ void AnimationPlayer::_notification(int p_what) { } } -void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { +void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_override) { // Already cached? if (p_anim->node_cache.size() == p_anim->animation->get_track_count()) { return; } - Node *parent = get_node(root); + Node *parent = p_root_override ? p_root_override : get_node(root); ERR_FAIL_COND(!parent); @@ -236,6 +252,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { ObjectID id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id(); int bone_idx = -1; +#ifndef _3D_DISABLED if (a->track_get_path(i).get_subname_count() == 1 && Object::cast_to<Skeleton3D>(child)) { Skeleton3D *sk = Object::cast_to<Skeleton3D>(child); bone_idx = sk->find_bone(a->track_get_path(i).get_subname(0)); @@ -243,6 +260,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { continue; } } +#endif // _3D_DISABLED { if (!child->is_connected("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed))) { @@ -263,11 +281,12 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { p_anim->node_cache[i]->node = child; p_anim->node_cache[i]->resource = resource; p_anim->node_cache[i]->node_2d = Object::cast_to<Node2D>(child); - if (a->track_get_type(i) == Animation::TYPE_TRANSFORM) { +#ifndef _3D_DISABLED + if (a->track_get_type(i) == Animation::TYPE_TRANSFORM3D) { // special cases and caches for transform tracks - // cache spatial - p_anim->node_cache[i]->spatial = Object::cast_to<Node3D>(child); + // cache node_3d + p_anim->node_cache[i]->node_3d = Object::cast_to<Node3D>(child); // cache skeleton p_anim->node_cache[i]->skeleton = Object::cast_to<Skeleton3D>(child); if (p_anim->node_cache[i]->skeleton) { @@ -278,7 +297,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { if (p_anim->node_cache[i]->bone_idx < 0) { // broken track (nonexistent bone) p_anim->node_cache[i]->skeleton = nullptr; - p_anim->node_cache[i]->spatial = nullptr; + p_anim->node_cache[i]->node_3d = nullptr; ERR_CONTINUE(p_anim->node_cache[i]->bone_idx < 0); } } else { @@ -287,6 +306,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { } } } +#endif // _3D_DISABLED 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())) { @@ -321,7 +341,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { } } -void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started) { +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) { _ensure_node_caches(p_anim); ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); @@ -350,13 +370,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float } switch (a->track_get_type(i)) { - case Animation::TYPE_TRANSFORM: { - if (!nc->spatial) { + case Animation::TYPE_TRANSFORM3D: { +#ifndef _3D_DISABLED + if (!nc->node_3d) { continue; } Vector3 loc; - Quat rot; + Quaternion rot; Vector3 scale; Error err = a->transform_track_interpolate(i, p_time, &loc, &rot, &scale); @@ -379,7 +400,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float nc->rot_accum = nc->rot_accum.slerp(rot, p_interp); nc->scale_accum = nc->scale_accum.lerp(scale, p_interp); } - +#endif // _3D_DISABLED } break; case Animation::TYPE_VALUE: { if (!nc->node) { @@ -396,7 +417,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float Animation::UpdateMode update_mode = a->value_track_get_update_mode(i); if (update_mode == Animation::UPDATE_CAPTURE) { - if (p_started) { + if (p_started || pa->capture == Variant()) { pa->capture = pa->object->get_indexed(pa->subpath); } @@ -464,8 +485,8 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float List<int> indices; a->value_track_get_key_indices(i, p_time, p_delta, &indices); - for (List<int>::Element *F = indices.front(); F; F = F->next()) { - Variant value = a->track_get_key_value(i, F->get()); + for (int &F : indices) { + Variant value = a->track_get_key_value(i, F); switch (pa->special) { case SP_NONE: { bool valid; @@ -492,7 +513,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float } #endif - static_cast<Node2D *>(pa->object)->set_rotation(Math::deg2rad((double)value)); + static_cast<Node2D *>(pa->object)->set_rotation((double)value); } break; case SP_NODE2D_SCALE: { #ifdef DEBUG_ENABLED @@ -523,9 +544,9 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float a->method_track_get_key_indices(i, p_time, p_delta, &indices); - for (List<int>::Element *E = indices.front(); E; E = E->next()) { - StringName method = a->method_track_get_name(i, E->get()); - Vector<Variant> params = a->method_track_get_params(i, E->get()); + for (int &E : indices) { + StringName method = a->method_track_get_name(i, E); + Vector<Variant> params = a->method_track_get_params(i, E); int s = params.size(); @@ -536,6 +557,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float } #endif + static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8"); if (can_call) { if (method_call_mode == ANIMATION_METHOD_CALL_DEFERRED) { MessageQueue::get_singleton()->push_call( @@ -545,7 +567,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float s >= 2 ? params[1] : Variant(), s >= 3 ? params[2] : Variant(), s >= 4 ? params[3] : Variant(), - s >= 5 ? params[4] : Variant()); + s >= 5 ? params[4] : Variant(), + s >= 6 ? params[5] : Variant(), + s >= 7 ? params[6] : Variant(), + s >= 8 ? params[7] : Variant()); } else { nc->node->call( method, @@ -553,7 +578,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float s >= 2 ? params[1] : Variant(), s >= 3 ? params[2] : Variant(), s >= 4 ? params[3] : Variant(), - s >= 5 ? params[4] : Variant()); + s >= 5 ? params[4] : Variant(), + s >= 6 ? params[5] : Variant(), + s >= 7 ? params[6] : Variant(), + s >= 8 ? params[7] : Variant()); } } } @@ -589,7 +617,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float } if (p_seeked) { - //find whathever should be playing + //find whatever should be playing int idx = a->track_find_key(i, p_time); if (idx < 0) { continue; @@ -618,7 +646,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float nc->audio_playing = true; playing_caches.insert(nc); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time nc->audio_len = len - start_ofs - end_ofs; } else { nc->audio_len = 0; @@ -649,7 +677,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float nc->audio_playing = true; playing_caches.insert(nc); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time nc->audio_len = len - start_ofs - end_ofs; } else { nc->audio_len = 0; @@ -695,7 +723,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float continue; } - float pos = a->track_get_key_time(i, idx); + double pos = a->track_get_key_time(i, idx); StringName anim_name = a->animation_track_get_key_animation(i, idx); if (String(anim_name) == "[stop]" || !player->has_animation(anim_name)) { @@ -704,12 +732,12 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float Ref<Animation> anim = player->get_animation(anim_name); - float at_anim_pos; + double at_anim_pos; if (anim->has_loop()) { - at_anim_pos = Math::fposmod(p_time - pos, anim->get_length()); //seek to loop + at_anim_pos = Math::fposmod(p_time - pos, (double)anim->get_length()); //seek to loop } else { - at_anim_pos = MAX(anim->get_length(), p_time - pos); //seek to end + at_anim_pos = MAX((double)anim->get_length(), p_time - pos); //seek to end } if (player->is_playing() || p_seeked) { @@ -748,11 +776,11 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float } } -void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started) { - float delta = p_delta * speed_scale * cd.speed_scale; - float next_pos = cd.pos + delta; +void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started) { + double delta = p_delta * speed_scale * cd.speed_scale; + double next_pos = cd.pos + delta; - float len = cd.from->animation->get_length(); + real_t len = cd.from->animation->get_length(); bool loop = cd.from->animation->has_loop(); if (!loop) { @@ -762,19 +790,17 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f next_pos = len; } - // fix delta - delta = next_pos - cd.pos; + 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) if (&cd == &playback.current) { - bool backwards = delta < 0; - - if (!backwards && cd.pos <= len && next_pos == len /*&& playback.blend.empty()*/) { + if (!backwards && cd.pos <= len && next_pos == len) { //playback finished end_reached = true; end_notify = cd.pos < len; // Notify only if not already at the end } - if (backwards && cd.pos >= 0 && next_pos == 0 /*&& playback.blend.empty()*/) { + if (backwards && cd.pos >= 0 && next_pos == 0) { //playback finished end_reached = true; end_notify = cd.pos > 0; // Notify only if not already at the beginning @@ -782,7 +808,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f } } else { - float looped_next_pos = Math::fposmod(next_pos, len); + double looped_next_pos = Math::fposmod(next_pos, (double)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 @@ -797,7 +823,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f _animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started); } -void AnimationPlayer::_animation_process2(float p_delta, bool p_started) { +void AnimationPlayer::_animation_process2(double p_delta, bool p_started) { Playback &c = playback; accum_pass++; @@ -824,20 +850,21 @@ void AnimationPlayer::_animation_process2(float p_delta, bool p_started) { void AnimationPlayer::_animation_update_transforms() { { - Transform t; + Transform3D t; for (int i = 0; i < cache_update_size; i++) { TrackNodeCache *nc = cache_update[i]; ERR_CONTINUE(nc->accum_pass != accum_pass); t.origin = nc->loc_accum; - t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum); + t.basis.set_quaternion_scale(nc->rot_accum, nc->scale_accum); +#ifndef _3D_DISABLED if (nc->skeleton && nc->bone_idx >= 0) { nc->skeleton->set_bone_pose(nc->bone_idx, t); - - } else if (nc->spatial) { - nc->spatial->set_transform(t); + } else if (nc->node_3d) { + nc->node_3d->set_transform(t); } +#endif // _3D_DISABLED } } @@ -900,7 +927,7 @@ void AnimationPlayer::_animation_update_transforms() { cache_update_bezier_size = 0; } -void AnimationPlayer::_animation_process(float p_delta) { +void AnimationPlayer::_animation_process(double p_delta) { if (playback.current.from) { end_reached = false; end_notify = false; @@ -955,7 +982,7 @@ Error AnimationPlayer::add_animation(const StringName &p_name, const Ref<Animati } _ref_anim(p_animation); - _change_notify(); + notify_property_list_changed(); return OK; } @@ -967,7 +994,7 @@ void AnimationPlayer::remove_animation(const StringName &p_name) { animation_set.erase(p_name); clear_caches(); - _change_notify(); + notify_property_list_changed(); } void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) { @@ -1025,7 +1052,7 @@ void AnimationPlayer::rename_animation(const StringName &p_name, const StringNam } clear_caches(); - _change_notify(); + notify_property_list_changed(); } bool AnimationPlayer::has_animation(const StringName &p_name) const { @@ -1049,12 +1076,14 @@ void AnimationPlayer::get_animation_list(List<StringName> *p_animations) const { anims.sort(); - for (List<String>::Element *E = anims.front(); E; E = E->next()) { - p_animations->push_back(E->get()); + for (const String &E : anims) { + p_animations->push_back(E); } } void AnimationPlayer::set_blend_time(const StringName &p_animation1, const StringName &p_animation2, float p_time) { + ERR_FAIL_COND(!animation_set.has(p_animation1)); + ERR_FAIL_COND(!animation_set.has(p_animation2)); ERR_FAIL_COND_MSG(p_time < 0, "Blend time cannot be smaller than 0."); BlendKey bk; @@ -1089,8 +1118,8 @@ void AnimationPlayer::queue(const StringName &p_name) { Vector<String> AnimationPlayer::get_queue() { Vector<String> ret; - for (List<StringName>::Element *E = queued.front(); E; E = E->next()) { - ret.push_back(E->get()); + for (const StringName &E : queued) { + ret.push_back(E); } return ret; @@ -1116,7 +1145,7 @@ void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float Playback &c = playback; if (c.current.from) { - float blend_time = 0; + float blend_time = 0.0; // find if it can blend BlendKey bk; bk.from = c.current.from->name; @@ -1254,7 +1283,7 @@ float AnimationPlayer::get_playing_speed() const { return speed_scale * playback.current.speed_scale; } -void AnimationPlayer::seek(float p_time, bool p_update) { +void AnimationPlayer::seek(double p_time, bool p_update) { if (!playback.current.from) { if (playback.assigned) { ERR_FAIL_COND(!animation_set.has(playback.assigned)); @@ -1270,7 +1299,7 @@ void AnimationPlayer::seek(float p_time, bool p_update) { } } -void AnimationPlayer::seek_delta(float p_time, float p_delta) { +void AnimationPlayer::seek_delta(double p_time, float p_delta) { if (!playback.current.from) { if (playback.assigned) { ERR_FAIL_COND(!animation_set.has(playback.assigned)); @@ -1292,18 +1321,18 @@ bool AnimationPlayer::is_valid() const { } float AnimationPlayer::get_current_animation_position() const { - ERR_FAIL_COND_V(!playback.current.from, 0); + 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 { - ERR_FAIL_COND_V(!playback.current.from, 0); + ERR_FAIL_COND_V_MSG(!playback.current.from, 0, "AnimationPlayer has no current animation"); return playback.current.from->animation->get_length(); } void AnimationPlayer::_animation_changed() { clear_caches(); - emit_signal("caches_cleared"); + emit_signal(SNAME("caches_cleared")); if (is_playing()) { playback.seeked = true; //need to restart stuff, like audio } @@ -1327,7 +1356,7 @@ void AnimationPlayer::_stop_playing_caches() { } void AnimationPlayer::_node_removed(Node *p_node) { - clear_caches(); // nodes contained here ar being removed, clear the caches + clear_caches(); // nodes contained here are being removed, clear the caches } void AnimationPlayer::clear_caches() { @@ -1379,8 +1408,16 @@ String AnimationPlayer::get_autoplay() const { return autoplay; } -void AnimationPlayer::set_animation_process_mode(AnimationProcessMode p_mode) { - if (animation_process_mode == p_mode) { +void AnimationPlayer::set_reset_on_save_enabled(bool p_enabled) { + reset_on_save = p_enabled; +} + +bool AnimationPlayer::is_reset_on_save_enabled() const { + return reset_on_save; +} + +void AnimationPlayer::set_process_callback(AnimationProcessCallback p_mode) { + if (process_callback == p_mode) { return; } @@ -1388,14 +1425,14 @@ void AnimationPlayer::set_animation_process_mode(AnimationProcessMode p_mode) { if (pr) { _set_process(false); } - animation_process_mode = p_mode; + process_callback = p_mode; if (pr) { _set_process(true); } } -AnimationPlayer::AnimationProcessMode AnimationPlayer::get_animation_process_mode() const { - return animation_process_mode; +AnimationPlayer::AnimationProcessCallback AnimationPlayer::get_process_callback() const { + return process_callback; } void AnimationPlayer::set_method_call_mode(AnimationMethodCallMode p_mode) { @@ -1411,7 +1448,7 @@ void AnimationPlayer::_set_process(bool p_process, bool p_force) { return; } - switch (animation_process_mode) { + switch (process_callback) { case ANIMATION_PROCESS_PHYSICS: set_physics_process_internal(p_process && active); break; @@ -1456,32 +1493,32 @@ NodePath AnimationPlayer::get_root() const { void AnimationPlayer::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { #ifdef TOOLS_ENABLED - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\""; + const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\""; #else const String quote_style = "\""; #endif String pf = p_function; - if (p_function == "play" || p_function == "play_backwards" || p_function == "remove_animation" || p_function == "has_animation" || p_function == "queue") { + if (p_idx == 0 && (p_function == "play" || p_function == "play_backwards" || p_function == "remove_animation" || p_function == "has_animation" || p_function == "queue")) { List<StringName> al; get_animation_list(&al); - for (List<StringName>::Element *E = al.front(); E; E = E->next()) { - r_options->push_back(quote_style + String(E->get()) + quote_style); + for (const StringName &name : al) { + r_options->push_back(String(name).quote(quote_style)); } } Node::get_argument_options(p_function, p_idx, r_options); } #ifdef TOOLS_ENABLED -AnimatedValuesBackup AnimationPlayer::backup_animated_values() { +Ref<AnimatedValuesBackup> AnimationPlayer::backup_animated_values(Node *p_root_override) { + Ref<AnimatedValuesBackup> backup; if (!playback.current.from) { - return AnimatedValuesBackup(); + return backup; } - _ensure_node_caches(playback.current.from); - - AnimatedValuesBackup backup; + _ensure_node_caches(playback.current.from, p_root_override); + backup.instantiate(); for (int i = 0; i < playback.current.from->node_cache.size(); i++) { TrackNodeCache *nc = playback.current.from->node_cache[i]; if (!nc) { @@ -1497,15 +1534,15 @@ AnimatedValuesBackup AnimationPlayer::backup_animated_values() { entry.object = nc->skeleton; entry.bone_idx = nc->bone_idx; entry.value = nc->skeleton->get_bone_pose(nc->bone_idx); - backup.entries.push_back(entry); + backup->entries.push_back(entry); } else { - if (nc->spatial) { + if (nc->node_3d) { AnimatedValuesBackup::Entry entry; - entry.object = nc->spatial; + entry.object = nc->node_3d; entry.subpath.push_back("transform"); - entry.value = nc->spatial->get_transform(); + entry.value = nc->node_3d->get_transform(); entry.bone_idx = -1; - backup.entries.push_back(entry); + backup->entries.push_back(entry); } else { for (Map<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.front(); E; E = E->next()) { AnimatedValuesBackup::Entry entry; @@ -1515,7 +1552,7 @@ AnimatedValuesBackup AnimationPlayer::backup_animated_values() { entry.value = E->value().object->get_indexed(E->value().subpath, &valid); entry.bone_idx = -1; if (valid) { - backup.entries.push_back(entry); + backup->entries.push_back(entry); } } } @@ -1525,15 +1562,41 @@ AnimatedValuesBackup AnimationPlayer::backup_animated_values() { return backup; } -void AnimationPlayer::restore_animated_values(const AnimatedValuesBackup &p_backup) { - for (int i = 0; i < p_backup.entries.size(); i++) { - const AnimatedValuesBackup::Entry *entry = &p_backup.entries[i]; - if (entry->bone_idx == -1) { - entry->object->set_indexed(entry->subpath, entry->value); - } else { - Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose(entry->bone_idx, entry->value); - } +Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) { + ERR_FAIL_COND_V(!can_apply_reset(), Ref<AnimatedValuesBackup>()); + + Ref<Animation> reset_anim = animation_set["RESET"].animation; + ERR_FAIL_COND_V(reset_anim.is_null(), Ref<AnimatedValuesBackup>()); + + Node *root_node = get_node_or_null(root); + ERR_FAIL_COND_V(!root_node, Ref<AnimatedValuesBackup>()); + + AnimationPlayer *aux_player = memnew(AnimationPlayer); + EditorNode::get_singleton()->add_child(aux_player); + aux_player->add_animation("RESET", reset_anim); + aux_player->set_assigned_animation("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); + aux_player->seek(0.0f, true); + aux_player->queue_delete(); + + if (p_user_initiated) { + Ref<AnimatedValuesBackup> new_values = aux_player->backup_animated_values(); + old_values->restore(); + + UndoRedo *ur = EditorNode::get_singleton()->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"); + ur->commit_action(); } + + return old_values; +} + +bool AnimationPlayer::can_apply_reset() const { + return has_animation("RESET") && playback.assigned != StringName("RESET"); } #endif @@ -1577,6 +1640,9 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_autoplay", "name"), &AnimationPlayer::set_autoplay); ClassDB::bind_method(D_METHOD("get_autoplay"), &AnimationPlayer::get_autoplay); + ClassDB::bind_method(D_METHOD("set_reset_on_save_enabled", "enabled"), &AnimationPlayer::set_reset_on_save_enabled); + ClassDB::bind_method(D_METHOD("is_reset_on_save_enabled"), &AnimationPlayer::is_reset_on_save_enabled); + ClassDB::bind_method(D_METHOD("set_root", "path"), &AnimationPlayer::set_root); ClassDB::bind_method(D_METHOD("get_root"), &AnimationPlayer::get_root); @@ -1584,8 +1650,8 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_caches"), &AnimationPlayer::clear_caches); - ClassDB::bind_method(D_METHOD("set_animation_process_mode", "mode"), &AnimationPlayer::set_animation_process_mode); - ClassDB::bind_method(D_METHOD("get_animation_process_mode"), &AnimationPlayer::get_animation_process_mode); + ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &AnimationPlayer::set_process_callback); + ClassDB::bind_method(D_METHOD("get_process_callback"), &AnimationPlayer::get_process_callback); 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); @@ -1598,15 +1664,16 @@ void AnimationPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_node"), "set_root", "get_root"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "current_animation", PROPERTY_HINT_ENUM, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ANIMATE_AS_TRIGGER), "set_current_animation", "get_current_animation"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "assigned_animation", PROPERTY_HINT_NONE, "", 0), "set_assigned_animation", "get_assigned_animation"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "assigned_animation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_assigned_animation", "get_assigned_animation"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "autoplay", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_autoplay", "get_autoplay"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_length", PROPERTY_HINT_NONE, "", 0), "", "get_current_animation_length"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_position", PROPERTY_HINT_NONE, "", 0), "", "get_current_animation_position"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reset_on_save", PROPERTY_HINT_NONE, ""), "set_reset_on_save_enabled", "is_reset_on_save_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_current_animation_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_current_animation_position"); ADD_GROUP("Playback Options", "playback_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_animation_process_mode", "get_animation_process_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_callback", "get_process_callback"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playback_active", PROPERTY_HINT_NONE, "", 0), "set_active", "is_active"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playback_active", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_active", "is_active"); 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"); @@ -1624,22 +1691,7 @@ void AnimationPlayer::_bind_methods() { } AnimationPlayer::AnimationPlayer() { - accum_pass = 1; - cache_update_size = 0; - cache_update_prop_size = 0; - cache_update_bezier_size = 0; - speed_scale = 1; - end_reached = false; - end_notify = false; - animation_process_mode = ANIMATION_PROCESS_IDLE; - method_call_mode = ANIMATION_METHOD_CALL_DEFERRED; - processing = false; - default_blend_time = 0; root = SceneStringNames::get_singleton()->path_pp; - playing = false; - active = true; - playback.seeked = false; - playback.started = false; } AnimationPlayer::~AnimationPlayer() { |