Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FlareActor callback never called #198

Open
workerbee22 opened this issue Dec 2, 2019 · 3 comments
Open

FlareActor callback never called #198

workerbee22 opened this issue Dec 2, 2019 · 3 comments

Comments

@workerbee22
Copy link

Continuing to try and get a basic countdown going. Sample code uses the flare speed control example https://github.com/luigi-rosso/flare_control_speed_example/blob/master/lib/main.dart

Using flare_flutter 1.7.3

This code never prints"finished":

import 'package:flutter/material.dart';

import 'dart:async';   // for Timer

import 'package:flutter/material.dart';

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

import 'package:flare_dart/math/mat2d.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flare Single Digit',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flare Single Digit'),
    );
  }
}

/// Flare related -----------------------------------------------------------------------------------------

/// From Flare contact, see issue https://github.com/2d-inc/Flare-Flutter/issues/167
/// Sample code here: https://github.com/luigi-rosso/flare_control_speed_example/blob/master/lib/main.dart
class SpeedController extends FlareController {

  final String animationName;
  ActorAnimation _animation;
  double speed;
  double _time = 0;

  // Optional param spped defaults to 1 if not provided
  SpeedController(this.animationName, {this.speed = 1});

  @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(Mat2D viewTransform) {
    // intentionally empty, we don't need the viewTransform in this controller
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  int digit = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            SizedBox(
              height: 150,
              width: 80,

              /// FlareActor()
              // Use controller to specify which animation and see above controls speed and thus duration
              // but the artboard ie. the digit is passed in here
              child: Digit(digit),
            ),

            RaisedButton(
              child: Text(
                "Next",
              ),
              elevation: 2.0,
              onPressed: () {
                setState(() {
                  if(digit == 9) {
                    digit = 0;
                  } else {
                    digit = digit + 1;
                  }
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

// Digit - single digit using the flare SpeedController
class Digit extends StatefulWidget {

  final int digitNew;

  Digit(this.digitNew);

  @override
  _DigitState createState() => _DigitState();
}

class _DigitState extends State<Digit> {

  SpeedController controller;

  @override
  void initState() {
    super.initState();
    // Instantiate a speed controlled controller for the animation
    controller = SpeedController("in", speed: 0.1);
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    return Container(
      margin: const EdgeInsets.all(0.0),
      padding: const EdgeInsets.all(0.0),
      child: Stack(
          children: <Widget>[
            SizedBox(
              height: 150,
              width: 80,

              /// FlareActor()
              // Use controller to specify which animation and see above controls speed and thus duration
              // but the artboard ie. the digit is passed in here
              child: FlareActor(
                "assets/io_2018_digits.flr",
                controller: controller,
                artboard: widget.digitNew.toString(),
                fit: BoxFit.contain,
                callback: (value) {
                  print('finished?');
                },
              ),
            ),

          ]
      ),
    );
  }
}
@umberto-sonnino
Copy link
Contributor

umberto-sonnino commented Dec 3, 2019

The callback registered within FlareActor is used on the animations that are played through FlareActor only.
Since you're playing animations with your SpeedController, you should add a callback parameter to that as well:

class SpeedController extends FlareController {
  [...]
  FlareCompletedCallback onAnimationCompleted;

  // Optional param spped defaults to 1 if not provided
  SpeedController(this.animationName, {this.speed = 1, this.onAnimationCompleted});

  @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;

    if (_time > _animation.duration && onAnimationCompleted != null) {
      onAnimationCompleted(_animation.name);
    }
    // Stop advancing if animation is done and we're not looping.
    return _animation.isLooping || _time < _animation.duration;
  }
  [...]
}

@workerbee22
Copy link
Author

Thanks @umberto-sonnino but is there any documentation on how FlareCompletedCallback works? Changes above crash when onAnimationCompleted(_animation.name); is executed.

@umberto-sonnino
Copy link
Contributor

FlareCompletedCallback is just a type definition:
typedef void FlareCompletedCallback(String name);
It is a function that takes a String parameter and doesn't return any value.

In the snippet above, you need to specify a callback in the constructor for it to not crash. I'll update it with a null check!
And when instantiating your SpeedController:

SpeedController(
 myAnimationName,
 onAnimationCompleted: (name) {
  print("Animation $name completed!");
 }
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants