Added Easing functions for the gui Animations
This commit is contained in:
parent
cab2095668
commit
9526fe42b9
|
@ -0,0 +1,3 @@
|
||||||
|
# Tests that should be done.
|
||||||
|
|
||||||
|
- Test starting animations with delays of each other to see if they act properly.
|
|
@ -5,6 +5,7 @@ public class MathUtils {
|
||||||
private static final float[] COS_TABLE;
|
private static final float[] COS_TABLE;
|
||||||
private static final float TABLE_MASK;
|
private static final float TABLE_MASK;
|
||||||
private static final int SIN_MASK;
|
private static final int SIN_MASK;
|
||||||
|
public static final double HALF_PI = Math.PI * 0.5D;
|
||||||
public static final double PI_INVERSION = 180D / Math.PI;
|
public static final double PI_INVERSION = 180D / Math.PI;
|
||||||
|
|
||||||
public static float sin(float a) {
|
public static float sin(float a) {
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package speiger.src.coreengine.math.misc;
|
||||||
|
|
||||||
|
import speiger.src.coreengine.math.MathUtils;
|
||||||
|
|
||||||
|
public class EasingFunctions {
|
||||||
|
public static double easeInSine(double progress) {
|
||||||
|
return 1D - MathUtils.cos(progress * MathUtils.HALF_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeOutSine(double progress) {
|
||||||
|
return MathUtils.sin(progress * MathUtils.HALF_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeInOutSine(double progress) {
|
||||||
|
return -MathUtils.cos(progress * Math.PI - 1D) * 0.5D;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeInSqrt(double progress) {
|
||||||
|
return Math.sqrt(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeOutSqrt(double progress) {
|
||||||
|
return 1D - Math.sqrt(1D - progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeInOutSqrt(double progress) {
|
||||||
|
return progress < 0.5D ? Math.sqrt(progress) : 1D-Math.sqrt(1-progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeInQuad(double progress) {
|
||||||
|
return progress * progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeOutQuad(double progress) {
|
||||||
|
double inverse = 1D - progress;
|
||||||
|
return 1D - (inverse * inverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeInOutQuad(double progress) {
|
||||||
|
if(progress < 0.5D) return 2D * progress * progress;
|
||||||
|
double inverse = 1D - progress;
|
||||||
|
return 1D - (-4D * (1D - inverse * inverse) + 4D) * 0.5D;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeInExpo(double progress) {
|
||||||
|
return Math.pow(2D, (10D * progress) - 10D);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeOutExpo(double progress) {
|
||||||
|
return 1D - Math.pow(2D, -10D * progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double easeInOutExpo(double progress) {
|
||||||
|
return progress <= 0.5D ? Math.pow(2D, (20D * progress) - 10D) * 0.5D : (2D - Math.pow(2D, (-20D * progress) + 10D)) * 0.5D;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package speiger.src.coreengine.math.misc;
|
||||||
|
|
||||||
|
import speiger.src.coreengine.math.MathUtils;
|
||||||
|
|
||||||
|
public interface IEasing {
|
||||||
|
public double ease(double progress);
|
||||||
|
|
||||||
|
public default double ease(double progress, double max) {
|
||||||
|
return ease(MathUtils.clamp(progress/max, 0D, 1D));
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ public class GuiAnimationSnapshot implements ToFloatFunction<Target>, ObjectFloa
|
||||||
final float scale;
|
final float scale;
|
||||||
final boolean looping;
|
final boolean looping;
|
||||||
float progress;
|
float progress;
|
||||||
|
int loops;
|
||||||
|
|
||||||
public GuiAnimationSnapshot(GuiAnimator animator, IGuiBox box, boolean looping) {
|
public GuiAnimationSnapshot(GuiAnimator animator, IGuiBox box, boolean looping) {
|
||||||
this(animator, box.getBaseX(), box.getBaseY(), box.getBaseWidth(), box.getBaseHeight(), box.getBaseScale(), looping);
|
this(animator, box.getBaseX(), box.getBaseY(), box.getBaseWidth(), box.getBaseHeight(), box.getBaseScale(), looping);
|
||||||
|
@ -29,7 +30,7 @@ public class GuiAnimationSnapshot implements ToFloatFunction<Target>, ObjectFloa
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.looping = looping;
|
this.looping = looping;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float applyAsFloat(Target k) {
|
public float applyAsFloat(Target k) {
|
||||||
return switch(k) {
|
return switch(k) {
|
||||||
|
@ -53,6 +54,10 @@ public class GuiAnimationSnapshot implements ToFloatFunction<Target>, ObjectFloa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int loops() {
|
||||||
|
return loops;
|
||||||
|
}
|
||||||
|
|
||||||
public GuiAnimationSnapshot applyDifference(GuiComponent component) {
|
public GuiAnimationSnapshot applyDifference(GuiComponent component) {
|
||||||
for(Target target : Target.values()) {
|
for(Target target : Target.values()) {
|
||||||
animator.accept(target, applyAsFloat(target) - target.get(component));
|
animator.accept(target, applyAsFloat(target) - target.get(component));
|
||||||
|
@ -66,7 +71,8 @@ public class GuiAnimationSnapshot implements ToFloatFunction<Target>, ObjectFloa
|
||||||
if(progress >= animation.duration()) {
|
if(progress >= animation.duration()) {
|
||||||
if(!looping) return true;
|
if(!looping) return true;
|
||||||
progress = 0F;
|
progress = 0F;
|
||||||
|
loops++;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,6 +33,11 @@ public class GuiAnimator implements ObjectFloatConsumer<Target> {
|
||||||
return activeAnimations.containsKey(animation);
|
return activeAnimations.containsKey(animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getLoopAmount(GuiAnimation animation) {
|
||||||
|
GuiAnimationSnapshot snapshot = activeAnimations.get(animation);
|
||||||
|
return snapshot == null ? -1 : snapshot.loops();
|
||||||
|
}
|
||||||
|
|
||||||
public void removeAnimation(GuiAnimation animation) {
|
public void removeAnimation(GuiAnimation animation) {
|
||||||
activeAnimations.remove(animation);
|
activeAnimations.remove(animation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ public interface IAction {
|
||||||
public default IAction withPreDelay(float delay) { return this instanceof PreDelayedAction delayed ? new PreDelayedAction(delayed.action(), delay + delayed.delay()) : new PreDelayedAction(this, delay); }
|
public default IAction withPreDelay(float delay) { return this instanceof PreDelayedAction delayed ? new PreDelayedAction(delayed.action(), delay + delayed.delay()) : new PreDelayedAction(this, delay); }
|
||||||
public default IAction withPostDelay(float delay) { return this instanceof PostDelayedAction delayed ? new PostDelayedAction(delayed.action(), delay + delayed.delay()) : new PostDelayedAction(this, delay); }
|
public default IAction withPostDelay(float delay) { return this instanceof PostDelayedAction delayed ? new PostDelayedAction(delayed.action(), delay + delayed.delay()) : new PostDelayedAction(this, delay); }
|
||||||
public default IAction reverse() { return this instanceof ReversedAction reversed ? reversed.action() : new ReversedAction(this); }
|
public default IAction reverse() { return this instanceof ReversedAction reversed ? reversed.action() : new ReversedAction(this); }
|
||||||
|
public default IAction asLoop() { return this instanceof LoopingAction loop ? loop : new LoopingAction(this); }
|
||||||
|
|
||||||
public record PreDelayedAction(IAction action, float delay) implements IAction {
|
public record PreDelayedAction(IAction action, float delay) implements IAction {
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,5 +39,13 @@ public interface IAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record LoopingAction(IAction action) implements IAction {
|
||||||
|
@Override
|
||||||
|
public float duration() { return action.duration() * 2F; }
|
||||||
|
@Override
|
||||||
|
public void apply(Target target, ToFloatFunction<Target> getter, ObjectFloatConsumer<Target> setter, float progress) {
|
||||||
|
float duration = action.duration();
|
||||||
|
action.apply(target, getter, setter, progress >= duration ? duration - (progress - duration) : progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package speiger.src.coreengine.rendering.gui.animation.actions;
|
||||||
|
|
||||||
|
import speiger.src.collections.objects.functions.consumer.ObjectFloatConsumer;
|
||||||
|
import speiger.src.collections.objects.functions.function.ToFloatFunction;
|
||||||
|
import speiger.src.coreengine.math.MathUtils;
|
||||||
|
import speiger.src.coreengine.math.misc.IEasing;
|
||||||
|
import speiger.src.coreengine.rendering.gui.animation.GuiAnimation.Target;
|
||||||
|
import speiger.src.coreengine.rendering.gui.animation.IAction;
|
||||||
|
|
||||||
|
public class EasedAction implements IAction {
|
||||||
|
float duration;
|
||||||
|
float targetValue;
|
||||||
|
IEasing function;
|
||||||
|
|
||||||
|
public EasedAction(float duration, float targetValue, IEasing function) {
|
||||||
|
this.duration = duration;
|
||||||
|
this.targetValue = targetValue;
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float duration() { return duration; }
|
||||||
|
@Override
|
||||||
|
public void apply(Target target, ToFloatFunction<Target> getter, ObjectFloatConsumer<Target> setter, float progress) {
|
||||||
|
setter.accept(target, MathUtils.lerp(getter.applyAsFloat(target), targetValue, (float)function.ease(progress, duration)));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue