Skip to content

Commit

Permalink
feat: Added GamepadState that can be updated (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
Levi-Lesches authored Oct 3, 2024
1 parent ca9916b commit 0c9890e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 6 deletions.
9 changes: 7 additions & 2 deletions packages/gamepads/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,13 @@ class _MyHomePageState extends State<MyHomePage> {
const Text('Gamepads:'),
if (loading)
const CircularProgressIndicator()
else
..._gamepads.map((e) => Text('${e.id} - ${e.name}')),
else ...[
for (final gamepad in _gamepads) ...[
Text('${gamepad.id} - ${gamepad.name}'),
Text(' Analog inputs: ${gamepad.state.analogInputs}'),
Text(' Button inputs: ${gamepad.state.buttonInputs}'),
],
],
],
),
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import 'dart:async';

import 'package:gamepads_platform_interface/api/gamepad_event.dart';
import 'package:gamepads_platform_interface/api/gamepad_state.dart';
import 'package:gamepads_platform_interface/gamepads_platform_interface.dart';

/// Represents a single, currently connected joystick controller (or gamepad).
///
/// By calling the constructor, this object will automatically subscribe to
/// events and update its internal [state]. To stop listening, be sure to call
/// [dispose]. Failing to do so may result in the object leaking memory.
class GamepadController {
/// A unique identifier for the gamepad controller.
///
Expand All @@ -9,14 +19,30 @@ class GamepadController {
/// A user-facing, platform-dependant name for the gamepad controller.
final String name;

final state = GamepadState();

StreamSubscription<GamepadEvent>? _subscription;

GamepadController({
required this.id,
required this.name,
});
required GamepadsPlatformInterface plugin,
}) {
_subscription = plugin.eventsByGamepad(id).listen(state.update);
}

factory GamepadController.parse(Map<dynamic, dynamic> map) {
factory GamepadController.parse(
Map<dynamic, dynamic> map,
GamepadsPlatformInterface plugin,
) {
final id = map['id'] as String;
final name = map['name'] as String;
return GamepadController(id: id, name: name);
return GamepadController(id: id, name: name, plugin: plugin);
}

/// Stops listening for new inputs.
Future<void> dispose() async {
await _subscription?.cancel();
_subscription = null;
}
}
27 changes: 27 additions & 0 deletions packages/gamepads_platform_interface/lib/api/gamepad_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:gamepads_platform_interface/api/gamepad_event.dart';

/// The current state of a gamepad.
///
/// This class keeps mutable state and is intended to be kept up-to-date by
/// calling [update] with the latest [GamepadEvent]. The [analogInputs] and
/// [buttonInputs] maps correspond to [KeyType.analog] and [KeyType.button],
/// respectively.
class GamepadState {
/// Contains inputs from events where [GamepadEvent.type] is [KeyType.analog].
final Map<String, double> analogInputs = {};

/// Contains inputs from events where [GamepadEvent.type] is [KeyType.button].
final Map<String, bool> buttonInputs = {};

/// Updates the state based on the given event.
void update(GamepadEvent event) {
switch (event.type) {
case KeyType.analog:
analogInputs[event.key] = event.value;
break;
case KeyType.button:
buttonInputs[event.key] = event.value == 1;
break;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ abstract class GamepadsPlatformInterface extends PlatformInterface {
Future<List<GamepadController>> listGamepads();

Stream<GamepadEvent> get gamepadEventsStream;

Stream<GamepadEvent> eventsByGamepad(String gamepadId) =>
gamepadEventsStream.where((event) => event.gamepadId == gamepadId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class MethodChannelGamepadsPlatformInterface extends GamepadsPlatformInterface {
<String, dynamic>{},
);
return result!.map((Object? e) {
return GamepadController.parse(e! as Map<dynamic, dynamic>);
return GamepadController.parse(e! as Map<dynamic, dynamic>, this);
}).toList();
}

Expand Down

0 comments on commit 0c9890e

Please sign in to comment.