diff --git a/src/main/java/dev/resent/ui/animation/Animation.java b/src/main/java/dev/resent/ui/animation/Animation.java new file mode 100644 index 00000000..4699470e --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/Animation.java @@ -0,0 +1,118 @@ +package dev.resent.ui.animation; + +public abstract class Animation { + + public AnimationTimer timer = new AnimationTimer(); + + protected int duration; + + protected double endPoint; + + protected Direction direction; + + public Animation(int ms, double endPoint) { + this.duration = ms; + this.endPoint = endPoint; + this.direction = Direction.FORWARDS; + } + + public Animation(int ms, double endPoint, Direction direction) { + this.duration = ms; + this.endPoint = endPoint; + this.direction = direction; + } + + public boolean isDone(Direction direction) { + return isDone() && this.direction.equals(direction); + } + + public double getLinearOutput() { + return 1 - ((timer.getTime() / (double) duration) * endPoint); + } + + public void reset() { + timer.reset(); + } + + public boolean isDone() { + return timer.hasTimeElapsed(duration); + } + + public void changeDirection() { + setDirection(direction.opposite()); + } + + public void setDirection(Direction direction) { + if (this.direction != direction) { + this.direction = direction; + timer.setTime(System.currentTimeMillis() - (duration - Math.min(duration, timer.getTime()))); + } + } + + protected boolean correctOutput() { + return false; + } + + public double getValue() { + if (direction == Direction.FORWARDS) { + if (isDone()) + return endPoint; + return (getEquation(timer.getTime()) * endPoint); + } else { + if (isDone()) return 0; + if (correctOutput()) { + double revTime = Math.min(duration, Math.max(0, duration - timer.getTime())); + return getEquation(revTime) * endPoint; + } else return (1 - getEquation(timer.getTime())) * endPoint; + } + } + + protected abstract double getEquation(double x); + + public double getEndPoint() { + return endPoint; + } + + public void setEndPoint(double endPoint) { + this.endPoint = endPoint; + } + + public int getDuration() { + return duration; + } + + public Direction getDirection() { + return direction; + } +} + +class AnimationTimer { + + public long lastMS = System.currentTimeMillis(); + + public void reset() { + lastMS = System.currentTimeMillis(); + } + + public boolean hasTimeElapsed(long time, boolean reset) { + if (System.currentTimeMillis() - lastMS > time) { + if (reset) reset(); + return true; + } + + return false; + } + + public boolean hasTimeElapsed(long time) { + return System.currentTimeMillis() - lastMS > time; + } + + public long getTime() { + return System.currentTimeMillis() - lastMS; + } + + public void setTime(long time) { + lastMS = time; + } + +} diff --git a/src/main/java/dev/resent/ui/animation/AnimationUtils.java b/src/main/java/dev/resent/ui/animation/AnimationUtils.java new file mode 100644 index 00000000..57895480 --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/AnimationUtils.java @@ -0,0 +1,31 @@ +package dev.resent.ui.animation; + +public class AnimationUtils { + + public static float calculateCompensation(final float target, float current, final double speed, long delta) { + + final float diff = current - target; + + double add = (delta * (speed / 50)); + + if (diff > speed){ + if(current - add > target) { + current -= add; + }else { + current = target; + } + } + else if (diff < -speed) { + if(current + add < target) { + current += add; + }else { + current = target; + } + } + else{ + current = target; + } + + return current; + } +} diff --git a/src/main/java/dev/resent/ui/animation/Direction.java b/src/main/java/dev/resent/ui/animation/Direction.java new file mode 100644 index 00000000..0eb58214 --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/Direction.java @@ -0,0 +1,12 @@ +package dev.resent.ui.animation; + +public enum Direction { + FORWARDS, + BACKWARDS; + + public Direction opposite() { + if (this == Direction.FORWARDS) { + return Direction.BACKWARDS; + } else return Direction.FORWARDS; + } +} diff --git a/src/main/java/dev/resent/ui/animation/SimpleAnimation.java b/src/main/java/dev/resent/ui/animation/SimpleAnimation.java new file mode 100644 index 00000000..0c034c7d --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/SimpleAnimation.java @@ -0,0 +1,40 @@ +package dev.resent.ui.animation; + +public class SimpleAnimation { + + private float value; + private long lastMS; + + public SimpleAnimation(final float value){ + this.value = value; + this.lastMS = System.currentTimeMillis(); + } + + public void setAnimation(final float value, double speed){ + + final long currentMS = System.currentTimeMillis(); + final long delta = currentMS - this.lastMS; + this.lastMS = currentMS; + + double deltaValue = 0.0; + + if(speed > 28) { + speed = 28; + } + + if (speed != 0.0) + { + deltaValue = Math.abs(value - this.value) * 0.35f / (10.0 / speed); + } + + this.value = AnimationUtils.calculateCompensation(value, this.value, deltaValue, delta); + } + + public float getValue() { + return value; + } + + public void setValue(float value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/main/java/dev/resent/ui/animation/impl/DecelerateAnimation.java b/src/main/java/dev/resent/ui/animation/impl/DecelerateAnimation.java new file mode 100644 index 00000000..100feba0 --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/impl/DecelerateAnimation.java @@ -0,0 +1,20 @@ +package dev.resent.ui.animation.impl; + +import dev.resent.ui.animation.Animation; +import dev.resent.ui.animation.Direction; + +public class DecelerateAnimation extends Animation { + + public DecelerateAnimation(int ms, double endPoint) { + super(ms, endPoint); + } + + public DecelerateAnimation(int ms, double endPoint, Direction direction) { + super(ms, endPoint, direction); + } + + protected double getEquation(double x) { + double x1 = x / duration; + return 1 - ((x1 - 1) * (x1 - 1)); + } +} diff --git a/src/main/java/dev/resent/ui/animation/impl/EaseBackIn.java b/src/main/java/dev/resent/ui/animation/impl/EaseBackIn.java new file mode 100644 index 00000000..3d68af64 --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/impl/EaseBackIn.java @@ -0,0 +1,31 @@ +package dev.resent.ui.animation.impl; + +import dev.resent.ui.animation.Animation; +import dev.resent.ui.animation.Direction; + +public class EaseBackIn extends Animation { + private final float easeAmount; + + public EaseBackIn(int ms, double endPoint, float easeAmount) { + super(ms, endPoint); + this.easeAmount = easeAmount; + } + + public EaseBackIn(int ms, double endPoint, float easeAmount, Direction direction) { + super(ms, endPoint, direction); + this.easeAmount = easeAmount; + } + + @Override + protected boolean correctOutput() { + return true; + } + + @Override + protected double getEquation(double x) { + double x1 = x / duration; + float shrink = easeAmount + 1; + return Math.max(0, 1 + shrink * Math.pow(x1 - 1, 3) + easeAmount * Math.pow(x1 - 1, 2)); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/resent/ui/animation/impl/EaseInOutQuad.java b/src/main/java/dev/resent/ui/animation/impl/EaseInOutQuad.java new file mode 100644 index 00000000..5862ca3b --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/impl/EaseInOutQuad.java @@ -0,0 +1,21 @@ +package dev.resent.ui.animation.impl; + +import dev.resent.ui.animation.Animation; +import dev.resent.ui.animation.Direction; + +public class EaseInOutQuad extends Animation { + + public EaseInOutQuad(int ms, double endPoint) { + super(ms, endPoint); + } + + public EaseInOutQuad(int ms, double endPoint, Direction direction) { + super(ms, endPoint, direction); + } + + protected double getEquation(double x1) { + double x = x1 / duration; + return x < 0.5 ? 2 * Math.pow(x, 2) : 1 - Math.pow(-2 * x + 2, 2) / 2; + } + +} diff --git a/src/main/java/dev/resent/ui/animation/impl/ElasticAnimation.java b/src/main/java/dev/resent/ui/animation/impl/ElasticAnimation.java new file mode 100644 index 00000000..20132e93 --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/impl/ElasticAnimation.java @@ -0,0 +1,32 @@ +package dev.resent.ui.animation.impl; + +import dev.resent.ui.animation.Animation; +import dev.resent.ui.animation.Direction; + +public class ElasticAnimation extends Animation { + + float easeAmount; + float smooth; + boolean reallyElastic; + + public ElasticAnimation(int ms, double endPoint, float elasticity, float smooth, boolean moreElasticity) { + super(ms, endPoint); + this.easeAmount = elasticity; + this.smooth = smooth; + this.reallyElastic = moreElasticity; + } + + public ElasticAnimation(int ms, double endPoint, float elasticity, float smooth, boolean moreElasticity, Direction direction) { + super(ms, endPoint, direction); + this.easeAmount = elasticity; + this.smooth = smooth; + this.reallyElastic = moreElasticity; + } + + @Override + protected double getEquation(double x) { + double x1 = Math.pow(x / duration, smooth); + double elasticity = easeAmount * .1f; + return Math.pow(2, -10 * (reallyElastic ? Math.sqrt(x1) : x1)) * Math.sin((x1 - (elasticity / 4)) * ((2 * Math.PI) / elasticity)) + 1; + } +} \ No newline at end of file diff --git a/src/main/java/dev/resent/ui/animation/impl/SmoothStepAnimation.java b/src/main/java/dev/resent/ui/animation/impl/SmoothStepAnimation.java new file mode 100644 index 00000000..8558111d --- /dev/null +++ b/src/main/java/dev/resent/ui/animation/impl/SmoothStepAnimation.java @@ -0,0 +1,21 @@ +package dev.resent.ui.animation.impl; + +import dev.resent.ui.animation.Animation; +import dev.resent.ui.animation.Direction; + +public class SmoothStepAnimation extends Animation { + + public SmoothStepAnimation(int ms, double endPoint) { + super(ms, endPoint); + } + + public SmoothStepAnimation(int ms, double endPoint, Direction direction) { + super(ms, endPoint, direction); + } + + protected double getEquation(double x) { + double x1 = x / (double) duration; //Used to force input to range from 0 - 1 + return -2 * Math.pow(x1, 3) + (3 * Math.pow(x1, 2)); + } + +} \ No newline at end of file