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

Fix animation mixer breaking animations with redundant check #88554

Conversation

TCROC
Copy link
Contributor

@TCROC TCROC commented Feb 19, 2024

The animation mixer is breaking animations as described here: #88428

Shoutout to @monxa and @personalmountains for helping with the fix! Simply removing the incorrect and redundant check fixes it.

Incorrect reasoning here: #88428 (comment)

Redundant reasoning here: #88428 (comment)

@TCROC TCROC requested a review from a team as a code owner February 19, 2024 14:35
@akien-mga akien-mga added this to the 4.3 milestone Feb 19, 2024
@akien-mga akien-mga changed the title Fixed animation mixer breaking animations with redundant check Fix animation mixer breaking animations with redundant check Feb 19, 2024
Copy link
Member

@TokageItLab TokageItLab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the inside of get_node_and_resource(), you can see that get_node() is called in the second line.

Node *Node::get_node_and_resource(const NodePath &p_path, Ref<Resource> &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property) const {
	ERR_THREAD_GUARD_V(nullptr);
	Node *node = get_node(p_path);

This means that if the node is not found, an error will occur that cannot be controlled by check_path, so the check is necessary. Perhaps some additional method for checking that does not target path needs to be implemented.

Copy link
Member

@akien-mga akien-mga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirm that this fixes broken animations on https://github.com/gdquest-demos/godot-4-3d-third-person-controller and https://github.com/godotengine/tps-demo/

Warning: The Godot TPS demo has another rendering regression since 4.3-dev3, which makes crazily flashing lights, this is not epilepsy safe.

@akien-mga
Copy link
Member

@TokageItLab's assessment seems correct, but the demos I mentioned do not seem to raise any get_node errors, yet this check seems to completely break their animations. I'm puzzled.

@akien-mga
Copy link
Member

Ok right, see #88428 (comment) which @TCROC linked in the OP. The difference is the value of the p_last_is_property boolean. So this means that has_node_and_resource fails in this case, when what you seem to want is to just prevent get_node from failing.

So you should just check has_node, or add p_last_is_property to has_node_and_resource if it's needed to do all the checks.

@akien-mga
Copy link
Member

diff --git a/scene/animation/animation_mixer.cpp b/scene/animation/animation_mixer.cpp
index 706d210064..eec70e737f 100644
--- a/scene/animation/animation_mixer.cpp
+++ b/scene/animation/animation_mixer.cpp
@@ -661,7 +661,7 @@ bool AnimationMixer::_update_caches() {
 				Ref<Resource> resource;
 				Vector<StringName> leftover_path;
 
-				if (!parent->has_node_and_resource(path)) {
+				if (!parent->has_node(path)) {
 					if (check_path) {
 						WARN_PRINT_ED(mixer_name + ": '" + String(E) + "', couldn't resolve track:  '" + String(path) + "'. This warning can be disabled in Project Settings.");
 					}

This is a more minimal fix that should still prevent errors when get_node(p_path) fails.

@TokageItLab
Copy link
Member

TokageItLab commented Feb 19, 2024

@akien-mga I think it's a problem when resource is not found.

I think it would be straighforward to add a p_last_is_property argument to has_node_and_resource() and propagate it to the internal get_node_and_resource(), but I am sure you are still double checking for its existence.

Probably the most intelligent way is to add an optional argument to get_node_and_resource(const NodePath &p_path, Ref<Resource> &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property, bool p_throw_error = true) and get_node(const NodePath &p_path, bool p_throw_error = true) to hide errors.

@akien-mga
Copy link
Member

I wouldn't change get_node (you can always just call has_node first), but get_node_and_resource can simply use has_node.

@TokageItLab
Copy link
Member

TokageItLab commented Feb 19, 2024

Ah right, get_node_and_resource() does not give any additional errors. So #88554 (comment) seems correct way.

@akien-mga
Copy link
Member

I would just add this change to this PR:

diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index e814e4f0cd..f827f68def 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -3025,9 +3025,9 @@ Array Node::_get_node_and_resource(const NodePath &p_path) {
 
 Node *Node::get_node_and_resource(const NodePath &p_path, Ref<Resource> &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property) const {
 	ERR_THREAD_GUARD_V(nullptr);
-	Node *node = get_node(p_path);
 	r_res = Ref<Resource>();
 	r_leftover_subpath = Vector<StringName>();
+	Node *node = get_node_or_null(p_path);
 	if (!node) {
 		return nullptr;
 	}

And then I think it's good to go. It's probably reasonable for get_node_and_resource not to print an error and just return nullptr.

@TokageItLab
Copy link
Member

TokageItLab commented Feb 19, 2024

However, since path checking should be enabled by default (to detect errors for invalid path), the following code would be necessary.

if (check_path && !parent->has_node(path)) {
	WARN_PRINT_ED(mixer_name + ": '" + String(E) + "', couldn't resolve track:  '" + String(path) + "'. This warning can be disabled in Project Settings.");
	continue;
}

@akien-mga
Copy link
Member

@TokageItLab This is already handled by the next check:

				Node *child = parent->get_node_and_resource(path, resource, leftover_path);
				if (!child) {
					if (check_path) {
						WARN_PRINT_ED(mixer_name + ": '" + String(E) + "', couldn't resolve track:  '" + String(path) + "'. This warning can be disabled in Project Settings.");
					}
					continue;
				}

child will be nullptr if it wouldn't pass has_node.

@TokageItLab
Copy link
Member

@akien-mga Ah, make sense. So just replacing get_node to get_node_or_null is sufficient.

@akien-mga
Copy link
Member

Superseded by #88557 which adds the Node::get_node_and_resource change.

Thanks for the contribution!

@akien-mga akien-mga closed this Feb 19, 2024
@AThousandShips AThousandShips removed this from the 4.3 milestone Feb 19, 2024
@TCROC
Copy link
Contributor Author

TCROC commented Feb 19, 2024

Superseded by #88557 which adds the Node::get_node_and_resource change.

Thanks for the contribution!

Absolutely! :) Glad to help! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants