All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.brashmonkey.spriter.Curve Maven / Gradle / Ivy

Go to download

overlap2d-runtime-libgdx provides functionality to load, manipulate and render scenes generated by Overlap2D.

There is a newer version: 0.1.1
Show newest version
package com.brashmonkey.spriter;

import static  com.brashmonkey.spriter.Calculator.*;
import static com.brashmonkey.spriter.Interpolator.*;

/**
 * Represents a curve in a Spriter SCML file.
 * An instance of this class is responsible for tweening given data.
 * The most important method of this class is {@link #tween(float, float, float)}.
 * Curves can be changed with sub curves {@link Curve#subCurve}.
 * @author Trixt0r
 *
 */
public class Curve {
	
	/**
	 * Represents a curve type in a Spriter SCML file.
	 * @author Trixt0r
	 *
	 */
	public static enum Type {
		Instant, Linear, Quadratic, Cubic, Quartic, Quintic, Bezier;
	}
	
	/**
	 * Returns a curve type based on the given curve name.
	 * @param name the name of the curve
	 * @return the curve type. {@link Type#Linear} is returned as a default type.
	 */
	public static Type getType(String name){
		if(name.equals("instant")) return Type.Instant;
		else if(name.equals("quadratic")) return Type.Quadratic;
		else if(name.equals("cubic")) return Type.Cubic;
		else if(name.equals("quartic")) return Type.Quartic;
		else if(name.equals("quintic")) return Type.Quintic;
		else if(name.equals("bezier")) return Type.Bezier;
		else return Type.Linear;
	}
	
	private Type type;
	/**
	 * The sub curve of this curve, which can be null.
	 */
	public Curve subCurve;
	/**
	 * The constraints of a curve which will affect a curve of the types different from {@link Type#Linear} and {@link Type#Instant}.
	 */
	public final Constraints constraints = new Constraints(0, 0, 0, 0);
	
	/**
	 * Creates a new linear curve.
	 */
	public Curve(){
		this(Type.Linear);
	}
	
	/**
	 * Creates a new curve with the given type.
	 * @param type the curve type
	 */
	public Curve(Type type){
		this(type, null);
	}
	
	/**
	 * Creates a new curve with the given type and sub cuve.
	 * @param type the curve type
	 * @param subCurve the sub curve. Can be null
	 */
	public Curve(Type type, Curve subCurve){
		this.setType(type);
		this.subCurve = subCurve;
	}
	
	/**
	 * Sets the type of this curve.
	 * @param type the curve type.
	 * @throws SpriterException if the type is null
	 */
	public void setType(Type type){
		if(type == null) throw new SpriterException("The type of a curve cannot be null!");
		this.type = type;
	}
	
	/**
	 * Returns the type of this curve.
	 * @return the curve type
	 */
	public Type getType(){
		return this.type;
	}

	
	private float lastCubicSolution = 0f;
	/**
	 * Returns a new value based on the given values.
	 * Tweens the weight with the set sub curve.
	 * @param a the start value
	 * @param b the end value
	 * @param t the weight which lies between 0.0 and 1.0
	 * @return tweened value
	 */
	public float tween(float a, float b, float t){
		t = tweenSub(0f,1f,t);
		switch(type){
		case Instant: return a;
		case Linear: return linear(a, b, t);
		case Quadratic: return quadratic(a, linear(a, b, constraints.c1), b, t);
		case Cubic: return cubic(a, linear(a, b, constraints.c1), linear(a, b, constraints.c2), b, t);
		case Quartic: return quartic(a, linear(a, b, constraints.c1), linear(a, b, constraints.c2),	linear(a, b, constraints.c3), b, t);
		case Quintic: return quintic(a, linear(a, b, constraints.c1), linear(a, b, constraints.c2),	linear(a, b, constraints.c3), linear(a, b, constraints.c4), b, t);
		case Bezier: Float cubicSolution = solveCubic(3f*(constraints.c1-constraints.c3) + 1f, 3f*(constraints.c3-2f*constraints.c1), 3f*constraints.c1, -t);
					 if(cubicSolution == null) cubicSolution = lastCubicSolution;
					 else lastCubicSolution = cubicSolution;
					 return linear(a, b, bezier(cubicSolution, 0f, constraints.c2, constraints.c4, 1f));
		default: return linear(a, b, t);
		}
	}
	
