Draggables weren't using the new coordinate system (#777)

* refactoring drag start events

* Fixing joystick, adding tests and examples

* format fixes
This commit is contained in:
Erick
2021-04-30 10:01:42 -03:00
committed by GitHub
parent d9e0acd3ff
commit 0cb64fb57f
11 changed files with 159 additions and 56 deletions

View File

@ -52,7 +52,17 @@ void addControlsStories(Dashbook dashbook) {
)
..add(
'Draggables',
(_) => GameWidget(game: DraggablesGame()),
(context) {
return GameWidget(
game: DraggablesGame(
zoom: context.listProperty(
'zoom',
1,
[0.5, 1, 1.5],
),
),
);
},
codeLink: baseLink('gestures/draggables.dart'),
)
..add(

View File

@ -27,8 +27,8 @@ class DraggableSquare extends PositionComponent
}
@override
bool onDragStart(int pointerId, Vector2 startPosition) {
dragDeltaPosition = startPosition - position;
bool onDragStart(int pointerId, DragStartInfo info) {
dragDeltaPosition = info.eventPosition.game - position;
return false;
}
@ -57,8 +57,13 @@ class DraggableSquare extends PositionComponent
}
class DraggablesGame extends BaseGame with HasDraggableComponents {
final double zoom;
DraggablesGame({required this.zoom});
@override
Future<void> onLoad() async {
camera.zoom = zoom;
add(DraggableSquare());
add(DraggableSquare()..y = 350);
}

View File

@ -39,9 +39,9 @@ class MultitapAdvancedGame extends BaseGame
}
@override
void onDragStart(int pointerId, Vector2 position) {
void onDragStart(int pointerId, DragStartInfo info) {
end = null;
start = position;
start = info.eventPosition.game;
}
@override

View File

@ -163,13 +163,13 @@ class JoystickAction extends BaseComponent with Draggable, HasGameRef {
}
@override
bool onDragStart(int pointerId, Vector2 startPosition) {
bool onDragStart(int pointerId, DragStartInfo info) {
if (_dragging) {
return true;
}
if (enableDirection) {
_dragPosition = startPosition;
_dragPosition = info.eventPosition.widget;
_dragging = true;
}
_sendEvent(ActionEvent.down);

View File

@ -130,11 +130,11 @@ class JoystickDirectional extends BaseComponent with Draggable, HasGameRef {
}
@override
bool onDragStart(int pointerId, Vector2 startPosition) {
_updateDirectionalRect(startPosition);
bool onDragStart(int pointerId, DragStartInfo info) {
_updateDirectionalRect(info.eventPosition.widget);
if (!_dragging) {
_dragging = true;
_dragPosition = startPosition;
_dragPosition = info.eventPosition.widget;
return true;
}
return false;

View File

@ -1,20 +1,19 @@
import 'package:flutter/material.dart';
import '../../../extensions.dart';
import '../../game/base_game.dart';
import '../../gestures/events.dart';
import '../base_component.dart';
mixin Draggable on BaseComponent {
bool onDragStart(int pointerId, Vector2 startPosition) {
bool onDragStart(int pointerId, DragStartInfo info) {
return true;
}
bool onDragUpdate(int pointerId, DragUpdateInfo details) {
bool onDragUpdate(int pointerId, DragUpdateInfo info) {
return true;
}
bool onDragEnd(int pointerId, DragEndInfo details) {
bool onDragEnd(int pointerId, DragEndInfo info) {
return true;
}
@ -25,10 +24,10 @@ mixin Draggable on BaseComponent {
final List<int> _currentPointerIds = [];
bool _checkPointerId(int pointerId) => _currentPointerIds.contains(pointerId);
bool handleDragStart(int pointerId, Vector2 startPosition) {
if (containsPoint(startPosition)) {
bool handleDragStart(int pointerId, DragStartInfo info) {
if (containsPoint(info.eventPosition.game)) {
_currentPointerIds.add(pointerId);
return onDragStart(pointerId, startPosition);
return onDragStart(pointerId, info);
}
return true;
}
@ -59,8 +58,8 @@ mixin Draggable on BaseComponent {
mixin HasDraggableComponents on BaseGame {
@mustCallSuper
void onDragStart(int pointerId, Vector2 startPosition) {
_onGenericEventReceived((c) => c.handleDragStart(pointerId, startPosition));
void onDragStart(int pointerId, DragStartInfo info) {
_onGenericEventReceived((c) => c.handleDragStart(pointerId, info));
}
@mustCallSuper

View File

@ -192,14 +192,28 @@ Widget applyAdvancedGesturesDetectors(Game game, Widget child) {
);
}
void addDragRecognizer(Drag Function(int, Vector2) config) {
void addDragRecognizer(Game game, Drag Function(int, DragStartInfo) config) {
addAndConfigureRecognizer(
() => ImmediateMultiDragGestureRecognizer(),
(ImmediateMultiDragGestureRecognizer instance) {
instance.onStart = (Offset o) {
final pointerId = lastGeneratedDragId++;
final position = game.convertGlobalToLocalCoordinate(o.toVector2());
return config(pointerId, position);
final global = o;
final local = game
.convertGlobalToLocalCoordinate(
global.toVector2(),
)
.toOffset();
final details = DragStartDetails(
localPosition: local,
globalPosition: global,
);
return config(
pointerId,
DragStartInfo.fromDetails(game, details),
);
};
},
);
@ -228,15 +242,15 @@ Widget applyAdvancedGesturesDetectors(Game game, Widget child) {
}
if (game is MultiTouchDragDetector) {
addDragRecognizer((int pointerId, Vector2 position) {
game.onDragStart(pointerId, position);
addDragRecognizer(game, (int pointerId, DragStartInfo info) {
game.onDragStart(pointerId, info);
return _DragEvent(game)
..onUpdate = ((details) => game.onDragUpdate(pointerId, details))
..onEnd = ((details) => game.onDragEnd(pointerId, details))
..onCancel = (() => game.onDragCancel(pointerId));
});
} else if (game is HasDraggableComponents) {
addDragRecognizer((int pointerId, Vector2 position) {
addDragRecognizer(game, (int pointerId, DragStartInfo position) {
game.onDragStart(pointerId, position);
return _DragEvent(game)
..onUpdate = ((details) => game.onDragUpdate(pointerId, details))

View File

@ -1,4 +1,3 @@
import '../../extensions.dart';
import '../game/game.dart';
import 'events.dart';
@ -11,7 +10,7 @@ mixin MultiTouchTapDetector on Game {
}
mixin MultiTouchDragDetector on Game {
void onDragStart(int pointerId, Vector2 startPosition) {}
void onDragStart(int pointerId, DragStartInfo info) {}
void onDragUpdate(int pointerId, DragUpdateInfo info) {}
void onDragEnd(int pointerId, DragEndInfo info) {}
void onDragCancel(int pointerId) {}

View File

@ -1,25 +0,0 @@
import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:test/test.dart';
class _GameWithDraggables extends BaseGame with HasDraggableComponents {}
class _GameWithoutDraggables extends BaseGame {}
class DraggableComponent extends PositionComponent with Draggable {}
void main() {
group('draggables test', () {
test('make sure they cannot be added to invalid games', () async {
final game1 = _GameWithDraggables();
// should be ok
await game1.add(DraggableComponent());
final game2 = _GameWithoutDraggables();
expect(
() => game2.add(DraggableComponent()),
isA<AssertionError>(),
);
});
});
}

View File

@ -0,0 +1,93 @@
import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame/gestures.dart';
import 'package:flutter/gestures.dart';
import 'package:test/test.dart';
class _GameWithDraggables extends BaseGame with HasDraggableComponents {}
class _GameWithoutDraggables extends BaseGame {}
class DraggableComponent extends PositionComponent with Draggable {
bool hasStartedDragging = false;
@override
bool onDragStart(int pointerId, DragStartInfo event) {
hasStartedDragging = true;
return true;
}
}
void main() {
group('draggables test', () {
test('make sure they cannot be added to invalid games', () async {
final game1 = _GameWithDraggables();
game1.onResize(Vector2.all(100));
// should be ok
await game1.add(DraggableComponent());
final game2 = _GameWithoutDraggables();
game2.onResize(Vector2.all(100));
var hasError = false;
try {
await game2.add(DraggableComponent());
} catch (e) {
hasError = true;
}
expect(hasError, true);
});
test('can be dragged', () async {
final game = _GameWithDraggables();
game.onResize(Vector2.all(100));
final component = DraggableComponent()
..x = 10
..y = 10
..width = 10
..height = 10;
await game.add(component);
// So component is added
game.update(0.01);
game.onDragStart(
1,
DragStartInfo.fromDetails(
game,
DragStartDetails(
localPosition: const Offset(12, 12),
globalPosition: const Offset(12, 12),
),
),
);
expect(component.hasStartedDragging, true);
});
test('when the game has camera zoom, can be dragged', () async {
final game = _GameWithDraggables();
game.onResize(Vector2.all(100));
final component = DraggableComponent()
..x = 10
..y = 10
..width = 10
..height = 10;
await game.add(component);
game.camera.zoom = 1.5;
// So component is added
game.update(0.01);
game.onDragStart(
1,
DragStartInfo.fromDetails(
game,
DragStartDetails(
localPosition: const Offset(12, 12),
globalPosition: const Offset(12, 12),
),
),
);
expect(component.hasStartedDragging, true);
});
});
}

View File

@ -12,14 +12,22 @@ void main() {
group('tapables test', () {
test('make sure they cannot be added to invalid games', () async {
final game1 = _GameWithTapables();
game1.onResize(Vector2.all(100));
// should be ok
await game1.add(TapableComponent());
final game2 = _GameWithoutTapables();
expect(
() => game2.add(TapableComponent()),
isA<AssertionError>(),
);
game2.onResize(Vector2.all(100));
var hasError = false;
try {
await game2.add(TapableComponent());
} catch (e) {
hasError = true;
}
expect(hasError, true);
});
});
}