Skip to content
New issue

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

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

Already on GitHub? # to your account

feat: Adding callbacks for EffectController (#1926) #1931

Merged
merged 10 commits into from
Sep 23, 2022
8 changes: 8 additions & 0 deletions doc/flame/effects.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ EffectController({
int? repeatCount,
bool infinite = false,
double startDelay = 0.0,
VoidCallback? onPeak,
VoidCallback? onReversePeak,
});
```

Expand Down Expand Up @@ -397,6 +399,12 @@ EffectController({
Using this parameter is the simplest way to create a chain of effects that execute one after
another (or with an overlap).

- *`onPeak`* -- callback function which will be invoked right after reaching its max progress and
before the optional pause and reverse stage.

- *`onReversePeak`* -- callback function which will be invoked right after reaching its lowest progress
at the end of the reverse stage and before the optional pause and forward stage.

The effect controller returned by this factory constructor will be composited of multiple simpler
effect controllers described further below. If this constructor proves to be too limited for your
needs, you can always create your own combination from the same building blocks.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'dart:ui';
import 'package:flame/effects.dart';

/// The [callback] will be invoked once the effect's [progress] is reached.
/// 1.0 to match `duration` or 0.0 to match when the `reverseDuration`
/// has been reached.
class CallbackController extends DurationEffectController {
CallbackController({required this.callback, required double progress})
: _progress = progress,
super(0.0);

final VoidCallback callback;
final double _progress;

@override
double get progress => _progress;

@override
bool get completed => true;

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

@override
double recede(double dt) {
callback();
return dt;
}
}
19 changes: 19 additions & 0 deletions packages/flame/lib/src/effects/controllers/effect_controller.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import 'dart:ui';

import 'package:flame/src/effects/controllers/callback_controller.dart';
import 'package:flame/src/effects/controllers/curved_effect_controller.dart';
import 'package:flame/src/effects/controllers/delayed_effect_controller.dart';
import 'package:flame/src/effects/controllers/infinite_effect_controller.dart';
Expand Down Expand Up @@ -71,6 +74,10 @@ abstract class EffectController {
/// If the animation is finite and there are no "backward" or "atMin" stages
/// then the animation will complete at `progress == 1`, otherwise it will
/// complete at `progress == 0`.
///
/// Before [atMaxDuration] and [atMinDuration] a callback function can be
/// provided which will be called after the corresponding [progress] has
/// finished.
factory EffectController({
double? duration,
double? speed,
Expand All @@ -84,6 +91,8 @@ abstract class EffectController {
double startDelay = 0.0,
double atMaxDuration = 0.0,
double atMinDuration = 0.0,
VoidCallback? onPeak,
VoidCallback? onReversePeak,
}) {
assert(
(duration ?? 1) >= 0,
Expand Down Expand Up @@ -155,6 +164,11 @@ abstract class EffectController {
);
}

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

// AT-MAX
if (atMaxDuration != 0) {
items.add(PauseEffectController(atMaxDuration, progress: 1.0));
Expand Down Expand Up @@ -193,6 +207,11 @@ abstract class EffectController {
}
}

// ON REVERSE PEAK CALLBACK
if (onReversePeak != null) {
items.add(CallbackController(callback: onReversePeak, progress: 0.0));
}

// AT-MIN
if (atMinDuration != 0) {
items.add(PauseEffectController(atMinDuration, progress: 0.0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ import 'package:flame/game.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter/animation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

abstract class Callback {
void call();
}

class CallbackMock extends Mock implements Callback {}

void main() {
group('EffectController', () {
Expand Down Expand Up @@ -312,6 +319,38 @@ void main() {
);
});

test('onPeak and onReversePeak callbacks', () {
final mockOnPeak = CallbackMock();
final mockOnReversePeak = CallbackMock();
final ec = EffectController(
duration: 1,
reverseDuration: 1,
onPeak: mockOnPeak,
onReversePeak: mockOnReversePeak,
infinite: true,
);

ec.advance(1);
verifyNever(mockOnPeak.call);
verifyNever(mockOnReversePeak.call);

ec.advance(0.1);
verify(mockOnPeak.call).called(1);
verifyNever(mockOnReversePeak.call);

ec.advance(1); // after this call a .setToStart() is performed
verifyNever(mockOnPeak.call);
verify(mockOnReversePeak.call).called(1);

ec.advance(0.5);
verifyNever(mockOnPeak.call);
verifyNever(mockOnReversePeak.call);

ec.advance(0.5);
verify(mockOnPeak.call).called(1);
verifyNever(mockOnReversePeak.call);
});

group('errors', () {
test('empty', () {
expect(
Expand Down