diff --git a/editor/animation/animation_player_editor_plugin.cpp b/editor/animation/animation_player_editor_plugin.cpp index d4b5ad9681..36722a5892 100644 --- a/editor/animation/animation_player_editor_plugin.cpp +++ b/editor/animation/animation_player_editor_plugin.cpp @@ -126,13 +126,15 @@ void AnimationPlayerEditor::_notification(int p_what) { } frame->set_value(player->get_current_animation_position()); track_editor->set_anim_pos(player->get_current_animation_position()); - } else if (!player->is_valid()) { - // Reset timeline when the player has been stopped externally - frame->set_value(0); - } else if (last_active) { - // Need the last frame after it stopped. - frame->set_value(player->get_current_animation_position()); - track_editor->set_anim_pos(player->get_current_animation_position()); + } else { + if (!player->is_valid()) { + // Reset timeline when the player has been stopped externally + frame->set_value(0); + } else if (last_active) { + // Need the last frame after it stopped. + frame->set_value(player->get_current_animation_position()); + track_editor->set_anim_pos(player->get_current_animation_position()); + } stop->set_button_icon(stop_icon); } @@ -317,7 +319,7 @@ void AnimationPlayerEditor::_play_pressed() { if (!current.is_empty()) { if (current == player->get_assigned_animation()) { - player->stop(); //so it won't blend with itself + player->stop(); // So it won't blend with itself. } ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing."); PackedStringArray markers = track_editor->get_selected_section(); @@ -338,9 +340,13 @@ void AnimationPlayerEditor::_play_from_pressed() { String current = _get_current(); if (!current.is_empty()) { + if (!player->is_valid()) { + _play_pressed(); // Fallback. + return; + } double time = player->get_current_animation_position(); if (current == player->get_assigned_animation() && player->is_playing()) { - player->clear_caches(); //so it won't blend with itself + player->clear_caches(); // So it won't blend with itself. } ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing."); player->seek_internal(time, true, true, true); @@ -369,7 +375,7 @@ void AnimationPlayerEditor::_play_bw_pressed() { String current = _get_current(); if (!current.is_empty()) { if (current == player->get_assigned_animation()) { - player->stop(); //so it won't blend with itself + player->stop(); // So it won't blend with itself. } ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing."); PackedStringArray markers = track_editor->get_selected_section(); @@ -390,9 +396,13 @@ void AnimationPlayerEditor::_play_bw_from_pressed() { String current = _get_current(); if (!current.is_empty()) { + if (!player->is_valid()) { + _play_bw_pressed(); // Fallback. + return; + } double time = player->get_current_animation_position(); if (current == player->get_assigned_animation() && player->is_playing()) { - player->clear_caches(); //so it won't blend with itself + player->clear_caches(); // So it won't blend with itself. } ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing."); player->seek_internal(time, true, true, true); @@ -1546,6 +1556,7 @@ void AnimationPlayerEditor::_current_animation_changed(const StringName &p_name) void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float p_len) { frame->set_max(p_len); } + void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_timeline_only, bool p_update_position_only) { timeline_position = p_pos; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index fa348fae73..0265cdaab8 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -595,7 +595,12 @@ bool AnimationPlayer::is_playing() const { void AnimationPlayer::set_current_animation(const StringName &p_animation) { if (p_animation == SNAME("[stop]") || p_animation.is_empty()) { - stop(); + // It should be call deferred and handled only when is_playing() == true to prevent infinite loops caused by seeking within stop(). + // Especially when the key current_animation = "[stop]" is placed at the beginning of an animation, + // this line is called when the animation changes, so is_playing() == true must be checked. + if (is_playing()) { + callable_mp(this, &AnimationPlayer::stop).call_deferred(false); + } } else if (!is_playing()) { play(p_animation); } else if (playback.assigned != p_animation) { @@ -786,16 +791,13 @@ bool AnimationPlayer::is_movie_quit_on_finish_enabled() const { void AnimationPlayer::_stop_internal(bool p_reset, bool p_keep_state) { _clear_caches(); Playback &c = playback; - // c.blend.clear(); double start = c.current.is_enabled ? playback.current.get_start_time() : 0; if (p_reset) { c.blend.clear(); if (p_keep_state) { c.current.pos = start; } else { - is_stopping = true; seek_internal(start, true, true, true); - is_stopping = false; } c.current.is_enabled = false; c.current.animation_name = String(); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index c74bd0da8a..68506310f3 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -62,8 +62,6 @@ private: Tween::TransitionType auto_capture_transition_type = Tween::TRANS_LINEAR; Tween::EaseType auto_capture_ease_type = Tween::EASE_IN; - bool is_stopping = false; - struct PlaybackData { bool is_enabled = false; String animation_name;