Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import 'package:flame/events.dart';
/// At present, flutter detects only one double-tap events simultaneously.
/// This means that if you're double-tapping two [DoubleTapCallbacks] located
/// far away from each other, only one callback will be fired (or none).
///
/// This callback uses [DoubleTapDispatcher] to route events.
mixin DoubleTapCallbacks on Component {
/// This triggers when the pointer stops contacting the device after the
/// second tap.
Expand All @@ -25,11 +27,6 @@ mixin DoubleTapCallbacks on Component {
@override
void onMount() {
super.onMount();
final game = findRootGame()!;
if (game.findByKey(const DoubleTapDispatcherKey()) == null) {
final dispatcher = DoubleTapDispatcher();
game.registerKey(const DoubleTapDispatcherKey(), dispatcher);
game.add(dispatcher);
}
DoubleTapDispatcher.addDispatcher(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import 'package:meta/meta.dart';
/// the component.
///
/// This mixin is the replacement of the Draggable mixin.
///
/// This callback uses [MultiDragDispatcher] to route events.
mixin DragCallbacks on Component {
bool _isDragged = false;

Expand Down Expand Up @@ -61,11 +63,6 @@ mixin DragCallbacks on Component {
@mustCallSuper
void onMount() {
super.onMount();
final game = findRootGame()!;
if (game.findByKey(const MultiDragDispatcherKey()) == null) {
final dispatcher = MultiDragDispatcher();
game.registerKey(const MultiDragDispatcherKey(), dispatcher);
game.add(dispatcher);
}
MultiDragDispatcher.addDispatcher(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import 'package:meta/meta.dart';
/// component.
///
/// This mixin is the replacement of the Hoverable mixin.
///
/// This callback uses [PointerMoveDispatcher] to route events.
mixin HoverCallbacks on Component implements PointerMoveCallbacks {
bool _isHovered = false;

Expand Down Expand Up @@ -56,6 +58,6 @@ mixin HoverCallbacks on Component implements PointerMoveCallbacks {
@mustCallSuper
void onMount() {
super.onMount();
PointerMoveCallbacks.onMountHandler(this);
PointerMoveDispatcher.addDispatcher(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import 'package:flutter/foundation.dart';
/// long press.
/// - [onLongPressEnd]: called when the pointer is lifted after a long press.
/// - [onLongPressCancel]: called if the gesture is cancelled before completion.
///
/// This callback uses [LongPressDispatcher] to route events.
mixin LongPressCallbacks on Component {
bool _isLongPressing = false;

Expand Down Expand Up @@ -46,11 +48,6 @@ mixin LongPressCallbacks on Component {
@mustCallSuper
void onMount() {
super.onMount();
final game = findRootGame()!;
if (game.findByKey(const LongPressDispatcherKey()) == null) {
final dispatcher = LongPressDispatcher();
game.registerKey(const LongPressDispatcherKey(), dispatcher);
game.add(dispatcher);
}
LongPressDispatcher.addDispatcher(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'package:meta/meta.dart';

/// This mixin can be added to a [Component] allowing it to receive
/// pointer movement events.
///
/// This callback uses [PointerMoveDispatcher] to route events.
mixin PointerMoveCallbacks on Component {
void onPointerMove(PointerMoveEvent event) {}

Expand All @@ -13,16 +15,6 @@ mixin PointerMoveCallbacks on Component {
@mustCallSuper
void onMount() {
super.onMount();
onMountHandler(this);
}

static void onMountHandler(PointerMoveCallbacks instance) {
final game = instance.findRootGame()!;
const key = MouseMoveDispatcherKey();
if (game.findByKey(key) == null) {
final dispatcher = PointerMoveDispatcher();
game.registerKey(key, dispatcher);
game.add(dispatcher);
}
PointerMoveDispatcher.addDispatcher(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flame/events.dart';
import 'package:flame/src/events/flame_game_mixins/scale_dispatcher.dart';
import 'package:flutter/foundation.dart';

/// This callback uses [ScaleDispatcher] to route events.
mixin ScaleCallbacks on Component {
bool _isScaling = false;

Expand All @@ -25,11 +26,6 @@ mixin ScaleCallbacks on Component {
@mustCallSuper
void onMount() {
super.onMount();
final game = findRootGame()!;
if (game.findByKey(const ScaleDispatcherKey()) == null) {
final dispatcher = ScaleDispatcher();
game.registerKey(const ScaleDispatcherKey(), dispatcher);
game.add(dispatcher);
}
ScaleDispatcher.addDispatcher(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,15 @@ import 'package:meta/meta.dart';

/// This mixin can be added to a [Component] allowing it to receive
/// pointer scroll (mouse wheel) events.
///
/// This callback uses [ScrollDispatcher] to route events.
mixin ScrollCallbacks on Component {
void onScroll(ScrollEvent event) {}

@override
@mustCallSuper
void onMount() {
super.onMount();
onMountHandler(this);
}

static void onMountHandler(ScrollCallbacks instance) {
final game = instance.findRootGame()!;
const key = ScrollDispatcherKey();
if (game.findByKey(key) == null) {
final dispatcher = ScrollDispatcher();
game.registerKey(key, dispatcher);
game.add(dispatcher);
}
ScrollDispatcher.addDispatcher(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import 'package:meta/meta.dart';
///
/// Note that FlameGame _is_ a [Component] and does implement
/// [containsLocalPoint]; so this can be used at the game level.
///
/// This callback uses [SecondaryTapDispatcher] to route events.
mixin SecondaryTapCallbacks on Component {
void onSecondaryTapDown(SecondaryTapDownEvent event) {}
void onSecondaryTapUp(SecondaryTapUpEvent event) {}
Expand All @@ -20,11 +22,6 @@ mixin SecondaryTapCallbacks on Component {
@mustCallSuper
void onMount() {
super.onMount();
final game = findRootGame()!;
if (game.findByKey(const SecondaryTapDispatcherKey()) == null) {
final dispatcher = SecondaryTapDispatcher();
game.registerKey(const SecondaryTapDispatcherKey(), dispatcher);
game.add(dispatcher);
}
SecondaryTapDispatcher.addDispatcher(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import 'package:meta/meta.dart';
///
/// Note that FlameGame _is_ a [Component] and does implement
/// [containsLocalPoint]; so this can be used at the game level.
///
/// This callback uses [MultiTapDispatcher] to route events.
mixin TapCallbacks on Component {
void onTapDown(TapDownEvent event) {}
void onLongTapDown(TapDownEvent event) {}
Expand All @@ -20,11 +22,6 @@ mixin TapCallbacks on Component {
@mustCallSuper
void onMount() {
super.onMount();
final game = findRootGame()!;
if (game.findByKey(const MultiTapDispatcherKey()) == null) {
final dispatcher = MultiTapDispatcher();
game.registerKey(const MultiTapDispatcherKey(), dispatcher);
game.add(dispatcher);
}
MultiTapDispatcher.addDispatcher(this);
}
}
23 changes: 23 additions & 0 deletions packages/flame/lib/src/events/flame_game_mixins/dispatcher.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:flame/components.dart';
import 'package:flame/src/game/flame_game.dart';

abstract class Dispatcher<G extends FlameGame> extends Component
with HasGameReference<G> {
static void addDispatcher<T extends Component>(
Component component,
ComponentKey key,
T Function() create,
) {
final game = component.findRootGame()!;
if (game.findByKey(key) != null) {
return;
}
final dispatcher = create();
game.registerKey(key, dispatcher);
game.add(dispatcher);
}

static void removeDispatcher(FlameGame game, ComponentKey key) {
game.unregisterKey(key);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flame/components.dart';
import 'package:flame/events.dart';
import 'package:flame/game.dart';
import 'package:flame/src/events/flame_game_mixins/dispatcher.dart';
import 'package:flutter/gestures.dart';

class DoubleTapDispatcherKey implements ComponentKey {
Expand All @@ -18,7 +19,7 @@ class DoubleTapDispatcherKey implements ComponentKey {
/// the component tree that is mixed with [DoubleTapCallbacks]. This will be
/// attached to the [FlameGame] instance automatically whenever any
/// [DoubleTapCallbacks] are mounted into the component tree.
class DoubleTapDispatcher extends Component with HasGameReference<FlameGame> {
class DoubleTapDispatcher extends Dispatcher<FlameGame> {
final _components = <DoubleTapCallbacks>{};

void _onDoubleTapDown(DoubleTapDownEvent event) {
Expand All @@ -44,9 +45,17 @@ class DoubleTapDispatcher extends Component with HasGameReference<FlameGame> {
_components.clear();
}

static void addDispatcher(Component component) {
Dispatcher.addDispatcher(
component,
const DoubleTapDispatcherKey(),
DoubleTapDispatcher.new,
);
}

@override
void onMount() {
game.gestureDetectors.add(
game.gestureDetectors.register<DoubleTapGestureRecognizer>(
DoubleTapGestureRecognizer.new,
(DoubleTapGestureRecognizer instance) {
instance.onDoubleTapDown = (details) =>
Expand All @@ -60,7 +69,7 @@ class DoubleTapDispatcher extends Component with HasGameReference<FlameGame> {

@override
void onRemove() {
game.gestureDetectors.remove<DoubleTapGestureRecognizer>();
game.unregisterKey(const DoubleTapDispatcherKey());
game.gestureDetectors.unregister<DoubleTapGestureRecognizer>();
Dispatcher.removeDispatcher(game, const DoubleTapDispatcherKey());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flame/components.dart';
import 'package:flame/src/events/component_mixins/long_press_callbacks.dart';
import 'package:flame/src/events/flame_game_mixins/dispatcher.dart';
import 'package:flame/src/events/messages/long_press_cancel_event.dart';
import 'package:flame/src/events/messages/long_press_end_event.dart';
import 'package:flame/src/events/messages/long_press_move_update_event.dart';
Expand All @@ -13,12 +14,10 @@ import 'package:meta/meta.dart';
/// that use the [LongPressCallbacks] mixin. It will be attached to the
/// [FlameGame] instance automatically whenever any [LongPressCallbacks]
/// components are mounted into the component tree.
class LongPressDispatcher extends Component {
class LongPressDispatcher extends Dispatcher<FlameGame> {
/// Records all components currently being long-pressed, keyed by pointerId.
final Set<TaggedComponent<LongPressCallbacks>> _records = {};

FlameGame get game => parent! as FlameGame;

/// Monotonically increasing id assigned to each new long press gesture.
int _nextPointerId = 0;

Expand Down Expand Up @@ -123,9 +122,17 @@ class LongPressDispatcher extends Component {

//#endregion

static void addDispatcher(Component component) {
Dispatcher.addDispatcher(
component,
const LongPressDispatcherKey(),
LongPressDispatcher.new,
);
}

@override
void onMount() {
game.gestureDetectors.add<LongPressGestureRecognizer>(
game.gestureDetectors.register<LongPressGestureRecognizer>(
LongPressGestureRecognizer.new,
(LongPressGestureRecognizer instance) {
instance
Expand All @@ -140,9 +147,8 @@ class LongPressDispatcher extends Component {

@override
void onRemove() {
game.gestureDetectors.remove<LongPressGestureRecognizer>();
game.unregisterKey(const LongPressDispatcherKey());
super.onRemove();
game.gestureDetectors.unregister<LongPressGestureRecognizer>();
Dispatcher.removeDispatcher(game, const LongPressDispatcherKey());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flame/components.dart';
import 'package:flame/events.dart';
import 'package:flame/src/events/flame_drag_adapter.dart';
import 'package:flame/src/events/flame_game_mixins/dispatcher.dart';
import 'package:flame/src/events/tagged_component.dart';
import 'package:flame/src/game/flame_game.dart';
import 'package:flame/src/game/game_render_box.dart';
Expand All @@ -24,7 +25,8 @@ class MultiDragDispatcherKey implements ComponentKey {
/// [DragCallbacks] components in the component tree. It will be attached to
/// the [FlameGame] instance automatically whenever any [DragCallbacks]
/// components are mounted into the component tree.
class MultiDragDispatcher extends Component implements MultiDragListener {
class MultiDragDispatcher extends Dispatcher<FlameGame>
implements MultiDragListener {
/// The record of all components currently being touched.
final Set<TaggedComponent<DragCallbacks>> _records = {};

Expand Down Expand Up @@ -52,8 +54,6 @@ class MultiDragDispatcher extends Component implements MultiDragListener {

Stream<DragCancelEvent> get onCancel => _dragCancelController.stream;

FlameGame get game => parent! as FlameGame;

/// Called when the user initiates a drag gesture, for example by touching the
/// screen and then moving the finger.
///
Expand Down Expand Up @@ -186,9 +186,17 @@ class MultiDragDispatcher extends Component implements MultiDragListener {

//#endregion

static void addDispatcher(Component component) {
Dispatcher.addDispatcher(
component,
const MultiDragDispatcherKey(),
MultiDragDispatcher.new,
);
}

@override
void onMount() {
game.gestureDetectors.add<ImmediateMultiDragGestureRecognizer>(
game.gestureDetectors.register<ImmediateMultiDragGestureRecognizer>(
ImmediateMultiDragGestureRecognizer.new,
(ImmediateMultiDragGestureRecognizer instance) {
instance.onStart = (Offset point) => FlameDragAdapter(this, point);
Expand All @@ -198,8 +206,8 @@ class MultiDragDispatcher extends Component implements MultiDragListener {

@override
void onRemove() {
game.gestureDetectors.remove<ImmediateMultiDragGestureRecognizer>();
game.unregisterKey(const MultiDragDispatcherKey());
game.gestureDetectors.unregister<ImmediateMultiDragGestureRecognizer>();
Dispatcher.removeDispatcher(game, const MultiDragDispatcherKey());
_dragUpdateController.close();
_dragCancelController.close();
_dragStartController.close();
Expand Down
Loading
Loading