Reputation: 103
I have a .riv file created with Rive 2. It contains multiple animations.
I want to play a default animation but change it depending on an input from a stream.
The below code only plays the 'default' animation and isn't updating even if the switch case changes. The code jumps into the right switch case statement, I checked that with logging. But the animation isn't changing.
How can I play a different animation from the Rive artboard?
The State Class:
class _GraphicState extends State<Graphic> {
final riveFileName = 'assets/rive/character.riv';
Artboard _artboard;
@override
void initState() {
_loadRiveFile();
super.initState();
}
// loads a Rive file
void _loadRiveFile() async {
final bytes = await rootBundle.load(riveFileName);
final file = RiveFile();
if (file.import(bytes)) {
// Select an animation by its name
setState(() => _artboard = file.mainArtboard
..addController(
SimpleAnimation('default'),
));
}
}
The build function:
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: widget.gameStageBloc.hangingParts,
builder: (BuildContext ctx, AsyncSnapshot<int> status) {
return Container(
width: 350.0,
height: 350.0,
child: Align(
alignment: Alignment.topCenter,
child: Container(
width: 350.0,
height: 350.0,
child: selectGraphic(status),
),
),
);
});
}
The custom function to return the correct animation:
Widget selectGraphic(state) {
if (_artboard != null) {
switch (state) {
case 1:
_artboard.artboard..addController(SimpleAnimation('run'));
break;
case 2:
_artboard.artboard..addController(SimpleAnimation('stand'));
break;
case 3:
_artboard.artboard..addController(SimpleAnimation('dead'));
break;
default:
_artboard.artboard..addController(SimpleAnimation('default'));
}
return Rive(
artboard: _artboard,
fit: BoxFit.cover,
);
} else {
return Container();
}
}
Upvotes: 4
Views: 2720
Reputation: 1261
Well, you can use 'Mixing Rive animations' reference
Code:
AnimationController animationController;
final String animationSell = "sell_item";
final String animationAdd = "add_item";
final String animationEmpty = "empty_cart";
final riveFileName = 'assets/animation/cart.riv';
Artboard _artboard;
RiveAnimationController _wipersController;
@override
void initState() {
_loadRiveFile();
super.initState();
}
void _loadRiveFile() async {
final bytes = await rootBundle.load(riveFileName);
final file = rive.RiveFile();
if (file.import(bytes)) {
setState(() => _artboard = file.mainArtboard..addController(rive.SimpleAnimation(animationSell)));
}
}
void _wipersChange(KartState state) {
switch (state.index) {
case 0:
_artboard.addController(
_wipersController = rive.SimpleAnimation(animationEmpty),
);
break;
case 1:
_artboard.addController(
_wipersController = rive.SimpleAnimation(animationAdd),
);
break;
case 2:
_artboard.addController(
_wipersController = rive.SimpleAnimation(animationSell),
);
break;
default:
_artboard.addController(
_wipersController = rive.SimpleAnimation(animationEmpty),
);
}
}
And put the widget anywhere
Container(
height: 100.0, width: 100.0,
child: Rive(
artboard: _artboard,
fit: BoxFit.scaleDown,
alignment: Alignment.center,
),
)
Upvotes: 0
Reputation: 89
Try to call setState(() => {})
every time you do _artboard.artboard..addController
Upvotes: 0