Improvements on the overlay API (#592)

* Adding game to overlaybuilder and visible overlays

* Fixing things

* Format

* Adding Renan's suggestions

* Removing wrongly commited integration test files

* Fixing active overlay when it is null

* Update CHANGELOG.md

Co-authored-by: Jochum van der Ploeg <jochum@vdploeg.net>

* Adding some more changes from suggestions

* Removing unnecessary elvis operator

Co-authored-by: Jochum van der Ploeg <jochum@vdploeg.net>
This commit is contained in:
Erick
2020-12-30 16:37:41 -03:00
committed by GitHub
parent 3bd75c8599
commit 089438c6c8
5 changed files with 56 additions and 22 deletions

View File

@ -1,6 +1,8 @@
# CHANGELOG # CHANGELOG
## [next] ## [next]
- Option for overlays to be already visible on the GameWidget
- Adding game to the overlay builder
- Rename retreive -> Retrieve - Rename retreive -> Retrieve
- Use internal children set in BaseComponent (fixes issue adding multiple children) - Use internal children set in BaseComponent (fixes issue adding multiple children)
- Remove develop branches from github workflow definition - Remove develop branches from github workflow definition

View File

@ -5,8 +5,6 @@ import 'package:flame/palette.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class ExampleGame extends Game with TapDetector { class ExampleGame extends Game with TapDetector {
bool isPaused = false;
@override @override
void update(double dt) {} void update(double dt) {}
@ -25,14 +23,10 @@ class ExampleGame extends Game with TapDetector {
@override @override
void onTap() { void onTap() {
if (isPaused) { if (overlays.isActive('PauseMenu')) {
overlays.remove('PauseMenu'); overlays.remove('PauseMenu');
isPaused = false;
} else { } else {
overlays.add( overlays.add('PauseMenu');
'PauseMenu',
);
isPaused = true;
} }
} }
} }

View File

