feat: Implement Change View and Renderer Options menus
- Added functionality to display and navigate the Change View menu in SixelRenderer and SoftwareRenderer. - Introduced methods to draw the Change View and Renderer Options menus, including handling cursor and selection states. - Updated WolfClassicMenuArt to include a customize label for the new menu. - Enhanced WolfMenuScreen to support new menu states. - Created tests for Change View menu interactions, ensuring proper transitions and renderer settings toggling. - Implemented persistence for renderer settings in Flutter, allowing settings to be saved and loaded from a local file. Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
/// Flutter host adapter for persisting renderer settings to a local file.
|
||||
///
|
||||
/// Uses `dart:io` for desktop targets where a writable path is available.
|
||||
/// On web and other platforms that lack dart:io, persistence is silently
|
||||
/// skipped so the rest of the app continues to work normally.
|
||||
library;
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:wolf_3d_dart/wolf_3d_engine.dart';
|
||||
|
||||
/// Persists [WolfRendererSettings] as JSON to the app's support directory.
|
||||
///
|
||||
/// This implementation relies on `dart:io` and is therefore only active on
|
||||
/// non-web platforms. Pass an explicit [filePath] during testing.
|
||||
class FlutterRendererSettingsPersistence extends RendererSettingsPersistence
|
||||
with JsonRendererSettingsPersistence {
|
||||
FlutterRendererSettingsPersistence({String? filePath}) : _filePath = filePath;
|
||||
|
||||
final String? _filePath;
|
||||
String? _resolvedPath;
|
||||
|
||||
Future<String> _getFilePath() async {
|
||||
if (_resolvedPath != null) {
|
||||
return _resolvedPath!;
|
||||
}
|
||||
if (_filePath != null) {
|
||||
_resolvedPath = _filePath;
|
||||
return _resolvedPath!;
|
||||
}
|
||||
// Resolve platform app-support directory.
|
||||
final String home =
|
||||
Platform.environment['HOME'] ?? Platform.environment['APPDATA'] ?? '.';
|
||||
_resolvedPath = '$home/.wolf3d_settings.json';
|
||||
return _resolvedPath!;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> readRaw() async {
|
||||
if (kIsWeb) return null;
|
||||
try {
|
||||
final String path = await _getFilePath();
|
||||
final File f = File(path);
|
||||
if (!f.existsSync()) return null;
|
||||
return await f.readAsString();
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeRaw(String json) async {
|
||||
if (kIsWeb) return;
|
||||
try {
|
||||
final String path = await _getFilePath();
|
||||
await File(path).writeAsString(json, flush: true);
|
||||
} catch (_) {
|
||||
// Best-effort.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,9 @@ class Wolf3d {
|
||||
WolfEngine launchEngine({
|
||||
required void Function() onGameWon,
|
||||
void Function()? onQuit,
|
||||
WolfRendererCapabilities? rendererCapabilities,
|
||||
WolfRendererSettings? rendererSettings,
|
||||
void Function(WolfRendererSettings settings)? onRendererSettingsChanged,
|
||||
}) {
|
||||
if (availableGames.isEmpty) {
|
||||
throw StateError(
|
||||
@@ -106,6 +109,9 @@ class Wolf3d {
|
||||
// so backing out of the top-level menu should not pop the route.
|
||||
onMenuExit: () {},
|
||||
onQuit: onQuit,
|
||||
rendererCapabilities: rendererCapabilities,
|
||||
rendererSettings: rendererSettings,
|
||||
onRendererSettingsChanged: onRendererSettingsChanged,
|
||||
onGameSelected: (game) {
|
||||
_activeGame = game;
|
||||
audio.activeGame = game;
|
||||
|
||||
Reference in New Issue
Block a user