flame icon indicating copy to clipboard operation
flame copied to clipboard

[flame] Allow InfiniteEffectController be stopped

Open rivella50 opened this issue 3 years ago • 2 comments

What could be improved

It should be possible that a running InfiniteEffectController can be stopped.

Why should this be improved

Since InfiniteEffectController simplifies running a repeating effect (also without knowing the amount of steps yet) it would be great if that controller could be stopped from outside by considering the 2 possible end cycles (after completing duration and/or reverseDuration), i.e. by not just removing the effect from its parent in the middle of running the effect.

Any risks?

My current suggestion would allow defining 2 callback functions in the EffectController factory:

factory EffectController({
    double? duration,
    double? speed,
    Curve curve = Curves.linear,
    double? reverseDuration,
    double? reverseSpeed,
    Curve? reverseCurve,
    bool infinite = false,
    bool alternate = false,
    int? repeatCount,
    double startDelay = 0.0,
    double atMaxDuration = 0.0,
    double atMinDuration = 0.0,
    VoidCallback? onPeak,
    VoidCallback? onReversePeak,
  })

More information

A new CallbackController would be created and inserted in EffectController just before checking atMaxDuration and atMinDuration:

// ON PEAK CALLBACK
if (onPeak != null) {
  items.add(CallbackController(onPeak, 1.0));
}

// AT-MAX
if (atMaxDuration != 0) {
  items.add(PauseEffectController(atMaxDuration, progress: 1.0));
}
// ON REVERSE PEAK CALLBACK
if (onReversePeak != null) {
  items.add(CallbackController(onReversePeak, 0.0));
}

// AT-MIN
if (atMinDuration != 0) {
  items.add(PauseEffectController(atMinDuration, progress: 0.0));
}

The CallbackController looks like this:

import 'dart:ui';
import 'package:flame/effects.dart';

class CallbackController extends DurationEffectController {
  CallbackController(this.callback, this._progress) : super(0.0);

  final VoidCallback callback;

  final double _progress;

  @override
  double get progress => _progress;

  @override
  bool get completed => false;


  @override
  double advance(double dt) {
    callback();
    return 0.1;
  }

  @override
  double recede(double dt) {
    callback();
    return 0.1;
  }
}

With that implementation a cycle will be finished before onPeak or onReversePeak callbacks will be invoked. I'm curious what you think about it - i've talked about this suggestion quite a lot to spydon and DevKage on Discord channel. These callbacks can of course also be used for other purposes and therefore will not only improve InfiniteEffectController.

rivella50 avatar Sep 20 '22 12:09 rivella50

@st-pasha what do you think of this design?

spydon avatar Sep 20 '22 13:09 spydon

Yes, this sounds reasonable.

st-pasha avatar Sep 20 '22 18:09 st-pasha