package com.brashmonkey.spriter; import java.util.HashMap; import java.util.Map.Entry; import com.brashmonkey.spriter.Mainline.Key.BoneRef; import com.brashmonkey.spriter.Timeline.Key.Bone; /** * A IKResolver is responsible for resolving previously set constraints. * @see <a href="http://en.wikipedia.org/wiki/Inverse_kinematics"> Inverse kinematics</a> * @author Trixt0r * */ public abstract class IKResolver { /** * Resolves the inverse kinematics constraint with a specific algtorithm * @param x the target x value * @param y the target y value * @param chainLength number of parents which are affected * @param effector the actual effector where the resolved information has to be stored in. */ protected abstract void resolve(float x, float y, int chainLength, BoneRef effector); protected HashMap<IKObject, BoneRef> ikMap; protected float tolerance; protected Player player; /** * Creates a resolver with a default tolerance of 5f. */ public IKResolver(Player player) { this.tolerance = 5f; this.ikMap = new HashMap<IKObject, BoneRef>(); this.setPlayer(player); } /** * Sets the player for this resolver. * @param player the player which gets affected. * @throws SpriterException if player is <code>null</code> */ public void setPlayer(Player player){ if(player == null) throw new SpriterException("player cannot be null!"); this.player = player; } /** * Returns the current set player. * @return the current player. */ public Player getPlayer(){ return this.player; } /** * Resolves the inverse kinematics constraints with the implemented algorithm * */ public void resolve(){ for(Entry<IKObject, BoneRef> entry: this.ikMap.entrySet()){ for(int j = 0; j < entry.getKey().iterations; j++) this.resolve(entry.getKey().x, entry.getKey().y, entry.getKey().chainLength, entry.getValue()); } } /** * Adds the given object to the internal IKObject - Bone map. * This means, the values of the given ik object affect the mapped bone. * @param ikObject the ik object * @param boneRef the bone reference which gets affected */ public void mapIKObject(IKObject ikObject, BoneRef boneRef){ this.ikMap.put(ikObject, boneRef); } /** * Adds the given object to the internal IKObject - Bone map. * This means, the values of the given ik object affect the mapped bone. * @param ikObject the ik object * @param bone the bone which gets affected */ public void mapIKObject(IKObject ikObject, Bone bone){ this.ikMap.put(ikObject, player.getBoneRef(bone)); } /** * Removes the given object from the internal map. * @param ikObject the ik object to remove */ public void unmapIKObject(IKObject ikObject){ this.ikMap.remove(ikObject); } /** * Returns the tolerance of this resolver. * @return the tolerance */ public float getTolerance() { return tolerance; } /** * Sets the tolerance distance of this resolver. * The resolver should stop the algorithm if the distance to the set ik object is less than the tolerance. * @param tolerance the tolerance */ public void setTolerance(float tolerance) { this.tolerance = tolerance; } }