Skip to content

Prevent PhysicsDirectSpaceState3D::instersect_ray when mouse is over non-ignorable gui#87362

Open
stokatyan wants to merge 1 commit intogodotengine:masterfrom
stokatyan:fix/prevent-extra-call-to-_mouse_enter-for-CollisionObject3D
Open

Prevent PhysicsDirectSpaceState3D::instersect_ray when mouse is over non-ignorable gui#87362
stokatyan wants to merge 1 commit intogodotengine:masterfrom
stokatyan:fix/prevent-extra-call-to-_mouse_enter-for-CollisionObject3D

Conversation

@stokatyan
Copy link
Copy Markdown

@stokatyan stokatyan commented Jan 19, 2024

Overview

This PR is intended to fix #87322, where a non-ignorable gui element was not blocking a CollisionShape3D's _mouse_enter from being emitted.

Issue

The cause of this bug is that _drop_physics_mouseover (in viewport.cpp) would get called when the mouse would move over gui, and that would cause a _mouse_exit to occur, and it would also result in the following if statement condition to be true: new_collider != physics_object_over because the physics_object_over would be null. That shouldn't be an issue, except that it is possible for _process_picking to be invoked on the same exact frame as the previous _drop_physics_mouseover.

I'm not 100% certain about the last sentence above, but that was my best understanding based on my debugging. I look forward to hearing from others that understand the engine better than I do.

Fix

I think the fix is to only check for 3D objects in process_picking if !gui.mouse_over. This does not break the Stop, Ignore, and Pass settings (as far as I can tell), but I have only tested on the minimum example project attached to this PR, and in the MRPs created based on comments from others.

Minimum Fix Project

minimal_mouse_hove_example.zip

Screen Recording of Fix

FIX_Prevent.on.enter.over.gui.mp4

When the mouse hovers over the 3D shape (it looks 2D because there is no lighting), the shape scales up use _mouse_enter. When the mouse hovers off the 3D shape it scales down to its original scale. I can explain the logs further if people have questions, but I want to keep this description short so I will hold off on that.

@stokatyan stokatyan requested a review from a team as a code owner January 19, 2024 09:02
@akien-mga akien-mga changed the title Prevent PhysicsDirectSpaceState3D::instersect_ray when mouse is over non-ignorable gui Prevent PhysicsDirectSpaceState3D::instersect_ray when mouse is over non-ignorable gui Jan 19, 2024
@akien-mga akien-mga added this to the 4.3 milestone Jan 19, 2024
@Sauermann Sauermann self-requested a review January 19, 2024 09:42
Comment thread scene/main/viewport.cpp Outdated
@stokatyan stokatyan marked this pull request as draft January 19, 2024 22:34
@stokatyan stokatyan force-pushed the fix/prevent-extra-call-to-_mouse_enter-for-CollisionObject3D branch from 60e1194 to 2c6ba09 Compare January 20, 2024 02:57
@stokatyan
Copy link
Copy Markdown
Author

stokatyan commented Jan 20, 2024

@Sauermann I am moving this out of draft mode. My latest commit fixes the bug I reported, and the issue you found. Please let me know what you think.

Latest Fix

2c6ba092265c9a1b0f5d7adac9dcaa575e33aed7 Fixes the issues by blocking PhysicsDirectSpaceState3D::instersect_ray when the mouse is over a Control with mouse filter set to MOUSE_FILTER_STOP.

