diff --git a/sandbox/lib/main.dart b/sandbox/lib/main.dart index e6ea822..90d28ea 100644 --- a/sandbox/lib/main.dart +++ b/sandbox/lib/main.dart @@ -4,12 +4,28 @@ import 'presets.dart'; import 'scene.dart'; import 'widgets/left_menu.dart'; import 'widgets/scene_widget.dart'; +import 'widgets/top_menu.dart'; void main() { runApp( MaterialApp( title: 'Radiance sandbox', - theme: ThemeData.dark(), + theme: ThemeData( + brightness: Brightness.dark, + textButtonTheme: TextButtonThemeData( + style: ButtonStyle( + minimumSize: MaterialStateProperty.all(const Size(30, 30)), + padding: MaterialStateProperty.all(const EdgeInsets.all(5)), + foregroundColor: MaterialStateProperty.resolveWith( + (Set states) => + states.contains(MaterialState.disabled) + ? const Color(0xFF5F5F5F) + : const Color(0xFFBBBBBB), + ), + overlayColor: MaterialStateProperty.all(const Color(0xFF555555)), + ), + ), + ), home: const _MyApp(), ), ); @@ -23,8 +39,28 @@ class _MyApp extends StatefulWidget { } class SandboxState extends State<_MyApp> { + SandboxState() { + currentScene = kPresets[currentPreset](); + } + int currentPreset = 0; - Scene get currentScene => kPresets[currentPreset]; + EngineState engineState = EngineState.running; + late Scene currentScene; + + void startEngine() { + setState(() => engineState = EngineState.running); + } + + void pauseEngine() { + setState(() => engineState = EngineState.paused); + } + + void stopEngine() { + setState(() { + engineState = EngineState.stopped; + currentScene = kPresets[currentPreset](); + }); + } @override Widget build(BuildContext context) { @@ -49,6 +85,7 @@ class SandboxState extends State<_MyApp> { Container( constraints: const BoxConstraints.expand(height: 40), color: Theme.of(context).cardColor, + child: TopMenu(this), ), // Main canvas area Expanded( @@ -81,3 +118,9 @@ class SandboxState extends State<_MyApp> { ); } } + +enum EngineState { + running, + paused, + stopped, +} diff --git a/sandbox/lib/presets.dart b/sandbox/lib/presets.dart index 9d3baa5..d3e57d1 100644 --- a/sandbox/lib/presets.dart +++ b/sandbox/lib/presets.dart @@ -5,8 +5,8 @@ import 'entities/max_acceleration_entity.dart'; import 'entities/static_target_entity.dart'; import 'scene.dart'; -final kPresets = [ - _seek(), +final kPresets = [ + _seek, ]; Scene _seek() { diff --git a/sandbox/lib/widgets/left_menu.dart b/sandbox/lib/widgets/left_menu.dart index f3eedcd..9ca0ff0 100644 --- a/sandbox/lib/widgets/left_menu.dart +++ b/sandbox/lib/widgets/left_menu.dart @@ -74,7 +74,7 @@ class _ListItemState extends State<_ListItem> { child: Padding( padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 4), child: Text( - kPresets[widget.index].name, + widget.app.currentScene.name, style: isCurrent ? styleWhenCurrent : null, ), ), diff --git a/sandbox/lib/widgets/scene_widget.dart b/sandbox/lib/widgets/scene_widget.dart index a593de3..124a44f 100644 --- a/sandbox/lib/widgets/scene_widget.dart +++ b/sandbox/lib/widgets/scene_widget.dart @@ -16,6 +16,7 @@ class SceneWidget extends StatefulWidget { class _SceneWidgetState extends State { Ticker? ticker; Duration currentTime = Duration.zero; + EngineState currentState = EngineState.running; double dt = 0.0; void _handleTick(Duration time) { @@ -26,6 +27,16 @@ class _SceneWidgetState extends State { }); } + void _handleStateChange() { + if (widget.app.engineState == EngineState.running) { + ticker?.start(); + } else { + ticker?.stop(); + currentTime = Duration.zero; + } + currentState = widget.app.engineState; + } + @override void initState() { super.initState(); @@ -40,6 +51,9 @@ class _SceneWidgetState extends State { @override Widget build(BuildContext context) { + if (currentState != widget.app.engineState) { + _handleStateChange(); + } return Align( child: AspectRatio( aspectRatio: 100 / 80, diff --git a/sandbox/lib/widgets/top_menu.dart b/sandbox/lib/widgets/top_menu.dart new file mode 100644 index 0000000..9e358a4 --- /dev/null +++ b/sandbox/lib/widgets/top_menu.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import '../main.dart'; + +class TopMenu extends StatelessWidget { + const TopMenu(this.app); + + final SandboxState app; + + @override + Widget build(BuildContext context) { + final canPause = app.engineState == EngineState.running; + final canStop = app.engineState != EngineState.stopped; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 10), + child: Row( + children: [ + TextButton( + onPressed: canPause ? _handlePause : _handleStart, + child: + Icon(canPause ? Icons.pause_rounded : Icons.play_arrow_rounded), + ), + TextButton( + onPressed: canStop ? _handleStop : null, + child: const Icon(Icons.stop_rounded), + ), + ], + ), + ); + } + + void _handleStart() => app.startEngine(); + void _handlePause() => app.pauseEngine(); + void _handleStop() => app.stopEngine(); +}