Added Easing functions for the gui Animations
This commit is contained in:
		
							parent
							
								
									cab2095668
								
							
						
					
					
						commit
						9526fe42b9
					
				
							
								
								
									
										3
									
								
								TESTS_TO_DO.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								TESTS_TO_DO.md
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/main/java/speiger/src/coreengine/math/misc/IEasing.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/main/java/speiger/src/coreengine/math/misc/IEasing.java
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
				
			||||||
@ -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,6 +71,7 @@ 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user