This commit also prevents an unneeded _mouse_exit from occurring when initially entering a Control with mouse a filter set to MOUSE_FILTER_PASS (by only allowing _drop_physics_mouseover to be called when gui.mouse_over's filter is MOUSE_FILTER_STOP). The unneeded _mouse_exit was triggering an extra _mouse_enter -- similar to the original bug.

Latest MRP

minimal_mouse_hover_example_02.zip (no .godot folder)

Screen Recording

1-19-2023-7_21.mp4

The screen recording shows that there are no extra calls to the 3D collision object's mouse enter/exit, and the PASS-Control does not prevent print statements from being executed when mouse is moved over it.

Question

I noticed that the print statement for mouse movement still get printed even over the section of the PASS-Control that overlaps the STOP-Control (~9s into the screen recording). That might be another bug, but if it is, I think it is separate from this PR, and might be less of a big deal than the current bug since devs can make easier workarounds for it.

My question is: does the engine keep track of every Control hierarchy that it is over, or does it only keep track of the top-most Control hierarchy? I couldn't find anything like "gui.mouse_over_all_hierarchies" so I am assuming it only keeps track of the top-most.

@stokatyan stokatyan marked this pull request as ready for review January 20, 2024 03:36
@kitbdev
Copy link
Copy Markdown
Contributor

kitbdev commented Jan 20, 2024

related:

There is an issue when there are multiple Controls in the mouse over hierarchy and the top one is STOP.
In this Gif:

  • ta0 is the red one and has mouse filter STOP
  • ta1 is the child of ta0 and has mouse filter PASS
    godot mouse over issue 87362
    When entering the PASS Control from the Area2D, it keeps mouse over and does not drop it when the mouse is no longer overlapping it. When entering the Area2D from the PASS Control, it does not receive mouse over at all.
    Area2D and Area3D are the same here.

does the engine keep track of every Control hierarchy that it is over, or does it only keep track of the top-most Control hierarchy?

Yes, it only keeps track of the the top most since it is intended that the mouse can only be over one chain of Control nodes at a time.

The mouse filter MOUSE_FILTER_PASS actually sends events up to its parent with event bubbling, it is not intended to let events behind it.
See these issues for more about it:

Since PASS sends events up and not behind, I feel that PASS and STOP should work the same in this case and not let mouse events through to the physics picking at all, but others have different opinions about it (#54529).

@stokatyan
Copy link
Copy Markdown
Author

@kitbdev I'm not sure I completely understand your comment. I see the issue, but are you suggesting that this PR is the cause of the issue you linked? Is there something I should change in my PR or are you just pointing out that there is a separate, but possibly related, issue?

@kitbdev
Copy link
Copy Markdown
Contributor

kitbdev commented Jan 20, 2024

The linked issues are only related.

The issue in the Gif is a result of this PR, since you changed the behavior (_drop_physics_mouseover() affects 2d and 3d)
Not that the original behavior was completely functional, since the original issue you fixed also exists in 2D as well.

@stokatyan
Copy link
Copy Markdown
Author

@kitbdev can you share the MRP of the gif you shared? I see the issue in your gif, but I'd like to be sure I test against the same setup.

I think I know the issue -- my changes don't take into account the gui.mouse_over_hierarchy. I will take another look.

@kitbdev
Copy link
Copy Markdown
Contributor

kitbdev commented Jan 20, 2024

Sure, here's the MRP:
mouseover_87362_2D.zip

@stokatyan stokatyan force-pushed the fix/prevent-extra-call-to-_mouse_enter-for-CollisionObject3D branch from 2c6ba09 to d6efa63 Compare January 21, 2024 01:01
@stokatyan
Copy link
Copy Markdown
Author

stokatyan commented Jan 21, 2024

@kitbdev d6efa63 fixes the issue exposed by your MRP, and fixes the issue exposed in my MRP.

I did not expect it, but on master a PASS-Control that is a child of a STOP-Control must result in an invocation of _drop_physics_mouseover even if the portion of the PASS-Control that the mouse is over is not overlapping the STOP-Control. This commit keeps that behavior by checking if any ancestor of the PASS-Control is a STOP-Control.

Comment thread scene/main/viewport.cpp Outdated
@stokatyan stokatyan force-pushed the fix/prevent-extra-call-to-_mouse_enter-for-CollisionObject3D branch from d6efa63 to 3fc735f Compare January 21, 2024 17:20
@stokatyan
Copy link
Copy Markdown
Author

stokatyan commented Feb 8, 2024

Hi @Sauermann, this is my first PR for Godot and just want to know if I need to do anything on my end to make sure this gets reviewed in time for the the milestone deadline. Is there anything else I need to do in particular to get the reviewed?

@Sauermann
Copy link
Copy Markdown
Contributor

A large part of the reviews are done by volunteers in their spare time. So it depends on their availability.

This PR is not a trivial change and will require some effort to review and test it in depth, because PRs that touch a core-class can easily introduces unintended consequences.

@KoBeWi KoBeWi added this to the 4.4 milestone Aug 2, 2024
@Repiteo Repiteo modified the milestones: 4.4, 4.5 Feb 24, 2025
@Repiteo Repiteo modified the milestones: 4.5, 4.6 Sep 8, 2025
@mournguard
Copy link
Copy Markdown

This issue is breaking a lot of my interactions and it took me a while to figure out what was happening, I basically couldn't believe the events could be this wrong and thought it was my code for hours.

I think there's many more problems with this, all these issues seem related: #81287, #108240, #104724, #101903, and maybe more.

Many of these are about specific nodes or cases, but it might be a bit more general ; The original issue was about Area3Ds, but I stumbled on that problem with a StaticBody3D on the latest 4.5.rc1.

Nevertheless, if this PR still fixes it, even if only for 3d nodes, that's a still a good thing to merge in considering how glaring the problem is.

@SpruceBruce64
Copy link
Copy Markdown

@stokatyan If you're still interested in this PR I tested this fix by taking your commit and applying it over the latest master and found an edge case where if your control node tree has a margin container with the mouse filtering set to pass the original issue persists. If you change the filter to stop then the fix works. I think there's more cases like this but I wasn't able to recreate it often enough to pin point the cause.

I made a minimum project to demonstrate it with a margin container so you can test out changing the mouse filter
bug-test.zip

@stokatyan
Copy link
Copy Markdown
Author

@SpruceBruce64 I see your comment, but won't be able to get back into this PR until later next week. Thanks for sharing your comment, I will share an update soon.

@Repiteo Repiteo modified the milestones: 4.6, 4.x Jan 26, 2026
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.

Mouse Stop Filter unexpectedly triggers Area3D's mouse_enter signal after triggering expected mouse_exit signal

9 participants