mirror of
https://github.com/rive-app/rive-flutter.git
synced 2025-06-27 10:18:12 +08:00
Adds onStateChange callback
This commit is contained in:
@ -1,8 +1,13 @@
|
|||||||
|
## [0.7.21] - 2021-06-21 14:00:00
|
||||||
|
- Adds onStateChange callback to state machine controllers
|
||||||
|
|
||||||
## [0.7.20] - 2021-06-19 19:01:10
|
## [0.7.20] - 2021-06-19 19:01:10
|
||||||
- Quick start fixes in README.md.
|
- Quick start fixes in README.md
|
||||||
|
|
||||||
## [0.7.19] - 2021-06-18 12:00:00
|
## [0.7.19] - 2021-06-18 12:00:00
|
||||||
- BREAKING CHANGE: onInit callback now takes an artboard as a parameter
|
- BREAKING CHANGE: onInit callback now takes an artboard as a parameter
|
||||||
- Adds simple state machine example
|
- Adds simple state machine example
|
||||||
|
|
||||||
## [0.7.18] - 2021-06-14 12:00:00
|
## [0.7.18] - 2021-06-14 12:00:00
|
||||||
- Adds ability to pass controllers into RiveAnimation widgets
|
- Adds ability to pass controllers into RiveAnimation widgets
|
||||||
- Adds autoplay option to SimpleAnimation controller
|
- Adds autoplay option to SimpleAnimation controller
|
||||||
|
@ -8,7 +8,7 @@ Runtime docs are available in [Rive's help center](https://help.rive.app/runtime
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
rive: ^0.7.20
|
rive: ^0.7.21
|
||||||
```
|
```
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
@ -15,6 +15,9 @@ class _LittleMachineState extends State<LittleMachine> {
|
|||||||
/// Tracks if the animation is playing by whether controller is running.
|
/// Tracks if the animation is playing by whether controller is running.
|
||||||
bool get isPlaying => _controller?.isActive ?? false;
|
bool get isPlaying => _controller?.isActive ?? false;
|
||||||
|
|
||||||
|
/// Message that displays when state has changed
|
||||||
|
String stateChangeMessage = '';
|
||||||
|
|
||||||
Artboard? _riveArtboard;
|
Artboard? _riveArtboard;
|
||||||
StateMachineController? _controller;
|
StateMachineController? _controller;
|
||||||
SMIInput<bool>? _trigger;
|
SMIInput<bool>? _trigger;
|
||||||
@ -33,8 +36,11 @@ class _LittleMachineState extends State<LittleMachine> {
|
|||||||
// The artboard is the root of the animation and gets drawn in the
|
// The artboard is the root of the animation and gets drawn in the
|
||||||
// Rive widget.
|
// Rive widget.
|
||||||
final artboard = file.mainArtboard;
|
final artboard = file.mainArtboard;
|
||||||
var controller =
|
var controller = StateMachineController.fromArtboard(
|
||||||
StateMachineController.fromArtboard(artboard, 'State Machine 1');
|
artboard,
|
||||||
|
'State Machine 1',
|
||||||
|
onStateChange: _onStateChange,
|
||||||
|
);
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
artboard.addController(controller);
|
artboard.addController(controller);
|
||||||
_trigger = controller.findInput('Trigger 1');
|
_trigger = controller.findInput('Trigger 1');
|
||||||
@ -44,6 +50,12 @@ class _LittleMachineState extends State<LittleMachine> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do something when the state machine changes state
|
||||||
|
void _onStateChange(String stateMachineName, String stateName) => setState(
|
||||||
|
() => stateChangeMessage =
|
||||||
|
'State Changed in $stateMachineName to $stateName',
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -71,6 +83,9 @@ class _LittleMachineState extends State<LittleMachine> {
|
|||||||
artboard: _riveArtboard!,
|
artboard: _riveArtboard!,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Text('$stateChangeMessage'),
|
||||||
|
const SizedBox(height: 10),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -119,7 +119,10 @@ class StateMachineController extends core.StateMachineController {
|
|||||||
/// A list of inputs available in the StateMachine.
|
/// A list of inputs available in the StateMachine.
|
||||||
Iterable<SMIInput> get inputs => _inputs;
|
Iterable<SMIInput> get inputs => _inputs;
|
||||||
|
|
||||||
StateMachineController(StateMachine stateMachine) : super(stateMachine) {
|
StateMachineController(
|
||||||
|
StateMachine stateMachine, {
|
||||||
|
core.OnStateChange? onStateChange,
|
||||||
|
}) : super(stateMachine, onStateChange: onStateChange) {
|
||||||
isActive = true;
|
isActive = true;
|
||||||
for (final input in stateMachine.inputs) {
|
for (final input in stateMachine.inputs) {
|
||||||
switch (input.coreType) {
|
switch (input.coreType) {
|
||||||
@ -140,10 +143,13 @@ class StateMachineController extends core.StateMachineController {
|
|||||||
/// [stateMachineName]. Returns the [StateMachineController] or null if no
|
/// [stateMachineName]. Returns the [StateMachineController] or null if no
|
||||||
/// [StateMachine] with [stateMachineName] is found.
|
/// [StateMachine] with [stateMachineName] is found.
|
||||||
static StateMachineController? fromArtboard(
|
static StateMachineController? fromArtboard(
|
||||||
Artboard artboard, String stateMachineName) {
|
Artboard artboard,
|
||||||
|
String stateMachineName, {
|
||||||
|
core.OnStateChange? onStateChange,
|
||||||
|
}) {
|
||||||
for (final animation in artboard.animations) {
|
for (final animation in artboard.animations) {
|
||||||
if (animation is StateMachine && animation.name == stateMachineName) {
|
if (animation is StateMachine && animation.name == stateMachineName) {
|
||||||
return StateMachineController(animation);
|
return StateMachineController(animation, onStateChange: onStateChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:rive/src/core/core.dart';
|
import 'package:rive/src/core/core.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:rive/src/rive_core/animation/animation_state_instance.dart';
|
import 'package:rive/src/rive_core/animation/animation_state_instance.dart';
|
||||||
@ -12,6 +13,16 @@ import 'package:rive/src/rive_core/animation/state_machine_layer.dart';
|
|||||||
import 'package:rive/src/rive_core/animation/state_transition.dart';
|
import 'package:rive/src/rive_core/animation/state_transition.dart';
|
||||||
import 'package:rive/src/rive_core/rive_animation_controller.dart';
|
import 'package:rive/src/rive_core/rive_animation_controller.dart';
|
||||||
|
|
||||||
|
import 'animation/animation_state.dart';
|
||||||
|
import 'animation/entry_state.dart';
|
||||||
|
import 'animation/exit_state.dart';
|
||||||
|
|
||||||
|
/// Callback signature for satate machine state changes
|
||||||
|
typedef OnStateChange = void Function(String, String);
|
||||||
|
|
||||||
|
/// Callback signature for layer state changes
|
||||||
|
typedef OnLayerStateChange = void Function(LayerState);
|
||||||
|
|
||||||
class LayerController {
|
class LayerController {
|
||||||
final StateMachineLayer layer;
|
final StateMachineLayer layer;
|
||||||
final StateInstance anyStateInstance;
|
final StateInstance anyStateInstance;
|
||||||
@ -23,7 +34,11 @@ class LayerController {
|
|||||||
double _mix = 1.0;
|
double _mix = 1.0;
|
||||||
double _mixFrom = 1.0;
|
double _mixFrom = 1.0;
|
||||||
|
|
||||||
LayerController(this.layer)
|
/// Optional callback which is called when a state changes
|
||||||
|
/// Takes the state machine name and state name
|
||||||
|
final OnLayerStateChange? onLayerStateChange;
|
||||||
|
|
||||||
|
LayerController(this.layer, {this.onLayerStateChange})
|
||||||
: assert(layer.anyState != null),
|
: assert(layer.anyState != null),
|
||||||
anyStateInstance = layer.anyState!.makeInstance() {
|
anyStateInstance = layer.anyState!.makeInstance() {
|
||||||
_changeState(layer.entryState);
|
_changeState(layer.entryState);
|
||||||
@ -167,6 +182,10 @@ class LayerController {
|
|||||||
// Make sure to reset _waitingForExit to false if we succeed at taking a
|
// Make sure to reset _waitingForExit to false if we succeed at taking a
|
||||||
// transition.
|
// transition.
|
||||||
_waitingForExit = false;
|
_waitingForExit = false;
|
||||||
|
// State has changed, fire the callback if there's one
|
||||||
|
if (_currentState != null) {
|
||||||
|
onLayerStateChange?.call(_currentState!.state);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (allowed == AllowTransition.waitingForExit) {
|
} else if (allowed == AllowTransition.waitingForExit) {
|
||||||
_waitingForExit = true;
|
_waitingForExit = true;
|
||||||
@ -179,9 +198,14 @@ class LayerController {
|
|||||||
class StateMachineController extends RiveAnimationController<CoreContext> {
|
class StateMachineController extends RiveAnimationController<CoreContext> {
|
||||||
final StateMachine stateMachine;
|
final StateMachine stateMachine;
|
||||||
final inputValues = HashMap<int, dynamic>();
|
final inputValues = HashMap<int, dynamic>();
|
||||||
StateMachineController(this.stateMachine);
|
|
||||||
final layerControllers = <LayerController>[];
|
final layerControllers = <LayerController>[];
|
||||||
|
|
||||||
|
/// Optional callback for state changes
|
||||||
|
final OnStateChange? onStateChange;
|
||||||
|
|
||||||
|
/// Constructor that takes a state machine and optional state change callback
|
||||||
|
StateMachineController(this.stateMachine, {this.onStateChange});
|
||||||
|
|
||||||
void _clearLayerControllers() {
|
void _clearLayerControllers() {
|
||||||
for (final layer in layerControllers) {
|
for (final layer in layerControllers) {
|
||||||
layer.dispose();
|
layer.dispose();
|
||||||
@ -189,12 +213,33 @@ class StateMachineController extends RiveAnimationController<CoreContext> {
|
|||||||
layerControllers.clear();
|
layerControllers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles state change callbacks
|
||||||
|
void _onStateChange(LayerState layerState) =>
|
||||||
|
SchedulerBinding.instance?.addPostFrameCallback((_) {
|
||||||
|
String stateName = 'unknown';
|
||||||
|
print('Layer state type ${layerState.runtimeType}');
|
||||||
|
if (layerState is AnimationState && layerState.animation != null) {
|
||||||
|
stateName = layerState.animation!.name;
|
||||||
|
} else if (layerState is EntryState) {
|
||||||
|
stateName = 'EntryState';
|
||||||
|
} else if (layerState is AnyState) {
|
||||||
|
stateName = 'EntryState';
|
||||||
|
} else if (layerState is ExitState) {
|
||||||
|
stateName = 'ExitState';
|
||||||
|
}
|
||||||
|
|
||||||
|
onStateChange?.call(stateMachine.name, stateName);
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool init(CoreContext core) {
|
bool init(CoreContext core) {
|
||||||
_clearLayerControllers();
|
_clearLayerControllers();
|
||||||
|
|
||||||
for (final layer in stateMachine.layers) {
|
for (final layer in stateMachine.layers) {
|
||||||
layerControllers.add(LayerController(layer));
|
layerControllers.add(LayerController(
|
||||||
|
layer,
|
||||||
|
onLayerStateChange: _onStateChange,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure triggers are all reset.
|
// Make sure triggers are all reset.
|
||||||
|
Reference in New Issue
Block a user