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

Make CanvasItem's "drawing outside of NOTIFICATION_DRAW" error a macro #89298

Merged

Conversation

Mickeon
Copy link
Contributor

@Mickeon Mickeon commented Mar 8, 2024

The premise is simple:
image
Imagine this but 25 times.

I also took the chance to improve upon the error message itself. At least, attempted to.

Please give suggestions for a better macro name, I do not know the pattern.

Resolves #75376.

@Mickeon Mickeon added this to the 4.3 milestone Mar 8, 2024
@Mickeon Mickeon requested a review from a team as a code owner March 8, 2024 21:19
@Mickeon Mickeon force-pushed the CanvasItem-error-clean-as-hell branch from fcfeebf to e4b908e Compare March 8, 2024 21:36
@Mickeon
Copy link
Contributor Author

Mickeon commented Mar 9, 2024

I do not have the capacity to test any of this so I just stripped the DEBUG_ENABLED

Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

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

LGTM

Worth doing a future pass to see if it's something to make a debug only check, but generally we don't make that distinction unless it's very development side, if it's possible without weird side effects it'd be worth considering, but since the check is so cheap I don't think it's worth evaluating on it's own, maybe a future sweep for different checks would be something to consider

@kleonc
Copy link
Member

kleonc commented Mar 9, 2024

I also took the chance to improve upon the error message itself. At least, attempted to.

This should resolve #75376. But maybe the error message should also explicitly state what this and CanvasItem::current_item_drawn are when the error happens? Directly pointing out the problematic nodes should make debugging / understanding what's the problem much easier.

@Mickeon
Copy link
Contributor Author

Mickeon commented Mar 9, 2024

I do agree and I tried to do that. Problem is I just couldn't find a nice "spot" to explicitly state both.

@AThousandShips
Copy link
Member

CanvasItem::current_item_drawn will always be nullptr when drawing is false though

@Mickeon
Copy link
Contributor Author

Mickeon commented Mar 9, 2024

Yeah, that one cannot be done. But the node name can. I wouldn't want the error to be too verbose as it will be prone to get spammed in the debugger. Not pretty, so I gotta be careful.

@AThousandShips
Copy link
Member

Risks causing unhelpful editor paths indeed, like parenting errors at times root/@EditorNode@17034/@Panel@13/@VBoxContainer@14/@HSplitContainer@17/@HSplitContainer@25/@VSplitContainer@27/@TabContainer@29/Scene/@P

@Mickeon
Copy link
Contributor Author

Mickeon commented Mar 9, 2024

I thought about it and I cannot fit the name anywhere. I wish there was a standard way to mention it.
vformat("Node (%s) cannot draw outside of its drawing routine. Drawing is only allowed inside this node's `_draw()`, functions connected to its `draw` signal, or when it receives NOTIFICATION_DRAW.", )

But this is bad already.
image
Of course that doesn't mean errors shouldn't be more explicit, and the Errors tab should be MUCH IMPROVED for this, but if this message is any longer it'd be just plain irritating.
This behavior is already documented (by yours truly may I add) but perhaps it needs to be even more explicit, as what the "drawing routine" is isn't exactly clear on the surface.

scene/main/canvas_item.h Outdated Show resolved Hide resolved
@Mickeon Mickeon force-pushed the CanvasItem-error-clean-as-hell branch from 9d95596 to 05afbb8 Compare March 9, 2024 21:40
@Mickeon
Copy link
Contributor Author

Mickeon commented Mar 9, 2024

Applied both suggestions. Note that the ERR_THREAD_GUARDs are not formatted the same way.

@Mickeon Mickeon force-pushed the CanvasItem-error-clean-as-hell branch from 05afbb8 to e44927a Compare March 9, 2024 21:45
@Mickeon Mickeon force-pushed the CanvasItem-error-clean-as-hell branch from e44927a to e08fb19 Compare March 9, 2024 21:47
Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

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

Re-confirming, let's take a look later at a standardized and low-clutter way to convey where errors occur as per the suggestions above, but looks good just as a cleanup

@kleonc
Copy link
Member

kleonc commented Mar 10, 2024

CanvasItem::current_item_drawn will always be nullptr when drawing is false though

Not really, you can call draw_x methods on a different CanvasItem than current_item_drawn and it will result in such errors, as such other CanvasItem is not drawing at that point (drawing is non-static contrary to current_item_drawn).
That's exactly when the current error message (pre this PR) would confuse people when they try to do something like:

extends Node2D
func _draw():
	# When this is called `current_item_drawn` is `self`.
	some_other_canvas_item.draw_circle(...) # Any `draw_x` method called on non-self canvas item.

	# Error: "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."
	# User: What do you mean?! It is in `_draw()`...

The error being changed to:

"Drawing is only allowed inside this node's `_draw()`, functions connected to its `draw` signal, or when it receives NOTIFICATION_DRAW."

already makes the error message correct/clearier. 👍


Regarding further improvement - yeah, I agree it's out of scope of this PR. I'm also not sure what would be a good way to refer to the problematic nodes. Path seems too long, just names too vague, Node::to_string which includes ObjectID not "friendly enough" and still it doesn't provide info the path does, etc.


BTW it could be also considered to have slightly different error messages depending on the case, like:

ERR_FAIL_COND_MSG(current_item_drawn == nulltpr, "..."); // Not in drawing routine at all.
ERR_FAIL_COND_MSG(current_item_drawn != this, "..."); // In drawing routine of a different CanvasItem.

(drawing bool would be no longer needed if the error conditions would be changed like that.)

Wondering if something like this could make things clearer even if not directly specifying what canvas item(s) this happened for. But also not sure how doubling the checks would affect performance.

Just a thought, not saying it should be done in here. This PR is fine as is.

@Mickeon
Copy link
Contributor Author

Mickeon commented Mar 10, 2024

Speaking of the much prior topic, if only checking for drawing in debug builds has a good chance of breaking things in release builds, I have to question how bad things can break when the raw RenderingServer methods try to draw outside of the routine, as well? If that's even possible?

@akien-mga akien-mga merged commit ba062e1 into godotengine:master Mar 10, 2024
16 checks passed
@akien-mga
Copy link
Member

Thanks!

@Mickeon Mickeon deleted the CanvasItem-error-clean-as-hell branch March 10, 2024 20:53
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.

Cannot call Callable in a draw method (because no way to set_object on Callable?)
4 participants