From 01f3bf46f6a63def1ada3d34aa1c7d7f75403230 Mon Sep 17 00:00:00 2001 From: garysm Date: Mon, 25 Jul 2022 15:01:29 -0400 Subject: [PATCH 01/14] feat: Add cursor components mixin to Game --- packages/flame/lib/components.dart | 1 + packages/flame/lib/events.dart | 1 + .../lib/src/components/mixins/cursor_handler.dart | 8 ++++++++ packages/flame/lib/src/game/mixins/cursor.dart | 15 +++++++++++++++ packages/flame/lib/src/gestures/detectors.dart | 10 +++++++++- 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 packages/flame/lib/src/components/mixins/cursor_handler.dart create mode 100644 packages/flame/lib/src/game/mixins/cursor.dart diff --git a/packages/flame/lib/components.dart b/packages/flame/lib/components.dart index 757d120fb20..9668da9c7f6 100644 --- a/packages/flame/lib/components.dart +++ b/packages/flame/lib/components.dart @@ -11,6 +11,7 @@ export 'src/components/input/joystick_component.dart'; export 'src/components/input/keyboard_listener_component.dart'; export 'src/components/isometric_tile_map_component.dart'; export 'src/components/mixins/component_viewport_margin.dart'; +export 'src/components/mixins/cursor_handler.dart'; export 'src/components/mixins/draggable.dart'; export 'src/components/mixins/gesture_hitboxes.dart'; export 'src/components/mixins/has_ancestor.dart'; diff --git a/packages/flame/lib/events.dart b/packages/flame/lib/events.dart index 27db244cfd9..c433bee706d 100644 --- a/packages/flame/lib/events.dart +++ b/packages/flame/lib/events.dart @@ -4,6 +4,7 @@ export 'src/events/game_mixins/multi_touch_tap_detector.dart' show MultiTouchTapDetector; export 'src/events/interfaces/multi_drag_listener.dart' show MultiDragListener; export 'src/events/interfaces/multi_tap_listener.dart' show MultiTapListener; +export 'src/game/mixins/cursor.dart' show HasCursorHandlerComponents; export 'src/game/mixins/has_draggables.dart' show HasDraggables; export 'src/game/mixins/has_hoverables.dart' show HasHoverables; export 'src/game/mixins/has_tappables.dart' show HasTappables; diff --git a/packages/flame/lib/src/components/mixins/cursor_handler.dart b/packages/flame/lib/src/components/mixins/cursor_handler.dart new file mode 100644 index 00000000000..14ce98bb7bc --- /dev/null +++ b/packages/flame/lib/src/components/mixins/cursor_handler.dart @@ -0,0 +1,8 @@ +import 'package:flame/components.dart'; +import 'package:flame/src/gestures/events.dart'; + +mixin CursorHandler on Component { + bool onMouseMove(PointerHoverInfo info) { + return true; + } +} diff --git a/packages/flame/lib/src/game/mixins/cursor.dart b/packages/flame/lib/src/game/mixins/cursor.dart new file mode 100644 index 00000000000..4badd1cbe2e --- /dev/null +++ b/packages/flame/lib/src/game/mixins/cursor.dart @@ -0,0 +1,15 @@ +import 'package:flame/game.dart'; +import 'package:flame/src/components/mixins/cursor_handler.dart'; +import 'package:flame/src/gestures/detectors.dart'; +import 'package:flame/src/gestures/events.dart'; +import 'package:flutter/material.dart'; + +mixin HasCursorHandlerComponents on FlameGame implements MouseMovementDetector { + @override + @mustCallSuper + void onMouseMove(PointerHoverInfo info) { + propagateToChildren( + (CursorHandler child) => child.onMouseMove(info), + ); + } +} diff --git a/packages/flame/lib/src/gestures/detectors.dart b/packages/flame/lib/src/gestures/detectors.dart index 13cb63ac66f..ee6b5f7bb5e 100644 --- a/packages/flame/lib/src/gestures/detectors.dart +++ b/packages/flame/lib/src/gestures/detectors.dart @@ -1,4 +1,5 @@ import 'package:flame/src/game/game.dart'; +import 'package:flame/src/game/mixins/cursor.dart'; import 'package:flame/src/gestures/events.dart'; import 'package:flutter/gestures.dart'; @@ -177,7 +178,14 @@ mixin ScaleDetector on Game { } mixin MouseMovementDetector on Game { - void onMouseMove(PointerHoverInfo info) {} + void onMouseMove(PointerHoverInfo info) { + assert( + this is! HasCursorHandlerComponents, + 'A mouse movement event was registered by MouseMovementDetector for a game also ' + 'mixed with HasCursorHandlerComponents. Do not mix with both, ' + 'HasCursorHandlerComponents removes the necessity of MouseMovementDetector', + ); + } } mixin ScrollDetector on Game { From ceb61bca71a402fc950509d6e832095adef4273a Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 12 Aug 2022 22:06:25 +0200 Subject: [PATCH 02/14] Fix too long lines --- packages/flame/lib/src/gestures/detectors.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/flame/lib/src/gestures/detectors.dart b/packages/flame/lib/src/gestures/detectors.dart index 7d82c2b7dbc..5719220d5a9 100644 --- a/packages/flame/lib/src/gestures/detectors.dart +++ b/packages/flame/lib/src/gestures/detectors.dart @@ -195,9 +195,10 @@ mixin MouseMovementDetector on Game { void onMouseMove(PointerHoverInfo info) { assert( this is! HasCursorHandlerComponents, - 'A mouse movement event was registered by MouseMovementDetector for a game also ' - 'mixed with HasCursorHandlerComponents. Do not mix with both, ' - 'HasCursorHandlerComponents removes the necessity of MouseMovementDetector', + 'A mouse movement event was registered by MouseMovementDetector for a ' + 'game also mixed with HasCursorHandlerComponents. Do not mix with both, ' + 'HasCursorHandlerComponents removes the necessity of ' + 'MouseMovementDetector.', ); } } From 84dc8b3c55d66954a1456cbb62fe25561d7ccd24 Mon Sep 17 00:00:00 2001 From: garysm Date: Tue, 23 Aug 2022 15:44:46 -0400 Subject: [PATCH 03/14] Add example for CursorHandler components --- examples/lib/stories/input/input.dart | 7 ++ .../mouse_movement_listener_example.dart | 72 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 examples/lib/stories/input/mouse_movement_listener_example.dart diff --git a/examples/lib/stories/input/input.dart b/examples/lib/stories/input/input.dart index 793f4fb7378..b845739e481 100644 --- a/examples/lib/stories/input/input.dart +++ b/examples/lib/stories/input/input.dart @@ -9,6 +9,7 @@ import 'package:examples/stories/input/keyboard_example.dart'; import 'package:examples/stories/input/keyboard_listener_component_example.dart'; import 'package:examples/stories/input/mouse_cursor_example.dart'; import 'package:examples/stories/input/mouse_movement_example.dart'; +import 'package:examples/stories/input/mouse_movement_listener_example.dart'; import 'package:examples/stories/input/multitap_advanced_example.dart'; import 'package:examples/stories/input/multitap_example.dart'; import 'package:examples/stories/input/overlapping_tappables_example.dart'; @@ -61,6 +62,12 @@ void addInputStories(Dashbook dashbook) { codeLink: baseLink('input/mouse_movement_example.dart'), info: MouseMovementExample.description, ) + ..add( + 'Mouse Movement (Component)', + (_) => GameWidget(game: MouseMovementListenerExample()), + codeLink: baseLink('input/mouse_movement_listener_example.dart'), + info: MouseMovementListenerExample.description, + ) ..add( 'Mouse Cursor', (_) => GameWidget( diff --git a/examples/lib/stories/input/mouse_movement_listener_example.dart b/examples/lib/stories/input/mouse_movement_listener_example.dart new file mode 100644 index 00000000000..50c1a49e971 --- /dev/null +++ b/examples/lib/stories/input/mouse_movement_listener_example.dart @@ -0,0 +1,72 @@ +import 'dart:math'; + +import 'package:flame/components.dart'; +import 'package:flame/events.dart'; +import 'package:flame/game.dart'; +import 'package:flutter/material.dart'; + +class MouseMovementListenerExample extends FlameGame + with HasCursorHandlerComponents { + static const String description = ''' + This example shows how to handle mouse movement using `CursorHandler` Components.\n\n + Moving the mouse around the canvas changes the angle of each Component, and causes + the line drawn on them to face towards the mouse's position. + '''; + + @override + Future onLoad() async { + add( + CursorFollowerCircle( + radius: 20.0, + )..position = size / 2, + ); + add( + CursorFollowerCircle( + radius: 20.0, + )..position = Vector2(100.0, 100.0), + ); + } +} + +class CursorFollowerCircle extends PositionComponent with CursorHandler { + final double _radius; + + final Paint _paint; + + CursorFollowerCircle({required double radius}) + : _radius = radius, + _paint = Paint()..color = const Color(0xFF80C080), + super( + size: Vector2.all(2 * radius), + anchor: Anchor.center, + ); + + @override + bool onMouseMove(PointerHoverInfo info) { + final gameMousePositionX = info.eventPosition.game.x; + + final gameMousePositionY = info.eventPosition.game.y; + + angle = + atan2(gameMousePositionY - position.y, gameMousePositionX - position.x); + return super.onMouseMove(info); + } + + @override + void render(Canvas canvas) { + super.render(canvas); + + canvas.drawCircle( + Offset(_radius, _radius), + _radius, + _paint, + ); + canvas.drawLine( + Offset(_radius, _radius), + Offset(_radius * 3.0, _radius), + Paint() + ..color = const Color(0xFFFFFFFF) + ..strokeWidth = 2.0, + ); + } +} From c70680b1e2793798c5fc785790fb197a36741942 Mon Sep 17 00:00:00 2001 From: garysm Date: Mon, 25 Jul 2022 15:01:29 -0400 Subject: [PATCH 04/14] feat: Add cursor components mixin to Game --- packages/flame/lib/components.dart | 1 + packages/flame/lib/events.dart | 1 + .../lib/src/components/mixins/cursor_handler.dart | 8 ++++++++ packages/flame/lib/src/game/mixins/cursor.dart | 15 +++++++++++++++ packages/flame/lib/src/gestures/detectors.dart | 10 +++++++++- 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 packages/flame/lib/src/components/mixins/cursor_handler.dart create mode 100644 packages/flame/lib/src/game/mixins/cursor.dart diff --git a/packages/flame/lib/components.dart b/packages/flame/lib/components.dart index 6ffb0896670..0fdaebecba3 100644 --- a/packages/flame/lib/components.dart +++ b/packages/flame/lib/components.dart @@ -12,6 +12,7 @@ export 'src/components/input/joystick_component.dart'; export 'src/components/input/keyboard_listener_component.dart'; export 'src/components/isometric_tile_map_component.dart'; export 'src/components/mixins/component_viewport_margin.dart'; +export 'src/components/mixins/cursor_handler.dart'; export 'src/components/mixins/draggable.dart'; export 'src/components/mixins/gesture_hitboxes.dart'; export 'src/components/mixins/has_ancestor.dart'; diff --git a/packages/flame/lib/events.dart b/packages/flame/lib/events.dart index 05f38aabe87..cc467e82b3d 100644 --- a/packages/flame/lib/events.dart +++ b/packages/flame/lib/events.dart @@ -4,6 +4,7 @@ export 'src/events/game_mixins/multi_touch_tap_detector.dart' show MultiTouchTapDetector; export 'src/events/interfaces/multi_drag_listener.dart' show MultiDragListener; export 'src/events/interfaces/multi_tap_listener.dart' show MultiTapListener; +export 'src/game/mixins/cursor.dart' show HasCursorHandlerComponents; export 'src/game/mixins/has_draggables.dart' show HasDraggables; export 'src/game/mixins/has_hoverables.dart' show HasHoverables; export 'src/game/mixins/has_tappables.dart' show HasTappables; diff --git a/packages/flame/lib/src/components/mixins/cursor_handler.dart b/packages/flame/lib/src/components/mixins/cursor_handler.dart new file mode 100644 index 00000000000..14ce98bb7bc --- /dev/null +++ b/packages/flame/lib/src/components/mixins/cursor_handler.dart @@ -0,0 +1,8 @@ +import 'package:flame/components.dart'; +import 'package:flame/src/gestures/events.dart'; + +mixin CursorHandler on Component { + bool onMouseMove(PointerHoverInfo info) { + return true; + } +} diff --git a/packages/flame/lib/src/game/mixins/cursor.dart b/packages/flame/lib/src/game/mixins/cursor.dart new file mode 100644 index 00000000000..4badd1cbe2e --- /dev/null +++ b/packages/flame/lib/src/game/mixins/cursor.dart @@ -0,0 +1,15 @@ +import 'package:flame/game.dart'; +import 'package:flame/src/components/mixins/cursor_handler.dart'; +import 'package:flame/src/gestures/detectors.dart'; +import 'package:flame/src/gestures/events.dart'; +import 'package:flutter/material.dart'; + +mixin HasCursorHandlerComponents on FlameGame implements MouseMovementDetector { + @override + @mustCallSuper + void onMouseMove(PointerHoverInfo info) { + propagateToChildren( + (CursorHandler child) => child.onMouseMove(info), + ); + } +} diff --git a/packages/flame/lib/src/gestures/detectors.dart b/packages/flame/lib/src/gestures/detectors.dart index 02ad2613b88..7d82c2b7dbc 100644 --- a/packages/flame/lib/src/gestures/detectors.dart +++ b/packages/flame/lib/src/gestures/detectors.dart @@ -1,4 +1,5 @@ import 'package:flame/src/game/game.dart'; +import 'package:flame/src/game/mixins/cursor.dart'; import 'package:flame/src/gestures/events.dart'; import 'package:flutter/gestures.dart'; @@ -191,7 +192,14 @@ mixin ScaleDetector on Game { } mixin MouseMovementDetector on Game { - void onMouseMove(PointerHoverInfo info) {} + void onMouseMove(PointerHoverInfo info) { + assert( + this is! HasCursorHandlerComponents, + 'A mouse movement event was registered by MouseMovementDetector for a game also ' + 'mixed with HasCursorHandlerComponents. Do not mix with both, ' + 'HasCursorHandlerComponents removes the necessity of MouseMovementDetector', + ); + } } mixin ScrollDetector on Game { From aab7e1077c99f6032c513af639eeeb1aa0104455 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 12 Aug 2022 22:06:25 +0200 Subject: [PATCH 05/14] Fix too long lines --- packages/flame/lib/src/gestures/detectors.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/flame/lib/src/gestures/detectors.dart b/packages/flame/lib/src/gestures/detectors.dart index 7d82c2b7dbc..5719220d5a9 100644 --- a/packages/flame/lib/src/gestures/detectors.dart +++ b/packages/flame/lib/src/gestures/detectors.dart @@ -195,9 +195,10 @@ mixin MouseMovementDetector on Game { void onMouseMove(PointerHoverInfo info) { assert( this is! HasCursorHandlerComponents, - 'A mouse movement event was registered by MouseMovementDetector for a game also ' - 'mixed with HasCursorHandlerComponents. Do not mix with both, ' - 'HasCursorHandlerComponents removes the necessity of MouseMovementDetector', + 'A mouse movement event was registered by MouseMovementDetector for a ' + 'game also mixed with HasCursorHandlerComponents. Do not mix with both, ' + 'HasCursorHandlerComponents removes the necessity of ' + 'MouseMovementDetector.', ); } } From 8a52989f035bf8dda6bd3c1a51c1aa549f7ad1d2 Mon Sep 17 00:00:00 2001 From: garysm Date: Tue, 23 Aug 2022 15:44:46 -0400 Subject: [PATCH 06/14] Add example for CursorHandler components --- examples/lib/stories/input/input.dart | 7 ++ .../mouse_movement_listener_example.dart | 72 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 examples/lib/stories/input/mouse_movement_listener_example.dart diff --git a/examples/lib/stories/input/input.dart b/examples/lib/stories/input/input.dart index 8dfb39845b1..e595b264fe2 100644 --- a/examples/lib/stories/input/input.dart +++ b/examples/lib/stories/input/input.dart @@ -9,6 +9,7 @@ import 'package:examples/stories/input/keyboard_example.dart'; import 'package:examples/stories/input/keyboard_listener_component_example.dart'; import 'package:examples/stories/input/mouse_cursor_example.dart'; import 'package:examples/stories/input/mouse_movement_example.dart'; +import 'package:examples/stories/input/mouse_movement_listener_example.dart'; import 'package:examples/stories/input/multitap_advanced_example.dart'; import 'package:examples/stories/input/multitap_example.dart'; import 'package:examples/stories/input/overlapping_tappables_example.dart'; @@ -61,6 +62,12 @@ void addInputStories(Dashbook dashbook) { codeLink: baseLink('input/mouse_movement_example.dart'), info: MouseMovementExample.description, ) + ..add( + 'Mouse Movement (Component)', + (_) => GameWidget(game: MouseMovementListenerExample()), + codeLink: baseLink('input/mouse_movement_listener_example.dart'), + info: MouseMovementListenerExample.description, + ) ..add( 'Mouse Cursor', (_) => GameWidget( diff --git a/examples/lib/stories/input/mouse_movement_listener_example.dart b/examples/lib/stories/input/mouse_movement_listener_example.dart new file mode 100644 index 00000000000..50c1a49e971 --- /dev/null +++ b/examples/lib/stories/input/mouse_movement_listener_example.dart @@ -0,0 +1,72 @@ +import 'dart:math'; + +import 'package:flame/components.dart'; +import 'package:flame/events.dart'; +import 'package:flame/game.dart'; +import 'package:flutter/material.dart'; + +class MouseMovementListenerExample extends FlameGame + with HasCursorHandlerComponents { + static const String description = ''' + This example shows how to handle mouse movement using `CursorHandler` Components.\n\n + Moving the mouse around the canvas changes the angle of each Component, and causes + the line drawn on them to face towards the mouse's position. + '''; + + @override + Future onLoad() async { + add( + CursorFollowerCircle( + radius: 20.0, + )..position = size / 2, + ); + add( + CursorFollowerCircle( + radius: 20.0, + )..position = Vector2(100.0, 100.0), + ); + } +} + +class CursorFollowerCircle extends PositionComponent with CursorHandler { + final double _radius; + + final Paint _paint; + + CursorFollowerCircle({required double radius}) + : _radius = radius, + _paint = Paint()..color = const Color(0xFF80C080), + super( + size: Vector2.all(2 * radius), + anchor: Anchor.center, + ); + + @override + bool onMouseMove(PointerHoverInfo info) { + final gameMousePositionX = info.eventPosition.game.x; + + final gameMousePositionY = info.eventPosition.game.y; + + angle = + atan2(gameMousePositionY - position.y, gameMousePositionX - position.x); + return super.onMouseMove(info); + } + + @override + void render(Canvas canvas) { + super.render(canvas); + + canvas.drawCircle( + Offset(_radius, _radius), + _radius, + _paint, + ); + canvas.drawLine( + Offset(_radius, _radius), + Offset(_radius * 3.0, _radius), + Paint() + ..color = const Color(0xFFFFFFFF) + ..strokeWidth = 2.0, + ); + } +} From 316dd3f3030a9f6a6f47efa2f5c95e2a79ec9a37 Mon Sep 17 00:00:00 2001 From: garysm Date: Tue, 30 Aug 2022 14:39:02 -0400 Subject: [PATCH 07/14] rename example --- examples/lib/stories/input/input.dart | 6 +++--- ..._example.dart => mouse_movement_components_example.dart} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename examples/lib/stories/input/{mouse_movement_listener_example.dart => mouse_movement_components_example.dart} (96%) diff --git a/examples/lib/stories/input/input.dart b/examples/lib/stories/input/input.dart index e595b264fe2..f0cddbf7713 100644 --- a/examples/lib/stories/input/input.dart +++ b/examples/lib/stories/input/input.dart @@ -8,8 +8,8 @@ import 'package:examples/stories/input/joystick_example.dart'; import 'package:examples/stories/input/keyboard_example.dart'; import 'package:examples/stories/input/keyboard_listener_component_example.dart'; import 'package:examples/stories/input/mouse_cursor_example.dart'; +import 'package:examples/stories/input/mouse_movement_components_example.dart'; import 'package:examples/stories/input/mouse_movement_example.dart'; -import 'package:examples/stories/input/mouse_movement_listener_example.dart'; import 'package:examples/stories/input/multitap_advanced_example.dart'; import 'package:examples/stories/input/multitap_example.dart'; import 'package:examples/stories/input/overlapping_tappables_example.dart'; @@ -64,9 +64,9 @@ void addInputStories(Dashbook dashbook) { ) ..add( 'Mouse Movement (Component)', - (_) => GameWidget(game: MouseMovementListenerExample()), + (_) => GameWidget(game: MouseMovementComponentsExample()), codeLink: baseLink('input/mouse_movement_listener_example.dart'), - info: MouseMovementListenerExample.description, + info: MouseMovementComponentsExample.description, ) ..add( 'Mouse Cursor', diff --git a/examples/lib/stories/input/mouse_movement_listener_example.dart b/examples/lib/stories/input/mouse_movement_components_example.dart similarity index 96% rename from examples/lib/stories/input/mouse_movement_listener_example.dart rename to examples/lib/stories/input/mouse_movement_components_example.dart index 50c1a49e971..07243de12ac 100644 --- a/examples/lib/stories/input/mouse_movement_listener_example.dart +++ b/examples/lib/stories/input/mouse_movement_components_example.dart @@ -5,7 +5,7 @@ import 'package:flame/events.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; -class MouseMovementListenerExample extends FlameGame +class MouseMovementComponentsExample extends FlameGame with HasCursorHandlerComponents { static const String description = ''' This example shows how to handle mouse movement using `CursorHandler` Components.\n\n From b229f0cf2f65cc8ad0abd941e7a6fce3956c33fb Mon Sep 17 00:00:00 2001 From: garysm Date: Tue, 30 Aug 2022 14:40:14 -0400 Subject: [PATCH 08/14] Add mouse movement to docs --- doc/flame/inputs/gesture-input.md | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/doc/flame/inputs/gesture-input.md b/doc/flame/inputs/gesture-input.md index 199ec3630ec..dde1610efed 100644 --- a/doc/flame/inputs/gesture-input.md +++ b/doc/flame/inputs/gesture-input.md @@ -488,3 +488,37 @@ More information about how to define hitboxes can be found in the hitbox section An example of how to use it can be seen [here](https://github.com/flame-engine/flame/blob/main/examples/lib/stories/input/gesture_hitboxes_example.dart). + +### MouseMovement on the game level + +To give a `Game` class the ability to handle mouse movement/hover events, use the `MouseMovementDetector` mixin. + +You can then override an `onMouseMove` method. This method receives [`PointerHoverInfo`](https://pub.dev/documentation/flame/latest/events/PointerHoverInfo-class.html) which provides the position of the hover event, as well as the raw [`PointerHoverEvent`](https://api.flutter.dev/flutter/gestures/PointerHoverEvent-class.html) + + + +> ⚠️ Note: This should not be used on platforms that do not +> support mouse cursors. + +Example: + +```dart +class MouseCursorExample extends FlameGame with MouseMovementDetector { + // ... + @override + void onMouseMove(PointerHoverInfo info) { + print('X: ${info.eventPosition.game.x}'); + print('Y: ${info.eventPosition.game.y}'); + } +} + +``` + + +### MouseMovement on the component level + +To recieve mouse movement/hover events in components, use the `HasCursorHandlerComponents` mixin on any `Game` sub class first, and remove the `MouseMovementDetector` mixin (if present). + +Then, use the `CursorHandler` mixin on any `Component` sub class. + +See [here](https://github.com/flame-engine/flame/blob/main/examples/lib/stores/input/mouse_movement_components_example.dart) for an example. \ No newline at end of file From 1d26c1858d76af168e22379ac7b50c0067c28da1 Mon Sep 17 00:00:00 2001 From: garysm Date: Sun, 20 Nov 2022 22:06:31 -0500 Subject: [PATCH 09/14] update docs for linting --- doc/flame/inputs/gesture-input.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/flame/inputs/gesture-input.md b/doc/flame/inputs/gesture-input.md index 9380b8e83fc..1492c47aadb 100644 --- a/doc/flame/inputs/gesture-input.md +++ b/doc/flame/inputs/gesture-input.md @@ -4,8 +4,8 @@ This includes documentation for gesture inputs, which is, mouse and touch pointe For other input documents, see also: -- [Keyboard Input](keyboard-input.md): for keystrokes -- [Other Inputs](other-inputs.md): For joysticks, game pads, etc. +- [Keyboard Input](keyboard_input.md): for keystrokes +- [Other Inputs](other_inputs.md): For joysticks, game pads, etc. ## Intro @@ -17,7 +17,7 @@ of these `mixin`s and its methods: ## Touch and mouse detectors -```txt +```text - TapDetector - onTap - onTapCancel @@ -89,7 +89,7 @@ of these `mixin`s and its methods: Mouse only events -```txt +```text - MouseMovementDetector - onMouseMove - ScrollDetector @@ -112,8 +112,8 @@ also read more about Flutter's gestures ## PanDetector and ScaleDetector -If you add a `PanDetector` together with a `ScaleDetector` you will be prompted with a quite -cryptic assertion from Flutter that says: +If you add a `PanDetector` together with a `ScaleDetector` you will be prompted with a quite cryptic +assertion from Flutter that says: ```{note} Having both a pan gesture recognizer and a scale gesture recognizer is From ce40df16d7b87310a3bc7f73bc9a606fff5c71bc Mon Sep 17 00:00:00 2001 From: Gary Montgomery <54603459+garysm@users.noreply.github.com> Date: Sun, 27 Nov 2022 00:28:28 -0500 Subject: [PATCH 10/14] Update doc/flame/inputs/gesture-input.md Co-authored-by: Lukas Klingsbo --- doc/flame/inputs/gesture-input.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/flame/inputs/gesture-input.md b/doc/flame/inputs/gesture-input.md index 1492c47aadb..24c3895b175 100644 --- a/doc/flame/inputs/gesture-input.md +++ b/doc/flame/inputs/gesture-input.md @@ -519,7 +519,7 @@ class MouseCursorExample extends FlameGame with MouseMovementDetector { ### MouseMovement on the component level -To recieve mouse movement/hover events in components, use the `HasCursorHandlerComponents` mixin on any `Game` sub class first, and remove the `MouseMovementDetector` mixin (if present). +To receive mouse movement/hover events in components, use the `HasCursorHandlerComponents` mixin on any `Game` sub class first, and remove the `MouseMovementDetector` mixin (if present). Then, use the `CursorHandler` mixin on any `Component` sub class. From 4293baaa875d19a1e01ed22dcebabab721b9cf15 Mon Sep 17 00:00:00 2001 From: garysm Date: Sun, 27 Nov 2022 01:39:51 -0500 Subject: [PATCH 11/14] update doc for linting and admonition --- doc/flame/inputs/gesture_input.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/doc/flame/inputs/gesture_input.md b/doc/flame/inputs/gesture_input.md index 24c3895b175..d7fe0506290 100644 --- a/doc/flame/inputs/gesture_input.md +++ b/doc/flame/inputs/gesture_input.md @@ -491,17 +491,20 @@ More information about how to define hitboxes can be found in the hitbox section An example of how to use it can be seen [here](https://github.com/flame-engine/flame/blob/main/examples/lib/stories/input/gesture_hitboxes_example.dart). -### MouseMovement on the game level - -To give a `Game` class the ability to handle mouse movement/hover events, use the `MouseMovementDetector` mixin. - -You can then override an `onMouseMove` method. This method receives [`PointerHoverInfo`](https://pub.dev/documentation/flame/latest/events/PointerHoverInfo-class.html) which provides the position of the hover event, as well as the raw [`PointerHoverEvent`](https://api.flutter.dev/flutter/gestures/PointerHoverEvent-class.html) +### MouseMovement on the game level +To give a `Game` class the ability to handle mouse movement/hover events, +use the `MouseMovementDetector` mixin. -> ⚠️ Note: This should not be used on platforms that do not -> support mouse cursors. +You can then override an `onMouseMove` method. This method receives +[`PointerHoverInfo`](https://pub.dev/documentation/flame/latest/events/PointerHoverInfo-class.html) +which provides the position of the hover event, as well as the raw +[`PointerHoverEvent`](https://api.flutter.dev/flutter/gestures/PointerHoverEvent-class.html) +```{warning} +This should not be used on platforms that do not support mouse cursors. +``` Example: ```dart @@ -519,8 +522,11 @@ class MouseCursorExample extends FlameGame with MouseMovementDetector { ### MouseMovement on the component level -To receive mouse movement/hover events in components, use the `HasCursorHandlerComponents` mixin on any `Game` sub class first, and remove the `MouseMovementDetector` mixin (if present). +To receive mouse movement/hover events in components, use the `HasCursorHandlerComponents` +mixin on any `Game` sub class first, and remove the `MouseMovementDetector` mixin (if present). Then, use the `CursorHandler` mixin on any `Component` sub class. -See [here](https://github.com/flame-engine/flame/blob/main/examples/lib/stores/input/mouse_movement_components_example.dart) for an example. \ No newline at end of file +See +[here](https://github.com/flame-engine/flame/blob/main/examples/lib/stores/input/mouse_movement_components_example.dart) +for an example. From 0ebb400617a6c3529e0c43825577384213428a54 Mon Sep 17 00:00:00 2001 From: garysm Date: Sun, 27 Nov 2022 01:41:50 -0500 Subject: [PATCH 12/14] Add blank line in doc --- doc/flame/inputs/gesture_input.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/flame/inputs/gesture_input.md b/doc/flame/inputs/gesture_input.md index d7fe0506290..2562fb749af 100644 --- a/doc/flame/inputs/gesture_input.md +++ b/doc/flame/inputs/gesture_input.md @@ -505,6 +505,7 @@ which provides the position of the hover event, as well as the raw ```{warning} This should not be used on platforms that do not support mouse cursors. ``` + Example: ```dart From 0f0db95f1f4b2461caf7ac181a80e0e12da77cd0 Mon Sep 17 00:00:00 2001 From: garysm Date: Tue, 13 Jun 2023 00:27:29 -0400 Subject: [PATCH 13/14] Wip Add CursorHoverEvent, CursorHoverCallbacks, CursorHoverDispatcher --- examples/lib/stories/input/input.dart | 14 +- .../mouse_movement_components_example.dart | 122 +++++++++--------- .../cursor_hover_callbacks.dart | 19 +++ .../cursor_hover_dispatcher.dart | 41 ++++++ .../events/messages/cursor_hover_event.dart | 34 +++++ .../flame/lib/src/game/mixins/cursor.dart | 15 --- .../flame/lib/src/gestures/detectors.dart | 11 +- 7 files changed, 163 insertions(+), 93 deletions(-) create mode 100644 packages/flame/lib/src/events/component_mixins/cursor_hover_callbacks.dart create mode 100644 packages/flame/lib/src/events/flame_game_mixins/cursor_hover_dispatcher.dart create mode 100644 packages/flame/lib/src/events/messages/cursor_hover_event.dart delete mode 100644 packages/flame/lib/src/game/mixins/cursor.dart diff --git a/examples/lib/stories/input/input.dart b/examples/lib/stories/input/input.dart index 381de61f540..c97497e37cf 100644 --- a/examples/lib/stories/input/input.dart +++ b/examples/lib/stories/input/input.dart @@ -10,7 +10,6 @@ import 'package:examples/stories/input/joystick_example.dart'; import 'package:examples/stories/input/keyboard_example.dart'; import 'package:examples/stories/input/keyboard_listener_component_example.dart'; import 'package:examples/stories/input/mouse_cursor_example.dart'; -import 'package:examples/stories/input/mouse_movement_components_example.dart'; import 'package:examples/stories/input/mouse_movement_example.dart'; import 'package:examples/stories/input/multitap_advanced_example.dart'; import 'package:examples/stories/input/multitap_example.dart'; @@ -80,12 +79,13 @@ void addInputStories(Dashbook dashbook) { codeLink: baseLink('input/mouse_movement_example.dart'), info: MouseMovementExample.description, ) - ..add( - 'Mouse Movement (Component)', - (_) => GameWidget(game: MouseMovementComponentsExample()), - codeLink: baseLink('input/mouse_movement_listener_example.dart'), - info: MouseMovementComponentsExample.description, - ) + // TODO: Add example + // ..add( + // 'Mouse Movement (Component)', + // (_) => GameWidget(game: MouseMovementComponentsExample()), + // codeLink: baseLink('input/mouse_movement_listener_example.dart'), + // info: MouseMovementComponentsExample.description, + // ) ..add( 'Mouse Cursor', (_) => GameWidget( diff --git a/examples/lib/stories/input/mouse_movement_components_example.dart b/examples/lib/stories/input/mouse_movement_components_example.dart index 07243de12ac..e78b3ac39b2 100644 --- a/examples/lib/stories/input/mouse_movement_components_example.dart +++ b/examples/lib/stories/input/mouse_movement_components_example.dart @@ -1,72 +1,72 @@ -import 'dart:math'; +// import 'dart:math'; -import 'package:flame/components.dart'; -import 'package:flame/events.dart'; -import 'package:flame/game.dart'; -import 'package:flutter/material.dart'; +// import 'package:flame/components.dart'; +// import 'package:flame/events.dart'; +// import 'package:flame/game.dart'; +// import 'package:flutter/material.dart'; -class MouseMovementComponentsExample extends FlameGame - with HasCursorHandlerComponents { - static const String description = ''' - This example shows how to handle mouse movement using `CursorHandler` Components.\n\n - Moving the mouse around the canvas changes the angle of each Component, and causes - the line drawn on them to face towards the mouse's position. - '''; +// class MouseMovementComponentsExample extends FlameGame +// with HasCursorHandlerComponents { +// static const String description = ''' +// This example shows how to handle mouse movement using `CursorHandler` Components.\n\n +// Moving the mouse around the canvas changes the angle of each Component, and causes +// the line drawn on them to face towards the mouse's position. +// '''; - @override - Future onLoad() async { - add( - CursorFollowerCircle( - radius: 20.0, - )..position = size / 2, - ); - add( - CursorFollowerCircle( - radius: 20.0, - )..position = Vector2(100.0, 100.0), - ); - } -} +// @override +// Future onLoad() async { +// add( +// CursorFollowerCircle( +// radius: 20.0, +// )..position = size / 2, +// ); +// add( +// CursorFollowerCircle( +// radius: 20.0, +// )..position = Vector2(100.0, 100.0), +// ); +// } +// } -class CursorFollowerCircle extends PositionComponent with CursorHandler { - final double _radius; +// class CursorFollowerCircle extends PositionComponent with CursorHandler { +// final double _radius; - final Paint _paint; +// final Paint _paint; - CursorFollowerCircle({required double radius}) - : _radius = radius, - _paint = Paint()..color = const Color(0xFF80C080), - super( - size: Vector2.all(2 * radius), - anchor: Anchor.center, - ); +// CursorFollowerCircle({required double radius}) +// : _radius = radius, +// _paint = Paint()..color = const Color(0xFF80C080), +// super( +// size: Vector2.all(2 * radius), +// anchor: Anchor.center, +// ); - @override - bool onMouseMove(PointerHoverInfo info) { - final gameMousePositionX = info.eventPosition.game.x; +// @override +// bool onMouseMove(PointerHoverInfo info) { +// final gameMousePositionX = info.eventPosition.game.x; - final gameMousePositionY = info.eventPosition.game.y; +// final gameMousePositionY = info.eventPosition.game.y; - angle = - atan2(gameMousePositionY - position.y, gameMousePositionX - position.x); - return super.onMouseMove(info); - } +// angle = +// atan2(gameMousePositionY - position.y, gameMousePositionX - position.x); +// return super.onMouseMove(info); +// } - @override - void render(Canvas canvas) { - super.render(canvas); +// @override +// void render(Canvas canvas) { +// super.render(canvas); - canvas.drawCircle( - Offset(_radius, _radius), - _radius, - _paint, - ); - canvas.drawLine( - Offset(_radius, _radius), - Offset(_radius * 3.0, _radius), - Paint() - ..color = const Color(0xFFFFFFFF) - ..strokeWidth = 2.0, - ); - } -} +// canvas.drawCircle( +// Offset(_radius, _radius), +// _radius, +// _paint, +// ); +// canvas.drawLine( +// Offset(_radius, _radius), +// Offset(_radius * 3.0, _radius), +// Paint() +// ..color = const Color(0xFFFFFFFF) +// ..strokeWidth = 2.0, +// ); +// } +// } diff --git a/packages/flame/lib/src/events/component_mixins/cursor_hover_callbacks.dart b/packages/flame/lib/src/events/component_mixins/cursor_hover_callbacks.dart new file mode 100644 index 00000000000..0f8e50d3c93 --- /dev/null +++ b/packages/flame/lib/src/events/component_mixins/cursor_hover_callbacks.dart @@ -0,0 +1,19 @@ +import 'package:flame/src/components/core/component.dart'; +import 'package:flame/src/events/flame_game_mixins/cursor_hover_dispatcher.dart'; +import 'package:flame/src/events/messages/cursor_hover_event.dart'; +import 'package:flame/src/game/flame_game.dart'; +import 'package:meta/meta.dart'; + +mixin CursorHoverCallbacks on Component { + void onMouseMove(CursorHoverEvent event) {} + + @override + @mustCallSuper + void onMount() { + super.onMount(); + final game = findGame()! as FlameGame; + if (game.firstChild() == null) { + game.add(CursorHoverDispatcher()); + } + } +} diff --git a/packages/flame/lib/src/events/flame_game_mixins/cursor_hover_dispatcher.dart b/packages/flame/lib/src/events/flame_game_mixins/cursor_hover_dispatcher.dart new file mode 100644 index 00000000000..b8d635b1cf0 --- /dev/null +++ b/packages/flame/lib/src/events/flame_game_mixins/cursor_hover_dispatcher.dart @@ -0,0 +1,41 @@ +import 'package:flame/src/components/core/component.dart'; +import 'package:flame/src/events/component_mixins/cursor_hover_callbacks.dart'; +import 'package:flame/src/events/messages/cursor_hover_event.dart'; +import 'package:flame/src/game/flame_game.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; + +@internal +class CursorHoverDispatcher extends Component { + bool _eventHandlerRegistered = false; + FlameGame get game => parent! as FlameGame; + + @mustCallSuper + void onMouseMove(CursorHoverEvent event) { + event.deliverAtPoint( + rootComponent: game, + eventHandler: (CursorHoverCallbacks component) { + component.onMouseMove(event); + }, + ); + } + + @internal + void handleMouseMove(int pointerId, PointerHoverEvent pointerHoverEvent) { + onMouseMove(CursorHoverEvent(pointerId, pointerHoverEvent)); + } + + @override + void onMount() { + if (game.firstChild() == null) { + // TODO: Add detector to game + // game.gestureDetectors.add( + // PointerHoverEventListener.new, + // () {}, + // ); + } else { + removeFromParent(); + } + } +} diff --git a/packages/flame/lib/src/events/messages/cursor_hover_event.dart b/packages/flame/lib/src/events/messages/cursor_hover_event.dart new file mode 100644 index 00000000000..64963cc0b96 --- /dev/null +++ b/packages/flame/lib/src/events/messages/cursor_hover_event.dart @@ -0,0 +1,34 @@ +import 'package:flame/image_composition.dart'; +import 'package:flame/src/events/messages/position_event.dart'; +import 'package:flame/src/game/game.dart'; +import 'package:flame/src/gestures/events.dart'; + +import 'package:flutter/gestures.dart'; + +class CursorHoverEvent extends PositionEvent { + CursorHoverEvent(this.pointerId, PointerHoverEvent pointerHoverEvent) + : deviceKind = pointerHoverEvent.kind, + super( + canvasPosition: pointerHoverEvent.localPosition.toVector2(), + devicePosition: pointerHoverEvent.position.toVector2(), + ); + + final int pointerId; + + final PointerDeviceKind deviceKind; + + PointerHoverInfo asInfo(Game game) { + return PointerHoverInfo.fromDetails( + game, + PointerHoverEvent( + position: devicePosition.toOffset(), + kind: deviceKind, + ), + ); + } + + @override + String toString() => 'CursorHoverEvent(canvasPosition: $canvasPosition, ' + 'devicePosition: $devicePosition, ' + 'pointerId: $pointerId, deviceKind: $deviceKind)'; +} diff --git a/packages/flame/lib/src/game/mixins/cursor.dart b/packages/flame/lib/src/game/mixins/cursor.dart deleted file mode 100644 index 4badd1cbe2e..00000000000 --- a/packages/flame/lib/src/game/mixins/cursor.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:flame/game.dart'; -import 'package:flame/src/components/mixins/cursor_handler.dart'; -import 'package:flame/src/gestures/detectors.dart'; -import 'package:flame/src/gestures/events.dart'; -import 'package:flutter/material.dart'; - -mixin HasCursorHandlerComponents on FlameGame implements MouseMovementDetector { - @override - @mustCallSuper - void onMouseMove(PointerHoverInfo info) { - propagateToChildren( - (CursorHandler child) => child.onMouseMove(info), - ); - } -} diff --git a/packages/flame/lib/src/gestures/detectors.dart b/packages/flame/lib/src/gestures/detectors.dart index 5719220d5a9..02ad2613b88 100644 --- a/packages/flame/lib/src/gestures/detectors.dart +++ b/packages/flame/lib/src/gestures/detectors.dart @@ -1,5 +1,4 @@ import 'package:flame/src/game/game.dart'; -import 'package:flame/src/game/mixins/cursor.dart'; import 'package:flame/src/gestures/events.dart'; import 'package:flutter/gestures.dart'; @@ -192,15 +191,7 @@ mixin ScaleDetector on Game { } mixin MouseMovementDetector on Game { - void onMouseMove(PointerHoverInfo info) { - assert( - this is! HasCursorHandlerComponents, - 'A mouse movement event was registered by MouseMovementDetector for a ' - 'game also mixed with HasCursorHandlerComponents. Do not mix with both, ' - 'HasCursorHandlerComponents removes the necessity of ' - 'MouseMovementDetector.', - ); - } + void onMouseMove(PointerHoverInfo info) {} } mixin ScrollDetector on Game { From 135fc398c86138f4dfe6c35e8304a85ce577e312 Mon Sep 17 00:00:00 2001 From: garysm Date: Tue, 13 Jun 2023 00:29:25 -0400 Subject: [PATCH 14/14] fix export error --- packages/flame/lib/events.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/flame/lib/events.dart b/packages/flame/lib/events.dart index c149f15a611..4c6369560df 100644 --- a/packages/flame/lib/events.dart +++ b/packages/flame/lib/events.dart @@ -25,7 +25,6 @@ export 'src/events/messages/drag_update_event.dart' show DragUpdateEvent; export 'src/events/messages/tap_cancel_event.dart' show TapCancelEvent; export 'src/events/messages/tap_down_event.dart' show TapDownEvent; export 'src/events/messages/tap_up_event.dart' show TapUpEvent; -export 'src/game/mixins/cursor.dart' show HasCursorHandlerComponents; // ignore: deprecated_member_use_from_same_package export 'src/game/mixins/has_draggables.dart' show HasDraggables; // ignore: deprecated_member_use_from_same_package