diff --git a/apps/wolf_3d_gui/lib/screens/game_screen.dart b/apps/wolf_3d_gui/lib/screens/game_screen.dart index 61e6516..783745b 100644 --- a/apps/wolf_3d_gui/lib/screens/game_screen.dart +++ b/apps/wolf_3d_gui/lib/screens/game_screen.dart @@ -10,10 +10,10 @@ import 'package:wolf_3d_renderer/wolf_3d_ascii_renderer.dart'; import 'package:wolf_3d_renderer/wolf_3d_flutter_renderer.dart'; import 'package:wolf_3d_renderer/wolf_3d_glsl_renderer.dart'; -enum _RendererMode { +enum RendererMode { software, ascii, - glsl, + hardware, } /// Launches a [WolfEngine] via [Wolf3d] and exposes renderer/input integrations. @@ -33,7 +33,7 @@ class GameScreen extends StatefulWidget { class _GameScreenState extends State { late final WolfEngine _engine; - _RendererMode _rendererMode = _RendererMode.software; + RendererMode _rendererMode = RendererMode.hardware; AsciiTheme _asciiTheme = AsciiThemes.blocks; @override @@ -109,7 +109,7 @@ class _GameScreenState extends State { top: 16, right: 16, child: Text( - 'TAB: ${_modeLabel(_rendererMode)} T: ${_asciiTheme.name} `: FPS ${_engine.showFpsCounter ? 'On' : 'Off'}', + '<${widget.wolf3d.input.rendererToggleKeyLabel}> ${_rendererMode.name}${_rendererMode == RendererMode.ascii ? ' <${widget.wolf3d.input.asciiThemeCycleKeyLabel}> ${_asciiTheme.name}' : ''} <${widget.wolf3d.input.fpsToggleKeyLabel}> FPS ${_engine.showFpsCounter ? 'On' : 'Off'}', style: TextStyle( color: Colors.white.withValues(alpha: 0.5), ), @@ -128,18 +128,18 @@ class _GameScreenState extends State { // Keep all renderers behind the same engine so mode switching does not // reset level state or audio playback. switch (_rendererMode) { - case _RendererMode.software: + case RendererMode.software: return WolfFlutterRenderer( engine: _engine, onKeyEvent: _handleRendererKeyEvent, ); - case _RendererMode.ascii: + case RendererMode.ascii: return WolfAsciiRenderer( engine: _engine, theme: _asciiTheme, onKeyEvent: _handleRendererKeyEvent, ); - case _RendererMode.glsl: + case RendererMode.hardware: return WolfGlslRenderer( engine: _engine, onKeyEvent: _handleRendererKeyEvent, @@ -153,44 +153,41 @@ class _GameScreenState extends State { return; } - if (event.logicalKey == LogicalKeyboardKey.tab) { + if (event.logicalKey == widget.wolf3d.input.rendererToggleKey) { setState(_cycleRendererMode); return; } - if (event.logicalKey == LogicalKeyboardKey.backquote || - event.character == '`') { + if (event.logicalKey == widget.wolf3d.input.fpsToggleKey) { setState(_toggleFpsCounter); return; } - if (event.logicalKey == LogicalKeyboardKey.keyT || - event.character == 't' || - event.character == 'T') { + if (event.logicalKey == widget.wolf3d.input.asciiThemeCycleKey) { setState(_cycleAsciiTheme); } } void _cycleRendererMode() { switch (_rendererMode) { - case _RendererMode.software: - _rendererMode = _RendererMode.ascii; + case RendererMode.hardware: + _rendererMode = RendererMode.software; break; - case _RendererMode.ascii: - _rendererMode = _RendererMode.glsl; + case RendererMode.software: + _rendererMode = RendererMode.ascii; break; - case _RendererMode.glsl: - _rendererMode = _RendererMode.software; + case RendererMode.ascii: + _rendererMode = RendererMode.hardware; break; } } void _onGlslUnavailable() { - if (!mounted || _rendererMode != _RendererMode.glsl) { + if (!mounted || _rendererMode != RendererMode.hardware) { return; } setState(() { - _rendererMode = _RendererMode.software; + _rendererMode = RendererMode.software; }); } @@ -201,15 +198,4 @@ class _GameScreenState extends State { void _cycleAsciiTheme() { _asciiTheme = AsciiThemes.nextOf(_asciiTheme); } - - String _modeLabel(_RendererMode mode) { - switch (mode) { - case _RendererMode.software: - return 'Software'; - case _RendererMode.ascii: - return 'ASCII'; - case _RendererMode.glsl: - return 'GLSL'; - } - } } diff --git a/packages/wolf_3d_flutter/lib/wolf_3d_input_flutter.dart b/packages/wolf_3d_flutter/lib/wolf_3d_input_flutter.dart index fbdda9f..ae8e20c 100644 --- a/packages/wolf_3d_flutter/lib/wolf_3d_input_flutter.dart +++ b/packages/wolf_3d_flutter/lib/wolf_3d_input_flutter.dart @@ -12,6 +12,43 @@ import 'package:wolf_3d_dart/wolf_3d_input.dart'; /// Translates Flutter keyboard and mouse state into engine-friendly actions. class Wolf3dFlutterInput extends Wolf3dInput { + /// Keyboard shortcut used by the Flutter host to cycle renderer modes. + LogicalKeyboardKey rendererToggleKey = LogicalKeyboardKey.keyR; + + /// Keyboard shortcut used by the Flutter host to cycle ASCII themes. + LogicalKeyboardKey asciiThemeCycleKey = LogicalKeyboardKey.keyT; + + /// Keyboard shortcut used by the Flutter host to toggle the FPS counter. + LogicalKeyboardKey fpsToggleKey = LogicalKeyboardKey.backquote; + + /// Human-friendly label for [rendererToggleKey] shown in on-screen hints. + String get rendererToggleKeyLabel => _formatShortcutLabel(rendererToggleKey); + + /// Human-friendly label for [asciiThemeCycleKey] shown in on-screen hints. + String get asciiThemeCycleKeyLabel => + _formatShortcutLabel(asciiThemeCycleKey); + + /// Human-friendly label for [fpsToggleKey] shown in on-screen hints. + String get fpsToggleKeyLabel => _formatShortcutLabel(fpsToggleKey); + + String _formatShortcutLabel(LogicalKeyboardKey key) { + if (key == LogicalKeyboardKey.space) { + return 'SPACE'; + } + if (key == LogicalKeyboardKey.tab) { + return 'TAB'; + } + final label = key.keyLabel; + if (label.isNotEmpty) { + return label.toUpperCase(); + } + final debugName = key.debugName; + if (debugName == null || debugName.isEmpty) { + return 'KEY'; + } + return debugName.replaceFirst('Logical Keyboard Key ', '').toUpperCase(); + } + /// Mapping from logical game actions to one or more keyboard bindings. /// /// Each action can be rebound by replacing the matching set. The defaults