From 2851203e67a935fd90feadb4bb45e2fc609d731e Mon Sep 17 00:00:00 2001 From: Luigi Rosso Date: Mon, 12 Apr 2021 16:57:40 -0700 Subject: [PATCH 1/3] Improving state machine api and including more examples. --- example/assets/little_machine.riv | Bin 0 -> 17522 bytes example/assets/skills.riv | Bin 0 -> 79162 bytes example/lib/example_state_machine.dart | 7 +- example/lib/little_machine.dart | 80 ++++++++++ example/lib/main.dart | 32 +++- example/lib/state_machine_skills.dart | 92 ++++++++++++ .../animation/state_machine_number_base.dart | 41 +++++ .../transition_number_condition_base.dart | 41 +++++ lib/src/generated/rive_core_context.dart | 78 +++++----- .../animation/state_machine_double.dart | 11 -- .../animation/state_machine_number.dart | 11 ++ ....dart => transition_number_condition.dart} | 14 +- .../shapes/paint/shape_paint_mutator.dart | 2 +- .../rive_core/state_machine_controller.dart | 20 ++- lib/src/state_machine_controller.dart | 140 ++++++++++++++++-- 15 files changed, 484 insertions(+), 85 deletions(-) create mode 100644 example/assets/little_machine.riv create mode 100644 example/assets/skills.riv create mode 100644 example/lib/little_machine.dart create mode 100644 example/lib/state_machine_skills.dart create mode 100644 lib/src/generated/animation/state_machine_number_base.dart create mode 100644 lib/src/generated/animation/transition_number_condition_base.dart delete mode 100644 lib/src/rive_core/animation/state_machine_double.dart create mode 100644 lib/src/rive_core/animation/state_machine_number.dart rename lib/src/rive_core/animation/{transition_double_condition.dart => transition_number_condition.dart} (69%) diff --git a/example/assets/little_machine.riv b/example/assets/little_machine.riv new file mode 100644 index 0000000000000000000000000000000000000000..bbfd0243f58455b3dffc98bd7d27570185422ed8 GIT binary patch literal 17522 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 UvY?TWxEv(tGB8tY>_`Uu4_DmNRsaA1 literal 0 HcmV?d00001 diff --git a/example/assets/skills.riv b/example/assets/skills.riv new file mode 100644 index 0000000000000000000000000000000000000000..ee24fb8a45e52cb6e41026eadcf70bb87a576da9 GIT binary patch literal 79162 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 ImUKq;8}v1Zp8x;= literal 0 HcmV?d00001 diff --git a/example/lib/example_state_machine.dart b/example/lib/example_state_machine.dart index ec8db10..9eb220c 100644 --- a/example/lib/example_state_machine.dart +++ b/example/lib/example_state_machine.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:rive/rive.dart'; +/// An example showing how to drive two boolean state machine inputs. class ExampleStateMachine extends StatefulWidget { const ExampleStateMachine({Key? key}) : super(key: key); @@ -16,8 +17,8 @@ class _ExampleStateMachineState extends State { Artboard? _riveArtboard; StateMachineController? _controller; - StateMachineInput? _hoverInput; - StateMachineInput? _pressInput; + SMIInput? _hoverInput; + SMIInput? _pressInput; @override void initState() { @@ -50,7 +51,7 @@ class _ExampleStateMachineState extends State { return Scaffold( backgroundColor: Colors.grey, appBar: AppBar( - title: const Text('State Machine Example'), + title: const Text('Button State Machine'), ), body: Center( child: _riveArtboard == null diff --git a/example/lib/little_machine.dart b/example/lib/little_machine.dart new file mode 100644 index 0000000..d2237b4 --- /dev/null +++ b/example/lib/little_machine.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:rive/rive.dart'; + +/// An example showing how to drive a StateMachine via a trigger input. +class LittleMachine extends StatefulWidget { + const LittleMachine({Key? key}) : super(key: key); + + @override + _LittleMachineState createState() => _LittleMachineState(); +} + +class _LittleMachineState extends State { + /// Tracks if the animation is playing by whether controller is running. + bool get isPlaying => _controller?.isActive ?? false; + + Artboard? _riveArtboard; + StateMachineController? _controller; + SMIInput? _trigger; + + @override + void initState() { + super.initState(); + + // Load the animation file from the bundle, note that you could also + // download this. The RiveFile just expects a list of bytes. + rootBundle.load('assets/little_machine.riv').then( + (data) async { + // Load the RiveFile from the binary data. + final file = RiveFile.import(data); + + // The artboard is the root of the animation and gets drawn in the + // Rive widget. + final artboard = file.mainArtboard; + var controller = + StateMachineController.fromArtboard(artboard, 'State Machine 1'); + if (controller != null) { + artboard.addController(controller); + _trigger = controller.findInput('Trigger 1'); + } + setState(() => _riveArtboard = artboard); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.grey, + appBar: AppBar( + title: const Text('Little Machine'), + ), + body: Center( + child: _riveArtboard == null + ? const SizedBox() + : GestureDetector( + onTapDown: (_) => _trigger?.value = true, + child: Column( + children: [ + const SizedBox(height: 10), + const Text( + 'Press to activate!', + style: TextStyle( + fontSize: 18, + ), + ), + const SizedBox(height: 10), + Expanded( + child: Rive( + artboard: _riveArtboard!, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/example/lib/main.dart b/example/lib/main.dart index a89e7a1..2434d5e 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:rive_example/example_animation.dart'; import 'package:rive_example/example_state_machine.dart'; +import 'package:rive_example/little_machine.dart'; +import 'package:rive_example/state_machine_skills.dart'; void main() => runApp(MaterialApp( title: 'Navigation Basics', @@ -33,7 +35,7 @@ class Home extends StatelessWidget { height: 10, ), ElevatedButton( - child: const Text('State Machine'), + child: const Text('Button State Machine'), onPressed: () { Navigator.push( context, @@ -43,6 +45,34 @@ class Home extends StatelessWidget { ); }, ), + const SizedBox( + height: 10, + ), + ElevatedButton( + child: const Text('Skills Machine'), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const StateMachineSkills(), + ), + ); + }, + ), + const SizedBox( + height: 10, + ), + ElevatedButton( + child: const Text('Little Machine'), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const LittleMachine(), + ), + ); + }, + ), ], ), ), diff --git a/example/lib/state_machine_skills.dart b/example/lib/state_machine_skills.dart new file mode 100644 index 0000000..4b16f3f --- /dev/null +++ b/example/lib/state_machine_skills.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:rive/rive.dart'; + +/// An example showing how to drive a StateMachine via one numeric input. +class StateMachineSkills extends StatefulWidget { + const StateMachineSkills({Key? key}) : super(key: key); + + @override + _StateMachineSkillsState createState() => _StateMachineSkillsState(); +} + +class _StateMachineSkillsState extends State { + /// Tracks if the animation is playing by whether controller is running. + bool get isPlaying => _controller?.isActive ?? false; + + Artboard? _riveArtboard; + StateMachineController? _controller; + SMIInput? _levelInput; + + @override + void initState() { + super.initState(); + + // Load the animation file from the bundle, note that you could also + // download this. The RiveFile just expects a list of bytes. + rootBundle.load('assets/skills.riv').then( + (data) async { + // Load the RiveFile from the binary data. + final file = RiveFile.import(data); + + // The artboard is the root of the animation and gets drawn in the + // Rive widget. + final artboard = file.mainArtboard; + var controller = + StateMachineController.fromArtboard(artboard, 'Designer\'s Test'); + if (controller != null) { + artboard.addController(controller); + _levelInput = controller.findInput('Level'); + } + setState(() => _riveArtboard = artboard); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.grey, + appBar: AppBar( + title: const Text('Skills Machine'), + ), + body: Center( + child: _riveArtboard == null + ? const SizedBox() + : Stack( + children: [ + Positioned.fill( + child: Rive( + artboard: _riveArtboard!, + ), + ), + Positioned.fill( + bottom: 100, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + ElevatedButton( + child: const Text('Beginner'), + onPressed: () => _levelInput?.value = 0, + ), + const SizedBox(width: 10), + ElevatedButton( + child: const Text('Intermediate'), + onPressed: () => _levelInput?.value = 1, + ), + const SizedBox(width: 10), + ElevatedButton( + child: const Text('Expert'), + onPressed: () => _levelInput?.value = 2, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/src/generated/animation/state_machine_number_base.dart b/lib/src/generated/animation/state_machine_number_base.dart new file mode 100644 index 0000000..e3d4592 --- /dev/null +++ b/lib/src/generated/animation/state_machine_number_base.dart @@ -0,0 +1,41 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_number_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +import 'package:rive/src/generated/animation/state_machine_input_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart'; + +abstract class StateMachineNumberBase extends StateMachineInput { + static const int typeKey = 56; + @override + int get coreType => StateMachineNumberBase.typeKey; + @override + Set get coreTypes => { + StateMachineNumberBase.typeKey, + StateMachineInputBase.typeKey, + StateMachineComponentBase.typeKey + }; + + /// -------------------------------------------------------------------------- + /// Value field with key 140. + static const double valueInitialValue = 0; + double _value = valueInitialValue; + static const int valuePropertyKey = 140; + double get value => _value; + + /// Change the [_value] field value. + /// [valueChanged] will be invoked only if the field's value has changed. + set value(double value) { + if (_value == value) { + return; + } + double from = _value; + _value = value; + if (hasValidated) { + valueChanged(from, value); + } + } + + void valueChanged(double from, double to); +} diff --git a/lib/src/generated/animation/transition_number_condition_base.dart b/lib/src/generated/animation/transition_number_condition_base.dart new file mode 100644 index 0000000..9cc38d1 --- /dev/null +++ b/lib/src/generated/animation/transition_number_condition_base.dart @@ -0,0 +1,41 @@ +/// Core automatically generated +/// lib/src/generated/animation/transition_number_condition_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/transition_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; +import 'package:rive/src/rive_core/animation/transition_value_condition.dart'; + +abstract class TransitionNumberConditionBase extends TransitionValueCondition { + static const int typeKey = 70; + @override + int get coreType => TransitionNumberConditionBase.typeKey; + @override + Set get coreTypes => { + TransitionNumberConditionBase.typeKey, + TransitionValueConditionBase.typeKey, + TransitionConditionBase.typeKey + }; + + /// -------------------------------------------------------------------------- + /// Value field with key 157. + static const double valueInitialValue = 0; + double _value = valueInitialValue; + static const int valuePropertyKey = 157; + double get value => _value; + + /// Change the [_value] field value. + /// [valueChanged] will be invoked only if the field's value has changed. + set value(double value) { + if (_value == value) { + return; + } + double from = _value; + _value = value; + if (hasValidated) { + valueChanged(from, value); + } + } + + void valueChanged(double from, double to); +} diff --git a/lib/src/generated/rive_core_context.dart b/lib/src/generated/rive_core_context.dart index 13c43bb..6d12f31 100644 --- a/lib/src/generated/rive_core_context.dart +++ b/lib/src/generated/rive_core_context.dart @@ -21,13 +21,13 @@ import 'package:rive/src/generated/animation/linear_animation_base.dart'; import 'package:rive/src/generated/animation/state_machine_base.dart'; import 'package:rive/src/generated/animation/state_machine_bool_base.dart'; import 'package:rive/src/generated/animation/state_machine_component_base.dart'; -import 'package:rive/src/generated/animation/state_machine_double_base.dart'; import 'package:rive/src/generated/animation/state_machine_layer_base.dart'; +import 'package:rive/src/generated/animation/state_machine_number_base.dart'; import 'package:rive/src/generated/animation/state_machine_trigger_base.dart'; import 'package:rive/src/generated/animation/state_transition_base.dart'; import 'package:rive/src/generated/animation/transition_bool_condition_base.dart'; import 'package:rive/src/generated/animation/transition_condition_base.dart'; -import 'package:rive/src/generated/animation/transition_double_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_number_condition_base.dart'; import 'package:rive/src/generated/animation/transition_trigger_condition_base.dart'; import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; import 'package:rive/src/generated/artboard_base.dart'; @@ -81,12 +81,12 @@ import 'package:rive/src/rive_core/animation/keyframe_id.dart'; import 'package:rive/src/rive_core/animation/linear_animation.dart'; import 'package:rive/src/rive_core/animation/state_machine.dart'; import 'package:rive/src/rive_core/animation/state_machine_bool.dart'; -import 'package:rive/src/rive_core/animation/state_machine_double.dart'; import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; +import 'package:rive/src/rive_core/animation/state_machine_number.dart'; import 'package:rive/src/rive_core/animation/state_machine_trigger.dart'; import 'package:rive/src/rive_core/animation/state_transition.dart'; import 'package:rive/src/rive_core/animation/transition_bool_condition.dart'; -import 'package:rive/src/rive_core/animation/transition_double_condition.dart'; +import 'package:rive/src/rive_core/animation/transition_number_condition.dart'; import 'package:rive/src/rive_core/animation/transition_trigger_condition.dart'; import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/rive_core/backboard.dart'; @@ -129,14 +129,16 @@ class RiveCoreContext { return AnimationState(); case KeyedObjectBase.typeKey: return KeyedObject(); + case StateMachineNumberBase.typeKey: + return StateMachineNumber(); case TransitionTriggerConditionBase.typeKey: return TransitionTriggerCondition(); case KeyedPropertyBase.typeKey: return KeyedProperty(); - case StateMachineDoubleBase.typeKey: - return StateMachineDouble(); case KeyFrameIdBase.typeKey: return KeyFrameId(); + case TransitionNumberConditionBase.typeKey: + return TransitionNumberCondition(); case AnyStateBase.typeKey: return AnyState(); case StateMachineLayerBase.typeKey: @@ -145,8 +147,6 @@ class RiveCoreContext { return Animation(); case CubicInterpolatorBase.typeKey: return CubicInterpolator(); - case TransitionDoubleConditionBase.typeKey: - return TransitionDoubleCondition(); case StateTransitionBase.typeKey: return StateTransition(); case KeyFrameDoubleBase.typeKey: @@ -262,26 +262,26 @@ class RiveCoreContext { object.objectId = value; } break; - case TransitionConditionBase.inputIdPropertyKey: - if (object is TransitionConditionBase && value is int) { - object.inputId = value; - } - break; case StateMachineComponentBase.namePropertyKey: if (object is StateMachineComponentBase && value is String) { object.name = value; } break; + case StateMachineNumberBase.valuePropertyKey: + if (object is StateMachineNumberBase && value is double) { + object.value = value; + } + break; + case TransitionConditionBase.inputIdPropertyKey: + if (object is TransitionConditionBase && value is int) { + object.inputId = value; + } + break; case KeyedPropertyBase.propertyKeyPropertyKey: if (object is KeyedPropertyBase && value is int) { object.propertyKey = value; } break; - case StateMachineDoubleBase.valuePropertyKey: - if (object is StateMachineDoubleBase && value is double) { - object.value = value; - } - break; case KeyFrameBase.framePropertyKey: if (object is KeyFrameBase && value is int) { object.frame = value; @@ -302,6 +302,16 @@ class RiveCoreContext { object.value = value; } break; + case TransitionValueConditionBase.opValuePropertyKey: + if (object is TransitionValueConditionBase && value is int) { + object.opValue = value; + } + break; + case TransitionNumberConditionBase.valuePropertyKey: + if (object is TransitionNumberConditionBase && value is double) { + object.value = value; + } + break; case AnimationBase.namePropertyKey: if (object is AnimationBase && value is String) { object.name = value; @@ -327,16 +337,6 @@ class RiveCoreContext { object.y2 = value; } break; - case TransitionValueConditionBase.opValuePropertyKey: - if (object is TransitionValueConditionBase && value is int) { - object.opValue = value; - } - break; - case TransitionDoubleConditionBase.valuePropertyKey: - if (object is TransitionDoubleConditionBase && value is double) { - object.value = value; - } - break; case StateTransitionBase.stateToIdPropertyKey: if (object is StateTransitionBase && value is int) { object.stateToId = value; @@ -861,12 +861,12 @@ class RiveCoreContext { case DrawRulesBase.drawTargetIdPropertyKey: case TendonBase.boneIdPropertyKey: return uintType; - case StateMachineDoubleBase.valuePropertyKey: + case StateMachineNumberBase.valuePropertyKey: + case TransitionNumberConditionBase.valuePropertyKey: case CubicInterpolatorBase.x1PropertyKey: case CubicInterpolatorBase.y1PropertyKey: case CubicInterpolatorBase.x2PropertyKey: case CubicInterpolatorBase.y2PropertyKey: - case TransitionDoubleConditionBase.valuePropertyKey: case KeyFrameDoubleBase.valuePropertyKey: case LinearAnimationBase.speedPropertyKey: case LinearGradientBase.startXPropertyKey: @@ -1040,8 +1040,10 @@ class RiveCoreContext { static double getDouble(Core object, int propertyKey) { switch (propertyKey) { - case StateMachineDoubleBase.valuePropertyKey: - return (object as StateMachineDoubleBase).value; + case StateMachineNumberBase.valuePropertyKey: + return (object as StateMachineNumberBase).value; + case TransitionNumberConditionBase.valuePropertyKey: + return (object as TransitionNumberConditionBase).value; case CubicInterpolatorBase.x1PropertyKey: return (object as CubicInterpolatorBase).x1; case CubicInterpolatorBase.y1PropertyKey: @@ -1050,8 +1052,6 @@ class RiveCoreContext { return (object as CubicInterpolatorBase).x2; case CubicInterpolatorBase.y2PropertyKey: return (object as CubicInterpolatorBase).y2; - case TransitionDoubleConditionBase.valuePropertyKey: - return (object as TransitionDoubleConditionBase).value; case KeyFrameDoubleBase.valuePropertyKey: return (object as KeyFrameDoubleBase).value; case LinearAnimationBase.speedPropertyKey: @@ -1340,8 +1340,11 @@ class RiveCoreContext { static void setDouble(Core object, int propertyKey, double value) { switch (propertyKey) { - case StateMachineDoubleBase.valuePropertyKey: - (object as StateMachineDoubleBase).value = value; + case StateMachineNumberBase.valuePropertyKey: + (object as StateMachineNumberBase).value = value; + break; + case TransitionNumberConditionBase.valuePropertyKey: + (object as TransitionNumberConditionBase).value = value; break; case CubicInterpolatorBase.x1PropertyKey: (object as CubicInterpolatorBase).x1 = value; @@ -1355,9 +1358,6 @@ class RiveCoreContext { case CubicInterpolatorBase.y2PropertyKey: (object as CubicInterpolatorBase).y2 = value; break; - case TransitionDoubleConditionBase.valuePropertyKey: - (object as TransitionDoubleConditionBase).value = value; - break; case KeyFrameDoubleBase.valuePropertyKey: (object as KeyFrameDoubleBase).value = value; break; diff --git a/lib/src/rive_core/animation/state_machine_double.dart b/lib/src/rive_core/animation/state_machine_double.dart deleted file mode 100644 index 1fe1463..0000000 --- a/lib/src/rive_core/animation/state_machine_double.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:rive/src/generated/animation/state_machine_double_base.dart'; -export 'package:rive/src/generated/animation/state_machine_double_base.dart'; - -class StateMachineDouble extends StateMachineDoubleBase { - @override - void valueChanged(double from, double to) {} - @override - bool isValidType() => T == double; - @override - dynamic get controllerValue => value; -} diff --git a/lib/src/rive_core/animation/state_machine_number.dart b/lib/src/rive_core/animation/state_machine_number.dart new file mode 100644 index 0000000..26dfe13 --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_number.dart @@ -0,0 +1,11 @@ +import 'package:rive/src/generated/animation/state_machine_number_base.dart'; +export 'package:rive/src/generated/animation/state_machine_number_base.dart'; + +class StateMachineNumber extends StateMachineNumberBase { + @override + void valueChanged(double from, double to) {} + @override + bool isValidType() => T == double; + @override + dynamic get controllerValue => value; +} diff --git a/lib/src/rive_core/animation/transition_double_condition.dart b/lib/src/rive_core/animation/transition_number_condition.dart similarity index 69% rename from lib/src/rive_core/animation/transition_double_condition.dart rename to lib/src/rive_core/animation/transition_number_condition.dart index 8748f32..a7fb680 100644 --- a/lib/src/rive_core/animation/transition_double_condition.dart +++ b/lib/src/rive_core/animation/transition_number_condition.dart @@ -1,20 +1,20 @@ import 'dart:collection'; -import 'package:rive/src/rive_core/animation/state_machine_double.dart'; +import 'package:rive/src/rive_core/animation/state_machine_number.dart'; import 'package:rive/src/rive_core/animation/transition_condition.dart'; -import 'package:rive/src/generated/animation/transition_double_condition_base.dart'; -export 'package:rive/src/generated/animation/transition_double_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_number_condition_base.dart'; +export 'package:rive/src/generated/animation/transition_number_condition_base.dart'; -class TransitionDoubleCondition extends TransitionDoubleConditionBase { +class TransitionNumberCondition extends TransitionNumberConditionBase { @override void valueChanged(double from, double to) {} @override - bool validate() => super.validate() && (input is StateMachineDouble); + bool validate() => super.validate() && (input is StateMachineNumber); @override bool evaluate(HashMap values) { - if (input is! StateMachineDouble) { + if (input is! StateMachineNumber) { return true; } - var doubleInput = input as StateMachineDouble; + var doubleInput = input as StateMachineNumber; dynamic providedValue = values[input.id]; double inputValue = providedValue is double ? providedValue : doubleInput.value; diff --git a/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart b/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart index dfea358..53544ca 100644 --- a/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart +++ b/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart @@ -4,7 +4,7 @@ import 'package:rive/src/rive_core/shapes/shape_paint_container.dart'; abstract class ShapePaintMutator { ShapePaintContainer? _shapePaintContainer; - late Paint _paint; + Paint _paint = Paint(); ShapePaintContainer? get shapePaintContainer => _shapePaintContainer; Paint get paint => _paint; double _renderOpacity = 1; diff --git a/lib/src/rive_core/state_machine_controller.dart b/lib/src/rive_core/state_machine_controller.dart index c5af8e3..7a38896 100644 --- a/lib/src/rive_core/state_machine_controller.dart +++ b/lib/src/rive_core/state_machine_controller.dart @@ -37,12 +37,6 @@ class LayerController { if (_animationInstance != null) { _animationInstance!.advance(elapsedSeconds); } - for (int i = 0; updateState(inputValues); i++) { - if (i == 100) { - print('StateMachineController.apply exceeded max iterations.'); - return false; - } - } if (_transition != null && _stateFrom != null && _transition!.duration != 0) { @@ -52,22 +46,26 @@ class LayerController { } else { _mix = 1; } - var keepGoing = _mix != 1; if (_animationInstanceFrom != null && _mix < 1) { if (!_holdAnimationFrom) { _animationInstanceFrom!.advance(elapsedSeconds); } + } + for (int i = 0; updateState(inputValues); i++) { + if (i == 100) { + print('StateMachineController.apply exceeded max iterations.'); + return false; + } + } + if (_animationInstanceFrom != null && _mix < 1) { _animationInstanceFrom!.animation.apply(_animationInstanceFrom!.time, mix: 1 - _mix, coreContext: core); } if (_animationInstance != null) { _animationInstance!.animation .apply(_animationInstance!.time, mix: _mix, coreContext: core); - if (_animationInstance!.keepGoing) { - keepGoing = true; - } } - return keepGoing; + return _mix != 1 || (_animationInstance?.keepGoing ?? false); } bool updateState(HashMap inputValues) { diff --git a/lib/src/state_machine_controller.dart b/lib/src/state_machine_controller.dart index f70065a..17a701c 100644 --- a/lib/src/state_machine_controller.dart +++ b/lib/src/state_machine_controller.dart @@ -1,17 +1,51 @@ +import 'package:flutter/foundation.dart'; +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/generated/animation/state_machine_bool_base.dart'; +import 'package:rive/src/generated/animation/state_machine_number_base.dart'; +import 'package:rive/src/generated/animation/state_machine_trigger_base.dart'; import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/animation/state_machine_bool.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart' as core; +import 'package:rive/src/rive_core/animation/state_machine_number.dart'; +import 'package:rive/src/rive_core/animation/state_machine_trigger.dart'; import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/rive_core/state_machine_controller.dart' as core; -class StateMachineInput { - final int id; +/// [StateMachine]s supports three input types. The StateMachine mostly +/// abstracts types by allowing the programmer to query for an input of a +/// specific Dart backing type, mapping it to the correct StateMachine type. +/// This is the most flexible API to use to check if a type with a given name +/// exists. However, if you need to iterate inputs and query their types, this +/// enum is exposed for convenience. +enum SMIType { number, boolean, trigger } + +/// StateMachine Instance Input. This is the abstraction of an instanced input +/// from the [StateMachine]. Whenever a [StateMachineController] is created, the +/// list of inputs in the corresponding [StateMachine] is wrapped into a set of +/// [SMIInput] objects that ensure inputs are initialized to design-time values. +/// The implementation can now change these values freely as they are decoupled +/// from the backing [StateMachine] and can safely be re-instanced by another +/// controller later. +class SMIInput { + final core.StateMachineInput _input; final StateMachineController controller; - StateMachineInput._(this.id, this.controller); + final SMIType type; - T get value => controller.inputValues[id] as T; - set value(T newValue) => change(newValue); + SMIInput._(this._input, this.type, this.controller); - /// Change the value of the input, returns true if the value was changed the - /// and [StateMachineController] was activated. + @protected + void advance() {} + + /// The id of the input within the context of the [StateMachine] it belongs + /// to. + int get id => _input.id; + + /// The name given to this input at design time in Rive. + String get name => _input.name; + + /// Convenience method for changing the backing value of the input. Usually + /// it's easier to use the various value getter/setters on the derived + /// version of [SMIInput] like [SMIBool], [SMINumber], and [SMITrigger]. bool change(T value) { if (controller.inputValues[id] == value) { return false; @@ -20,15 +54,89 @@ class StateMachineInput { controller.isActive = true; return true; } + + T get value => controller.inputValues[id] as T; + set value(T newValue) => change(newValue); + + bool _is() { + return K == T; + } +} + +/// A boolean StateMachine input instance. Use the [value] property to change +/// the input which will automatically re-activate the [StateMachineController] +/// if necessary. +class SMIBool extends SMIInput { + SMIBool._(StateMachineBool input, StateMachineController controller) + : super._( + input, + SMIType.boolean, + controller, + ) { + controller.inputValues[id] = input.value; + } +} + +/// A numeric StateMachine input instance. Use the [value] property to change +/// the input which will automatically re-activate the [StateMachineController] +/// if necessary. +class SMINumber extends SMIInput { + SMINumber._(StateMachineNumber input, StateMachineController controller) + : super._( + input, + SMIType.number, + controller, + ) { + controller.inputValues[id] = input.value; + } +} + +/// A trigger StateMachine input instance. Use the [fire] method to change the +/// input which will automatically re-activate the [StateMachineController] if +/// necessary. +class SMITrigger extends SMIInput { + SMITrigger._(StateMachineTrigger input, StateMachineController controller) + : super._( + input, + SMIType.trigger, + controller, + ) { + controller.inputValues[id] = false; + } + + void fire() => change(true); + @override + void advance() => change(false); } /// An AnimationController which controls a StateMachine and provides access to /// the inputs of the StateMachine. class StateMachineController extends core.StateMachineController { + final List _inputs = []; + + /// A list of inputs available in the StateMachine. + Iterable get inputs => _inputs; + StateMachineController(StateMachine stateMachine) : super(stateMachine) { isActive = true; + for (final input in stateMachine.inputs) { + switch (input.coreType) { + case StateMachineNumberBase.typeKey: + _inputs.add(SMINumber._(input as StateMachineNumber, this)); + break; + case StateMachineBoolBase.typeKey: + _inputs.add(SMIBool._(input as StateMachineBool, this)); + break; + case StateMachineTriggerBase.typeKey: + _inputs.add(SMITrigger._(input as StateMachineTrigger, this)); + break; + } + } } + /// Instance a [StateMachineController] from an [artboard] with the given + /// [stateMachineName]. Returns the [StateMachineController] or null if no + /// [StateMachine] with [stateMachineName] is found. static StateMachineController? fromArtboard( Artboard artboard, String stateMachineName) { for (final animation in artboard.animations) { @@ -39,13 +147,21 @@ class StateMachineController extends core.StateMachineController { return null; } - StateMachineInput? findInput(String name) { - for (final input in stateMachine.inputs) { - if (input.name == name && input.isValidType()) { - inputValues[input.id] = input.controllerValue; - return StateMachineInput._(input.id, this); + /// Find an input with a specific backing type and a given name. + SMIInput? findInput(String name) { + for (final input in _inputs) { + if (input._is() && input.name == name) { + return input as SMIInput; } } return null; } + + @override + void apply(CoreContext core, double elapsedSeconds) { + super.apply(core, elapsedSeconds); + for (final input in _inputs) { + input.advance(); + } + } } From a37d1194d4d41139b8ce7a6cdae306079e6e3fdc Mon Sep 17 00:00:00 2001 From: Luigi Rosso Date: Mon, 12 Apr 2021 17:01:40 -0700 Subject: [PATCH 2/3] Prepping for pub. --- CHANGELOG.md | 5 +++++ pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b4898a..03ffdc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +## [0.7.2] - 2021-04-12 16:57:54 +- Breaking change! StateMachineInput has been renamed to SMIInput to follow conventions in other runtimes and clearly disambiguate between core.StateMachineInput (the backing type in Rive's core system, which is not explicitly exposed to this runtime) and the input instances which should be used by controllers in the Flutter ecosystem. +- New examples showing use of number, boolean, and trigger inputs. + ## [0.7.1] - 2021-04-06 16:19:04 - Fixes an issue with hold keyframes not loading properly. diff --git a/pubspec.yaml b/pubspec.yaml index 4d8ada8..edb631b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: rive description: Rive 2 Flutter Runtime. This package provides runtime functionality for playing back and interacting with animations built with the Rive editor available at https://rive.app. -version: 0.7.1 +version: 0.7.2 repository: https://github.com/rive-app/rive-flutter homepage: https://rive.app From 17c6f08334076b6e43f87b46b463e5bf4b71d5b6 Mon Sep 17 00:00:00 2001 From: Luigi Rosso Date: Tue, 13 Apr 2021 15:00:32 -0700 Subject: [PATCH 3/3] Improvements based on feedback --- lib/src/state_machine_controller.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/src/state_machine_controller.dart b/lib/src/state_machine_controller.dart index 17a701c..13aa852 100644 --- a/lib/src/state_machine_controller.dart +++ b/lib/src/state_machine_controller.dart @@ -19,14 +19,16 @@ import 'package:rive/src/rive_core/state_machine_controller.dart' as core; /// enum is exposed for convenience. enum SMIType { number, boolean, trigger } -/// StateMachine Instance Input. This is the abstraction of an instanced input +/// SMI = StateMachineInstance +/// +/// This is the abstraction of an instanced input /// from the [StateMachine]. Whenever a [StateMachineController] is created, the /// list of inputs in the corresponding [StateMachine] is wrapped into a set of /// [SMIInput] objects that ensure inputs are initialized to design-time values. /// The implementation can now change these values freely as they are decoupled /// from the backing [StateMachine] and can safely be re-instanced by another /// controller later. -class SMIInput { +abstract class SMIInput { final core.StateMachineInput _input; final StateMachineController controller; final SMIType type; @@ -43,9 +45,10 @@ class SMIInput { /// The name given to this input at design time in Rive. String get name => _input.name; - /// Convenience method for changing the backing value of the input. Usually - /// it's easier to use the various value getter/setters on the derived - /// version of [SMIInput] like [SMIBool], [SMINumber], and [SMITrigger]. + /// Convenience method for changing the backing [SMIInput.value] of the input. + /// For [SMITrigger] it's usually preferable to use the [SMITrigger.fire] + /// method to change the input value, but calling change(true) is totally + /// valid. bool change(T value) { if (controller.inputValues[id] == value) { return false;