Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animation CAPTURE mode does not work in AnimationTree #55110

Closed
kingoftheconnors opened this issue Nov 19, 2021 · 8 comments · Fixed by #86715
Closed

Animation CAPTURE mode does not work in AnimationTree #55110

kingoftheconnors opened this issue Nov 19, 2021 · 8 comments · Fixed by #86715

Comments

@kingoftheconnors
Copy link
Contributor

Godot version

3.3.2

System information

Windows 10, GLES3, Intel HD Graphics 4600

Issue description

I created an animation using the CAPTURE transition mode. I expected this to work in an AnimationTreeStateMachine, with the captured tween starting at the node's position when the animation starts. Instead, it acts just like a regular transition mode, causing the property to be insta-set to the first key.

Steps to reproduce

image

When run as an AnimationPlayer using $AnimationPlayer.start("animation"), it works as expected; however, when placing the animation in an AnimationTreeStateMachine and using $AnimationTree['parameters/playback'].travel("animation") it does not do any capturing and starts the node property at the first key.

Godot.Engine.-.AnimationTreeProblem.-.Test.tscn._.2021-11-18.21-33-50.mp4

It looks as though the AnimationTree does not handle the CAPTURE mode.

Animation_Player.cpp, line 400:

case Animation::TYPE_VALUE: {

	Map<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.find(a->track_get_path(i).get_concatenated_subnames());
	ERR_CONTINUE(!E); //should it continue, or create a new one?

	TrackNodeCache::PropertyAnim *pa = &E->get();

	Animation::UpdateMode update_mode = a->value_track_get_update_mode(i);

	if (update_mode == Animation::UPDATE_CAPTURE) {
		if (p_started || pa->capture == Variant()) {
			pa->capture = pa->object->get_indexed(pa->subpath);
		}

		int key_count = a->track_get_key_count(i);
		if (key_count == 0)
			continue; //eeh not worth it

		float first_key_time = a->track_get_key_time(i, 0);
		float transition = 1.0;
		int first_key = 0;

		if (first_key_time == 0.0) {
			//ignore, use for transition
			if (key_count == 1)
				continue; //with one key we can't do anything
			transition = a->track_get_key_transition(i, 0);
			first_key_time = a->track_get_key_time(i, 1);
			first_key = 1;
		}

		if (p_time < first_key_time) {
			float 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);

			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);
			}

			continue; //handled
		}
	}

	if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE || (p_delta == 0 && update_mode == Animation::UPDATE_DISCRETE)) { //delta == 0 means seek

		Variant value = a->value_track_interpolate(i, p_time);

		...

Animation_Tree.cpp, line 937:


case Animation::TYPE_VALUE: {
	TrackCacheValue *t = static_cast<TrackCacheValue *>(track);

	Animation::UpdateMode update_mode = a->value_track_get_update_mode(i);

	if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) { //delta == 0 means seek

		Variant value = a->value_track_interpolate(i, time);

		...

Both use a->value_track_interpolation(), but the AnimationTree does not intercept the request if p_time < first_time_key like the AnimationPlayer does.

Minimal reproduction project

AnimationTreeProblem.zip

@TokageItLab
Copy link
Member

TokageItLab commented Nov 27, 2021

May be related by #48432.

@akien-mga
Copy link
Member

akien-mga commented Feb 8, 2024

It's a stretch 2+ years later, but in case you still have a project trying to make use of CAPTURE in 4.x, could you assess whether #86715 solves the issue the way you would expect it to? You can test the PR by download a build (artifact) for your platform from the "Checks" (CI) tab.

@kingoftheconnors
Copy link
Contributor Author

@akien-mga I'll do it tonight!

@kingoftheconnors
Copy link
Contributor Author

@akien-mga No, it's not fixed. And it may be because capture node isn't working for AnimationPlayer either. So it's just straight-up broken.

_.TestAnimate.tscn.-.TestAnimationCapture.-.Godot.Engine.2024-02-09.09-09-09.mp4

Note, if I go back to 4.1 and test it out, the AnimationPlayer IS working with capture (although AnimationTree isn't), so it must have been broken by this commit or a recent one.

TestAnimate.tscn.-.TestAnimationCapture.-.Godot.Engine.2024-02-09.09-12-08.mp4

@TokageItLab
Copy link
Member

TokageItLab commented Feb 9, 2024

@kingoftheconnors You should read the PR description. Currently, the editor does not playback the capture so you must use capture() method in script to interpolate capture frame.

@kingoftheconnors
Copy link
Contributor Author

@TokageItLab Ah, thanks!

I've tested it out using capture(), and while running AnimationPlayer directly from a script DOES work, AnimationTree does not:

extends Timer

var is_left : bool = false
func _on_timeout() -> void:
	var animator : AnimationPlayer = get_node("../AnimationPlayer")
	var animation_tree : AnimationTree = get_node("../AnimationTree")
	if is_left:
		#animator.play_with_capture("go_right") #This DOES work
		animator.capture("go_right", 1.0)
		animation_tree['parameters/playback'].travel("go_right")
	else:
		#animator.play_with_capture("go_left") #This DOES work
		animator.capture("go_left", 1.0)
		animation_tree['parameters/playback'].travel("go_left")
	is_left = !is_left
TestAnimationCapture.DEBUG.2024-02-09.14-36-55.mp4

I also tested it with start(), instead of travel() and it was the same deal.

@TokageItLab
Copy link
Member

Use animation_tree.capture(), not animation_player.capture() if you want to use AnimationTree.

@kingoftheconnors
Copy link
Contributor Author

Ah, that works!

I can confirm this issue is fixed. I'll close this.

@TokageItLab TokageItLab modified the milestones: 4.x, 4.3 Feb 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants