From cf92856dc1ba7ae3c34e2b3019ce83c13d0f3421 Mon Sep 17 00:00:00 2001 From: Erick Date: Thu, 24 Mar 2022 14:36:57 -0300 Subject: [PATCH] feat: implementing composable blueprints (#92) * feat: implementing composable blueprints * fix: coverage --- lib/flame/blueprint.dart | 22 +++++++++++++++++- test/flame/blueprint_test.dart | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/flame/blueprint.dart b/lib/flame/blueprint.dart index d536d650..57af7d6d 100644 --- a/lib/flame/blueprint.dart +++ b/lib/flame/blueprint.dart @@ -14,6 +14,8 @@ const _attachedErrorMessage = "Can't add to attached Blueprints"; /// the [FlameGame] level. abstract class Blueprint { final List _components = []; + final List _blueprints = []; + bool _isAttached = false; /// Called before the the [Component]s managed @@ -25,7 +27,10 @@ abstract class Blueprint { @mustCallSuper Future attach(T game) async { build(game); - await game.addAll(_components); + await Future.wait([ + game.addAll(_components), + ..._blueprints.map(game.addFromBlueprint).toList(), + ]); _isAttached = true; } @@ -41,8 +46,23 @@ abstract class Blueprint { _components.add(component); } + /// Adds a list of [Blueprint]s to this blueprint. + void addAllBlueprints(List blueprints) { + assert(!_isAttached, _attachedErrorMessage); + _blueprints.addAll(blueprints); + } + + /// Adds a single [Blueprint] to this blueprint. + void addBlueprint(Blueprint blueprint) { + assert(!_isAttached, _attachedErrorMessage); + _blueprints.add(blueprint); + } + /// Returns a copy of the components built by this blueprint List get components => List.unmodifiable(_components); + + /// Returns a copy of the children blueprints + List get blueprints => List.unmodifiable(_blueprints); } /// A [Blueprint] that provides additional diff --git a/test/flame/blueprint_test.dart b/test/flame/blueprint_test.dart index 3a9f5ed3..e5fc2c4f 100644 --- a/test/flame/blueprint_test.dart +++ b/test/flame/blueprint_test.dart @@ -14,6 +14,28 @@ class MyBlueprint extends Blueprint { } } +class MyOtherBlueprint extends Blueprint { + @override + void build(_) { + add(Component()); + } +} + +class YetMyOtherBlueprint extends Blueprint { + @override + void build(_) { + add(Component()); + } +} + +class MyComposedBlueprint extends Blueprint { + @override + void build(_) { + addBlueprint(MyBlueprint()); + addAllBlueprints([MyOtherBlueprint(), YetMyOtherBlueprint()]); + } +} + class MyForge2dBlueprint extends Forge2DBlueprint { @override void build(_) { @@ -24,12 +46,23 @@ class MyForge2dBlueprint extends Forge2DBlueprint { void main() { group('Blueprint', () { + setUpAll(() { + registerFallbackValue(MyBlueprint()); + registerFallbackValue(Component()); + }); + test('components can be added to it', () { final blueprint = MyBlueprint()..build(MockPinballGame()); expect(blueprint.components.length, equals(3)); }); + test('blueprints can be added to it', () { + final blueprint = MyComposedBlueprint()..build(MockPinballGame()); + + expect(blueprint.blueprints.length, equals(3)); + }); + test('adds the components to a game on attach', () { final mockGame = MockPinballGame(); when(() => mockGame.addAll(any())).thenAnswer((_) async {}); @@ -38,6 +71,14 @@ void main() { verify(() => mockGame.addAll(any())).called(1); }); + test('adds components from a child Blueprint the to a game on attach', () { + final mockGame = MockPinballGame(); + when(() => mockGame.addAll(any())).thenAnswer((_) async {}); + MyComposedBlueprint().attach(mockGame); + + verify(() => mockGame.addAll(any())).called(4); + }); + test( 'throws assertion error when adding to an already attached blueprint', () async {