-
-
Notifications
You must be signed in to change notification settings - Fork 905
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
feat!: New AlternatePattern
argument for SequenceEffect
#3322
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,7 @@ class MoveToEffect extends MoveEffect { | |
@override | ||
void apply(double progress) { | ||
final dProgress = progress - previousProgress; | ||
target.position += _offset * dProgress; | ||
target.position += _offset * dProgress.abs(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, is this really correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After thinking about it some more yesterday I think the issue wasn't the reflected vector itself, but rather that the direction vector was incorrect when the camera has a viewport-aware bounds behavior. This causes it to never reach its destination and so the reflective vector is incorrect. That's why taking the absolute value was ok after I added the step to recalculate the vector. The camera won't be the only component that may never complete its effect with regards to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But this will potentially overshoot the destination right? And also it won't be matching the time anymore? |
||
} | ||
|
||
@override | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,13 +5,13 @@ import 'package:flame/src/effects/effect.dart'; | |
|
||
EffectController _createController({ | ||
required List<Effect> effects, | ||
required bool alternate, | ||
required AlternatePattern alternatePattern, | ||
required bool infinite, | ||
required int repeatCount, | ||
}) { | ||
EffectController ec = _SequenceEffectEffectController( | ||
effects, | ||
alternate: alternate, | ||
alternatePattern: alternatePattern, | ||
); | ||
if (infinite) { | ||
ec = InfiniteEffectController(ec); | ||
|
@@ -22,6 +22,32 @@ EffectController _createController({ | |
return ec; | ||
} | ||
|
||
/// Specifies how to alternate a [SequenceEffect] pattern. | ||
/// | ||
/// If [AlternatePattern.none] is provided, then | ||
/// the [SequenceEffect] does not repeat in reverse when the child | ||
/// [Effect]s have all completed playing. | ||
/// | ||
/// When [SequenceEffect] is provided a pattern other than | ||
/// [AlternatePattern.none], the sequence will repeat in the | ||
/// reverse order, doubling the length of [EffectController.duration]. | ||
/// | ||
/// [AlternatePattern.includeLast] will replay the last [Effect] at the start | ||
/// of the alternate pattern, effectively playing it twice in a row. | ||
/// | ||
/// [AlternatePattern.excludeLast] will not replay the last [Effect] and will | ||
/// jump to the second-to-last [Effect], if available, at the start of the | ||
/// alternate pattern instead, effectively playing the last [Effect] only once | ||
/// throughout the original and alternating pattern. | ||
enum AlternatePattern { | ||
none(0), | ||
includeLast(1), | ||
excludeLast(2); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It already behaved this way. Only the last one was ever being repeated. |
||
|
||
final int value; | ||
const AlternatePattern(this.value); | ||
} | ||
|
||
/// Run multiple effects in a sequence, one after another. | ||
/// | ||
/// The provided effects will be added as child components; however the custom | ||
|
@@ -48,7 +74,7 @@ EffectController _createController({ | |
class SequenceEffect extends Effect { | ||
SequenceEffect( | ||
List<Effect> effects, { | ||
bool alternate = false, | ||
AlternatePattern? alternatePattern = AlternatePattern.none, | ||
bool infinite = false, | ||
int repeatCount = 1, | ||
super.onComplete, | ||
|
@@ -62,7 +88,7 @@ class SequenceEffect extends Effect { | |
super( | ||
_createController( | ||
effects: effects, | ||
alternate: alternate, | ||
alternatePattern: alternatePattern!, | ||
infinite: infinite, | ||
repeatCount: repeatCount, | ||
), | ||
|
@@ -92,15 +118,16 @@ class SequenceEffect extends Effect { | |
class _SequenceEffectEffectController extends EffectController { | ||
_SequenceEffectEffectController( | ||
this.effects, { | ||
required this.alternate, | ||
required this.alternatePattern, | ||
}) : super.empty(); | ||
|
||
/// The list of children effects. | ||
final List<Effect> effects; | ||
|
||
/// If this flag is true, then after the sequence runs to the end, it will | ||
/// run again in the reverse order. | ||
final bool alternate; | ||
/// If this flag is not [AlternatePattern.none], then after the sequence runs | ||
/// to the end, it will run again in the reverse order according to the policy | ||
/// of the [AlternatePattern] value provided. | ||
final AlternatePattern alternatePattern; | ||
|
||
/// Index of the currently running effect within the [effects] list. If there | ||
/// are n effects in total, then this runs as 0, 1, ..., n-1. After that, if | ||
|
@@ -124,7 +151,7 @@ class _SequenceEffectEffectController extends EffectController { | |
for (final effect in effects) { | ||
totalDuration += effect.controller.duration ?? 0; | ||
} | ||
if (alternate) { | ||
if (alternatePattern != AlternatePattern.none) { | ||
totalDuration *= 2; | ||
} | ||
return totalDuration; | ||
|
@@ -136,7 +163,7 @@ class _SequenceEffectEffectController extends EffectController { | |
} | ||
|
||
@override | ||
double get progress => (_index + 1) / n; | ||
double get progress => (_index < 0 ? -_index : _index + 1) / n; | ||
|
||
@override | ||
double advance(double dt) { | ||
|
@@ -147,10 +174,13 @@ class _SequenceEffectEffectController extends EffectController { | |
if (t > 0) { | ||
_index += 1; | ||
if (_index == n) { | ||
if (alternate) { | ||
_index = -1; | ||
} else { | ||
_index = n - 1; | ||
_index = switch (alternatePattern) { | ||
AlternatePattern.includeLast => -1, | ||
AlternatePattern.excludeLast => -2, | ||
AlternatePattern.none => n - 1, | ||
}; | ||
|
||
if (_index == n - 1) { | ||
_completed = true; | ||
break; | ||
} | ||
|
@@ -208,13 +238,18 @@ class _SequenceEffectEffectController extends EffectController { | |
|
||
@override | ||
void setToEnd() { | ||
if (alternate) { | ||
_index = -n; | ||
effects.forEach((e) => e.reset()); | ||
} else { | ||
_index = n - 1; | ||
_index = switch (alternatePattern) { | ||
AlternatePattern.includeLast => -n, | ||
AlternatePattern.excludeLast => -n + 1, | ||
AlternatePattern.none => n - 1, | ||
}; | ||
|
||
if (_index == n - 1) { | ||
effects.forEach((e) => e.resetToEnd()); | ||
} else { | ||
effects.forEach((e) => e.reset()); | ||
} | ||
|
||
_completed = true; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be done additionally to
alternate
, so that it's not a breaking change, and also follows the same pattern as the other effects.