Skip to content

Commit

Permalink
Gave Easing an ID
Browse files Browse the repository at this point in the history
  • Loading branch information
LatvianModder committed Apr 20, 2024
1 parent a322c79 commit 012cd2c
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 91 deletions.
127 changes: 73 additions & 54 deletions src/main/java/dev/latvian/mods/kmath/util/Easing.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,69 +4,63 @@
import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction;
import net.minecraft.util.math.Vec3d;

@FunctionalInterface
public interface Easing extends Double2DoubleFunction {
double ease(double x);

default double easeClamped(double x) {
return ease(KMath.clamp(x, 0D, 1D));
import java.util.LinkedHashMap;
import java.util.Map;

/**
* <a href="https://easings.net/">Source</a>
*/
public final class Easing {
public static final Map<String, Easing> FUNCTIONS = new LinkedHashMap<>();

public static Easing add(String id, Double2DoubleFunction function) {
var easing = add(id, function);
FUNCTIONS.put(id, easing);
return easing;
}

@Override
default double get(double x) {
return ease(x);
}
public static final Easing LINEAR = add("linear", x -> x);
public static final Easing SMOOTHSTEP = add("smoothstep", KMath::smoothstep);
public static final Easing ISMOOTHSTEP = add("ismoothstep", KMath::ismoothstep);
public static final Easing SMOOTHERSTEP = add("smootherstep", KMath::smootherstep);

default double lerp(double t, double a, double b) {
return a + get(t) * (b - a);
}

default Vec3d lerp(double t, Vec3d a, Vec3d b) {
return new Vec3d(lerp(t, a.x, b.x), lerp(t, a.y, b.y), lerp(t, a.z, b.z));
}
public static final Easing SINE_IN = add("sine_in", x -> 1 - Math.cos((x - Math.PI) / 2));
public static final Easing SINE_OUT = add("sine_out", x -> Math.sin((x * Math.PI) / 2));
public static final Easing SINE_IN_OUT = add("sine_in_out", x -> -(Math.cos(Math.PI * x) - 1) / 2);

Easing LINEAR = x -> x;
Easing SMOOTHSTEP = KMath::smoothstep;
Easing ISMOOTHSTEP = KMath::ismoothstep;
Easing SMOOTHERSTEP = KMath::smootherstep;
public static final Easing QUAD_IN = add("quad_in", x -> x * x);
public static final Easing QUAD_OUT = add("quad_out", x -> 1 - (1 - x) * (1 - x));
public static final Easing QUAD_IN_OUT = add("quad_in_out", x -> x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2);

Easing SINE_IN = x -> 1 - Math.cos((x - Math.PI) / 2);
Easing SINE_OUT = x -> Math.sin((x * Math.PI) / 2);
Easing SINE_IN_OUT = x -> -(Math.cos(Math.PI * x) - 1) / 2;
public static final Easing CUBIC_IN = add("cubic_in", x -> x * x * x);
public static final Easing CUBIC_OUT = add("cubic_out", x -> 1 - Math.pow(1 - x, 3));
public static final Easing CUBIC_IN_OUT = add("cubic_in_out", x -> x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2D);

Easing QUAD_IN = x -> x * x;
Easing QUAD_OUT = x -> 1 - (1 - x) * (1 - x);
Easing QUAD_IN_OUT = x -> x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
public static final Easing QUART_IN = add("quart_in", x -> x * x * x * x);
public static final Easing QUART_OUT = add("quart_out", x -> 1 - Math.pow(1 - x, 4));
public static final Easing QUART_IN_OUT = add("quart_in_out", x -> x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2D);

Easing CUBIC_IN = x -> x * x * x;
Easing CUBIC_OUT = x -> 1 - Math.pow(1 - x, 3);
Easing CUBIC_IN_OUT = x -> x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2D;
public static final Easing QUINT_IN = add("quint_in", x -> x * x * x * x * x);
public static final Easing QUINT_OUT = add("quint_out", x -> 1 - Math.pow(1 - x, 5));
public static final Easing QUINT_IN_OUT = add("quint_in_out", x -> x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2D);

Easing QUART_IN = x -> x * x * x * x;
Easing QUART_OUT = x -> 1 - Math.pow(1 - x, 4);
Easing QUART_IN_OUT = x -> x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2D;
public static final Easing EXPO_IN = add("expo_in", x -> x == 0 ? 0 : Math.pow(2, 10 * x - 10));
public static final Easing EXPO_OUT = add("expo_out", x -> x == 1 ? 1 : 1 - Math.pow(2, -10 * x));
public static final Easing EXPO_IN_OUT = add("expo_in_out", x -> x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? Math.pow(2, 20 * x - 10) / 2 : (2 - Math.pow(2, -20 * x + 10)) / 2);

Easing QUINT_IN = x -> x * x * x * x * x;
Easing QUINT_OUT = x -> 1 - Math.pow(1 - x, 5);
Easing QUINT_IN_OUT = x -> x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2D;
public static final Easing CIRC_IN = add("circ_in", x -> 1 - Math.sqrt(1 - x * x));
public static final Easing CIRC_OUT = add("circ_out", x -> Math.sqrt(1 - (x - 1) * (x - 1)));
public static final Easing CIRC_IN_OUT = add("circ_in_out", x -> x < 0.5 ? (1 - Math.sqrt(1 - 4 * x * x)) / 2 : (Math.sqrt(1 - (-2 * x + 2) * (-2 * x + 2)) + 1) / 2);

Easing EXPO_IN = x -> x == 0 ? 0 : Math.pow(2, 10 * x - 10);
Easing EXPO_OUT = x -> x == 1 ? 1 : 1 - Math.pow(2, -10 * x);
Easing EXPO_IN_OUT = x -> x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? Math.pow(2, 20 * x - 10) / 2 : (2 - Math.pow(2, -20 * x + 10)) / 2;
public static final Easing BACK_IN = add("back_in", x -> x * x * (2.70158 * x - 1.70158));
public static final Easing BACK_OUT = add("back_out", x -> 1 - (1 - x) * (1 - x) * (2.70158 * (1 - x) - 1.70158));
public static final Easing BACK_IN_OUT = add("back_in_out", x -> x < 0.5 ? Math.pow(2 * x, 2) * ((2.5949095 + 1) * 2 * x - 2.5949095) / 2 : (Math.pow(2 * x - 2, 2) * ((2.5949095 + 1) * (x * 2 - 2) + 2.5949095) + 2) / 2);

Easing CIRC_IN = x -> 1 - Math.sqrt(1 - x * x);
Easing CIRC_OUT = x -> Math.sqrt(1 - (x - 1) * (x - 1));
Easing CIRC_IN_OUT = x -> x < 0.5 ? (1 - Math.sqrt(1 - 4 * x * x)) / 2 : (Math.sqrt(1 - (-2 * x + 2) * (-2 * x + 2)) + 1) / 2;
public static final Easing ELASTIC_IN = add("elastic_in", x -> Math.sin(13 * Math.PI / 2 * x) * Math.pow(2, 10 * x - 10));
public static final Easing ELASTIC_OUT = add("elastic_out", x -> Math.sin(-13 * Math.PI / 2 * (x + 1)) * Math.pow(2, -10 * x) + 1);
public static final Easing ELASTIC_IN_OUT = add("elastic_in_out", x -> x < 0.5 ? Math.sin(13 * Math.PI / 2 * (2 * x)) * Math.pow(2, 10 * (2 * x) - 10) / 2 : Math.sin(-13 * Math.PI / 2 * (2 * x - 1)) * Math.pow(2, -10 * (2 * x - 1)) / 2 + 1);

Easing BACK_IN = x -> x * x * (2.70158 * x - 1.70158);
Easing BACK_OUT = x -> 1 - (1 - x) * (1 - x) * (2.70158 * (1 - x) - 1.70158);
Easing BACK_IN_OUT = x -> x < 0.5 ? Math.pow(2 * x, 2) * ((2.5949095 + 1) * 2 * x - 2.5949095) / 2 : (Math.pow(2 * x - 2, 2) * ((2.5949095 + 1) * (x * 2 - 2) + 2.5949095) + 2) / 2;

Easing ELASTIC_IN = x -> Math.sin(13 * Math.PI / 2 * x) * Math.pow(2, 10 * x - 10);
Easing ELASTIC_OUT = x -> Math.sin(-13 * Math.PI / 2 * (x + 1)) * Math.pow(2, -10 * x) + 1;
Easing ELASTIC_IN_OUT = x -> x < 0.5 ? Math.sin(13 * Math.PI / 2 * (2 * x)) * Math.pow(2, 10 * (2 * x) - 10) / 2 : Math.sin(-13 * Math.PI / 2 * (2 * x - 1)) * Math.pow(2, -10 * (2 * x - 1)) / 2 + 1;

Easing BOUNCE_OUT = x -> {
public static final Easing BOUNCE_OUT = add("bounce_out", x -> {
if (x < 1 / 2.75) {
return 7.5625 * x * x;
} else if (x < 2 / 2.75) {
Expand All @@ -76,8 +70,33 @@ default Vec3d lerp(double t, Vec3d a, Vec3d b) {
} else {
return 7.5625 * (x -= 2.625 / 2.75) * x + 0.984375;
}
};
});

public static final Easing BOUNCE_IN = add("bounce_in", x -> 1 - BOUNCE_OUT.ease(1 - x));
public static final Easing BOUNCE_IN_OUT = add("bounce_in_out", x -> x < 0.5 ? BOUNCE_IN.ease(x * 2) / 2 : BOUNCE_OUT.ease(x * 2 - 1) / 2 + 0.5);

public final String id;
public final Double2DoubleFunction function;

Easing BOUNCE_IN = x -> 1 - BOUNCE_OUT.ease(1 - x);
Easing BOUNCE_IN_OUT = x -> x < 0.5 ? BOUNCE_IN.ease(x * 2) / 2 : BOUNCE_OUT.ease(x * 2 - 1) / 2 + 0.5;
private Easing(String id, Double2DoubleFunction function) {
this.id = id;
this.function = function;
}

public double ease(double x) {
return function.get(x);
}

public double easeClamped(double x) {
return function.get(KMath.clamp(x, 0D, 1D));
}

public double lerp(double t, double a, double b) {
return KMath.lerp(function.get(t), a, b);
}

public Vec3d lerp(double t, Vec3d a, Vec3d b) {
var e = function.get(t);
return new Vec3d(KMath.lerp(e, a.x, b.x), KMath.lerp(e, a.y, b.y), KMath.lerp(e, a.z, b.z));
}
}
61 changes: 24 additions & 37 deletions src/main/java/dev/latvian/mods/kmath/util/EasingGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,43 @@
import java.util.LinkedHashMap;
import java.util.Map;

/**
* <a href="https://easings.net/">Source</a>
*/
public enum EasingGroup {
LINEAR("linear", Easing.LINEAR),
SMOOTHSTEP("smoothstep", Easing.SMOOTHSTEP),
ISMOOTHSTEP("ismoothstep", Easing.ISMOOTHSTEP),
SMOOTHERSTEP("smootherstep", Easing.SMOOTHERSTEP),
SINE("sine", Easing.SINE_IN, Easing.SINE_OUT, Easing.SINE_IN_OUT),
QUAD("quad", Easing.QUAD_IN, Easing.QUAD_OUT, Easing.QUAD_IN_OUT),
CUBIC("cubic", Easing.CUBIC_IN, Easing.CUBIC_OUT, Easing.CUBIC_IN_OUT),
QUART("quart", Easing.QUART_IN, Easing.QUART_OUT, Easing.QUART_IN_OUT),
QUINT("quint", Easing.QUINT_IN, Easing.QUINT_OUT, Easing.QUINT_IN_OUT),
EXPO("expo", Easing.EXPO_IN, Easing.EXPO_OUT, Easing.EXPO_IN_OUT),
CIRC("circ", Easing.CIRC_IN, Easing.CIRC_OUT, Easing.CIRC_IN_OUT),
BACK("back", Easing.BACK_IN, Easing.BACK_OUT, Easing.BACK_IN_OUT),
ELASTIC("elastic", Easing.ELASTIC_IN, Easing.ELASTIC_OUT, Easing.ELASTIC_IN_OUT),
BOUNCE("bounce", Easing.BOUNCE_IN, Easing.BOUNCE_OUT, Easing.BOUNCE_IN_OUT);

public static final EasingGroup[] VALUES = values();
public class EasingGroup {
public static final Map<String, EasingGroup> GROUPS = new LinkedHashMap<>();
public static final Map<String, Easing> FUNCTIONS = new LinkedHashMap<>();

static {
for (var group : VALUES) {
GROUPS.put(group.id, group);
public static EasingGroup add(String id, Easing in, Easing out, Easing inOut) {
var group = new EasingGroup(id, in, out, inOut);
GROUPS.put(id, group);
return group;
}

if (group.in == group.out && group.in == group.inOut) {
FUNCTIONS.put(group.id, group.in);
} else {
FUNCTIONS.put(group.id + "_in", group.in);
FUNCTIONS.put(group.id + "_out", group.out);
FUNCTIONS.put(group.id + "_in_out", group.inOut);
}
}
public static EasingGroup add(String id, Easing easing) {
return add(id, easing, easing, easing);
}

public static final EasingGroup LINEAR = add("linear", Easing.LINEAR);
public static final EasingGroup SMOOTHSTEP = add("smoothstep", Easing.SMOOTHSTEP);
public static final EasingGroup ISMOOTHSTEP = add("ismoothstep", Easing.ISMOOTHSTEP);
public static final EasingGroup SMOOTHERSTEP = add("smootherstep", Easing.SMOOTHERSTEP);
public static final EasingGroup SINE = add("sine", Easing.SINE_IN, Easing.SINE_OUT, Easing.SINE_IN_OUT);
public static final EasingGroup QUAD = add("quad", Easing.QUAD_IN, Easing.QUAD_OUT, Easing.QUAD_IN_OUT);
public static final EasingGroup CUBIC = add("cubic", Easing.CUBIC_IN, Easing.CUBIC_OUT, Easing.CUBIC_IN_OUT);
public static final EasingGroup QUART = add("quart", Easing.QUART_IN, Easing.QUART_OUT, Easing.QUART_IN_OUT);
public static final EasingGroup QUINT = add("quint", Easing.QUINT_IN, Easing.QUINT_OUT, Easing.QUINT_IN_OUT);
public static final EasingGroup EXPO = add("expo", Easing.EXPO_IN, Easing.EXPO_OUT, Easing.EXPO_IN_OUT);
public static final EasingGroup CIRC = add("circ", Easing.CIRC_IN, Easing.CIRC_OUT, Easing.CIRC_IN_OUT);
public static final EasingGroup BACK = add("back", Easing.BACK_IN, Easing.BACK_OUT, Easing.BACK_IN_OUT);
public static final EasingGroup ELASTIC = add("elastic", Easing.ELASTIC_IN, Easing.ELASTIC_OUT, Easing.ELASTIC_IN_OUT);
public static final EasingGroup BOUNCE = add("bounce", Easing.BOUNCE_IN, Easing.BOUNCE_OUT, Easing.BOUNCE_IN_OUT);

public final String id;
public final Easing in;
public final Easing out;
public final Easing inOut;

EasingGroup(String id, Easing in, Easing out, Easing inOut) {
private EasingGroup(String id, Easing in, Easing out, Easing inOut) {
this.id = id;
this.in = in;
this.out = out;
this.inOut = inOut;
}

EasingGroup(String id, Easing common) {
this(id, common, common, common);
}
}

0 comments on commit 012cd2c

Please sign in to comment.