mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-02 20:13:50 +08:00
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:
@ -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(
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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) {}
|
||||
|
||||
@ -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>(),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
93
packages/flame/test/components/draggable_test.dart
Normal file
93
packages/flame/test/components/draggable_test.dart
Normal 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);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user