Skip to content

core: Fix MovieClip's AVM2 mouse picking for AVM1 content#23468

Open
ChrisCPI wants to merge 1 commit intoruffle-rs:masterfrom
ChrisCPI:fix-mixed-avm-mouse-pick
Open

core: Fix MovieClip's AVM2 mouse picking for AVM1 content#23468
ChrisCPI wants to merge 1 commit intoruffle-rs:masterfrom
ChrisCPI:fix-mixed-avm-mouse-pick

Conversation

@ChrisCPI
Copy link
Copy Markdown
Contributor

@ChrisCPI ChrisCPI commented Apr 16, 2026

Refactors the setting of the res value so that if mouse_pick_avm1 on the child returns None, instead of counting it as a Miss, it will allow the hit_test_shape check to happen, so that the pick can correctly propagate to the parent.

Prior to this, an AVM1 child would not respect mouseChildren on its parent, and landing on a non-interactive AVM1 object would just go through to the stage (or whatever would happen to be below it).

I also plan on making a follow up PR to apply a similar fix to LoaderDisplay.

@ChrisCPI ChrisCPI force-pushed the fix-mixed-avm-mouse-pick branch from 3d5e4c7 to 10c5556 Compare April 16, 2026 21:43
Comment thread core/src/display_object/movie_clip.rs Outdated
@ChrisCPI ChrisCPI force-pushed the fix-mixed-avm-mouse-pick branch 2 times, most recently from d82beed to 5ff719a Compare April 17, 2026 00:25
@ChrisCPI ChrisCPI requested a review from kjarosh April 17, 2026 00:37
@ChrisCPI
Copy link
Copy Markdown
Contributor Author

The only downside to this new approach is that it runs mouse_pick_avm1 twice, but not sure how I could get around that.

@ChrisCPI
Copy link
Copy Markdown
Contributor Author

Another possible option, which moves the hit_test_shape check to its own function and runs that twice. Would this be better?

                let hit_test_shape = |context: &mut UpdateContext<'gc>| {
                    if child.hit_test_shape(context, point, options)
                        && child
                            .masker()
                            .map(|mask| mask.hit_test_shape(context, point, options))
                            .unwrap_or(true)
                    {
                        if self.mouse_enabled() {
                            Avm2MousePick::Hit(this)
                        } else {
                            Avm2MousePick::PropagateToParent
                        }
                    } else {
                        Avm2MousePick::Miss
                    }
                };

                let mut res = if let Some(child) = child.as_interactive() {
                    if child.as_displayobject().movie().is_action_script_3() {
                        child.mouse_pick_avm2(context, point, require_button_mode)
                    } else {
                        let avm1_result =
                            child.mouse_pick_avm1(context, point, require_button_mode);
                        if let Some(result) = avm1_result {
                            Avm2MousePick::Hit(result)
                        } else {
                            hit_test_shape(context)
                        }
                    }
                } else {
                    hit_test_shape(context)
                };

Refactors the setting of the `res` value so that if `mouse_pick_avm1` on the child returns `None`, instead of counting it as a `Miss`, it will allow the `hit_test_shape` check to happen, so that the pick can correctly propagate to the parent.

Prior to this, an AVM1 child would not respect `mouseChildren` on its parent, and landing on a non-interactive AVM1 object would just go through to the stage (or whatever would happen to be below it).
@ChrisCPI ChrisCPI force-pushed the fix-mixed-avm-mouse-pick branch from 5ff719a to 758b8b7 Compare April 19, 2026 00:57
@ChrisCPI
Copy link
Copy Markdown
Contributor Author

Sorry for going back and forth on this, but I've finally landed on a solution I think I'm happy with.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants