library; import 'dart:async'; import 'package:flutter/material.dart'; import 'package:wolf_3d_flutter/wolf_3d_flutter.dart'; /// Minimal app shell that binds a prepared [Wolf3dFlutterEngine] instance to /// host screens. class Wolf3dApp extends StatefulWidget { /// Shared initialized facade that owns game data, input, and audio services. final Wolf3dFlutterEngine engine; const Wolf3dApp({ super.key, required this.engine, }); @override State createState() => _Wolf3dAppState(); } class _Wolf3dAppState extends State with WidgetsBindingObserver { late final Wolf3dAppManager _manager; @override void initState() { super.initState(); _manager = Wolf3dAppManager(engine: widget.engine); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); unawaited(_manager.ensureAudioShutdown()); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.detached) { unawaited(_manager.ensureAudioShutdown()); } } Future _pickGameDataDirectory() { return _manager.pickGameDataDirectory( notifyChanged: () { if (mounted) { setState(() {}); } }, ); } Future _pickGameDataFiles() { return _manager.pickGameDataFiles( notifyChanged: () { if (mounted) { setState(() {}); } }, ); } @override Widget build(BuildContext context) { return widget.engine.availableGames.isEmpty ? NoGameDataScreen( configuredDataDirectory: widget.engine.configuredDataDirectory, onPickGameDataDirectory: _pickGameDataDirectory, onPickGameDataFiles: _pickGameDataFiles, isLoadingGameData: _manager.isLoadingGameData, pickerError: _manager.pickerError, ) : GameScreen(wolf3d: widget.engine); } }