Skip to content

Conversation

@stilnat
Copy link
Contributor

@stilnat stilnat commented Nov 15, 2025

Description

Currently, scaling is only working on device scale. This PR allows scaling gesture to be applied on components, very much like dragging works with drag callbacks. I added a ScaleDispatcher component which works very similarly to MultiDragDispatcher, basically sending the callbacks of ScaleGestureRecognizer to the components.

There was some tricky parts though. The goal was to preserve multi drag functionality while adding scale functionality but I run into this issue :
When running concurrently ScaleGestureRecognizer and ImmediateMultiDragGestureRecognizer, since drag in a simpler gesture it is usually recognized before scale, and therefore, drag wins the gesture arena and one pointer (finger) gets reserved for dragging. Scale gets recognized a bit later, but with a single pointer, and data such as scale or rotation are meaningless with a single pointer.

More generally, multi dragging and scaling are two very similar gestures and it will inevitably lead to some ambiguities.

There was multiple solutions to this, all with their own drawbacks :

  1. Not allowing multi dragging and scaling at the same time, with a mechanic to switch between the two. Simple to implement
    but quite limiting.
  2. Introducing a delay with DelayedMultiDragGestureRecognizer, the simplest solution, works well since scaling then gets recognized before dragging, removing the ambiguity. The default delay is unacceptably long though but I did not experiment with shorter delay.
  3. Using the data from the dragging pointer, to reconstruct rotation and scaling data, as if the dragging pointer was part of the scaling gesture.

We decided to go with the third solution as it preserves the ability to do multi drag instantaneously while allowing scaling at the same time. One issue inherent to this solution is also linked to the ambiguity between some multi drag gestures and scaling, preventing some multi drag gestures to be performed properly (basically all multi drag gestures similar to scaling).

One possibility would be to use the data from the single pointer scaling and send that to MultiDragDispatcher, basically what solution 3 does but the other way around. this would allow for drag and scaling to work at the same time.

Another issue exists that might be fixable though : it doesn't behave great when three fingers are involved, basically when I lift one of the two first fingers, the third one is used in the scale and rotation computations leading to unwanted "jumps".
The issue is that pointers are not really tracked, so eventually the third finger position can be used as if it was the second one.

Future things to do after this PR

  • fix the 3 finger issues described above
  • add a simple switch mechanism to activate/deactivate scale gesture recognizing at run time to allow for full real multi drag to work OR investigate "use the data from the single pointer scaling" solution.

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation in docs and added dartdoc comments with ///.
  • I have updated/added relevant examples in examples or docs.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Closes #3768

@stilnat stilnat changed the title feat: add scaling gesture for components feat: Add scaling gesture for components Nov 16, 2025
@spydon
Copy link
Member

spydon commented Nov 21, 2025

@stilnat did you see this from DCM?

packages/flame/test/events/component_mixins/scale_callbacks_test.dart (2 issues):
WARNING   Avoid top-level declarations in tests. Try making this declaration private.
          at packages/flame/test/events/component_mixins/scale_callbacks_test.dart:380:14
          avoid-top-level-members-in-tests : https://dcm.dev/docs/rules/common/avoid-top-level-members-in-tests

WARNING   Avoid top-level declarations in tests. Try making this declaration private.
          at packages/flame/test/events/component_mixins/scale_callbacks_test.dart:449:11
          avoid-top-level-members-in-tests : https://dcm.dev/docs/rules/common/avoid-top-level-members-in-tests

@stilnat
Copy link
Contributor Author

stilnat commented Nov 21, 2025

yeah working on fixing the few linting error left

Copy link
Member

@spydon spydon left a comment

Choose a reason for hiding this comment

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

Looks good! Just two small comments and docs are missing, the docs live under the doc directory in the root.

Copy link
Member

@spydon spydon left a comment

Choose a reason for hiding this comment

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

Lgtm! Just some minor nits.
Thanks for your contribution.

super.update(dt);

if (addCameraRotation) {
camera.viewfinder.angle += 0.001;
Copy link
Member

Choose a reason for hiding this comment

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

These two should be dependent on dt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@spydon spydon enabled auto-merge (squash) November 22, 2025 23:55
@spydon spydon merged commit f413edd into flame-engine:main Nov 22, 2025
68 checks passed
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.

Add component level scale gesture detection

2 participants