You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			454 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C#
		
	
		
		
			
		
	
	
			454 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C#
		
	
| 
								 
											1 year ago
										 
									 | 
							
								using UnityEngine;
							 | 
						||
| 
								 | 
							
								using System.Collections;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace RootMotion.FinalIK {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/// <summary>
							 | 
						||
| 
								 | 
							
									/// The base abstract class for all %IK solvers
							 | 
						||
| 
								 | 
							
									/// </summary>
							 | 
						||
| 
								 | 
							
									[System.Serializable]
							 | 
						||
| 
								 | 
							
									public abstract class IKSolver {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        #region Main Interface
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        [HideInInspector] public bool executedInEditor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Determines whether this instance is valid or not.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public bool IsValid() {
							 | 
						||
| 
								 | 
							
											string message = string.Empty;
							 | 
						||
| 
								 | 
							
											return IsValid(ref message);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Determines whether this instance is valid or not. If returns false, also fills in an error message.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public abstract bool IsValid(ref string message);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Initiate the solver with specified root Transform. Use only if this %IKSolver is not a member of an %IK component.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public void Initiate(Transform root) {
							 | 
						||
| 
								 | 
							
								            if (executedInEditor) return;
							 | 
						||
| 
								 | 
							
											if (OnPreInitiate != null) OnPreInitiate();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (root == null) Debug.LogError("Initiating IKSolver with null root Transform.");
							 | 
						||
| 
								 | 
							
											this.root = root;
							 | 
						||
| 
								 | 
							
											initiated = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											string message = string.Empty;
							 | 
						||
| 
								 | 
							
											if (!IsValid(ref message)) {
							 | 
						||
| 
								 | 
							
												Warning.Log(message, root, false);
							 | 
						||
| 
								 | 
							
												return;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											OnInitiate();
							 | 
						||
| 
								 | 
							
											StoreDefaultLocalState();
							 | 
						||
| 
								 | 
							
											initiated = true;
							 | 
						||
| 
								 | 
							
											firstInitiation = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (OnPostInitiate != null) OnPostInitiate();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Updates the %IK solver. Use only if this %IKSolver is not a member of an %IK component or the %IK component has been disabled and you intend to manually control the updating.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public void Update() {
							 | 
						||
| 
								 | 
							
											if (OnPreUpdate != null) OnPreUpdate();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (firstInitiation) Initiate(root); // when the IK component has been disabled in Awake, this will initiate it.
							 | 
						||
| 
								 | 
							
											if (!initiated) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											OnUpdate();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (OnPostUpdate != null) OnPostUpdate();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// The %IK position.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										[HideInInspector] public Vector3 IKPosition;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										[Tooltip("The positional or the master weight of the solver.")]
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// The %IK position weight or the master weight of the solver.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										[Range(0f, 1f)]
							 | 
						||
| 
								 | 
							
										public float IKPositionWeight = 1f;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Gets the %IK position. NOTE: You are welcome to read IKPosition directly, this method is here only to match the Unity's built in %IK API.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public virtual Vector3 GetIKPosition() {
							 | 
						||
| 
								 | 
							
											return IKPosition;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Sets the %IK position. NOTE: You are welcome to set IKPosition directly, this method is here only to match the Unity's built in %IK API.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public void SetIKPosition(Vector3 position) {
							 | 
						||
| 
								 | 
							
											IKPosition = position;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Gets the %IK position weight. NOTE: You are welcome to read IKPositionWeight directly, this method is here only to match the Unity's built in %IK API.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public float GetIKPositionWeight() {
							 | 
						||
| 
								 | 
							
											return IKPositionWeight;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Sets the %IK position weight. NOTE: You are welcome to set IKPositionWeight directly, this method is here only to match the Unity's built in %IK API.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public void SetIKPositionWeight(float weight) {
							 | 
						||
| 
								 | 
							
											IKPositionWeight = Mathf.Clamp(weight, 0f, 1f);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Gets the root Transform.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public Transform GetRoot() {
							 | 
						||
| 
								 | 
							
											return root;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /// <summary>
							 | 
						||
| 
								 | 
							
								        /// Gets a value indicating whether this <see cref="IKSolver"/> has successfully initiated.
							 | 
						||
| 
								 | 
							
								        /// </summary>
							 | 
						||
| 
								 | 
							
								        public bool initiated { get; private set; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Gets all the points used by the solver.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public abstract IKSolver.Point[] GetPoints();
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Gets the point with the specified Transform.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public abstract IKSolver.Point GetPoint(Transform transform);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Fixes all the Transforms used by the solver to their initial state.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public abstract void FixTransforms();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Stores the default local state for the bones used by the solver.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public abstract void StoreDefaultLocalState();
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// The most basic element type in the %IK chain that all other types extend from.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										[System.Serializable]
							 | 
						||
| 
								 | 
							
										public class Point {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// The transform.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public Transform transform;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// The weight of this bone in the solver.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											[Range(0f, 1f)]
							 | 
						||
| 
								 | 
							
											public float weight = 1f;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Virtual position in the %IK solver.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public Vector3 solverPosition;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Virtual rotation in the %IK solver.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public Quaternion solverRotation = Quaternion.identity;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// The default local position of the Transform.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public Vector3 defaultLocalPosition;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// The default local rotation of the Transform.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public Quaternion defaultLocalRotation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Stores the default local state of the point.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public void StoreDefaultLocalState() {
							 | 
						||
| 
								 | 
							
												defaultLocalPosition = transform.localPosition;
							 | 
						||
| 
								 | 
							
												defaultLocalRotation = transform.localRotation;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Fixes the transform to its default local state.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public void FixTransform() {
							 | 
						||
| 
								 | 
							
												if (transform.localPosition != defaultLocalPosition) transform.localPosition = defaultLocalPosition;
							 | 
						||
| 
								 | 
							
												if (transform.localRotation != defaultLocalRotation) transform.localRotation = defaultLocalRotation;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Updates the solverPosition (in world space).
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public void UpdateSolverPosition() {
							 | 
						||
| 
								 | 
							
												solverPosition = transform.position;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Updates the solverPosition (in local space).
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public void UpdateSolverLocalPosition() {
							 | 
						||
| 
								 | 
							
												solverPosition = transform.localPosition;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Updates the solverPosition/Rotation (in world space).
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public void UpdateSolverState() {
							 | 
						||
| 
								 | 
							
												solverPosition = transform.position;
							 | 
						||
| 
								 | 
							
												solverRotation = transform.rotation;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Updates the solverPosition/Rotation (in local space).
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public void UpdateSolverLocalState() {
							 | 
						||
| 
								 | 
							
												solverPosition = transform.localPosition;
							 | 
						||
| 
								 | 
							
												solverRotation = transform.localRotation;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// %Bone type of element in the %IK chain. Used in the case of skeletal Transform hierarchies.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										[System.Serializable]
							 | 
						||
| 
								 | 
							
										public class Bone: Point {
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// The length of the bone.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public float length;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// The sqr mag of the bone.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public float sqrMag;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Local axis to target/child bone.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public Vector3 axis = -Vector3.right;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Gets the rotation limit component from the Transform if there is any.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public RotationLimit rotationLimit {
							 | 
						||
| 
								 | 
							
												get {
							 | 
						||
| 
								 | 
							
													if (!isLimited) return null;
							 | 
						||
| 
								 | 
							
													if (_rotationLimit == null) _rotationLimit = transform.GetComponent<RotationLimit>();
							 | 
						||
| 
								 | 
							
													isLimited = _rotationLimit != null;
							 | 
						||
| 
								 | 
							
													return _rotationLimit;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												set {
							 | 
						||
| 
								 | 
							
													_rotationLimit = value;
							 | 
						||
| 
								 | 
							
													isLimited = value != null;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
											/*
							 | 
						||
| 
								 | 
							
											 * Swings the Transform's axis towards the swing target
							 | 
						||
| 
								 | 
							
											 * */
							 | 
						||
| 
								 | 
							
											public void Swing(Vector3 swingTarget, float weight = 1f) {
							 | 
						||
| 
								 | 
							
												if (weight <= 0f) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												Quaternion r = Quaternion.FromToRotation(transform.rotation * axis, swingTarget - transform.position);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if (weight >= 1f) {
							 | 
						||
| 
								 | 
							
													transform.rotation = r * transform.rotation;
							 | 
						||
| 
								 | 
							
													return;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												transform.rotation = Quaternion.Lerp(Quaternion.identity, r, weight) * transform.rotation;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											public static void SolverSwing(Bone[] bones, int index, Vector3 swingTarget, float weight = 1f) {
							 | 
						||
| 
								 | 
							
												if (weight <= 0f) return;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												Quaternion r = Quaternion.FromToRotation(bones[index].solverRotation * bones[index].axis, swingTarget - bones[index].solverPosition);
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												if (weight >= 1f) {
							 | 
						||
| 
								 | 
							
													for (int i = index; i < bones.Length; i++) {
							 | 
						||
| 
								 | 
							
														bones[i].solverRotation = r * bones[i].solverRotation;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													return;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												for (int i = index; i < bones.Length; i++) {
							 | 
						||
| 
								 | 
							
													bones[i].solverRotation = Quaternion.Lerp(Quaternion.identity, r, weight) * bones[i].solverRotation;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/*
							 | 
						||
| 
								 | 
							
											 * Swings the Transform's axis towards the swing target on the XY plane only
							 | 
						||
| 
								 | 
							
											 * */
							 | 
						||
| 
								 | 
							
											public void Swing2D(Vector3 swingTarget, float weight = 1f) {
							 | 
						||
| 
								 | 
							
												if (weight <= 0f) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												Vector3 from = transform.rotation * axis;
							 | 
						||
| 
								 | 
							
												Vector3 to = swingTarget - transform.position;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												float angleFrom = Mathf.Atan2(from.x, from.y) * Mathf.Rad2Deg;
							 | 
						||
| 
								 | 
							
												float angleTo = Mathf.Atan2(to.x, to.y) * Mathf.Rad2Deg;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												transform.rotation = Quaternion.AngleAxis(Mathf.DeltaAngle(angleFrom, angleTo) * weight, Vector3.back) * transform.rotation;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											/*
							 | 
						||
| 
								 | 
							
											 * Moves the bone to the solver position
							 | 
						||
| 
								 | 
							
											 * */
							 | 
						||
| 
								 | 
							
											public void SetToSolverPosition() {
							 | 
						||
| 
								 | 
							
												transform.position = solverPosition;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											public Bone() {}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											public Bone (Transform transform) {
							 | 
						||
| 
								 | 
							
												this.transform = transform;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											public Bone (Transform transform, float weight) {
							 | 
						||
| 
								 | 
							
												this.transform = transform;
							 | 
						||
| 
								 | 
							
												this.weight = weight;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											private RotationLimit _rotationLimit;
							 | 
						||
| 
								 | 
							
											private bool isLimited = true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// %Node type of element in the %IK chain. Used in the case of mixed/non-hierarchical %IK systems
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										[System.Serializable]
							 | 
						||
| 
								 | 
							
										public class Node: Point {
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Distance to child node.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public float length;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// The effector position weight.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public float effectorPositionWeight;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// The effector rotation weight.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public float effectorRotationWeight;
							 | 
						||
| 
								 | 
							
											/// <summary>
							 | 
						||
| 
								 | 
							
											/// Position offset.
							 | 
						||
| 
								 | 
							
											/// </summary>
							 | 
						||
| 
								 | 
							
											public Vector3 offset;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											public Node() {}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											public Node (Transform transform) {
							 | 
						||
| 
								 | 
							
												this.transform = transform;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											public Node (Transform transform, float weight) {
							 | 
						||
| 
								 | 
							
												this.transform = transform;
							 | 
						||
| 
								 | 
							
												this.weight = weight;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Delegates solver update events.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public delegate void UpdateDelegate();
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Delegates solver iteration events.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public delegate void IterationDelegate(int i);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Called before initiating the solver.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public UpdateDelegate OnPreInitiate;
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Called after initiating the solver.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public UpdateDelegate OnPostInitiate;
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Called before updating.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public UpdateDelegate OnPreUpdate;
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Called after writing the solved pose
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public UpdateDelegate OnPostUpdate;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										#endregion Main Interface
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										protected abstract void OnInitiate();
							 | 
						||
| 
								 | 
							
										protected abstract void OnUpdate();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										protected bool firstInitiation = true;
							 | 
						||
| 
								 | 
							
										[SerializeField][HideInInspector] protected Transform root;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										protected void LogWarning(string message) {
							 | 
						||
| 
								 | 
							
											Warning.Log(message, root, true);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										#region Class Methods
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/// <summary>
							 | 
						||
| 
								 | 
							
										/// Checks if an array of objects contains any duplicates.
							 | 
						||
| 
								 | 
							
										/// </summary>
							 | 
						||
| 
								 | 
							
										public static Transform ContainsDuplicateBone(Bone[] bones) {
							 | 
						||
| 
								 | 
							
											for (int i = 0; i < bones.Length; i++) {
							 | 
						||
| 
								 | 
							
												for (int i2 = 0; i2 < bones.Length; i2++) {
							 | 
						||
| 
								 | 
							
													if (i != i2 && bones[i].transform == bones[i2].transform) return bones[i].transform;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											return null;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Make sure the bones are in valid Hierarchy
							 | 
						||
| 
								 | 
							
										 * */
							 | 
						||
| 
								 | 
							
										public static bool HierarchyIsValid(IKSolver.Bone[] bones) {
							 | 
						||
| 
								 | 
							
											for (int i = 1; i < bones.Length; i++) {
							 | 
						||
| 
								 | 
							
												// If parent bone is not an ancestor of bone, the hierarchy is invalid
							 | 
						||
| 
								 | 
							
												if (!Hierarchy.IsAncestor(bones[i].transform, bones[i - 1].transform)) {
							 | 
						||
| 
								 | 
							
													return false;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Calculates bone lengths and axes, returns the length of the entire chain
							 | 
						||
| 
								 | 
							
										protected static float PreSolveBones(ref Bone[] bones) {
							 | 
						||
| 
								 | 
							
											float length = 0;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											for (int i = 0; i < bones.Length; i++) {
							 | 
						||
| 
								 | 
							
												bones[i].solverPosition = bones[i].transform.position;
							 | 
						||
| 
								 | 
							
												bones[i].solverRotation = bones[i].transform.rotation;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											for (int i = 0; i < bones.Length; i++) {
							 | 
						||
| 
								 | 
							
												if (i < bones.Length - 1) {
							 | 
						||
| 
								 | 
							
													bones[i].sqrMag = (bones[i + 1].solverPosition - bones[i].solverPosition).sqrMagnitude;
							 | 
						||
| 
								 | 
							
													bones[i].length = Mathf.Sqrt(bones[i].sqrMag);
							 | 
						||
| 
								 | 
							
													length += bones[i].length;
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													bones[i].axis = Quaternion.Inverse(bones[i].solverRotation) * (bones[i + 1].solverPosition - bones[i].solverPosition);
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													bones[i].sqrMag = 0f;
							 | 
						||
| 
								 | 
							
													bones[i].length = 0f;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											return length;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										#endregion Class Methods
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 |