-
-
Notifications
You must be signed in to change notification settings - Fork 899
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Initial functionality of flame_devtools (#3061)
![image](https://github.com/flame-engine/flame/assets/744771/4ca93f5f-369e-4644-b7fb-1d7790b962e2) This adds a structure and some basic functionality for the Flame devtools extension. Later I will add a pre/post-hook for publishing to Melos so that it can build the devtools extension before publishing (and remove the directory afterwards), since it isn't committed to this repository. For now one has to run `melos devtools-build` before publishing. --------- Co-authored-by: Renan <6718144+renancaraujo@users.noreply.github.com> Co-authored-by: Erick <erickzanardoo@gmail.com>
- Loading branch information
1 parent
30fde80
commit c92910c
Showing
22 changed files
with
677 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
extensions: | ||
- flame: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
name: flame | ||
issueTracker: https://github.com/flame-engine/flame/issues | ||
version: 0.1.0 | ||
materialIconCodePoint: '0xe392' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
packages/flame/lib/src/devtools/connectors/component_count_connector.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import 'dart:convert'; | ||
import 'dart:developer'; | ||
|
||
import 'package:flame/src/devtools/dev_tools_connector.dart'; | ||
|
||
/// The [ComponentCountConnector] is responsible for reporting the component | ||
/// count of the game to the devtools extension. | ||
class ComponentCountConnector extends DevToolsConnector { | ||
@override | ||
void init() { | ||
// Get the amount of components in the tree. | ||
registerExtension( | ||
'ext.flame_devtools.getComponentCount', | ||
(method, parameters) async { | ||
var componentCount = 0; | ||
game.propagateToChildren((_) { | ||
componentCount++; | ||
return true; | ||
}); | ||
|
||
return ServiceExtensionResponse.result( | ||
json.encode({ | ||
'component_count': componentCount, | ||
}), | ||
); | ||
}, | ||
); | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import 'dart:convert'; | ||
import 'dart:developer'; | ||
|
||
import 'package:flame/components.dart'; | ||
import 'package:flame/game.dart'; | ||
import 'package:flame/src/devtools/dev_tools_connector.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
|
||
/// The [DebugModeConnector] is responsible for reporting and setting the | ||
/// `debugMode` of the game from the devtools extension. | ||
class DebugModeConnector extends DevToolsConnector { | ||
var _debugModeNotifier = ValueNotifier<bool>(false); | ||
|
||
@override | ||
void init() { | ||
// Get the current `debugMode`. | ||
registerExtension( | ||
'ext.flame_devtools.getDebugMode', | ||
(method, parameters) async { | ||
return ServiceExtensionResponse.result( | ||
json.encode({ | ||
'debug_mode': _debugModeNotifier.value, | ||
}), | ||
); | ||
}, | ||
); | ||
|
||
// Set the `debugMode` for all components in the tree. | ||
registerExtension( | ||
'ext.flame_devtools.setDebugMode', | ||
(method, parameters) async { | ||
final debugMode = bool.parse(parameters['debug_mode'] ?? 'false'); | ||
_debugModeNotifier.value = debugMode; | ||
return ServiceExtensionResponse.result( | ||
json.encode({ | ||
'debug_mode': debugMode, | ||
}), | ||
); | ||
}, | ||
); | ||
} | ||
|
||
@override | ||
void initGame(FlameGame game) { | ||
super.initGame(game); | ||
_debugModeNotifier = ValueNotifier<bool>(game.debugMode); | ||
_debugModeNotifier.addListener(() { | ||
final newDebugMode = _debugModeNotifier.value; | ||
game.propagateToChildren<Component>( | ||
(c) { | ||
c.debugMode = newDebugMode; | ||
return true; | ||
}, | ||
includeSelf: true, | ||
); | ||
}); | ||
} | ||
|
||
@override | ||
void disposeGame() { | ||
_debugModeNotifier.dispose(); | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
packages/flame/lib/src/devtools/connectors/game_loop_connector.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import 'dart:convert'; | ||
import 'dart:developer'; | ||
|
||
import 'package:flame/game.dart'; | ||
import 'package:flame/src/devtools/dev_tools_connector.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
|
||
/// The [GameLoopConnector] is responsible for reporting and setting the | ||
/// pause/running state of the game and stepping the game forwards or backwards | ||
/// from the devtools extension. | ||
class GameLoopConnector extends DevToolsConnector { | ||
var _pauseNotifier = ValueNotifier<bool>(true); | ||
|
||
@override | ||
void init() { | ||
// Get the current `debugMode`. | ||
registerExtension( | ||
'ext.flame_devtools.getPaused', | ||
(method, parameters) async { | ||
return ServiceExtensionResponse.result( | ||
json.encode({ | ||
'paused': _pauseNotifier.value, | ||
}), | ||
); | ||
}, | ||
); | ||
|
||
// Set whether the game should be paused or not. | ||
registerExtension( | ||
'ext.flame_devtools.setPaused', | ||
(method, parameters) async { | ||
final shouldPause = bool.parse(parameters['paused'] ?? 'false'); | ||
_pauseNotifier.value = shouldPause; | ||
return ServiceExtensionResponse.result( | ||
json.encode({ | ||
'paused': shouldPause, | ||
}), | ||
); | ||
}, | ||
); | ||
|
||
// Set whether the game should be paused or not. | ||
registerExtension( | ||
'ext.flame_devtools.step', | ||
(method, parameters) async { | ||
final stepTime = double.parse(parameters['step_time'] ?? '0'); | ||
game.stepEngine(stepTime: stepTime); | ||
return ServiceExtensionResponse.result( | ||
json.encode({ | ||
'step_time': stepTime, | ||
}), | ||
); | ||
}, | ||
); | ||
} | ||
|
||
@override | ||
void initGame(FlameGame game) { | ||
super.initGame(game); | ||
_pauseNotifier = ValueNotifier<bool>(game.paused); | ||
_pauseNotifier.addListener(() { | ||
final newPaused = _pauseNotifier.value; | ||
if (newPaused) { | ||
game.pauseEngine(); | ||
} else { | ||
game.resumeEngine(); | ||
} | ||
}); | ||
} | ||
|
||
@override | ||
void disposeGame() { | ||
_pauseNotifier.dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import 'dart:developer'; | ||
|
||
import 'package:flame/debug.dart'; | ||
import 'package:flame/game.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
|
||
/// When a [DevToolsConnector] is initialized by the [DevToolsService] it will | ||
/// call the [init] method the first time, where you should will register | ||
/// service extensions which makes it possible for the devtools extension to | ||
/// communicate with your interface. Then the [initGame] method will be called | ||
/// every time a new game is set in the service. | ||
abstract class DevToolsConnector { | ||
DevToolsConnector() { | ||
init(); | ||
} | ||
|
||
late FlameGame game; | ||
|
||
/// In this method, you should register service extensions using | ||
/// [registerExtension] from dart:developer | ||
/// (see https://api.flutter.dev/flutter/dart-developer/registerExtension.html). | ||
void init(); | ||
|
||
@mustCallSuper | ||
// ignore: use_setters_to_change_properties | ||
void initGame(FlameGame game) { | ||
this.game = game; | ||
} | ||
|
||
/// Here you can do clean-up before a new game is set in the connector. | ||
void disposeGame() {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import 'package:flame/game.dart'; | ||
import 'package:flame/src/devtools/connectors/component_count_connector.dart'; | ||
import 'package:flame/src/devtools/connectors/debug_mode_connector.dart'; | ||
import 'package:flame/src/devtools/connectors/game_loop_connector.dart'; | ||
import 'package:flame/src/devtools/dev_tools_connector.dart'; | ||
|
||
/// When [DevToolsService] is initialized by the [FlameGame] it will call | ||
/// the `init` method for all [DevToolsConnector]s so that they can register | ||
/// service extensions which are the ones that makes it possible for the | ||
/// devtools extension to communicate with the game. | ||
/// | ||
/// Do note that if you have multiple games in your app, only the last one | ||
/// created will be connected to the devtools. If you want to change it to | ||
/// another game instance you can call [DevToolsService.initWithGame] with | ||
/// the game instance that you want to observe. | ||
class DevToolsService { | ||
DevToolsService._(); | ||
|
||
static final instance = DevToolsService._(); | ||
|
||
/// Initializes the service with the given game instance. | ||
factory DevToolsService.initWithGame(FlameGame game) { | ||
instance.initGame(game); | ||
return instance; | ||
} | ||
|
||
FlameGame? _game; | ||
FlameGame get game => _game!; | ||
|
||
/// The list of available connectors, remember to add your connector here if | ||
/// you create a new one. | ||
final connectors = [ | ||
DebugModeConnector(), | ||
ComponentCountConnector(), | ||
GameLoopConnector(), | ||
]; | ||
|
||
/// This method is called every time a new game is set in the service and it | ||
/// is responsible for calling the [DevToolsConnector.initGame] method in all | ||
/// the connectors. It is also responsible for calling | ||
/// [DevToolsConnector.disposeGame] of all connectors when a new game is set, | ||
/// if there was a game set previously. | ||
void initGame(FlameGame game) { | ||
if (_game != null) { | ||
for (final connector in connectors) { | ||
connector.disposeGame(); | ||
} | ||
} | ||
|
||
_game = game; | ||
for (final connector in connectors) { | ||
connector.initGame(game); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# This file tracks properties of this Flutter project. | ||
# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
# | ||
# This file should be version controlled and should not be manually edited. | ||
|
||
version: | ||
revision: "78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9" | ||
channel: "stable" | ||
|
||
project_type: app | ||
|
||
# Tracks metadata for the flutter migrate command | ||
migration: | ||
platforms: | ||
- platform: root | ||
create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9 | ||
base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9 | ||
- platform: web | ||
create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9 | ||
base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9 | ||
|
||
# User provided section | ||
|
||
# List of Local paths (relative to this file) that should be | ||
# ignored by the migrate tool. | ||
# | ||
# Files that are not part of the templates will be ignored by default. | ||
unmanaged_files: | ||
- 'lib/main.dart' | ||
- 'ios/Runner.xcodeproj/project.pbxproj' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# flame_devtools | ||
|
||
A DevTools extension for Flame games. To use it you just have to run your | ||
Flame game in debug mode and open the DevTools in your browser, and it should | ||
ask you if you want to add the Flame DevTools extension as a separate tab. | ||
|
||
|
||
## Development | ||
|
||
To run it locally, make sure to run `melos devtools-build` to build the | ||
extension so that it can be loaded in the browser (the build files are not | ||
committed to the repository). | ||
|
||
After you have done any changes, make sure to run `melos devtools-build` to | ||
build and copy the changes to `packages/flame/extension/build`. | ||
|
||
To develop things from the Flame side, create a new `DevToolsConnector` which | ||
registers the new extension end points so that you can communicate with Flame | ||
from the devtools extension. Don't forget to add the new connector to the | ||
list of connectors in the `DevToolsService` class. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include: package:flame_lint/analysis_options.yaml |
Oops, something went wrong.