diff --git a/packages/flame/lib/src/components/core/component.dart b/packages/flame/lib/src/components/core/component.dart index dde857a500..52515535d5 100644 --- a/packages/flame/lib/src/components/core/component.dart +++ b/packages/flame/lib/src/components/core/component.dart @@ -381,6 +381,8 @@ class Component { @internal static Game? staticGameInstance; + + /// Fetches the nearest [FlameGame] ancestor to the component. FlameGame? findGame() { assert( staticGameInstance is FlameGame || staticGameInstance == null, @@ -393,6 +395,15 @@ class Component { ((this is FlameGame) ? (this as FlameGame) : _parent?.findGame()); } + /// Fetches the root [FlameGame] ancestor to the component. + FlameGame? findRootGame() { + var game = findGame(); + while (game?.parent != null) { + game = game!.parent!.findGame(); + } + return game; + } + /// Whether the children list contains the given component. /// /// This method uses reference equality. diff --git a/packages/flame/lib/src/events/component_mixins/double_tap_callbacks.dart b/packages/flame/lib/src/events/component_mixins/double_tap_callbacks.dart index 30bab8694c..b427d3b0d4 100644 --- a/packages/flame/lib/src/events/component_mixins/double_tap_callbacks.dart +++ b/packages/flame/lib/src/events/component_mixins/double_tap_callbacks.dart @@ -28,7 +28,7 @@ mixin DoubleTapCallbacks on Component { @override void onMount() { super.onMount(); - final game = findGame()!; + final game = findRootGame()!; if (game.findByKey(const DoubleTapDispatcherKey()) == null) { final dispatcher = DoubleTapDispatcher(); game.registerKey(const DoubleTapDispatcherKey(), dispatcher); diff --git a/packages/flame/lib/src/events/component_mixins/drag_callbacks.dart b/packages/flame/lib/src/events/component_mixins/drag_callbacks.dart index 0660000c74..3e482b4f28 100644 --- a/packages/flame/lib/src/events/component_mixins/drag_callbacks.dart +++ b/packages/flame/lib/src/events/component_mixins/drag_callbacks.dart @@ -65,7 +65,7 @@ mixin DragCallbacks on Component { @mustCallSuper void onMount() { super.onMount(); - final game = findGame()!; + final game = findRootGame()!; if (game.findByKey(const MultiDragDispatcherKey()) == null) { final dispatcher = MultiDragDispatcher(); game.registerKey(const MultiDragDispatcherKey(), dispatcher); diff --git a/packages/flame/lib/src/events/component_mixins/pointer_move_callbacks.dart b/packages/flame/lib/src/events/component_mixins/pointer_move_callbacks.dart index 03847d57a9..e72a14dfb4 100644 --- a/packages/flame/lib/src/events/component_mixins/pointer_move_callbacks.dart +++ b/packages/flame/lib/src/events/component_mixins/pointer_move_callbacks.dart @@ -18,7 +18,7 @@ mixin PointerMoveCallbacks on Component { } static void onMountHandler(PointerMoveCallbacks instance) { - final game = instance.findGame()!; + final game = instance.findRootGame()!; const key = MouseMoveDispatcherKey(); if (game.findByKey(key) == null) { final dispatcher = PointerMoveDispatcher(); diff --git a/packages/flame/lib/src/events/component_mixins/tap_callbacks.dart b/packages/flame/lib/src/events/component_mixins/tap_callbacks.dart index e4250ff5c8..3b4b6fcff8 100644 --- a/packages/flame/lib/src/events/component_mixins/tap_callbacks.dart +++ b/packages/flame/lib/src/events/component_mixins/tap_callbacks.dart @@ -22,7 +22,7 @@ mixin TapCallbacks on Component { @mustCallSuper void onMount() { super.onMount(); - final game = findGame()!; + final game = findRootGame()!; if (game.findByKey(const MultiTapDispatcherKey()) == null) { final dispatcher = MultiTapDispatcher(); game.registerKey(const MultiTapDispatcherKey(), dispatcher); diff --git a/packages/flame/test/components/component_test.dart b/packages/flame/test/components/component_test.dart index 293072e112..a0897861fa 100644 --- a/packages/flame/test/components/component_test.dart +++ b/packages/flame/test/components/component_test.dart @@ -1121,6 +1121,28 @@ void main() { }); }); + group('findRootGame()', () { + testWithFlameGame('finds root game in nested game structure', + (game) async { + final component = Component(); + await game.ensureAdd( + FlameGame( + children: [ + Component(children: [component]), + ], + ), + ); + expect(component.findRootGame(), game); + }); + + testWithFlameGame('finds root game in non-nested game structure', + (game) async { + final component = Component(); + await game.ensureAdd(component); + expect(component.findRootGame(), game); + }); + }); + group('miscellaneous', () { testWithFlameGame('childrenFactory', (game) async { final component0 = Component();