mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-02 20:13:50 +08:00
Add hoverables (#797)
This commit is contained in:
31
doc/input.md
31
doc/input.md
@ -138,10 +138,10 @@ class MyGame extends Game with TapDetector {
|
|||||||
You can also check more complete examples
|
You can also check more complete examples
|
||||||
[here](https://github.com/flame-engine/flame/tree/main/examples/lib/stories/controls/).
|
[here](https://github.com/flame-engine/flame/tree/main/examples/lib/stories/controls/).
|
||||||
|
|
||||||
## Tapable and Draggable components
|
## Tapable, Draggable and Hoverable components
|
||||||
|
|
||||||
Any component derived from `BaseComponent` (most components) can add the `Tapable` and/or the
|
Any component derived from `BaseComponent` (most components) can add the `Tapable`, the
|
||||||
`Draggable` mixins to handle taps and drags on the component.
|
`Draggable`, and/or the `Hoverable` mixins to handle taps, drags and hovers on the component.
|
||||||
|
|
||||||
All overridden methods return a boolean to control if the event should be passed down further along
|
All overridden methods return a boolean to control if the event should be passed down further along
|
||||||
to components underneath it. So say that you only want your top visible component to receive a tap
|
to components underneath it. So say that you only want your top visible component to receive a tap
|
||||||
@ -166,8 +166,7 @@ void onTapUp(TapUpInfo event) {}
|
|||||||
Minimal component example:
|
Minimal component example:
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'package:flame/components/component.dart';
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame/components/mixins/tapable.dart';
|
|
||||||
|
|
||||||
class TapableComponent extends PositionComponent with Tapable {
|
class TapableComponent extends PositionComponent with Tapable {
|
||||||
|
|
||||||
@ -229,8 +228,7 @@ Minimal component example (this example ignores pointerId so it wont work well i
|
|||||||
multi-drag):
|
multi-drag):
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'package:flame/components/component.dart';
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame/components/mixins/draggable.dart';
|
|
||||||
|
|
||||||
class DraggableComponent extends PositionComponent with Draggable {
|
class DraggableComponent extends PositionComponent with Draggable {
|
||||||
|
|
||||||
@ -275,6 +273,25 @@ class MyGame extends BaseGame with HasDraggableComponents {
|
|||||||
**Note**: `HasDraggableComponents` uses an advanced gesture detector under the hood and as explained
|
**Note**: `HasDraggableComponents` uses an advanced gesture detector under the hood and as explained
|
||||||
further up on this page, shouldn't be used alongside basic detectors.
|
further up on this page, shouldn't be used alongside basic detectors.
|
||||||
|
|
||||||
|
### Hoverable components
|
||||||
|
|
||||||
|
Just like the others, this mixin allows for easy wiring of your component to listen to hover states
|
||||||
|
and events.
|
||||||
|
|
||||||
|
By adding the `HasHoverableComponents` mixin to your base game, and by using the mixin `Hoverable` on
|
||||||
|
your components, they get an `isHovered` field and a couple of methods (`onHoverStart`, `onHoverEnd`) that
|
||||||
|
you can override if you want to listen to the events.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
bool isHovered = false;
|
||||||
|
void onHoverEnter(PointerHoverInfo event) {}
|
||||||
|
void onHoverLeave(PointerHoverInfo event) {}
|
||||||
|
```
|
||||||
|
|
||||||
|
The provided event info is from the mouse move that triggered the action (entering or leaving).
|
||||||
|
While the mouse movement is kept inside or outside, no events are fired and those mouse move events are
|
||||||
|
not propagated. Only when the state is changed the handlers are triggered.
|
||||||
|
|
||||||
## Hitbox
|
## Hitbox
|
||||||
The `Hitbox` mixin is used to make detection of gestures on top of your `PositionComponent`s more
|
The `Hitbox` mixin is used to make detection of gestures on top of your `PositionComponent`s more
|
||||||
accurate. Say that you have a fairly round rock as a `SpriteComponent` for example, then you don't
|
accurate. Say that you have a fairly round rock as a `SpriteComponent` for example, then you don't
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'package:flame/game.dart';
|
|||||||
import '../../commons/commons.dart';
|
import '../../commons/commons.dart';
|
||||||
import 'advanced_joystick.dart';
|
import 'advanced_joystick.dart';
|
||||||
import 'draggables.dart';
|
import 'draggables.dart';
|
||||||
|
import 'hoverables.dart';
|
||||||
import 'joystick.dart';
|
import 'joystick.dart';
|
||||||
import 'keyboard.dart';
|
import 'keyboard.dart';
|
||||||
import 'mouse_movement.dart';
|
import 'mouse_movement.dart';
|
||||||
@ -55,16 +56,18 @@ void addControlsStories(Dashbook dashbook) {
|
|||||||
(context) {
|
(context) {
|
||||||
return GameWidget(
|
return GameWidget(
|
||||||
game: DraggablesGame(
|
game: DraggablesGame(
|
||||||
zoom: context.listProperty(
|
zoom: context.listProperty('zoom', 1, [0.5, 1, 1.5]),
|
||||||
'zoom',
|
|
||||||
1,
|
|
||||||
[0.5, 1, 1.5],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
codeLink: baseLink('controls/draggables.dart'),
|
codeLink: baseLink('controls/draggables.dart'),
|
||||||
)
|
)
|
||||||
|
..add(
|
||||||
|
'Hoverables',
|
||||||
|
(_) => GameWidget(game: HoverablesGame()),
|
||||||
|
codeLink: baseLink('controls/hoverables.dart'),
|
||||||
|
info: 'Add more squares by clicking. Hover squares to change colors.',
|
||||||
|
)
|
||||||
..add(
|
..add(
|
||||||
'Joystick',
|
'Joystick',
|
||||||
(_) => GameWidget(game: JoystickGame()),
|
(_) => GameWidget(game: JoystickGame()),
|
||||||
|
|||||||
34
examples/lib/stories/controls/hoverables.dart
Normal file
34
examples/lib/stories/controls/hoverables.dart
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import 'package:flame/components.dart';
|
||||||
|
import 'package:flame/gestures.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flame/game.dart';
|
||||||
|
import 'package:flame/extensions.dart';
|
||||||
|
|
||||||
|
class HoverableSquare extends PositionComponent with Hoverable {
|
||||||
|
static final Paint _white = Paint()..color = const Color(0xFFFFFFFF);
|
||||||
|
static final Paint _grey = Paint()..color = const Color(0xFFA5A5A5);
|
||||||
|
|
||||||
|
HoverableSquare(Vector2 position)
|
||||||
|
: super(position: position, size: Vector2.all(100)) {
|
||||||
|
anchor = Anchor.center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void render(Canvas canvas) {
|
||||||
|
super.render(canvas);
|
||||||
|
canvas.drawRect(size.toRect(), isHovered ? _grey : _white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HoverablesGame extends BaseGame with HasHoverableComponents, TapDetector {
|
||||||
|
@override
|
||||||
|
Future<void> onLoad() async {
|
||||||
|
add(HoverableSquare(Vector2(200, 500)));
|
||||||
|
add(HoverableSquare(Vector2(700, 300)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onTapDown(TapDownInfo event) {
|
||||||
|
add(HoverableSquare(event.eventPosition.game));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@
|
|||||||
- No need to send size in ParallaxComponent.fromParallax since Parallax already contains it
|
- No need to send size in ParallaxComponent.fromParallax since Parallax already contains it
|
||||||
- Fix Text Rendering not working properly
|
- Fix Text Rendering not working properly
|
||||||
- Add more useful methods to the IsometricTileMap component
|
- Add more useful methods to the IsometricTileMap component
|
||||||
|
- Add Hoverables
|
||||||
|
|
||||||
## [1.0.0-rc10]
|
## [1.0.0-rc10]
|
||||||
- Updated tutorial documentation to indicate use of new version
|
- Updated tutorial documentation to indicate use of new version
|
||||||
|
|||||||
@ -8,6 +8,7 @@ export 'src/components/mixins/draggable.dart';
|
|||||||
export 'src/components/mixins/has_collidables.dart';
|
export 'src/components/mixins/has_collidables.dart';
|
||||||
export 'src/components/mixins/has_game_ref.dart';
|
export 'src/components/mixins/has_game_ref.dart';
|
||||||
export 'src/components/mixins/hitbox.dart';
|
export 'src/components/mixins/hitbox.dart';
|
||||||
|
export 'src/components/mixins/hoverable.dart';
|
||||||
export 'src/components/mixins/single_child_particle.dart';
|
export 'src/components/mixins/single_child_particle.dart';
|
||||||
export 'src/components/mixins/tapable.dart';
|
export 'src/components/mixins/tapable.dart';
|
||||||
export 'src/components/nine_tile_box_component.dart';
|
export 'src/components/nine_tile_box_component.dart';
|
||||||
|
|||||||
48
packages/flame/lib/src/components/mixins/hoverable.dart
Normal file
48
packages/flame/lib/src/components/mixins/hoverable.dart
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
import '../../../game.dart';
|
||||||
|
import '../../game/base_game.dart';
|
||||||
|
import '../../gestures/events.dart';
|
||||||
|
import '../base_component.dart';
|
||||||
|
|
||||||
|
mixin Hoverable on BaseComponent {
|
||||||
|
bool _isHovered = false;
|
||||||
|
bool get isHovered => _isHovered;
|
||||||
|
void onHoverEnter(PointerHoverInfo event) {}
|
||||||
|
void onHoverLeave(PointerHoverInfo event) {}
|
||||||
|
|
||||||
|
@nonVirtual
|
||||||
|
void doHandleMouseMovement(PointerHoverInfo event, Vector2 p) {
|
||||||
|
if (containsPoint(p)) {
|
||||||
|
if (!_isHovered) {
|
||||||
|
_isHovered = true;
|
||||||
|
onHoverEnter(event);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_isHovered) {
|
||||||
|
_isHovered = false;
|
||||||
|
onHoverLeave(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin HasHoverableComponents on BaseGame {
|
||||||
|
@mustCallSuper
|
||||||
|
void onMouseMove(PointerHoverInfo event) {
|
||||||
|
final p = event.eventPosition.game;
|
||||||
|
bool _mouseMoveHandler(Hoverable c) {
|
||||||
|
c.doHandleMouseMovement(event, p);
|
||||||
|
return true; // always continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final c in components.toList().reversed) {
|
||||||
|
if (c is BaseComponent) {
|
||||||
|
c.propagateToChildren<Hoverable>(_mouseMoveHandler);
|
||||||
|
}
|
||||||
|
if (c is Hoverable) {
|
||||||
|
_mouseMoveHandler(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ import '../components/mixins/collidable.dart';
|
|||||||
import '../components/mixins/draggable.dart';
|
import '../components/mixins/draggable.dart';
|
||||||
import '../components/mixins/has_collidables.dart';
|
import '../components/mixins/has_collidables.dart';
|
||||||
import '../components/mixins/has_game_ref.dart';
|
import '../components/mixins/has_game_ref.dart';
|
||||||
|
import '../components/mixins/hoverable.dart';
|
||||||
import '../components/mixins/tapable.dart';
|
import '../components/mixins/tapable.dart';
|
||||||
import '../components/position_component.dart';
|
import '../components/position_component.dart';
|
||||||
import '../fps_counter.dart';
|
import '../fps_counter.dart';
|
||||||
@ -106,6 +107,12 @@ class BaseGame extends Game with FPSCounter {
|
|||||||
'Draggable Components can only be added to a BaseGame with HasDraggableComponents',
|
'Draggable Components can only be added to a BaseGame with HasDraggableComponents',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (c is Hoverable) {
|
||||||
|
assert(
|
||||||
|
this is HasHoverableComponents,
|
||||||
|
'Hoverable Components can only be added to a BaseGame with HasHoverableComponents',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (debugMode && c is PositionComponent) {
|
if (debugMode && c is PositionComponent) {
|
||||||
c.debugMode = true;
|
c.debugMode = true;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
import '../../../components.dart';
|
||||||
import '../../../extensions.dart';
|
import '../../../extensions.dart';
|
||||||
import '../../components/mixins/draggable.dart';
|
import '../../components/mixins/draggable.dart';
|
||||||
import '../../components/mixins/tapable.dart';
|
import '../../components/mixins/tapable.dart';
|
||||||
@ -27,7 +28,9 @@ bool hasAdvancedGesturesDetectors(Game game) =>
|
|||||||
game is HasDraggableComponents;
|
game is HasDraggableComponents;
|
||||||
|
|
||||||
bool hasMouseDetectors(Game game) =>
|
bool hasMouseDetectors(Game game) =>
|
||||||
game is MouseMovementDetector || game is ScrollDetector;
|
game is MouseMovementDetector ||
|
||||||
|
game is ScrollDetector ||
|
||||||
|
game is HasHoverableComponents;
|
||||||
|
|
||||||
Widget applyBasicGesturesDetectors(Game game, Widget child) {
|
Widget applyBasicGesturesDetectors(Game game, Widget child) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
@ -267,12 +270,13 @@ Widget applyAdvancedGesturesDetectors(Game game, Widget child) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget applyMouseDetectors(Game game, Widget child) {
|
Widget applyMouseDetectors(Game game, Widget child) {
|
||||||
|
final mouseMoveFn = game is MouseMovementDetector
|
||||||
|
? game.onMouseMove
|
||||||
|
: (game is HasHoverableComponents ? game.onMouseMove : null);
|
||||||
return Listener(
|
return Listener(
|
||||||
child: MouseRegion(
|
child: MouseRegion(
|
||||||
child: child,
|
child: child,
|
||||||
onHover: game is MouseMovementDetector
|
onHover: (e) => mouseMoveFn?.call(PointerHoverInfo.fromDetails(game, e)),
|
||||||
? (e) => game.onMouseMove(PointerHoverInfo.fromDetails(game, e))
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
onPointerSignal: (event) =>
|
onPointerSignal: (event) =>
|
||||||
game is ScrollDetector && event is PointerScrollEvent
|
game is ScrollDetector && event is PointerScrollEvent
|
||||||
|
|||||||
@ -24,7 +24,7 @@ void main() {
|
|||||||
test('fail to parse invalid anchor', () {
|
test('fail to parse invalid anchor', () {
|
||||||
expect(
|
expect(
|
||||||
() => Anchor.valueOf('foobar'),
|
() => Anchor.valueOf('foobar'),
|
||||||
throwsA(const TypeMatcher<AssertionError>()),
|
throwsA(isA<AssertionError>()),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -28,15 +28,11 @@ void main() {
|
|||||||
|
|
||||||
final game2 = _GameWithoutDraggables();
|
final game2 = _GameWithoutDraggables();
|
||||||
game2.onResize(Vector2.all(100));
|
game2.onResize(Vector2.all(100));
|
||||||
var hasError = false;
|
|
||||||
|
|
||||||
try {
|
expect(
|
||||||
await game2.add(DraggableComponent());
|
() => game2.add(DraggableComponent()),
|
||||||
} catch (e) {
|
throwsA(isA<AssertionError>()),
|
||||||
hasError = true;
|
);
|
||||||
}
|
|
||||||
|
|
||||||
expect(hasError, true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can be dragged', () async {
|
test('can be dragged', () async {
|
||||||
|
|||||||
162
packages/flame/test/components/hoverable_test.dart
Normal file
162
packages/flame/test/components/hoverable_test.dart
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flame/components.dart';
|
||||||
|
import 'package:flame/game.dart';
|
||||||
|
import 'package:flame/src/components/mixins/hoverable.dart';
|
||||||
|
import 'package:flame/src/gestures/events.dart';
|
||||||
|
import 'package:flutter/gestures.dart' show PointerHoverEvent;
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
class _GameWithHoverables extends BaseGame with HasHoverableComponents {}
|
||||||
|
|
||||||
|
class _GameWithoutHoverables extends BaseGame {}
|
||||||
|
|
||||||
|
class HoverableComponent extends PositionComponent with Hoverable {
|
||||||
|
int enterCount = 0;
|
||||||
|
int leaveCount = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onHoverEnter(PointerHoverInfo event) {
|
||||||
|
enterCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onHoverLeave(PointerHoverInfo event) {
|
||||||
|
leaveCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('hoverable test', () {
|
||||||
|
test('make sure they cannot be added to invalid games', () async {
|
||||||
|
final game1 = _GameWithHoverables();
|
||||||
|
game1.onResize(Vector2.all(100));
|
||||||
|
// should be ok
|
||||||
|
await game1.add(HoverableComponent());
|
||||||
|
|
||||||
|
final game2 = _GameWithoutHoverables();
|
||||||
|
game2.onResize(Vector2.all(100));
|
||||||
|
|
||||||
|
expect(
|
||||||
|
() => game2.add(HoverableComponent()),
|
||||||
|
throwsA(isA<AssertionError>()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('single component', () async {
|
||||||
|
final game = _GameWithHoverables();
|
||||||
|
game.onResize(Vector2.all(100));
|
||||||
|
|
||||||
|
final c = HoverableComponent()
|
||||||
|
..position = Vector2(10, 20)
|
||||||
|
..size = Vector2(3, 3);
|
||||||
|
await game.add(c);
|
||||||
|
game.update(0);
|
||||||
|
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
expect(c.enterCount, 0);
|
||||||
|
expect(c.leaveCount, 0);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 0, 0);
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
expect(c.enterCount, 0);
|
||||||
|
expect(c.leaveCount, 0);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 11, 0);
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
expect(c.enterCount, 0);
|
||||||
|
expect(c.leaveCount, 0);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 11, 21); // enter!
|
||||||
|
expect(c.isHovered, true);
|
||||||
|
expect(c.enterCount, 1);
|
||||||
|
expect(c.leaveCount, 0);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 12, 22); // still inside
|
||||||
|
expect(c.isHovered, true);
|
||||||
|
expect(c.enterCount, 1);
|
||||||
|
expect(c.leaveCount, 0);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 11, 25); // leave
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
expect(c.enterCount, 1);
|
||||||
|
expect(c.leaveCount, 1);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 11, 21); // enter again
|
||||||
|
expect(c.isHovered, true);
|
||||||
|
expect(c.enterCount, 2);
|
||||||
|
expect(c.leaveCount, 1);
|
||||||
|
});
|
||||||
|
test('camera is respected', () async {
|
||||||
|
final game = _GameWithHoverables();
|
||||||
|
game.onResize(Vector2.all(100));
|
||||||
|
|
||||||
|
final c = HoverableComponent()
|
||||||
|
..position = Vector2(10, 20)
|
||||||
|
..size = Vector2(3, 3);
|
||||||
|
await game.add(c);
|
||||||
|
game.update(0);
|
||||||
|
|
||||||
|
// component is now at the corner of the screen
|
||||||
|
game.camera.snapTo(Vector2(10, 20));
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 11, 21);
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
_triggerMouseMove(game, 11, 1);
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
_triggerMouseMove(game, 1, 1);
|
||||||
|
expect(c.isHovered, true);
|
||||||
|
_triggerMouseMove(game, 5, 1);
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
});
|
||||||
|
test('multiple components', () async {
|
||||||
|
final game = _GameWithHoverables();
|
||||||
|
game.onResize(Vector2.all(100));
|
||||||
|
|
||||||
|
final a = HoverableComponent()
|
||||||
|
..position = Vector2(10, 0)
|
||||||
|
..size = Vector2(2, 20);
|
||||||
|
final b = HoverableComponent()
|
||||||
|
..position = Vector2(10, 10)
|
||||||
|
..size = Vector2(2, 2);
|
||||||
|
final c = HoverableComponent()
|
||||||
|
..position = Vector2(0, 7)
|
||||||
|
..size = Vector2(20, 2);
|
||||||
|
await game.add(a);
|
||||||
|
await game.add(b);
|
||||||
|
await game.add(c);
|
||||||
|
game.update(0);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 0, 0);
|
||||||
|
expect(a.isHovered, false);
|
||||||
|
expect(b.isHovered, false);
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 10, 10);
|
||||||
|
expect(a.isHovered, true);
|
||||||
|
expect(b.isHovered, true);
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 11, 8);
|
||||||
|
expect(a.isHovered, true);
|
||||||
|
expect(b.isHovered, false);
|
||||||
|
expect(c.isHovered, true);
|
||||||
|
|
||||||
|
_triggerMouseMove(game, 11, 6);
|
||||||
|
expect(a.isHovered, true);
|
||||||
|
expect(b.isHovered, false);
|
||||||
|
expect(c.isHovered, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(luan) we can probably provide some helpers to facilitate testing events
|
||||||
|
void _triggerMouseMove(HasHoverableComponents game, double dx, double dy) {
|
||||||
|
game.onMouseMove(
|
||||||
|
PointerHoverInfo.fromDetails(
|
||||||
|
game,
|
||||||
|
PointerHoverEvent(
|
||||||
|
position: Offset(dx, dy),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -19,15 +19,10 @@ void main() {
|
|||||||
final game2 = _GameWithoutTapables();
|
final game2 = _GameWithoutTapables();
|
||||||
game2.onResize(Vector2.all(100));
|
game2.onResize(Vector2.all(100));
|
||||||
|
|
||||||
var hasError = false;
|
expect(
|
||||||
|
() => game2.add(TapableComponent()),
|
||||||
try {
|
throwsA(isA<AssertionError>()),
|
||||||
await game2.add(TapableComponent());
|
);
|
||||||
} catch (e) {
|
|
||||||
hasError = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(hasError, true);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user