From c0b088bb8a312e3bee6f1575c84f83fd088be1ec Mon Sep 17 00:00:00 2001 From: Leo dev Date: Mon, 28 Apr 2025 15:20:16 -0500 Subject: [PATCH] experiment: animation curve functions --- .../java/org/saturnclient/ui2/Element.java | 4 +- .../org/saturnclient/ui2/SaturnScreen.java | 38 +++++++++ .../org/saturnclient/ui2/anim/Animation.java | 7 ++ .../java/org/saturnclient/ui2/anim/Curve.java | 85 +++++++++++++++++++ .../org/saturnclient/ui2/anim/SlideUp.java | 20 +++++ .../saturnclient/ui2/screens/ShiftMenu.java | 22 ++--- .../java/org/test/test/AnimationExample.java | 48 +++++++++++ .../java/org/test/test/CurveFunctions.java | 34 ++++++++ 8 files changed, 245 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/saturnclient/ui2/anim/Animation.java create mode 100644 src/main/java/org/saturnclient/ui2/anim/Curve.java create mode 100644 src/main/java/org/saturnclient/ui2/anim/SlideUp.java create mode 100644 src/main/java/org/test/test/AnimationExample.java create mode 100644 src/main/java/org/test/test/CurveFunctions.java diff --git a/src/main/java/org/saturnclient/ui2/Element.java b/src/main/java/org/saturnclient/ui2/Element.java index d87923d..7423320 100644 --- a/src/main/java/org/saturnclient/ui2/Element.java +++ b/src/main/java/org/saturnclient/ui2/Element.java @@ -1,8 +1,8 @@ package org.saturnclient.ui2; public class Element { - protected int x; - protected int y; + public int x; + public int y; public int width; public int height; public boolean focused; diff --git a/src/main/java/org/saturnclient/ui2/SaturnScreen.java b/src/main/java/org/saturnclient/ui2/SaturnScreen.java index a025886..1b3803c 100644 --- a/src/main/java/org/saturnclient/ui2/SaturnScreen.java +++ b/src/main/java/org/saturnclient/ui2/SaturnScreen.java @@ -1,10 +1,16 @@ package org.saturnclient.ui2; +import java.time.Instant; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; +import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.config.ThemeManager; import org.saturnclient.saturnclient.mixin.DrawContextAccessor; +import org.saturnclient.ui2.anim.Animation; +import org.saturnclient.ui2.anim.Curve; +import org.saturnclient.ui2.anim.SlideUp; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; @@ -19,9 +25,41 @@ public class SaturnScreen extends Screen { } public void draw(Element element) { + Animation animation = new SlideUp(); + // Function curve = Curve::easeIn; + + int duration = 500; + synchronized (elements) { elements.add(element); } + + // new Thread(() -> { + // boolean running = true; + // Instant start = Instant.now(); + // int tick = 0; + // while (running) { + // if (animation != null) { + // int elapsedMs = (int) java.time.Duration.between(start, Instant.now()).toMillis(); + + // if (elapsedMs > duration) { + // running = false; + // } + + // float progress = animation.tick(tick, element); + + // SaturnClient.LOGGER.info("ms: " + curve.apply(progress) + ", Progress: " + progress); + + // try { + // Thread.sleep(30); + // } catch (Exception e) { + // } + // tick++; + // } else { + // running = false; + // } + // } + // }).start(); } @Override diff --git a/src/main/java/org/saturnclient/ui2/anim/Animation.java b/src/main/java/org/saturnclient/ui2/anim/Animation.java new file mode 100644 index 0000000..fac53eb --- /dev/null +++ b/src/main/java/org/saturnclient/ui2/anim/Animation.java @@ -0,0 +1,7 @@ +package org.saturnclient.ui2.anim; + +import org.saturnclient.ui2.Element; + +public abstract class Animation { + public abstract float tick(int tick, Element element); +} diff --git a/src/main/java/org/saturnclient/ui2/anim/Curve.java b/src/main/java/org/saturnclient/ui2/anim/Curve.java new file mode 100644 index 0000000..81c5e3e --- /dev/null +++ b/src/main/java/org/saturnclient/ui2/anim/Curve.java @@ -0,0 +1,85 @@ +package org.saturnclient.ui2.anim; + +import java.time.Instant; +import java.util.function.Function; + +import org.saturnclient.saturnclient.SaturnClient; + +public class Curve { + // Define the curve functions (ease-in, ease-out, ease-in-out) + public static int easeIn(float progress, long elapsedTime, float totalDuration) { + // Ease-in: Modify the curve based on elapsed time + float t = progress; + t *= t; // Ease-in: t^2 + // Scale the delay based on the remaining time + return (int) ((t * (totalDuration - elapsedTime)) / totalDuration); + } + + public static int easeOut(float progress, long elapsedTime, float totalDuration) { + // Ease-out: Modify the curve based on elapsed time + float t = progress; + t = 1 - (1 - t) * (1 - t); // Ease-out: 1 - (1 - t)^2 + // Scale the delay based on the remaining time + return (int) ((t * (totalDuration - elapsedTime)) / totalDuration); + } + + public static int easeInOut(float progress, long elapsedTime, float totalDuration) { + // Ease-in-out: Modify the curve based on elapsed time + double t = progress; + if (t < 0.5) { + t = 2 * t * t; // Ease-in: t^2 + } else { + t = 1 - Math.pow(-2 * t + 2, 2) / 2; // Ease-out: 1 - (2t-2)^2 / 2 + } + // Scale the delay based on the remaining time + return (int) ((t * (totalDuration - elapsedTime)) / totalDuration); + } + + public static void animate(float totalDuration, float increment) { + long startTime = System.currentTimeMillis(); + float progress = 0.0f; + float progressPerStep = increment; + long elapsedTime = 0; // Track the total elapsed time + + // Animation loop until progress reaches 1.0 + while (progress < 1.0f) { + // Calculate the current progress value + progress = Math.min(progress + progressPerStep, 1.0f); // Ensure progress does not exceed 1.0 + + // Calculate the elapsed time + elapsedTime = System.currentTimeMillis() - startTime; + + // Calculate the delay based on the current progress and elapsed time using the easing function + // We switch between easeIn, easeOut, and easeInOut for different effects + int delay = easeInOut(progress, elapsedTime, totalDuration); + + // Print the progress and delay for debugging + System.out.println("Progress: " + (progress * 100) + "%, Delay: " + delay + "ms"); + + // Ensure we don't sleep for a negative value + if (delay < 1) { + delay = 1; // Avoid immediate jumps, ensure some delay for visual effect + } + + // Sleep for the delay calculated by the easing function + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // If the elapsed time exceeds the total duration, break out of the loop + if (elapsedTime >= totalDuration) { + break; + } + } + + System.out.println("Animation Complete!"); + } + + public static void main(String[] args) { + float durationInMillis = 500.0f; // Total duration of the animation in ms + float increment = 0.01f; // Increment the progress by 1% each step + animate(durationInMillis, increment); // Start the animation + } +} diff --git a/src/main/java/org/saturnclient/ui2/anim/SlideUp.java b/src/main/java/org/saturnclient/ui2/anim/SlideUp.java new file mode 100644 index 0000000..b7393ac --- /dev/null +++ b/src/main/java/org/saturnclient/ui2/anim/SlideUp.java @@ -0,0 +1,20 @@ +package org.saturnclient.ui2.anim; + +import org.saturnclient.ui2.Element; + +public class SlideUp extends Animation { + int targetY; + + @Override + public float tick(int tick, Element element) { + if (tick == 0) { + targetY = element.y; + element.y += 20; + } else if (element.y > targetY) { + element.y--; + return ((float) element.y) / targetY; + } + + return 0.1f; + } +} diff --git a/src/main/java/org/saturnclient/ui2/screens/ShiftMenu.java b/src/main/java/org/saturnclient/ui2/screens/ShiftMenu.java index 509e69d..e36602c 100644 --- a/src/main/java/org/saturnclient/ui2/screens/ShiftMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/ShiftMenu.java @@ -19,20 +19,20 @@ public class ShiftMenu extends SaturnScreen { @Override public void ui() { draw(new ImageTexture(Textures.LOGO).dimensions(49, 49).centerOffset(width, height, 0, -45)); - draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(49, 8).centerOffset(width, height, 0, -23)); + // draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(49, 8).centerOffset(width, height, 0, -23)); - Element button = new Button("Settings", () -> { - SaturnClient.client.setScreen(new ModMenu()); - }).center(width, height); + // Element button = new Button("Settings", () -> { + // SaturnClient.client.setScreen(new ModMenu()); + // }).center(width, height); - draw(button); + // draw(button); - draw(new TextureButton(Textures.COSMETICS, () -> { - client.setScreen(new CloaksMenu()); - }).dimensions(button.height, button.height).centerOffset(width, height, (button.width / 2) + (button.height / 2) + 4, 0)); + // draw(new TextureButton(Textures.COSMETICS, () -> { + // client.setScreen(new CloaksMenu()); + // }).dimensions(button.height, button.height).centerOffset(width, height, (button.width / 2) + (button.height / 2) + 4, 0)); - draw(new TextureButton(Textures.HUD_ICON, () -> { - client.setScreen(new HudEditor()); - }).dimensions(button.height, button.height).centerOffset(width, height, -((button.width / 2) + (button.height / 2) + 4), 0)); + // draw(new TextureButton(Textures.HUD_ICON, () -> { + // client.setScreen(new HudEditor()); + // }).dimensions(button.height, button.height).centerOffset(width, height, -((button.width / 2) + (button.height / 2) + 4), 0)); } } diff --git a/src/main/java/org/test/test/AnimationExample.java b/src/main/java/org/test/test/AnimationExample.java new file mode 100644 index 0000000..9b3863e --- /dev/null +++ b/src/main/java/org/test/test/AnimationExample.java @@ -0,0 +1,48 @@ +package org.test.test; + +import java.util.function.Function; + +public class AnimationExample { + public static void main(String[] args) { + long stime = System.currentTimeMillis(); + Function curveFunction = CurveFunctions::easeOut; + int duration = 300; + int delayOnProgress = duration / 4; + + // 0.1 -> 0.5 = +=0.01 + + float progress = 0f; + + while (System.currentTimeMillis() - stime < duration) { + float newProgress = Math.min(1.0f, curveFunction.apply(progress + 0.05f)); + + if (newProgress == progress) { + newProgress += 0.05; + } + + while (progress != newProgress) { + if (progress > newProgress) { + progress -= 0.05; + if (progress < newProgress) progress = newProgress; + } else if (progress < newProgress) { + progress += 0.05; + if (progress > newProgress) progress = newProgress; + } else { + progress += 0.05; + } + } + + System.out.println("New Progress: " + progress); + + } + + + System.out.println((System.currentTimeMillis() - stime) + "ms"); + } + + // Define the EasingFunction interface (to be passed to functions like easeInOut) + @FunctionalInterface + public interface EasingFunction { + double apply(double t); // Apply the easing function to the normalized progress + } +} diff --git a/src/main/java/org/test/test/CurveFunctions.java b/src/main/java/org/test/test/CurveFunctions.java new file mode 100644 index 0000000..3525c07 --- /dev/null +++ b/src/main/java/org/test/test/CurveFunctions.java @@ -0,0 +1,34 @@ +package org.test.test; + +public class CurveFunctions { + public static float linear(float t) { + return t; + } + + public static float easeIn(float t) { + return t * t; + } + + public static float easeOut(float t) { + return (float)(1 - Math.pow(1 - t, 2)); + } + + public static float easeInOut(float t) { + return (float)((-Math.cos(Math.PI * t) / 2.0) + 0.5); + } + + public static float bounceOut(float t) { + if (t < (1/2.75f)) { + return 7.5625f * t * t; + } else if (t < (2/2.75f)) { + t -= (1.5f/2.75f); + return 7.5625f * t * t + 0.75f; + } else if (t < (2.5/2.75)) { + t -= (2.25f/2.75f); + return 7.5625f * t * t + 0.9375f; + } else { + t -= (2.625f/2.75f); + return 7.5625f * t * t + 0.984375f; + } + } +}