	/**
	 * Interpolates the given two points with the given weight and saves the result in the target point.
	 * @param a the start point
	 * @param b the end point
	 * @param t the weight which lies between 0.0 and 1.0
	 * @param target the target point to save the result in
	 */
	public void tweenPoint(Point a, Point b, float t, Point target){
		target.set(this.tween(a.x, b.x, t), this.tween(a.y, b.y, t));
	}
	
	private float tweenSub(float a, float b, float t){
		if(this.subCurve != null) return subCurve.tween(a, b, t);
		else return t;
	}
	
	/**
	 * Returns a tweened angle based on the given angles, weight and the spin.
	 * @param a the start angle
	 * @param b the end angle
	 * @param t the weight which lies between 0.0 and 1.0
	 * @param spin the spin, which is either 0, 1 or -1
	 * @return tweened angle
	 */
	public float tweenAngle(float a, float b, float t, int spin){
	    if(spin>0){
	        if(b-a < 0)
	            b+=360;
	    }
	    else if(spin < 0){
	        if(b-a > 0)
	            b-=360;
	    }
	    else return a;

	    return tween(a, b, t);
	}
	
	/**
	 * @see {@link #tween(float, float, float)}
	 */
	public float tweenAngle(float a, float b, float t){
		t = tweenSub(0f,1f,t);
		switch(type){
		case Instant: return a;
		case Linear: return linearAngle(a, b, t);
		case Quadratic: return quadraticAngle(a, linearAngle(a, b, constraints.c1), b, t);
		case Cubic: return cubicAngle(a, linearAngle(a, b, constraints.c1), linearAngle(a, b, constraints.c2), b, t);
		case Quartic: return quarticAngle(a, linearAngle(a, b, constraints.c1), linearAngle(a, b, constraints.c2),	linearAngle(a, b, constraints.c3), b, t);
		case Quintic: return quinticAngle(a, linearAngle(a, b, constraints.c1), linearAngle(a, b, constraints.c2),	linearAngle(a, b, constraints.c3), linearAngle(a, b, constraints.c4), b, t);
		case Bezier: Float cubicSolution = solveCubic(3f*(constraints.c1-constraints.c3) + 1f, 3f*(constraints.c3-2f*constraints.c1), 3f*constraints.c1, -t);
					 if(cubicSolution == null) cubicSolution = lastCubicSolution;
					 else lastCubicSolution = cubicSolution;
					 return linearAngle(a, b, bezier(cubicSolution, 0f, constraints.c2, constraints.c4, 1f));
		default: return linearAngle(a, b, t);
		}
	}
	
	public String toString(){
		return getClass().getSimpleName()+"|["+type+":"+constraints+", subCurve: "+subCurve+"]";
	}
	
	/**
	 * Represents constraints for a curve.
	 * Constraints are important for curves which have a order higher than 1.
	 * @author Trixt0r
	 *
	 */
	public static class Constraints{
		public float c1, c2, c3, c4;
		
		public Constraints(float c1, float c2, float c3, float c4){
			this.set(c1, c2, c3, c4);
		}
		
		public void set(float c1, float c2, float c3, float c4){
			this.c1 = c1;
			this.c2 = c2;
			this.c3 = c3;
			this.c4 = c4;
		}
		
		public String toString(){
			return getClass().getSimpleName()+"| [c1:"+c1+", c2:"+c2+", c3:"+c3+", c4:"+c4+"]";
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy