mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	Fix seeking Animation immediate after playback for Discrete track
This commit is contained in:
		
							parent
							
								
									e96ad5af98
								
							
						
					
					
						commit
						bea47d877b
					
				
					 8 changed files with 47 additions and 31 deletions
				
			
		|  | @ -360,9 +360,12 @@ | ||||||
| 			<param index="1" name="time" type="float" /> | 			<param index="1" name="time" type="float" /> | ||||||
| 			<param index="2" name="find_mode" type="int" enum="Animation.FindMode" default="0" /> | 			<param index="2" name="find_mode" type="int" enum="Animation.FindMode" default="0" /> | ||||||
| 			<param index="3" name="limit" type="bool" default="false" /> | 			<param index="3" name="limit" type="bool" default="false" /> | ||||||
|  | 			<param index="4" name="backward" type="bool" default="false" /> | ||||||
| 			<description> | 			<description> | ||||||
| 				Finds the key index by time in a given track. Optionally, only find it if the approx/exact time is given. | 				Finds the key index by time in a given track. Optionally, only find it if the approx/exact time is given. | ||||||
| 				If [param limit] is [code]true[/code], it does not return keys outside the animation range. | 				If [param limit] is [code]true[/code], it does not return keys outside the animation range. | ||||||
|  | 				If [param backward] is [code]true[/code], the direction is reversed in methods that rely on one directional processing. | ||||||
|  | 				For example, in case [param find_mode] is [constant FIND_MODE_NEAREST], if there is no key in the current position just after seeked, the first key found is retrieved by searching before the position, but if [param backward] is [code]true[/code], the first key found is retrieved after the position. | ||||||
| 			</description> | 			</description> | ||||||
| 		</method> | 		</method> | ||||||
| 		<method name="track_get_interpolation_loop_wrap" qualifiers="const"> | 		<method name="track_get_interpolation_loop_wrap" qualifiers="const"> | ||||||
|  | @ -583,6 +586,7 @@ | ||||||
| 			<param index="2" name="backward" type="bool" default="false" /> | 			<param index="2" name="backward" type="bool" default="false" /> | ||||||
| 			<description> | 			<description> | ||||||
| 				Returns the interpolated value at the given time (in seconds). The [param track_idx] must be the index of a value track. | 				Returns the interpolated value at the given time (in seconds). The [param track_idx] must be the index of a value track. | ||||||
|  | 				A [param backward] mainly affects the direction of key retrieval of the track with [constant UPDATE_DISCRETE] converted by [constant AnimationMixer.ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS] to match the result with [method track_find_key]. | ||||||
| 			</description> | 			</description> | ||||||
| 		</method> | 		</method> | ||||||
| 		<method name="value_track_set_update_mode"> | 		<method name="value_track_set_update_mode"> | ||||||
|  |  | ||||||
|  | @ -243,12 +243,12 @@ void AnimationPlayerEditor::_play_from_pressed() { | ||||||
| 	String current = _get_current(); | 	String current = _get_current(); | ||||||
| 
 | 
 | ||||||
| 	if (!current.is_empty()) { | 	if (!current.is_empty()) { | ||||||
| 		float time = player->get_current_animation_position(); | 		double time = player->get_current_animation_position(); | ||||||
| 		if (current == player->get_assigned_animation() && player->is_playing()) { | 		if (current == player->get_assigned_animation() && player->is_playing()) { | ||||||
| 			player->stop(); //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."); | 		ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing."); | ||||||
| 		player->seek(time); | 		player->seek(time, true, true); | ||||||
| 		player->play(current); | 		player->play(current); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -281,12 +281,12 @@ void AnimationPlayerEditor::_play_bw_from_pressed() { | ||||||
| 	String current = _get_current(); | 	String current = _get_current(); | ||||||
| 
 | 
 | ||||||
| 	if (!current.is_empty()) { | 	if (!current.is_empty()) { | ||||||
| 		float time = player->get_current_animation_position(); | 		double time = player->get_current_animation_position(); | ||||||
| 		if (current == player->get_assigned_animation()) { | 		if (current == player->get_assigned_animation() && player->is_playing()) { | ||||||
| 			player->stop(); //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."); | 		ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing."); | ||||||
| 		player->seek(time); | 		player->seek(time, true, true); | ||||||
| 		player->play_backwards(current); | 		player->play_backwards(current); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -364,3 +364,9 @@ GH-92322 | ||||||
| Validate extension JSON: Error: Field 'classes/EditorInspectorPlugin/methods/add_property_editor/arguments': size changed value in new API, from 3 to 4. | Validate extension JSON: Error: Field 'classes/EditorInspectorPlugin/methods/add_property_editor/arguments': size changed value in new API, from 3 to 4. | ||||||
| 
 | 
 | ||||||
| Optional arguments added. Compatibility methods registered. | Optional arguments added. Compatibility methods registered. | ||||||
|  | 
 | ||||||
|  | GH-86661 | ||||||
|  | -------- | ||||||
|  | Validate extension JSON: Error: Field 'classes/Animation/methods/track_find_key/arguments': size changed value in new API, from 3 to 5. | ||||||
|  | 
 | ||||||
|  | Added optional argument to track_find_key to handle backward seeking. Compatibility method registered. | ||||||
|  |  | ||||||
|  | @ -1109,6 +1109,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { | ||||||
| 		real_t weight = ai.playback_info.weight; | 		real_t weight = ai.playback_info.weight; | ||||||
| 		Vector<real_t> track_weights = ai.playback_info.track_weights; | 		Vector<real_t> track_weights = ai.playback_info.track_weights; | ||||||
| 		bool backward = signbit(delta); // This flag is used by the root motion calculates or detecting the end of audio stream.
 | 		bool backward = signbit(delta); // This flag is used by the root motion calculates or detecting the end of audio stream.
 | ||||||
|  | 		bool seeked_backward = signbit(p_delta); | ||||||
| #ifndef _3D_DISABLED | #ifndef _3D_DISABLED | ||||||
| 		bool calc_root = !seeked || is_external_seeking; | 		bool calc_root = !seeked || is_external_seeking; | ||||||
| #endif // _3D_DISABLED
 | #endif // _3D_DISABLED
 | ||||||
|  | @ -1463,7 +1464,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { | ||||||
| 						} | 						} | ||||||
| 					} else { | 					} else { | ||||||
| 						if (seeked) { | 						if (seeked) { | ||||||
| 							int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT, true); | 							int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT, false, seeked_backward); | ||||||
| 							if (idx < 0) { | 							if (idx < 0) { | ||||||
| 								continue; | 								continue; | ||||||
| 							} | 							} | ||||||
|  | @ -1744,8 +1745,10 @@ void AnimationMixer::_blend_apply() { | ||||||
| 			case Animation::TYPE_VALUE: { | 			case Animation::TYPE_VALUE: { | ||||||
| 				TrackCacheValue *t = static_cast<TrackCacheValue *>(track); | 				TrackCacheValue *t = static_cast<TrackCacheValue *>(track); | ||||||
| 
 | 
 | ||||||
| 				if (t->use_discrete && !t->use_continuous) { | 				if (callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS) { | ||||||
| 					t->is_init = true; // If only disctere value is applied, no more RESET.
 | 					t->is_init = false; // Always update in Force Continuous.
 | ||||||
|  | 				} else if (!t->use_continuous && (t->use_discrete || !deterministic)) { | ||||||
|  | 					t->is_init = true; // If there is no continuous value and only disctere value is applied or just started, don't RESET.
 | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if ((t->is_init && (is_zero_amount || !t->use_continuous)) || | 				if ((t->is_init && (is_zero_amount || !t->use_continuous)) || | ||||||
|  | @ -1756,9 +1759,7 @@ void AnimationMixer::_blend_apply() { | ||||||
| 					break; // Don't overwrite the value set by UPDATE_DISCRETE.
 | 					break; // Don't overwrite the value set by UPDATE_DISCRETE.
 | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS) { | 				if (callback_mode_discrete != ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS) { | ||||||
| 					t->is_init = false; // Always update in Force Continuous.
 |  | ||||||
| 				} else { |  | ||||||
| 					t->is_init = !t->use_continuous; // If there is no Continuous in non-Force Continuous type, it means RESET.
 | 					t->is_init = !t->use_continuous; // If there is no Continuous in non-Force Continuous type, it means RESET.
 | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -234,6 +234,9 @@ void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, f | ||||||
| 		pi.delta = delta; | 		pi.delta = delta; | ||||||
| 		pi.seeked = p_seeked; | 		pi.seeked = p_seeked; | ||||||
| 	} | 	} | ||||||
|  | 	if (Math::is_zero_approx(pi.delta) && backwards) { | ||||||
|  | 		pi.delta = -0.0; // Sign is needed to handle converted Continuous track from Discrete track correctly.
 | ||||||
|  | 	} | ||||||
| 	// AnimationPlayer doesn't have internal seeking.
 | 	// AnimationPlayer doesn't have internal seeking.
 | ||||||
| 	// However, immediately after playback, discrete keys should be retrieved with EXACT mode since behind keys must be ignored at that time.
 | 	// However, immediately after playback, discrete keys should be retrieved with EXACT mode since behind keys must be ignored at that time.
 | ||||||
| 	pi.is_external_seeking = !p_started; | 	pi.is_external_seeking = !p_started; | ||||||
|  | @ -257,7 +260,7 @@ void AnimationPlayer::_blend_playback_data(double p_delta, bool p_started) { | ||||||
| 
 | 
 | ||||||
| 	bool seeked = c.seeked; // The animation may be changed during process, so it is safer that the state is changed before process.
 | 	bool seeked = c.seeked; // The animation may be changed during process, so it is safer that the state is changed before process.
 | ||||||
| 
 | 
 | ||||||
| 	if (p_delta != 0) { | 	if (!Math::is_zero_approx(p_delta)) { | ||||||
| 		c.seeked = false; | 		c.seeked = false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -581,6 +584,8 @@ void AnimationPlayer::seek(double p_time, bool p_update, bool p_update_only) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	bool is_backward = p_time < playback.current.pos; | ||||||
|  | 
 | ||||||
| 	_check_immediately_after_start(); | 	_check_immediately_after_start(); | ||||||
| 
 | 
 | ||||||
| 	playback.current.pos = p_time; | 	playback.current.pos = p_time; | ||||||
|  | @ -596,7 +601,7 @@ void AnimationPlayer::seek(double p_time, bool p_update, bool p_update_only) { | ||||||
| 
 | 
 | ||||||
| 	playback.seeked = true; | 	playback.seeked = true; | ||||||
| 	if (p_update) { | 	if (p_update) { | ||||||
| 		_process_animation(0, p_update_only); | 		_process_animation(is_backward ? -0.0 : 0.0, p_update_only); | ||||||
| 		playback.seeked = false; // If animation was proceeded here, no more seek in internal process.
 | 		playback.seeked = false; // If animation was proceeded here, no more seek in internal process.
 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -50,8 +50,8 @@ Variant Animation::_value_track_interpolate_bind_compat_86629(int p_track, doubl | ||||||
| 	return value_track_interpolate(p_track, p_time, false); | 	return value_track_interpolate(p_track, p_time, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int Animation::_track_find_key_bind_compat_86661(int p_track, double p_time, FindMode p_find_mode) const { | int Animation::_track_find_key_bind_compat_92861(int p_track, double p_time, FindMode p_find_mode) const { | ||||||
| 	return track_find_key(p_track, p_time, p_find_mode, false); | 	return track_find_key(p_track, p_time, p_find_mode, false, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Animation::_bind_compatibility_methods() { | void Animation::_bind_compatibility_methods() { | ||||||
|  | @ -60,7 +60,7 @@ void Animation::_bind_compatibility_methods() { | ||||||
| 	ClassDB::bind_compatibility_method(D_METHOD("scale_track_interpolate", "track_idx", "time_sec"), &Animation::_scale_track_interpolate_bind_compat_86629); | 	ClassDB::bind_compatibility_method(D_METHOD("scale_track_interpolate", "track_idx", "time_sec"), &Animation::_scale_track_interpolate_bind_compat_86629); | ||||||
| 	ClassDB::bind_compatibility_method(D_METHOD("blend_shape_track_interpolate", "track_idx", "time_sec"), &Animation::_blend_shape_track_interpolate_bind_compat_86629); | 	ClassDB::bind_compatibility_method(D_METHOD("blend_shape_track_interpolate", "track_idx", "time_sec"), &Animation::_blend_shape_track_interpolate_bind_compat_86629); | ||||||
| 	ClassDB::bind_compatibility_method(D_METHOD("value_track_interpolate", "track_idx", "time_sec"), &Animation::_value_track_interpolate_bind_compat_86629); | 	ClassDB::bind_compatibility_method(D_METHOD("value_track_interpolate", "track_idx", "time_sec"), &Animation::_value_track_interpolate_bind_compat_86629); | ||||||
| 	ClassDB::bind_compatibility_method(D_METHOD("track_find_key", "track_idx", "time", "find_mode"), &Animation::_track_find_key_bind_compat_86661, DEFVAL(FIND_MODE_NEAREST)); | 	ClassDB::bind_compatibility_method(D_METHOD("track_find_key", "track_idx", "time", "find_mode"), &Animation::_track_find_key_bind_compat_92861, DEFVAL(FIND_MODE_NEAREST)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif // DISABLE_DEPRECATED
 | #endif // DISABLE_DEPRECATED
 | ||||||
|  |  | ||||||
|  | @ -1496,7 +1496,7 @@ void Animation::track_remove_key(int p_track, int p_idx) { | ||||||
| 	emit_changed(); | 	emit_changed(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, bool p_limit) const { | int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, bool p_limit, bool p_backward) const { | ||||||
| 	ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); | 	ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); | ||||||
| 	Track *t = tracks[p_track]; | 	Track *t = tracks[p_track]; | ||||||
| 
 | 
 | ||||||
|  | @ -1518,7 +1518,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 				return key_index; | 				return key_index; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			int k = _find(tt->positions, p_time, false, p_limit); | 			int k = _find(tt->positions, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= tt->positions.size()) { | 			if (k < 0 || k >= tt->positions.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -1545,7 +1545,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 				return key_index; | 				return key_index; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			int k = _find(rt->rotations, p_time, false, p_limit); | 			int k = _find(rt->rotations, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= rt->rotations.size()) { | 			if (k < 0 || k >= rt->rotations.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -1572,7 +1572,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 				return key_index; | 				return key_index; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			int k = _find(st->scales, p_time, false, p_limit); | 			int k = _find(st->scales, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= st->scales.size()) { | 			if (k < 0 || k >= st->scales.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -1599,7 +1599,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 				return key_index; | 				return key_index; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			int k = _find(bst->blend_shapes, p_time, false, p_limit); | 			int k = _find(bst->blend_shapes, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= bst->blend_shapes.size()) { | 			if (k < 0 || k >= bst->blend_shapes.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -1611,7 +1611,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 		} break; | 		} break; | ||||||
| 		case TYPE_VALUE: { | 		case TYPE_VALUE: { | ||||||
| 			ValueTrack *vt = static_cast<ValueTrack *>(t); | 			ValueTrack *vt = static_cast<ValueTrack *>(t); | ||||||
| 			int k = _find(vt->values, p_time, false, p_limit); | 			int k = _find(vt->values, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= vt->values.size()) { | 			if (k < 0 || k >= vt->values.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -1623,7 +1623,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 		} break; | 		} break; | ||||||
| 		case TYPE_METHOD: { | 		case TYPE_METHOD: { | ||||||
| 			MethodTrack *mt = static_cast<MethodTrack *>(t); | 			MethodTrack *mt = static_cast<MethodTrack *>(t); | ||||||
| 			int k = _find(mt->methods, p_time, false, p_limit); | 			int k = _find(mt->methods, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= mt->methods.size()) { | 			if (k < 0 || k >= mt->methods.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -1635,7 +1635,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 		} break; | 		} break; | ||||||
| 		case TYPE_BEZIER: { | 		case TYPE_BEZIER: { | ||||||
| 			BezierTrack *bt = static_cast<BezierTrack *>(t); | 			BezierTrack *bt = static_cast<BezierTrack *>(t); | ||||||
| 			int k = _find(bt->values, p_time, false, p_limit); | 			int k = _find(bt->values, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= bt->values.size()) { | 			if (k < 0 || k >= bt->values.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -1647,7 +1647,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 		} break; | 		} break; | ||||||
| 		case TYPE_AUDIO: { | 		case TYPE_AUDIO: { | ||||||
| 			AudioTrack *at = static_cast<AudioTrack *>(t); | 			AudioTrack *at = static_cast<AudioTrack *>(t); | ||||||
| 			int k = _find(at->values, p_time, false, p_limit); | 			int k = _find(at->values, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= at->values.size()) { | 			if (k < 0 || k >= at->values.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -1659,7 +1659,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, | ||||||
| 		} break; | 		} break; | ||||||
| 		case TYPE_ANIMATION: { | 		case TYPE_ANIMATION: { | ||||||
| 			AnimationTrack *at = static_cast<AnimationTrack *>(t); | 			AnimationTrack *at = static_cast<AnimationTrack *>(t); | ||||||
| 			int k = _find(at->values, p_time, false, p_limit); | 			int k = _find(at->values, p_time, p_backward, p_limit); | ||||||
| 			if (k < 0 || k >= at->values.size()) { | 			if (k < 0 || k >= at->values.size()) { | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | @ -3836,7 +3836,7 @@ void Animation::_bind_methods() { | ||||||
| 	ClassDB::bind_method(D_METHOD("track_get_key_count", "track_idx"), &Animation::track_get_key_count); | 	ClassDB::bind_method(D_METHOD("track_get_key_count", "track_idx"), &Animation::track_get_key_count); | ||||||
| 	ClassDB::bind_method(D_METHOD("track_get_key_value", "track_idx", "key_idx"), &Animation::track_get_key_value); | 	ClassDB::bind_method(D_METHOD("track_get_key_value", "track_idx", "key_idx"), &Animation::track_get_key_value); | ||||||
| 	ClassDB::bind_method(D_METHOD("track_get_key_time", "track_idx", "key_idx"), &Animation::track_get_key_time); | 	ClassDB::bind_method(D_METHOD("track_get_key_time", "track_idx", "key_idx"), &Animation::track_get_key_time); | ||||||
| 	ClassDB::bind_method(D_METHOD("track_find_key", "track_idx", "time", "find_mode", "limit"), &Animation::track_find_key, DEFVAL(FIND_MODE_NEAREST), DEFVAL(false)); | 	ClassDB::bind_method(D_METHOD("track_find_key", "track_idx", "time", "find_mode", "limit", "backward"), &Animation::track_find_key, DEFVAL(FIND_MODE_NEAREST), DEFVAL(false), DEFVAL(false)); | ||||||
| 
 | 
 | ||||||
| 	ClassDB::bind_method(D_METHOD("track_set_interpolation_type", "track_idx", "interpolation"), &Animation::track_set_interpolation_type); | 	ClassDB::bind_method(D_METHOD("track_set_interpolation_type", "track_idx", "interpolation"), &Animation::track_set_interpolation_type); | ||||||
| 	ClassDB::bind_method(D_METHOD("track_get_interpolation_type", "track_idx"), &Animation::track_get_interpolation_type); | 	ClassDB::bind_method(D_METHOD("track_get_interpolation_type", "track_idx"), &Animation::track_get_interpolation_type); | ||||||
|  |  | ||||||
|  | @ -388,7 +388,7 @@ protected: | ||||||
| 	Vector3 _scale_track_interpolate_bind_compat_86629(int p_track, double p_time) const; | 	Vector3 _scale_track_interpolate_bind_compat_86629(int p_track, double p_time) const; | ||||||
| 	float _blend_shape_track_interpolate_bind_compat_86629(int p_track, double p_time) const; | 	float _blend_shape_track_interpolate_bind_compat_86629(int p_track, double p_time) const; | ||||||
| 	Variant _value_track_interpolate_bind_compat_86629(int p_track, double p_time) const; | 	Variant _value_track_interpolate_bind_compat_86629(int p_track, double p_time) const; | ||||||
| 	int _track_find_key_bind_compat_86661(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST) const; | 	int _track_find_key_bind_compat_92861(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST) const; | ||||||
| 	static void _bind_compatibility_methods(); | 	static void _bind_compatibility_methods(); | ||||||
| #endif // DISABLE_DEPRECATED
 | #endif // DISABLE_DEPRECATED
 | ||||||
| 
 | 
 | ||||||
|  | @ -423,7 +423,7 @@ public: | ||||||
| 	void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition); | 	void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition); | ||||||
| 	void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value); | 	void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value); | ||||||
| 	void track_set_key_time(int p_track, int p_key_idx, double p_time); | 	void track_set_key_time(int p_track, int p_key_idx, double p_time); | ||||||
| 	int track_find_key(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST, bool p_limit = false) const; | 	int track_find_key(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST, bool p_limit = false, bool p_backward = false) const; | ||||||
| 	void track_remove_key(int p_track, int p_idx); | 	void track_remove_key(int p_track, int p_idx); | ||||||
| 	void track_remove_key_at_time(int p_track, double p_time); | 	void track_remove_key_at_time(int p_track, double p_time); | ||||||
| 	int track_get_key_count(int p_track) const; | 	int track_get_key_count(int p_track) const; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Silc Lizard (Tokage) Renew
						Silc Lizard (Tokage) Renew