Better animation system
This commit is contained in:
@@ -41,6 +41,12 @@ public class Element {
|
|||||||
public void mouseReleased(double mouseX, double mouseY, int button) {
|
public void mouseReleased(double mouseX, double mouseY, int button) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void playAnimationFrame(long elapsed) {
|
||||||
|
if (this.animation != null) {
|
||||||
|
this.animation.tick(this.curve.apply(Math.min(1.0, (double) elapsed / this.animation.duration)), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Element dimensions(int width, int height) {
|
public Element dimensions(int width, int height) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ public class ElementContext {
|
|||||||
public int mouseX, mouseY;
|
public int mouseX, mouseY;
|
||||||
public int elementWidth, elementHeight;
|
public int elementWidth, elementHeight;
|
||||||
public float elementScale;
|
public float elementScale;
|
||||||
|
public long elapsed;
|
||||||
|
|
||||||
public ElementContext(int mouseX, int mouseY, Element e) {
|
public ElementContext(long elapsed, int mouseX, int mouseY, Element e) {
|
||||||
this.mouseX = mouseX - e.x;
|
this.mouseX = mouseX - e.x;
|
||||||
this.mouseY = mouseY - e.y;
|
this.mouseY = mouseY - e.y;
|
||||||
this.elementWidth = e.width;
|
this.elementWidth = e.width;
|
||||||
this.elementHeight = e.height;
|
this.elementHeight = e.height;
|
||||||
this.elementScale = e.scale;
|
this.elementScale = e.scale;
|
||||||
|
this.elapsed = elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHovering() {
|
public boolean isHovering() {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package org.saturnclient.ui2;
|
package org.saturnclient.ui2;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
|
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
|
||||||
import org.saturnclient.ui2.anim.Animation;
|
|
||||||
import org.saturnclient.ui2.anim.SlideXAbsolute;
|
|
||||||
import org.saturnclient.ui2.components.ElementRenderer;
|
import org.saturnclient.ui2.components.ElementRenderer;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
@@ -23,6 +23,7 @@ public abstract class SaturnScreen extends Screen {
|
|||||||
private final Pool pool = new Pool(3);
|
private final Pool pool = new Pool(3);
|
||||||
protected List<Element> elements = new ArrayList<>();
|
protected List<Element> elements = new ArrayList<>();
|
||||||
protected float backgroundOpacity = 1.0f;
|
protected float backgroundOpacity = 1.0f;
|
||||||
|
protected Instant start = null;
|
||||||
public int blurDuration = 700;
|
public int blurDuration = 700;
|
||||||
public float blurProgress = 0.0f;
|
public float blurProgress = 0.0f;
|
||||||
public int backgroundBlur = 10;
|
public int backgroundBlur = 10;
|
||||||
@@ -41,36 +42,7 @@ public abstract class SaturnScreen extends Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void draw(Element element) {
|
public void draw(Element element) {
|
||||||
synchronized (elements) {
|
ElementRenderer.draw(elements, element);
|
||||||
elements.add(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.animation != null) {
|
|
||||||
element.animation.init(element);
|
|
||||||
|
|
||||||
Animation.execute((Float progress) -> {
|
|
||||||
element.animation.tick(progress, element);
|
|
||||||
}, element.animation.duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.duration != null) {
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
Animation fadeOut = new SlideXAbsolute(700, -(width - element.x));
|
|
||||||
Thread.sleep(element.duration);
|
|
||||||
fadeOut.init(element);
|
|
||||||
Animation.executeSync((Float progress) -> {
|
|
||||||
fadeOut.tick(progress, element);
|
|
||||||
}, fadeOut.duration);
|
|
||||||
synchronized (elements) {
|
|
||||||
elements.remove(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,10 +51,6 @@ public abstract class SaturnScreen extends Screen {
|
|||||||
width *= 2;
|
width *= 2;
|
||||||
height *= 2;
|
height *= 2;
|
||||||
ui(); // abstraction to render the saturn ui and also render extra stuff here
|
ui(); // abstraction to render the saturn ui and also render extra stuff here
|
||||||
|
|
||||||
Animation.execute((Float progress) -> {
|
|
||||||
blurProgress = progress;
|
|
||||||
}, blurDuration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void ui();
|
public abstract void ui();
|
||||||
@@ -90,6 +58,11 @@ public abstract class SaturnScreen extends Screen {
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
|
if (start == null) {
|
||||||
|
start = Instant.now();
|
||||||
|
}
|
||||||
|
long elapsed = Duration.between(start, Instant.now()).toMillis();
|
||||||
|
|
||||||
mouseX *= 2;
|
mouseX *= 2;
|
||||||
mouseY *= 2;
|
mouseY *= 2;
|
||||||
|
|
||||||
@@ -114,7 +87,7 @@ public abstract class SaturnScreen extends Screen {
|
|||||||
|
|
||||||
renderScope.matrices.scale(0.5f, 0.5f, 0.5f);
|
renderScope.matrices.scale(0.5f, 0.5f, 0.5f);
|
||||||
|
|
||||||
ElementRenderer.render(new ArrayList<>(elements), renderScope, mouseX, mouseY);
|
ElementRenderer.render(new ArrayList<>(elements), elapsed, renderScope, mouseX, mouseY);
|
||||||
|
|
||||||
renderScope.matrices.pop();
|
renderScope.matrices.pop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package org.saturnclient.ui2.anim;
|
package org.saturnclient.ui2.anim;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.saturnclient.ui2.Element;
|
import org.saturnclient.ui2.Element;
|
||||||
|
|
||||||
public abstract class Animation {
|
public abstract class Animation {
|
||||||
@@ -12,64 +9,7 @@ public abstract class Animation {
|
|||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void tick(float progress, Element element);
|
public abstract void tick(double progress, Element element);
|
||||||
|
|
||||||
public abstract void init(Element element);
|
public abstract void init(Element element);
|
||||||
|
|
||||||
public static void execute(Consumer<Float> tick, int duration) {
|
|
||||||
new Thread(() -> {
|
|
||||||
Function<Double, Double> curveFunction = Curve::easeInOutCubic;
|
|
||||||
float progress = 0.0f;
|
|
||||||
double incremental = (1000 - duration) / 10000.0;
|
|
||||||
|
|
||||||
for (int i = 0; i <= 100; i++) {
|
|
||||||
float newProgress = (float) (double) curveFunction.apply(i / 100.0);
|
|
||||||
|
|
||||||
while (Math.abs(newProgress - progress) > 1e-6) {
|
|
||||||
if (progress < newProgress) {
|
|
||||||
progress += incremental;
|
|
||||||
if (progress > newProgress) progress = newProgress;
|
|
||||||
} else {
|
|
||||||
progress -= incremental;
|
|
||||||
if (progress < newProgress) progress = newProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
tick.accept(newProgress);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(duration / 100);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void executeSync(Consumer<Float> tick, int duration) {
|
|
||||||
Function<Double, Double> curveFunction = Curve::easeInOutCubic;
|
|
||||||
float progress = 0.0f;
|
|
||||||
double incremental = (1000 - duration) / 10000.0;
|
|
||||||
|
|
||||||
for (int i = 0; i <= 100; i++) {
|
|
||||||
float newProgress = (float) (double) curveFunction.apply(i / 100.0);
|
|
||||||
|
|
||||||
while (Math.abs(newProgress - progress) > 1e-6) {
|
|
||||||
if (progress < newProgress) {
|
|
||||||
progress += incremental;
|
|
||||||
if (progress > newProgress) progress = newProgress;
|
|
||||||
} else {
|
|
||||||
progress -= incremental;
|
|
||||||
if (progress < newProgress) progress = newProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
tick.accept(newProgress);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(duration / 100);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ public class Fade extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(float progress, Element element) {
|
public void tick(double progress, Element element) {
|
||||||
element.opacity = targetOpacity * progress;
|
element.opacity = targetOpacity * (float) progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ public class FadeOut extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(float progress, Element element) {
|
public void tick(double progress, Element element) {
|
||||||
element.opacity = targetOpacity - progress;
|
element.opacity = targetOpacity - (float) progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class SlideX extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(float progress, Element element) {
|
public void tick(double progress, Element element) {
|
||||||
element.x = elementX + (int) (offset * progress);
|
element.x = elementX + (int) (offset * progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class SlideXAbsolute extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(float progress, Element element) {
|
public void tick(double progress, Element element) {
|
||||||
element.x = elementX + (int) (offset * progress);
|
element.x = elementX + (int) (offset * progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class SlideY extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(float progress, Element element) {
|
public void tick(double progress, Element element) {
|
||||||
element.y = elementY + (int) (offset * progress);
|
element.y = elementY + (int) (offset * progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import org.saturnclient.ui2.Element;
|
|||||||
import org.saturnclient.ui2.ElementContext;
|
import org.saturnclient.ui2.ElementContext;
|
||||||
import org.saturnclient.ui2.RenderScope;
|
import org.saturnclient.ui2.RenderScope;
|
||||||
import org.saturnclient.ui2.Utils;
|
import org.saturnclient.ui2.Utils;
|
||||||
import org.saturnclient.ui2.anim.Animation;
|
|
||||||
|
|
||||||
public class ElementRenderer {
|
public class ElementRenderer {
|
||||||
public static void draw(List<Element> elements, Element element) {
|
public static void draw(List<Element> elements, Element element) {
|
||||||
@@ -17,20 +16,18 @@ public class ElementRenderer {
|
|||||||
|
|
||||||
if (element.animation != null) {
|
if (element.animation != null) {
|
||||||
element.animation.init(element);
|
element.animation.init(element);
|
||||||
|
|
||||||
Animation.execute((Float progress) -> {
|
|
||||||
element.animation.tick(progress, element);
|
|
||||||
}, element.animation.duration);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void render(List<Element> elements, RenderScope renderScope, int mouseX, int mouseY) {
|
public static void render(List<Element> elements, long elapsed, RenderScope renderScope, int mouseX, int mouseY) {
|
||||||
for (Element element : elements) {
|
for (Element element : elements) {
|
||||||
|
element.playAnimationFrame(elapsed);
|
||||||
|
|
||||||
renderScope.matrices.push();
|
renderScope.matrices.push();
|
||||||
renderScope.setOpacity(element.opacity);
|
renderScope.setOpacity(element.opacity);
|
||||||
renderScope.matrices.translate(element.x, element.y, 0);
|
renderScope.matrices.translate(element.x, element.y, 0);
|
||||||
renderScope.matrices.scale(element.scale, element.scale, 1.0f);
|
renderScope.matrices.scale(element.scale, element.scale, 1.0f);
|
||||||
element.render(renderScope, new ElementContext(mouseX, mouseY, element));
|
element.render(renderScope, new ElementContext(elapsed, mouseX, mouseY, element));
|
||||||
renderScope.matrices.pop();
|
renderScope.matrices.pop();
|
||||||
renderScope.setRenderLayer(null);
|
renderScope.setRenderLayer(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class Scroll extends Element {
|
|||||||
renderScope.matrices.push();
|
renderScope.matrices.push();
|
||||||
renderScope.matrices.translate(padding, -scroll + padding, 0);
|
renderScope.matrices.translate(padding, -scroll + padding, 0);
|
||||||
|
|
||||||
ElementRenderer.render(children, renderScope,
|
ElementRenderer.render(children, ctx.elapsed, renderScope,
|
||||||
ctx.mouseX - padding,
|
ctx.mouseX - padding,
|
||||||
ctx.mouseY - padding + scroll);
|
ctx.mouseY - padding + scroll);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user