2d-inc / Flare-Flutter

Load and get full control of your Rive files in a Flutter project using this library.
https://rive.app/
MIT License
2.55k stars 469 forks source link

Added playSpeed property to control the speed of the animation. Added… #188

Closed ovidiu-anghelina closed 4 years ago

ovidiu-anghelina commented 4 years ago

… loop property to control whether the animation loops or not. The callback is now invoked for looping animations too, at the end of each loop.

Those are some very small changes and additions that should make the life of any Flutter developer dealing with Flare a lot easier.

playSpeed - allows changing the speed of the animation. Setting it to 2 would play an animation twice as fast, while setting it to 0.5 would play it twice as slow. No known side effects.

loop - allows the developer to control whether the animation should loop or not. It happened too many times to me already where the designer forgot the loop toggle on while exporting because it helps him while designing the animation, and then I need to update my work ticket to Blocked, write emails to the designer explaining that the loop toggle is not just an editor feature but the actual result of his export, wait for him to get out of meetings and fix it and send the new file to me, and then I can actually finish my ticket after context switching several times because of this silly inconvenience. Or you could just let the devs set this flag instead. Side effects - the loop flag within the .flr file is ignored, therefore a breaking change.

callback - you have a callback feature, but it only works for animations that don't loop. Invoking it for looping animations is a matter of 2 more lines of code, so I don't understand why you haven't done this already. This makes even more sense once you allow the devs to control the 'loop' flag, because it means the outcome is deterministic - the dev will know exactly how and when the callback will be invoked based on whether the animation is looping or not. This is also a breaking change because the callback will be invoked in situations where previously it wasn't invoked (looping animations).

I'm impressed by the complexity and the low-level code that goes into this plugin, and at the same time baffled by the lack of very simple, easy to implement, productive features.

ovidiu-anghelina commented 4 years ago

Can anyone please review/comment on this? No feedback at all in a whole month now :(

umberto-sonnino commented 4 years ago

@ovidiu-anghelina apologies for not getting back to you sooner, we've been discussing this internally!

What you proposed can work, but these additions can be also implemented in a custom FlareController. FlareActor's behavior shouldn't differ from the Editor, and adding more parameters to it might make it a bit too bloated.

jonas-zebari commented 4 years ago

@umberto-sonnino @ovidiu-anghelina Perhaps it would be useful to provide multiple default implementations of a FlareController other than FlareControls, each with their own parameters? It would also be a good source to learn about how FlareActor and FlareController actually works.

praharshbhatt commented 4 years ago

What you proposed can work, but these additions can be also implemented in a custom FlareController.

I've tried with custom FlareController, although there is no change in speed of the animation

umberto-sonnino commented 4 years ago

Hey @praharshbhatt could you share your attempt? Maybe I can help..!

praharshbhatt commented 4 years ago

So I am using these files for animating: https://rive.app/explore/popular/trending/all#files:kQcnhE

Code:

Defining a controller

  //Breathing animation controller
  SlowMoController _flareController = SlowMoController("Artboard");

FlareActor:

FlareActor( "assets/animations/breathe_in_green.flr",
                  alignment: Alignment.center,
                  animation: "Breathing",
                  artboard: "Artboard",
                  controller: _flareController,
                ),

I try to control the Speed like this:

_flareController = SlowMoController("Artboard", speed: 2);

SlowMoController (SlowMoController.dart) is defined as:

import 'package:flare_flutter/flare.dart';
import 'package:flare_flutter/flare_controller.dart';

class SlowMoController extends FlareController {
  final String animationName;
  ActorAnimation _animation;
  double speed;
  double _time = 0;

  SlowMoController(this.animationName, {this.speed = 2});

  @override
  bool advance(FlutterActorArtboard artboard, double elapsed) {
    if (_animation == null) {
      return false;
    }
    if (_animation.isLooping) {
      _time %= _animation.duration;
    }
    _animation.apply(_time, artboard, 1.0);
    _time += elapsed * speed;
    // Stop advancing if animation is done and we're not looping.
    return _animation.isLooping || _time < _animation.duration;
  }

  @override
  void initialize(FlutterActorArtboard artboard) {
    _animation = artboard.getAnimation(animationName);
  }

  @override
  void setViewTransform(viewTransform) {
    // intentionally empty, we don't need the viewTransform in this controller
  }
}
umberto-sonnino commented 4 years ago

Hey @praharshbhatt, the link you sent is for the explore page on the website, you might want to pass a direct link to the single files, or your own profile on Rive.

I took a look at your snippet, and when passing an animation name to your FlareActor, that is the animation that is going to be played by that FlareActor. With controllers you can control your animation as you please, meaning that you need to first grab a reference to the animation, and then you can advance it with your own function. In the Controller initialize function you're fetching a reference to the animation called "Artboard". Is that right? Are you sure that the advance method for the controller is effectively advancing?

praharshbhatt commented 4 years ago

I just got this working! I was passing the artboard name instead of the animation-name 🤦‍♂️ Thanks for the clarification, @umberto-sonnino