rive-app / rive-flutter

Flutter runtime for Rive
https://rive.app
MIT License
1.16k stars 180 forks source link

Enable controlling animations durations for each trigger from the Flutter side #393

Open azatech opened 1 month ago

azatech commented 1 month ago

Description

The main idea is that I'm using the Visemes, which comprises a total of 22 visemes (animated from 0 to 1). All 'Visemes' created in Rive with identical animation durations of 10ms, for instance.

Depending on the Viseme, I'll trigger one of the 22 animations within a specific time frame, resulting in an animated-speaking avatar.

Question 1

Is it possible to control the animation speed of each trigger and adjust it dynamically, not limited to the constant animation duration of 10ms from Rive, but rather allowing control and dynamic adjustment on the Flutter side? For instance: Setting one trigger animation to 200ms and then to 3ms, and so on.

Question 2

Additionally, here's what I found online: link Was this done on the Rive or Flutter side? Were the joysticks controlled from the Flutter side? P.S. How would you suggest creating something similar on the Flutter side?

Video

In the video, I have 2 triggers, and I need to set a custom duration for each trigger animation every time from Flutter code. I've reviewed the 'apply()' method, but I believe I may be using it incorrectly.

Code

class _VisemeRiveAnimationPageState extends State<VisemeRiveAnimationPage> {
  StateMachineController? stateMachineController;
  SMITrigger? trigger;
  SMITrigger? trigger2;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Stack(
          alignment: Alignment.bottomCenter,
          children: [
            RiveAnimation.asset(
              "assets/rive/man.riv",
              onInit: (artboard) {
                final stateMachine = StateMachineController.fromArtboard(
                  artboard,
                  'State Machine 1',
                )!;
                trigger = stateMachine.getTriggerInput('0');
                trigger2 = stateMachine.getTriggerInput('1');

                artboard.addController(stateMachine);
                /// I've reviewed the 'apply' method, but I believe I may be using it incorrectly.
                artboard.linearAnimations.first
                    .apply(3.2, coreContext: artboard.context);

                artboard.linearAnimations
                    .toList()[1]
                    .apply(3.2, coreContext: artboard.context);
              },
            ),
            Column(
              children: [
                const SizedBox(height: 50),
                ElevatedButton(
                  onPressed: () => trigger?.fire(),
                  child: const Text('0'),
                ),
                const SizedBox(height: 20),
                ElevatedButton(
                  onPressed: () => trigger2?.fire(),
                  child: const Text('1'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}