@ -26,7 +26,7 @@ class MyHomePage extends StatefulWidget {
class _MyHomePageState extends State<MyHomePage> { class _MyHomePageState extends State<MyHomePage> {
ExampleGame _myGame; ExampleGame _myGame;
Widget pauseMenuBuilder(BuildContext buildContext) { Widget pauseMenuBuilder(BuildContext buildContext, ExampleGame game) {
return Center( return Center(
child: Container( child: Container(
width: 100, width: 100,
@ -52,6 +52,7 @@ class _MyHomePageState extends State<MyHomePage> {
overlayBuilderMap: { overlayBuilderMap: {
"PauseMenu": pauseMenuBuilder, "PauseMenu": pauseMenuBuilder,
}, },
initialActiveOverlays: const ['PauseMenu'],
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: () => newGame(), onPressed: () => newGame(),

View File

@ -191,4 +191,7 @@ class ActiveOverlaysNotifier extends ChangeNotifier {
/// A [Set] of the active overlay names. /// A [Set] of the active overlay names.
Set<String> get value => _activeOverlays; Set<String> get value => _activeOverlays;
/// Returns if the given [overlayName] is active
bool isActive(String overlayName) => _activeOverlays.contains(overlayName);
} }

View File

@ -14,6 +14,11 @@ typedef GameLoadingWidgetBuilder = Widget Function(
bool error, bool error,
); );
typedef OverlayWidgetBuilder<T extends Game> = Widget Function(
BuildContext context,
T game,
);
/// A [StatefulWidget] that is in charge of attaching a [Game] instance into the flutter tree /// A [StatefulWidget] that is in charge of attaching a [Game] instance into the flutter tree
/// ///
class GameWidget<T extends Game> extends StatefulWidget { class GameWidget<T extends Game> extends StatefulWidget {
@ -36,7 +41,15 @@ class GameWidget<T extends Game> extends StatefulWidget {
/// See also: /// See also:
/// - [new GameWidget] /// - [new GameWidget]
/// - [Game.overlays] /// - [Game.overlays]
final Map<String, WidgetBuilder> overlayBuilderMap; final Map<String, OverlayWidgetBuilder<T>> overlayBuilderMap;
/// A List of the initially active overlays, this is used only on the first build of the widget.
/// To control the overlays that are active use [Game.overlays]
///
/// See also:
/// - [new GameWidget]
/// - [Game.overlays]
final List<String> initialActiveOverlays;
/// Renders a [game] in a flutter widget tree. /// Renders a [game] in a flutter widget tree.
/// ///
@ -82,6 +95,7 @@ class GameWidget<T extends Game> extends StatefulWidget {
this.loadingBuilder, this.loadingBuilder,
this.backgroundBuilder, this.backgroundBuilder,
this.overlayBuilderMap, this.overlayBuilderMap,
this.initialActiveOverlays,
}) : super(key: key); }) : super(key: key);
/// Renders a [game] in a flutter widget tree alongside widgets overlays. /// Renders a [game] in a flutter widget tree alongside widgets overlays.
@ -89,11 +103,11 @@ class GameWidget<T extends Game> extends StatefulWidget {
/// To use overlays, the game subclass has to be mixed with [HasWidgetsOverlay], /// To use overlays, the game subclass has to be mixed with [HasWidgetsOverlay],
@override @override
_GameWidgetState createState() => _GameWidgetState(); _GameWidgetState<T> createState() => _GameWidgetState<T>();
} }
class _GameWidgetState extends State<GameWidget> { class _GameWidgetState<T extends Game> extends State<GameWidget<T>> {
Set<String> activeOverlays = {}; Set<String> initialActiveOverlays;
Future<void> _gameLoaderFuture; Future<void> _gameLoaderFuture;
Future<void> get _gameLoaderFutureCache => Future<void> get _gameLoaderFutureCache =>
@ -102,14 +116,30 @@ class _GameWidgetState extends State<GameWidget> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Add the initial overlays
_initActiveOverlays();
addOverlaysListener(widget.game); addOverlaysListener(widget.game);
} }
void _initActiveOverlays() {
if (widget.initialActiveOverlays != null) {
_checkOverlays(widget.initialActiveOverlays.toSet());
widget.initialActiveOverlays.forEach((key) {
widget.game.overlays.add(key);
});
}
}
@override @override
void didUpdateWidget(covariant GameWidget<Game> oldWidget) { void didUpdateWidget(GameWidget<T> oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (oldWidget.game != widget.game) { if (oldWidget.game != widget.game) {
removeOverlaysListener(oldWidget.game); removeOverlaysListener(oldWidget.game);
// Reset the overlays
_initActiveOverlays();
addOverlaysListener(widget.game); addOverlaysListener(widget.game);
// Reset the loader future // Reset the loader future
@ -124,22 +154,26 @@ class _GameWidgetState extends State<GameWidget> {
} }
// widget overlay stuff // widget overlay stuff
void addOverlaysListener(Game game) { void addOverlaysListener(T game) {
widget.game.overlays.addListener(onChangeActiveOverlays); widget.game.overlays.addListener(onChangeActiveOverlays);
activeOverlays = widget.game.overlays.value; initialActiveOverlays = widget.game.overlays.value;
} }
void removeOverlaysListener(Game game) { void removeOverlaysListener(T game) {
game.overlays.removeListener(onChangeActiveOverlays); game.overlays.removeListener(onChangeActiveOverlays);
} }
void onChangeActiveOverlays() { void _checkOverlays(Set<String> overlays) {
widget.game.overlays.value.forEach((overlayKey) { overlays.forEach((overlayKey) {
assert(widget.overlayBuilderMap.containsKey(overlayKey), assert(widget.overlayBuilderMap.containsKey(overlayKey),
"A non mapped overlay has been added: $overlayKey"); "A non mapped overlay has been added: $overlayKey");
}); });
}
void onChangeActiveOverlays() {
_checkOverlays(widget.game.overlays.value);
setState(() { setState(() {
activeOverlays = widget.game.overlays.value; initialActiveOverlays = widget.game.overlays.value;
}); });
} }
@ -224,11 +258,11 @@ class _GameWidgetState extends State<GameWidget> {
if (widget.overlayBuilderMap == null) { if (widget.overlayBuilderMap == null) {
return stackWidgets; return stackWidgets;
} }
final widgets = activeOverlays.map((String overlayKey) { final widgets = initialActiveOverlays.map((String overlayKey) {
final builder = widget.overlayBuilderMap[overlayKey]; final builder = widget.overlayBuilderMap[overlayKey];
return KeyedSubtree( return KeyedSubtree(
key: ValueKey(overlayKey), key: ValueKey(overlayKey),
child: builder(context), child: builder(context, widget.game),
); );
}); });
stackWidgets.addAll(widgets); stackWidgets.addAll(widgets);