Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Use ComponentKeys to keep track of dispatchers #2629

Merged
merged 6 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -30,8 +30,10 @@ mixin DoubleTapCallbacks on Component {
void onMount() {
super.onMount();
final game = findGame()! as FlameGame;
if (game.firstChild<DoubleTapDispatcher>() == null) {
game.add(DoubleTapDispatcher());
if (game.findByKey(const DoubleTapDispatcherKey()) == null) {
final dispatcher = DoubleTapDispatcher();
game.registerKey(const DoubleTapDispatcherKey(), dispatcher);
game.add(dispatcher);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ mixin DragCallbacks on Component {
void onMount() {
super.onMount();
final game = findGame()! as FlameGame;
if (game.firstChild<MultiDragDispatcher>() == null) {
game.add(MultiDragDispatcher());
if (game.findByKey(const MultiDragDispatcherKey()) == null) {
final dispatcher = MultiDragDispatcher();
game.registerKey(const MultiDragDispatcherKey(), dispatcher);
game.add(dispatcher);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ mixin TapCallbacks on Component {
void onMount() {
super.onMount();
final game = findGame()! as FlameGame;
if (game.firstChild<MultiTapDispatcher>() == null) {
game.add(MultiTapDispatcher());
if (game.findByKey(const MultiTapDispatcherKey()) == null) {
final dispatcher = MultiTapDispatcher();
game.registerKey(const MultiTapDispatcherKey(), dispatcher);
game.add(dispatcher);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,25 @@ import 'package:flame/src/events/messages/double_tap_event.dart';
import 'package:flutter/gestures.dart';
import 'package:meta/meta.dart';

@internal
class DoubleTapDispatcherKey implements ComponentKey {
const DoubleTapDispatcherKey();

@override
int get hashCode => 20260645; // 'DoubleTapDispatcherKey' as hashCode

@override
bool operator ==(dynamic other) =>
other is DoubleTapDispatcherKey && other.hashCode == hashCode;
}

/// [DoubleTapDispatcher] propagates double-tap events to every components in
/// 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.
@internal
class DoubleTapDispatcher extends Component with HasGameRef<FlameGame> {
final _components = <DoubleTapCallbacks>{};
bool _eventHandlerRegistered = false;

void _onDoubleTapDown(DoubleTapDownEvent event) {
event.deliverAtPoint(
Expand All @@ -37,30 +48,21 @@ class DoubleTapDispatcher extends Component with HasGameRef<FlameGame> {

@override
void onMount() {
if (game.firstChild<DoubleTapDispatcher>() == null) {
game.gestureDetectors.add(
DoubleTapGestureRecognizer.new,
(DoubleTapGestureRecognizer instance) {
instance.onDoubleTapDown =
(details) => _onDoubleTapDown(DoubleTapDownEvent(game, details));
instance.onDoubleTapCancel =
() => _onDoubleTapCancel(DoubleTapCancelEvent());
instance.onDoubleTap = () => _onDoubleTapUp(DoubleTapEvent());
},
);
_eventHandlerRegistered = true;
} else {
removeFromParent();
}
game.gestureDetectors.add(
DoubleTapGestureRecognizer.new,
(DoubleTapGestureRecognizer instance) {
instance.onDoubleTapDown =
(details) => _onDoubleTapDown(DoubleTapDownEvent(game, details));
instance.onDoubleTapCancel =
() => _onDoubleTapCancel(DoubleTapCancelEvent());
instance.onDoubleTap = () => _onDoubleTapUp(DoubleTapEvent());
},
);
}

@override
void onRemove() {
if (!_eventHandlerRegistered) {
return;
}

game.gestureDetectors.remove<DoubleTapGestureRecognizer>();
_eventHandlerRegistered = false;
game.unregisterKey(const DoubleTapDispatcherKey());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flame/src/components/core/component.dart';
import 'package:flame/src/components/core/component_key.dart';
import 'package:flame/src/components/mixins/draggable.dart';
import 'package:flame/src/events/component_mixins/drag_callbacks.dart';
import 'package:flame/src/events/flame_drag_adapter.dart';
Expand All @@ -14,6 +15,18 @@ import 'package:flame/src/game/game_render_box.dart';
import 'package:flutter/gestures.dart';
import 'package:meta/meta.dart';

@internal
class MultiDragDispatcherKey implements ComponentKey {
const MultiDragDispatcherKey();

@override
int get hashCode => 91604879; // 'MultiDragDispatcherKey' as hashCode

@override
bool operator ==(dynamic other) =>
other is MultiDragDispatcherKey && other.hashCode == hashCode;
}

/// **MultiDragDispatcher** facilitates dispatching of drag events to the
/// [DragCallbacks] components in the component tree. It will be attached to
/// the [FlameGame] instance automatically whenever any [DragCallbacks]
Expand All @@ -22,7 +35,6 @@ import 'package:meta/meta.dart';
class MultiDragDispatcher extends Component implements MultiDragListener {
/// The record of all components currently being touched.
final Set<TaggedComponent<DragCallbacks>> _records = {};
bool _eventHandlerRegistered = false;

FlameGame get game => parent! as FlameGame;

Expand Down Expand Up @@ -165,26 +177,18 @@ class MultiDragDispatcher extends Component implements MultiDragListener {

@override
void onMount() {
if (game.firstChild<MultiDragDispatcher>() == null) {
game.gestureDetectors.add<ImmediateMultiDragGestureRecognizer>(
ImmediateMultiDragGestureRecognizer.new,
(ImmediateMultiDragGestureRecognizer instance) {
instance.onStart = (Offset point) => FlameDragAdapter(this, point);
},
);
_eventHandlerRegistered = true;
} else {
// Ensures that only one MultiDragDispatcher is attached to the Game.
removeFromParent();
}
game.gestureDetectors.add<ImmediateMultiDragGestureRecognizer>(
ImmediateMultiDragGestureRecognizer.new,
(ImmediateMultiDragGestureRecognizer instance) {
instance.onStart = (Offset point) => FlameDragAdapter(this, point);
},
);
}

@override
void onRemove() {
if (_eventHandlerRegistered) {
game.gestureDetectors.remove<ImmediateMultiDragGestureRecognizer>();
_eventHandlerRegistered = false;
}
game.gestureDetectors.remove<ImmediateMultiDragGestureRecognizer>();
game.unregisterKey(const MultiDragDispatcherKey());
}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,22 @@ import 'package:flame/src/game/game_render_box.dart';
import 'package:flutter/gestures.dart';
import 'package:meta/meta.dart';

@internal
class MultiTapDispatcherKey implements ComponentKey {
const MultiTapDispatcherKey();

@override
int get hashCode => 401913931; // 'MultiTapDispatcherKey' as hashCode

@override
bool operator ==(dynamic other) =>
other is MultiTapDispatcherKey && other.hashCode == hashCode;
}

@internal
class MultiTapDispatcher extends Component implements MultiTapListener {
/// The record of all components currently being touched.
final Set<TaggedComponent<TapCallbacks>> _record = {};
bool _eventHandlerRegistered = false;

FlameGame get game => parent! as FlameGame;

Expand Down Expand Up @@ -179,33 +190,25 @@ class MultiTapDispatcher extends Component implements MultiTapListener {

@override
void onMount() {
if (game.firstChild<MultiTapDispatcher>() == null) {
game.gestureDetectors.add<MultiTapGestureRecognizer>(
MultiTapGestureRecognizer.new,
(MultiTapGestureRecognizer instance) {
instance.longTapDelay = Duration(
milliseconds: (longTapDelay * 1000).toInt(),
);
instance.onTap = handleTap;
instance.onTapDown = handleTapDown;
instance.onTapUp = handleTapUp;
instance.onTapCancel = handleTapCancel;
instance.onLongTapDown = handleLongTapDown;
},
);
_eventHandlerRegistered = true;
} else {
// Ensures that only one MultiTapDispatcher is attached to the Game.
removeFromParent();
}
game.gestureDetectors.add<MultiTapGestureRecognizer>(
MultiTapGestureRecognizer.new,
(MultiTapGestureRecognizer instance) {
instance.longTapDelay = Duration(
milliseconds: (longTapDelay * 1000).toInt(),
);
instance.onTap = handleTap;
instance.onTapDown = handleTapDown;
instance.onTapUp = handleTapUp;
instance.onTapCancel = handleTapCancel;
instance.onLongTapDown = handleLongTapDown;
},
);
}

@override
void onRemove() {
if (_eventHandlerRegistered) {
game.gestureDetectors.remove<MultiTapGestureRecognizer>();
_eventHandlerRegistered = false;
}
game.gestureDetectors.remove<MultiTapGestureRecognizer>();
game.unregisterKey(const MultiTapDispatcherKey());
}

@override
Expand Down