Skip to content

Commit

Permalink
8242523: Update the animation and clip envelope classes
Browse files Browse the repository at this point in the history
Reviewed-by: arapte, kcr
  • Loading branch information
nlisker committed Jun 2, 2020
1 parent 1ab653c commit a78b3fb
Show file tree
Hide file tree
Showing 9 changed files with 480 additions and 316 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@

public class TickCalculation {
public static final int TICKS_PER_SECOND = 6000;
private static final double TICKS_PER_MILI = TICKS_PER_SECOND / 1000.0;
private static final double TICKS_PER_NANO = TICKS_PER_MILI * 1e-6;
private static final double TICKS_PER_MILLI = TICKS_PER_SECOND / 1000.0;
private static final double TICKS_PER_NANO = TICKS_PER_MILLI * 1e-6;

private TickCalculation() {}

Expand Down Expand Up @@ -71,7 +71,7 @@ public static long sub(long op1, long op2) {
}

public static long fromMillis(double millis) {
return Math.round(TICKS_PER_MILI * millis);
return Math.round(TICKS_PER_MILLI * millis);
}

public static long fromNano(long nano) {
Expand All @@ -83,15 +83,15 @@ public static long fromDuration(Duration duration) {
}

public static long fromDuration(Duration duration, double rate) {
return Math.round(TICKS_PER_MILI * duration.toMillis() / Math.abs(rate));
return Math.round(TICKS_PER_MILLI * duration.toMillis() / Math.abs(rate));
}

public static Duration toDuration(long ticks) {
return Duration.millis(toMillis(ticks));
}

public static double toMillis(long ticks) {
return ticks / TICKS_PER_MILI;
return ticks / TICKS_PER_MILLI;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ public static double clamp(double min, double value, double max) {
return value;
}

/**
* Simple utility function which clamps the given value to be strictly
* between the min and max values.
*/
public static long clamp(long min, long value, long max) {
if (value < min) return min;
if (value > max) return max;
return value;
}

/**
* Simple utility function which clamps the given value to be strictly
* above the min value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,29 @@
* implementation plus eventually some fast-track implementations for common use
* cases.
*/

public abstract class ClipEnvelope {

protected static final long INDEFINITE = Long.MAX_VALUE;
protected static final double EPSILON = 1e-12;

protected Animation animation;

/**
* The rate of the animation that is used to calculate the current rate of an animation.
* It is the same as animation.rate, only ignores animation.rate = 0, so can never be 0.
*/
protected double rate = 1;

/**
* The number of ticks in a single cycle. Calculated from the cycle duration. Always >=0.
*/
protected long cycleTicks = 0;

// internal state-variables used by all implementations
protected long deltaTicks = 0;

/**
* The current position of the play head. 0 <= ticks <= totalTicks
*/
protected long ticks = 0;
protected double currentRate = rate;
protected boolean inTimePulse = false;
Expand All @@ -63,8 +74,7 @@ public abstract class ClipEnvelope {
protected ClipEnvelope(Animation animation) {
this.animation = animation;
if (animation != null) {
final Duration cycleDuration = animation.getCycleDuration();
cycleTicks = TickCalculation.fromDuration(cycleDuration);
cycleTicks = TickCalculation.fromDuration(animation.getCycleDuration());
rate = animation.getRate();
}
}
Expand All @@ -79,10 +89,29 @@ public static ClipEnvelope create(Animation animation) {
}
}

public abstract ClipEnvelope setCycleDuration(Duration cycleDuration);
public abstract void setRate(double rate);
public abstract void setAutoReverse(boolean autoReverse);
public abstract ClipEnvelope setCycleDuration(Duration cycleDuration);
public abstract ClipEnvelope setCycleCount(int cycleCount);
public abstract void setRate(double rate);

protected abstract double calculateCurrentRate();

protected void setInternalCurrentRate(double currentRate) {
this.currentRate = currentRate;
}

protected void setCurrentRate(double currentRate) {
this.currentRate = currentRate;
AnimationAccessor.getDefault().setCurrentRate(animation, currentRate);
}

public double getCurrentRate() {
return currentRate;
}

protected long ticksRateChange(double newRate) {
return Math.round((ticks - deltaTicks) * newRate / rate);
}

protected void updateCycleTicks(Duration cycleDuration) {
cycleTicks = TickCalculation.fromDuration(cycleDuration);
Expand All @@ -101,29 +130,10 @@ public void start() {

public abstract void jumpTo(long ticks);

public void abortCurrentPulse() {
public final void abortCurrentPulse() {
if (inTimePulse) {
aborted = true;
inTimePulse = false;
}
}

protected abstract double calculateCurrentRate();

protected void setInternalCurrentRate(double currentRate) {
this.currentRate = currentRate;
}

protected void setCurrentRate(double currentRate) {
this.currentRate = currentRate;
AnimationAccessor.getDefault().setCurrentRate(animation, currentRate);
}

protected static long checkBounds(long value, long max) {
return Math.max(0L, Math.min(value, max));
}

public double getCurrentRate() {
return currentRate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,19 @@

package com.sun.scenario.animation.shared;

import com.sun.javafx.util.Utils;

import javafx.animation.Animation;
import javafx.animation.Animation.Status;
import javafx.util.Duration;

public class FiniteClipEnvelope extends ClipEnvelope {
/**
* Clip envelope implementation for multi-cycles: cycleCount != (1 or indefinite) and cycleDuration != indefinite
*/
public class FiniteClipEnvelope extends MultiLoopClipEnvelope {

private boolean autoReverse;
private int cycleCount;
private long totalTicks;
private long pos;

protected FiniteClipEnvelope(Animation animation) {
super(animation);
Expand All @@ -45,17 +48,6 @@ protected FiniteClipEnvelope(Animation animation) {
updateTotalTicks();
}

@Override
public void setAutoReverse(boolean autoReverse) {
this.autoReverse = autoReverse;
}

@Override
protected double calculateCurrentRate() {
return !autoReverse? rate
: (ticks % (2 * cycleTicks) < cycleTicks) == (rate > 0)? rate : -rate;
}

@Override
public ClipEnvelope setCycleDuration(Duration cycleDuration) {
if (cycleDuration.isIndefinite()) {
Expand All @@ -77,17 +69,23 @@ public ClipEnvelope setCycleCount(int cycleCount) {
}

@Override
public void setRate(double rate) {
final boolean toggled = rate * this.rate < 0;
final long newTicks = toggled? totalTicks - ticks : ticks;
public void setRate(double newRate) {
final boolean toggled = isDirectionChanged(newRate);
final long newTicks = toggled ? totalTicks - ticks : ticks;
final Status status = animation.getStatus();
if (status != Status.STOPPED) {
setInternalCurrentRate((Math.abs(currentRate - this.rate) < EPSILON) ? rate : -rate);
deltaTicks = newTicks - Math.round((ticks - deltaTicks) * Math.abs(rate / this.rate));
setInternalCurrentRate((Math.abs(currentRate - rate) < EPSILON) ? newRate : -newRate);
deltaTicks = newTicks - ticksRateChange(newRate);
abortCurrentPulse();
}
ticks = newTicks;
this.rate = rate;
rate = newRate;
}

@Override
protected double calculateCurrentRate() {
return !autoReverse ? rate
: isDuringEvenCycle() == (rate > 0) ? rate : -rate;
}

private void updateTotalTicks() {
Expand All @@ -104,7 +102,8 @@ public void timePulse(long currentTick) {

try {
final long oldTicks = ticks;
ticks = ClipEnvelope.checkBounds(deltaTicks + Math.round(currentTick * Math.abs(rate)), totalTicks);
long ticksChange = Math.round(currentTick * Math.abs(rate));
ticks = Utils.clamp(0, deltaTicks + ticksChange, totalTicks);

final boolean reachedEnd = ticks >= totalTicks;

Expand All @@ -113,13 +112,13 @@ public void timePulse(long currentTick) {
return;
}

long cycleDelta = (currentRate > 0)? cycleTicks - pos : pos; // delta to reach end of cycle
long cycleDelta = (currentRate > 0) ? cycleTicks - cyclePos : cyclePos; // delta to reach end of cycle

while (overallDelta >= cycleDelta) {
if (cycleDelta > 0) {
pos = (currentRate > 0)? cycleTicks : 0;
cyclePos = (currentRate > 0)? cycleTicks : 0;
overallDelta -= cycleDelta;
AnimationAccessor.getDefault().playTo(animation, pos, cycleTicks);
AnimationAccessor.getDefault().playTo(animation, cyclePos, cycleTicks);
if (aborted) {
return;
}
Expand All @@ -129,16 +128,16 @@ public void timePulse(long currentTick) {
if (autoReverse) {
setCurrentRate(-currentRate);
} else {
pos = (currentRate > 0)? 0 : cycleTicks;
AnimationAccessor.getDefault().jumpTo(animation, pos, cycleTicks, false);
cyclePos = (currentRate > 0)? 0 : cycleTicks;
AnimationAccessor.getDefault().jumpTo(animation, cyclePos, cycleTicks, false);
}
}
cycleDelta = cycleTicks;
}

if (overallDelta > 0 && !reachedEnd) {
pos += (currentRate > 0)? overallDelta : -overallDelta;
AnimationAccessor.getDefault().playTo(animation, pos, cycleTicks);
cyclePos += (currentRate > 0) ? overallDelta : -overallDelta;
AnimationAccessor.getDefault().playTo(animation, cyclePos, cycleTicks);
}

if(reachedEnd && !aborted) {
Expand All @@ -160,36 +159,35 @@ public void jumpTo(long newTicks) {
if (rate < 0) {
newTicks = totalTicks - newTicks;
}
ticks = ClipEnvelope.checkBounds(newTicks, totalTicks);
ticks = Utils.clamp(0, newTicks, totalTicks);
final long delta = ticks - oldTicks;
if (delta != 0) {
deltaTicks += delta;
if (autoReverse) {
final boolean forward = ticks % (2 * cycleTicks) < cycleTicks;
if (forward == (rate > 0)) {
pos = ticks % cycleTicks;
cyclePos = ticks % cycleTicks;
if (animation.getStatus() == Status.RUNNING) {
setCurrentRate(Math.abs(rate));
}
} else {
pos = cycleTicks - (ticks % cycleTicks);
cyclePos = cycleTicks - (ticks % cycleTicks);
if (animation.getStatus() == Status.RUNNING) {
setCurrentRate(-Math.abs(rate));
}
}
} else {
pos = ticks % cycleTicks;
cyclePos = ticks % cycleTicks;
if (rate < 0) {
pos = cycleTicks - pos;
cyclePos = cycleTicks - cyclePos;
}
if ((pos == 0) && (ticks > 0)) {
pos = cycleTicks;
if ((cyclePos == 0) && (ticks > 0)) {
cyclePos = cycleTicks;
}
}

AnimationAccessor.getDefault().jumpTo(animation, pos, cycleTicks, false);
AnimationAccessor.getDefault().jumpTo(animation, cyclePos, cycleTicks, false);
abortCurrentPulse();
}
}

}
Loading

0 comments on commit a78b3fb

Please sign in to comment.