Skip to content

Added a Loop tween to Tweens factory class. Supports looping by count… #1846

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

Merged
merged 3 commits into from
Aug 24, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 118 additions & 1 deletion jme3-core/src/main/java/com/jme3/anim/tween/Tweens.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2021 jMonkeyEngine
* Copyright (c) 2015-2022 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -179,6 +179,40 @@ public static Tween callTweenMethod(double length, Object target, String method,
return new CallTweenMethod(length, target, method, args);
}

/**
* Creates a tween that loops the specified delegate tween or tweens
* to the desired count. If more than one tween is specified then they
* are wrapped in a sequence using the sequence() method.
*
* @param count the desired loop count
* @param delegates the desired sequence of tweens
* @return a new instance
*/
public static Tween loopCount(int count, Tween... delegates) {
if (delegates.length == 1) {
return new Loop(delegates[0], count);
}

return new Loop(sequence(delegates), count);
}

/**
* Creates a tween that loops the specified delegate tween or tweens
* to the desired duration. If more than one tween is specified then they
* are wrapped in a sequence using the sequence() method.
*
* @param duration the desired duration
* @param delegates the desired sequence of tweens
* @return a new instance
*/
public static Tween loopDuration(double duration, Tween... delegates) {
if (delegates.length == 1) {
return new Loop(delegates[0], duration);
}

return new Loop(sequence(delegates), duration);
}

private static interface CurveFunction {
public double curve(double input);
}
Expand Down Expand Up @@ -644,4 +678,87 @@ public String toString() {
return getClass().getSimpleName() + "[method=" + method + ", parms=" + Arrays.asList(args) + "]";
}
}

private static class Loop implements Tween, ContainsTweens {

private final Tween[] delegate = new Tween[1];
private final double length;
private final int loopCount;
private double baseTime;
private int current = 0;

public Loop (Tween delegate, double duration) {
if (delegate.getLength() <= 0) {
throw new IllegalArgumentException("Delegate length must be greater than 0");
}
if (duration <= 0) {
throw new IllegalArgumentException("Duration must be greater than 0");
}

this.delegate[0] = delegate;
this.length = duration;
this.loopCount = (int) Math.ceil(duration / delegate.getLength());
}

public Loop (Tween delegate, int count) {
if (count <= 0) {
throw new IllegalArgumentException("Loop count must be greater than 0");
}

this.delegate[0] = delegate;
this.length = count * delegate.getLength();
this.loopCount = count;
}

@Override
public double getLength() {
return length;
}

@Override
public Tween[] getTweens() {
return delegate;
}

@Override
public boolean interpolate(double t) {

// Sanity check the inputs
if (t < 0) {
return true;
}

if (t < baseTime) {
// We've rolled back before the current loop step
// which means we need to reset and start forward
// again. We have no idea how to 'roll back' and
// this is the only way to maintain consistency.
// The only 'normal' case where this happens is when looping
// in which case a full rollback is appropriate.
current = 0;
baseTime = 0;
}

if (current >= loopCount) {
return false;
}

// Skip any that are done
while (!delegate[0].interpolate(t - baseTime)) {
// Time to go to the next loop
baseTime += delegate[0].getLength();
current++;
if (current >= loopCount) {
return false;
}
}

return t < length;
}

@Override
public String toString() {
return getClass().getSimpleName() + "[delegate=" + delegate[0] + ", length=" + length + "]";
}
}
}