1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-01 16:38:31 +00:00

Merge pull request #113187 from TokageItLab/anim-map-revert

Revert: Fix AHashMap realloc cause AnimationPlayer crash
This commit is contained in:
Rémi Verschelde
2025-11-26 23:44:27 +01:00
2 changed files with 38 additions and 44 deletions

View File

@@ -164,11 +164,10 @@ void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, f
double start = cd.get_start_time(); double start = cd.get_start_time();
double end = cd.get_end_time(); double end = cd.get_end_time();
AnimationData *p_from = &animation_set[cd.animation_name];
Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE; Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE;
switch (p_from->animation->get_loop_mode()) { switch (cd.from->animation->get_loop_mode()) {
case Animation::LOOP_NONE: { case Animation::LOOP_NONE: {
if (Animation::is_less_approx(next_pos, start)) { if (Animation::is_less_approx(next_pos, start)) {
next_pos = start; next_pos = start;
@@ -208,7 +207,7 @@ void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, f
// End detection. // End detection.
if (p_is_current) { if (p_is_current) {
if (p_from->animation->get_loop_mode() == Animation::LOOP_NONE) { if (cd.from->animation->get_loop_mode() == Animation::LOOP_NONE) {
if (!backwards && Animation::is_less_or_equal_approx(prev_pos, end) && Math::is_equal_approx(next_pos, end)) { if (!backwards && Animation::is_less_or_equal_approx(prev_pos, end) && Math::is_equal_approx(next_pos, end)) {
// Playback finished. // Playback finished.
next_pos = end; // Snap to the edge. next_pos = end; // Snap to the edge.
@@ -249,7 +248,7 @@ void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, f
pi.is_external_seeking = !p_internal_seeked && !p_started; pi.is_external_seeking = !p_internal_seeked && !p_started;
pi.looped_flag = looped_flag; pi.looped_flag = looped_flag;
pi.weight = p_blend; pi.weight = p_blend;
make_animation_instance(cd.animation_name, pi); make_animation_instance(cd.from->name, pi);
} }
float AnimationPlayer::get_current_blend_amount() { float AnimationPlayer::get_current_blend_amount() {
@@ -301,13 +300,12 @@ void AnimationPlayer::_blend_playback_data(double p_delta, bool p_started) {
} }
bool AnimationPlayer::_blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) { bool AnimationPlayer::_blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) {
if (playback.current.animation_name.is_empty()) { if (!playback.current.from) {
_set_process(false); _set_process(false);
return false; return false;
} }
AnimationData *p_from = &animation_set[playback.current.animation_name]; tmp_from = playback.current.from->animation->get_instance_id();
tmp_from = p_from->animation->get_instance_id();
end_reached = false; end_reached = false;
end_notify = false; end_notify = false;
@@ -318,10 +316,10 @@ bool AnimationPlayer::_blend_pre_process(double p_delta, int p_track_count, cons
playback.started = false; playback.started = false;
} }
String prev_animation_name = playback.current.animation_name; AnimationData *prev_from = playback.current.from;
_blend_playback_data(p_delta, started); _blend_playback_data(p_delta, started);
if (prev_animation_name != playback.current.animation_name) { if (prev_from != playback.current.from) {
return false; // Animation has been changed in the process (may be caused by method track), abort process. return false; // Animation has been changed in the process (may be caused by method track), abort process.
} }
@@ -335,7 +333,7 @@ void AnimationPlayer::_blend_capture(double p_delta) {
void AnimationPlayer::_blend_post_process() { void AnimationPlayer::_blend_post_process() {
if (end_reached) { if (end_reached) {
// If the method track changes current animation, the animation is not finished. // If the method track changes current animation, the animation is not finished.
if (tmp_from == animation_set[playback.current.animation_name].animation->get_instance_id()) { if (tmp_from == playback.current.from->animation->get_instance_id()) {
if (playback_queue.size()) { if (playback_queue.size()) {
if (!finished_anim.is_empty()) { if (!finished_anim.is_empty()) {
emit_signal(SceneStringName(animation_finished), finished_anim); emit_signal(SceneStringName(animation_finished), finished_anim);
@@ -435,10 +433,10 @@ void AnimationPlayer::play_section_with_markers(const StringName &p_name, const
ERR_FAIL_COND_MSG(p_start_marker && p_end_marker && Animation::is_greater_approx(start_time, end_time), vformat("End marker %s is placed earlier than start marker %s in animation: %s.", p_end_marker, p_start_marker, name)); ERR_FAIL_COND_MSG(p_start_marker && p_end_marker && Animation::is_greater_approx(start_time, end_time), vformat("End marker %s is placed earlier than start marker %s in animation: %s.", p_end_marker, p_start_marker, name));
if (p_start_marker && Animation::is_less_approx(start_time, 0)) { if (p_start_marker && Animation::is_less_approx(start_time, 0)) {
WARN_PRINT_ED(vformat("Negative time start marker: %s is invalid in the section, so the start of the animation: %s is used instead.", p_start_marker, playback.current.animation_name)); WARN_PRINT_ED(vformat("Negative time start marker: %s is invalid in the section, so the start of the animation: %s is used instead.", p_start_marker, playback.current.from->animation->get_name()));
} }
if (p_end_marker && Animation::is_less_approx(end_time, 0)) { if (p_end_marker && Animation::is_less_approx(end_time, 0)) {
WARN_PRINT_ED(vformat("Negative time end marker: %s is invalid in the section, so the end of the animation: %s is used instead.", p_end_marker, playback.current.animation_name)); WARN_PRINT_ED(vformat("Negative time end marker: %s is invalid in the section, so the end of the animation: %s is used instead.", p_end_marker, playback.current.from->animation->get_name()));
} }
play_section(name, start_time, end_time, p_custom_blend, p_custom_scale, p_from_end); play_section(name, start_time, end_time, p_custom_blend, p_custom_scale, p_from_end);
@@ -457,11 +455,11 @@ void AnimationPlayer::play_section(const StringName &p_name, double p_start_time
Playback &c = playback; Playback &c = playback;
if (!c.current.animation_name.is_empty()) { if (c.current.from) {
double blend_time = 0.0; double blend_time = 0.0;
// Find if it can blend. // Find if it can blend.
BlendKey bk; BlendKey bk;
bk.from = c.current.animation_name; bk.from = c.current.from->name;
bk.to = name; bk.to = name;
if (Animation::is_greater_or_equal_approx(p_custom_blend, 0)) { if (Animation::is_greater_or_equal_approx(p_custom_blend, 0)) {
@@ -473,7 +471,7 @@ void AnimationPlayer::play_section(const StringName &p_name, double p_start_time
if (blend_times.has(bk)) { if (blend_times.has(bk)) {
blend_time = blend_times[bk]; blend_time = blend_times[bk];
} else { } else {
bk.from = c.current.animation_name; bk.from = c.current.from->name;
bk.to = "*"; bk.to = "*";
if (blend_times.has(bk)) { if (blend_times.has(bk)) {
@@ -500,8 +498,7 @@ void AnimationPlayer::play_section(const StringName &p_name, double p_start_time
_clear_playing_caches(); _clear_playing_caches();
} }
c.current.animation_name = name; c.current.from = &animation_set[name];
c.current.animation_length = animation_set[name].animation->get_length();
c.current.speed_scale = p_custom_scale; c.current.speed_scale = p_custom_scale;
c.current.start_time = p_start_time; c.current.start_time = p_start_time;
c.current.end_time = p_end_time; c.current.end_time = p_end_time;
@@ -616,8 +613,7 @@ void AnimationPlayer::set_assigned_animation(const StringName &p_animation) {
} else { } else {
ERR_FAIL_COND_MSG(!animation_set.has(p_animation), vformat("Animation not found: %s.", p_animation.operator String())); ERR_FAIL_COND_MSG(!animation_set.has(p_animation), vformat("Animation not found: %s.", p_animation.operator String()));
playback.current.pos = 0; playback.current.pos = 0;
playback.current.animation_name = p_animation; playback.current.from = &animation_set[p_animation];
playback.current.animation_length = animation_set[p_animation].animation->get_length();
playback.current.start_time = -1; playback.current.start_time = -1;
playback.current.end_time = -1; playback.current.end_time = -1;
playback.assigned = p_animation; playback.assigned = p_animation;
@@ -662,13 +658,12 @@ void AnimationPlayer::seek_internal(double p_time, bool p_update, bool p_update_
_check_immediately_after_start(); _check_immediately_after_start();
playback.current.pos = p_time; playback.current.pos = p_time;
if (!playback.current.animation_name.is_empty()) { if (!playback.current.from) {
if (playback.assigned) { if (playback.assigned) {
ERR_FAIL_COND_MSG(!animation_set.has(playback.assigned), vformat("Animation not found: %s.", playback.assigned)); ERR_FAIL_COND_MSG(!animation_set.has(playback.assigned), vformat("Animation not found: %s.", playback.assigned));
playback.current.animation_name = playback.assigned; playback.current.from = &animation_set[playback.assigned];
playback.current.animation_length = animation_set[playback.assigned].animation->get_length();
} }
if (!playback.current.animation_name.is_empty()) { if (!playback.current.from) {
return; // There is no animation. return; // There is no animation.
} }
} }
@@ -704,37 +699,37 @@ void AnimationPlayer::_check_immediately_after_start() {
} }
bool AnimationPlayer::is_valid() const { bool AnimationPlayer::is_valid() const {
return (!playback.current.animation_name.is_empty()); return (playback.current.from);
} }
double AnimationPlayer::get_current_animation_position() const { double AnimationPlayer::get_current_animation_position() const {
ERR_FAIL_COND_V_MSG(!playback.current.animation_name.is_empty(), 0, "AnimationPlayer has no current animation."); ERR_FAIL_NULL_V_MSG(playback.current.from, 0, "AnimationPlayer has no current animation.");
return playback.current.pos; return playback.current.pos;
} }
double AnimationPlayer::get_current_animation_length() const { double AnimationPlayer::get_current_animation_length() const {
ERR_FAIL_COND_V_MSG(!playback.current.animation_name.is_empty(), 0, "AnimationPlayer has no current animation."); ERR_FAIL_NULL_V_MSG(playback.current.from, 0, "AnimationPlayer has no current animation.");
return playback.current.animation_length; return playback.current.from->animation->get_length();
} }
void AnimationPlayer::set_section_with_markers(const StringName &p_start_marker, const StringName &p_end_marker) { void AnimationPlayer::set_section_with_markers(const StringName &p_start_marker, const StringName &p_end_marker) {
ERR_FAIL_COND_MSG(!playback.current.animation_name.is_empty(), "AnimationPlayer has no current animation."); ERR_FAIL_NULL_MSG(playback.current.from, "AnimationPlayer has no current animation.");
ERR_FAIL_COND_MSG(p_start_marker == p_end_marker && p_start_marker, vformat("Start marker and end marker cannot be the same marker: %s.", p_start_marker)); ERR_FAIL_COND_MSG(p_start_marker == p_end_marker && p_start_marker, vformat("Start marker and end marker cannot be the same marker: %s.", p_start_marker));
ERR_FAIL_COND_MSG(p_start_marker && !animation_set[playback.current.animation_name].animation->has_marker(p_start_marker), vformat("Marker %s not found in animation: %s.", p_start_marker, playback.current.animation_name)); ERR_FAIL_COND_MSG(p_start_marker && !playback.current.from->animation->has_marker(p_start_marker), vformat("Marker %s not found in animation: %s.", p_start_marker, playback.current.from->animation->get_name()));
ERR_FAIL_COND_MSG(p_end_marker && !animation_set[playback.current.animation_name].animation->has_marker(p_end_marker), vformat("Marker %s not found in animation: %s.", p_end_marker, playback.current.animation_name)); ERR_FAIL_COND_MSG(p_end_marker && !playback.current.from->animation->has_marker(p_end_marker), vformat("Marker %s not found in animation: %s.", p_end_marker, playback.current.from->animation->get_name()));
double start_time = p_start_marker ? animation_set[playback.current.animation_name].animation->get_marker_time(p_start_marker) : -1; double start_time = p_start_marker ? playback.current.from->animation->get_marker_time(p_start_marker) : -1;
double end_time = p_end_marker ? animation_set[playback.current.animation_name].animation->get_marker_time(p_end_marker) : -1; double end_time = p_end_marker ? playback.current.from->animation->get_marker_time(p_end_marker) : -1;
if (p_start_marker && Animation::is_less_approx(start_time, 0)) { if (p_start_marker && Animation::is_less_approx(start_time, 0)) {
WARN_PRINT_ONCE_ED(vformat("Marker %s time must be positive in animation: %s.", p_start_marker, playback.current.animation_name)); WARN_PRINT_ONCE_ED(vformat("Marker %s time must be positive in animation: %s.", p_start_marker, playback.current.from->animation->get_name()));
} }
if (p_end_marker && Animation::is_less_approx(end_time, 0)) { if (p_end_marker && Animation::is_less_approx(end_time, 0)) {
WARN_PRINT_ONCE_ED(vformat("Marker %s time must be positive in animation: %s.", p_end_marker, playback.current.animation_name)); WARN_PRINT_ONCE_ED(vformat("Marker %s time must be positive in animation: %s.", p_end_marker, playback.current.from->animation->get_name()));
} }
set_section(start_time, end_time); set_section(start_time, end_time);
} }
void AnimationPlayer::set_section(double p_start_time, double p_end_time) { void AnimationPlayer::set_section(double p_start_time, double p_end_time) {
ERR_FAIL_COND_MSG(!playback.current.animation_name.is_empty(), "AnimationPlayer has no current animation."); ERR_FAIL_NULL_MSG(playback.current.from, "AnimationPlayer has no current animation.");
ERR_FAIL_COND_MSG(Animation::is_greater_or_equal_approx(p_start_time, 0) && Animation::is_greater_or_equal_approx(p_end_time, 0) && Animation::is_greater_or_equal_approx(p_start_time, p_end_time), vformat("Start time %f is greater than end time %f.", p_start_time, p_end_time)); ERR_FAIL_COND_MSG(Animation::is_greater_or_equal_approx(p_start_time, 0) && Animation::is_greater_or_equal_approx(p_end_time, 0) && Animation::is_greater_or_equal_approx(p_start_time, p_end_time), vformat("Start time %f is greater than end time %f.", p_start_time, p_end_time));
playback.current.start_time = p_start_time; playback.current.start_time = p_start_time;
playback.current.end_time = p_end_time; playback.current.end_time = p_end_time;
@@ -747,12 +742,12 @@ void AnimationPlayer::reset_section() {
} }
double AnimationPlayer::get_section_start_time() const { double AnimationPlayer::get_section_start_time() const {
ERR_FAIL_COND_V_MSG(!playback.current.animation_name.is_empty(), playback.current.start_time, "AnimationPlayer has no current animation."); ERR_FAIL_NULL_V_MSG(playback.current.from, playback.current.start_time, "AnimationPlayer has no current animation.");
return playback.current.get_start_time(); return playback.current.get_start_time();
} }
double AnimationPlayer::get_section_end_time() const { double AnimationPlayer::get_section_end_time() const {
ERR_FAIL_COND_V_MSG(!playback.current.animation_name.is_empty(), playback.current.end_time, "AnimationPlayer has no current animation."); ERR_FAIL_NULL_V_MSG(playback.current.from, playback.current.end_time, "AnimationPlayer has no current animation.");
return playback.current.get_end_time(); return playback.current.get_end_time();
} }
@@ -784,7 +779,7 @@ void AnimationPlayer::_stop_internal(bool p_reset, bool p_keep_state) {
_clear_caches(); _clear_caches();
Playback &c = playback; Playback &c = playback;
// c.blend.clear(); // c.blend.clear();
double start = (!c.current.animation_name.is_empty()) ? playback.current.get_start_time() : 0; double start = c.current.from ? playback.current.get_start_time() : 0;
if (p_reset) { if (p_reset) {
c.blend.clear(); c.blend.clear();
if (p_keep_state) { if (p_keep_state) {
@@ -794,7 +789,7 @@ void AnimationPlayer::_stop_internal(bool p_reset, bool p_keep_state) {
seek_internal(start, true, true, true); seek_internal(start, true, true, true);
is_stopping = false; is_stopping = false;
} }
c.current.animation_name = String(); c.current.from = nullptr;
c.current.speed_scale = 1; c.current.speed_scale = 1;
emit_signal(SNAME("current_animation_changed"), ""); emit_signal(SNAME("current_animation_changed"), "");
} }

View File

@@ -65,21 +65,20 @@ private:
bool is_stopping = false; bool is_stopping = false;
struct PlaybackData { struct PlaybackData {
String animation_name; AnimationData *from = nullptr;
int animation_length = 0;
double pos = 0.0; double pos = 0.0;
float speed_scale = 1.0; float speed_scale = 1.0;
double start_time = 0.0; double start_time = 0.0;
double end_time = 0.0; double end_time = 0.0;
double get_start_time() const { double get_start_time() const {
if ((!animation_name.is_empty()) && (Animation::is_less_approx(start_time, 0) || Animation::is_greater_approx(start_time, animation_length))) { if (from && (Animation::is_less_approx(start_time, 0) || Animation::is_greater_approx(start_time, from->animation->get_length()))) {
return 0; return 0;
} }
return start_time; return start_time;
} }
double get_end_time() const { double get_end_time() const {
if ((!animation_name.is_empty()) && (Animation::is_less_approx(end_time, 0) || Animation::is_greater_approx(end_time, animation_length))) { if (from && (Animation::is_less_approx(end_time, 0) || Animation::is_greater_approx(end_time, from->animation->get_length()))) {
return animation_length; return from->animation->get_length();
} }
return end_time; return end_time;
} }