initial upload

This commit is contained in:
tom.hempel
2025-09-21 22:42:26 +02:00
commit d03bcd4ba5
6231 changed files with 351582 additions and 0 deletions

View File

@ -0,0 +1,149 @@
using UnityEngine;
using System.Collections;
using System;
namespace RootMotion.FinalIK {
/// <summary>
/// Posing the children of a Transform to match the children of another Transform
/// </summary>
public class GenericPoser : Poser {
/// <summary>
/// Mapping a bone to its target
/// </summary>
[System.Serializable]
public class Map {
public Transform bone;
public Transform target;
private Vector3 defaultLocalPosition;
private Quaternion defaultLocalRotation;
private Vector3 lerpLocalPosition;
private Quaternion lerpLocalRotation;
// Custom constructor
public Map(Transform bone, Transform target) {
this.bone = bone;
this.target = target;
StoreDefaultState();
}
public void StoreDefaultState() {
defaultLocalPosition = bone.localPosition;
defaultLocalRotation = bone.localRotation;
}
public void StoreCurrentPose()
{
lerpLocalPosition = bone.localPosition;
lerpLocalRotation = bone.localRotation;
}
public void FixTransform() {
bone.localPosition = defaultLocalPosition;
bone.localRotation = defaultLocalRotation;
}
// Update mapping
public void Update(float localRotationWeight, float localPositionWeight) {
bone.localRotation = Quaternion.Lerp(bone.localRotation, target.localRotation, localRotationWeight);
bone.localPosition = Vector3.Lerp(bone.localPosition, target.localPosition, localPositionWeight);
}
public void BlendFromLastPose(float lerpTimer)
{
bone.localPosition = Vector3.Lerp(lerpLocalPosition, bone.localPosition, lerpTimer);
bone.localRotation = Quaternion.Lerp(lerpLocalRotation, bone.localRotation, lerpTimer);
}
}
public Map[] maps;
/// <summary>
/// Finds mapping automatically. This requires for all children of the transform to have unique names. This method is not very memory efficient so try to avoid using it in play mode.
/// </summary>
[ContextMenu("Auto-Mapping")]
public override void AutoMapping() {
if (poseRoot == null) {
maps = new Map[0];
return;
}
maps = new Map[0];
Transform[] children = (Transform[])transform.GetComponentsInChildren<Transform>();
Transform[] poseChildren = (Transform[])poseRoot.GetComponentsInChildren<Transform>();
Transform target;
// Find all the bone to target matches
for (int i = 1; i < children.Length; i++) {
target = GetTargetNamed(children[i].name, poseChildren);
if (target != null) {
Array.Resize(ref maps, maps.Length + 1);
maps[maps.Length - 1] = new Map(children[i], target);
}
}
StoreDefaultState();
}
protected override void InitiatePoser() {
StoreDefaultState();
}
protected override void UpdatePoser() {
if (weight <= 0f) return;
if (localPositionWeight <= 0f && localRotationWeight <= 0f) return;
if (poseRoot == null) return;
// Calculate weights
float rW = localRotationWeight * weight;
float pW = localPositionWeight * weight;
// Lerping the localRotation and the localPosition
for (int i = 0; i < maps.Length; i++) maps[i].Update(rW, pW);
}
protected override void StoreCurrentPose()
{
for (int i = 0; i < maps.Length; i++)
{
maps[i].StoreCurrentPose();
}
}
protected override void BlendFromLastPose(float lerpTimer)
{
for (int i = 0; i < maps.Length; i++)
{
maps[i].BlendFromLastPose(lerpTimer);
}
}
protected override void FixPoserTransforms() {
for (int i = 0; i < maps.Length; i++) {
maps[i].FixTransform();
}
}
private void StoreDefaultState() {
for (int i = 0; i < maps.Length; i++) {
maps[i].StoreDefaultState();
}
}
// Returns a Transform from the array that has the specified name
private Transform GetTargetNamed(string tName, Transform[] array) {
for (int i = 0; i < array.Length; i++) {
if (array[i].name == tName) return array[i];
}
return null;
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: dd754e329e5ea4f139b08b9271641e12
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,100 @@
using UnityEngine;
using System.Collections;
namespace RootMotion.FinalIK {
/// <summary>
/// Posing the children of a Transform to match the children of another Transform
/// </summary>
public class HandPoser : Poser {
public override void AutoMapping() {
if (poseRoot == null) poseChildren = new Transform[0];
else poseChildren = (Transform[])poseRoot.GetComponentsInChildren<Transform>();
_poseRoot = poseRoot;
}
protected override void InitiatePoser() {
// Find the children
children = (Transform[])GetComponentsInChildren<Transform>();
StoreDefaultState();
}
protected override void FixPoserTransforms() {
for (int i = 0; i < children.Length; i++) {
children[i].localPosition = defaultLocalPositions[i];
children[i].localRotation = defaultLocalRotations[i];
}
}
protected override void UpdatePoser() {
if (weight <= 0f) return;
if (localPositionWeight <= 0f && localRotationWeight <= 0f) return;
// Get the children, if we don't have them already
if (_poseRoot != poseRoot) AutoMapping();
if (poseRoot == null) return;
// Something went wrong
if (children.Length != poseChildren.Length) {
Warning.Log("Number of children does not match with the pose", transform);
return;
}
// Calculate weights
float rW = localRotationWeight * weight;
float pW = localPositionWeight * weight;
// Lerping the localRotation and the localPosition
for (int i = 0; i < children.Length; i++) {
if (children[i] != transform) {
children[i].localRotation = Quaternion.Lerp(children[i].localRotation, poseChildren[i].localRotation, rW);
children[i].localPosition = Vector3.Lerp(children[i].localPosition, poseChildren[i].localPosition, pW);
}
}
}
protected override void StoreCurrentPose()
{
lerpLocalPositions = new Vector3[children.Length];
lerpLocalRotations = new Quaternion[children.Length];
for (int i = 0; i < children.Length; i++)
{
lerpLocalPositions[i] = children[i].localPosition;
lerpLocalRotations[i] = children[i].localRotation;
}
}
protected override void BlendFromLastPose(float lerpTimer)
{
for (int i = 0; i < children.Length; i++)
{
children[i].localPosition = Vector3.Lerp(lerpLocalPositions[i], children[i].localPosition, lerpTimer);
children[i].localRotation = Quaternion.Lerp(lerpLocalRotations[i], children[i].localRotation, lerpTimer);
}
}
protected Transform[] children;
private Transform _poseRoot;
private Transform[] poseChildren;
private Vector3[] defaultLocalPositions;
private Quaternion[] defaultLocalRotations;
private Vector3[] lerpLocalPositions;
private Quaternion[] lerpLocalRotations;
protected void StoreDefaultState() {
defaultLocalPositions = new Vector3[children.Length];
defaultLocalRotations = new Quaternion[children.Length];
for (int i = 0; i < children.Length; i++) {
defaultLocalPositions[i] = children[i].localPosition;
defaultLocalRotations[i] = children[i].localRotation;
}
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a98c3501ec8dc43c8a64321bd55c3f63
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,127 @@
using UnityEngine;
using System.Collections;
namespace RootMotion.FinalIK {
/// <summary>
/// The base abstract class for all class that are translating a hierarchy of bones to match the translation of bones in another hierarchy.
/// </summary>
public abstract class Poser: SolverManager {
/// <summary>
/// Reference to the other Transform (should be identical to this one)
/// </summary>
public Transform poseRoot;
/// <summary>
/// The master weight.
/// </summary>
[Range(0f, 1f)] public float weight = 1f;
/// <summary>
/// Weight of localRotation matching
/// </summary>
[Range(0f, 1f)] public float localRotationWeight = 1f;
/// <summary>
/// Weight of localPosition matching
/// </summary>
[Range(0f, 1f)] public float localPositionWeight;
/// <summary>
/// Map this instance to the poseRoot.
/// </summary>
public abstract void AutoMapping();
public virtual void AutoMapping(Transform[] bones) { }
/// <summary>
/// For manual update of the poser.
/// </summary>
public void UpdateManual(float deltaTime) {
UpdatePoser();
UpdateLerping(deltaTime);
if (storeCurrentPoseFlag) OnStoreCurrentPoseFlag();
}
public void SetPoseRoot(Transform newPoseRoot, Transform[] autoMappingBones, float blendSpeed)
{
this.blendSpeed = blendSpeed;
if (newPoseRoot != null && poseRoot != null && weight > 0f)
{
nextPoseRoot = newPoseRoot;
this.autoMappingBones = autoMappingBones;
storeCurrentPoseFlag = true;
} else
{
poseRoot = newPoseRoot;
AutoMapping(autoMappingBones);
storeCurrentPoseFlag = false;
}
}
private bool initiated;
protected abstract void InitiatePoser();
protected abstract void UpdatePoser();
protected abstract void StoreCurrentPose();
protected abstract void BlendFromLastPose(float lerpTimer);
protected abstract void FixPoserTransforms();
protected Transform nextPoseRoot;
protected bool storeCurrentPoseFlag;
private bool isLerping;
private float lerpTimer;
private Transform[] autoMappingBones = new Transform[0];
private float blendSpeed;
private void UpdateLerping(float deltaTime)
{
if (!isLerping) return;
lerpTimer = Mathf.MoveTowards(lerpTimer, 1f, deltaTime * blendSpeed);
BlendFromLastPose(lerpTimer);
if (lerpTimer >= 1f)
{
isLerping = false;
lerpTimer = 0f;
}
}
/*
* Updates the solver. If you need full control of the execution order of your IK solvers, disable this script and call UpdateSolver() instead.
* */
protected override void UpdateSolver() {
if (!initiated) InitiateSolver();
if (!initiated) return;
UpdatePoser();
UpdateLerping(Time.deltaTime);
if (storeCurrentPoseFlag) OnStoreCurrentPoseFlag();
}
private void OnStoreCurrentPoseFlag()
{
StoreCurrentPose();
isLerping = true;
lerpTimer = 0f;
poseRoot = nextPoseRoot;
AutoMapping(autoMappingBones);
nextPoseRoot = null;
storeCurrentPoseFlag = false;
}
/*
* Initiates the %IK solver
* */
protected override void InitiateSolver() {
if (initiated) return;
InitiatePoser();
initiated = true;
}
protected override void FixTransforms() {
if (!initiated) return;
FixPoserTransforms();
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 5c8218556cda043adb17da42f8151df0
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,175 @@
using UnityEngine;
using System.Collections;
using System;
namespace RootMotion.FinalIK
{
/// <summary>
/// Posing the children of a Transform to match the children of another Transform that has different bone orientations.
/// </summary>
public class UniversalPoser : Poser
{
/// <summary>
/// Mapping a bone to its target
/// </summary>
[System.Serializable]
public class Map
{
public Transform bone;
[HideInInspector]
public Transform target;
private Vector3 defaultLocalPosition;
private Quaternion defaultLocalRotation;
private Vector3 lerpLocalPosition;
private Quaternion lerpLocalRotation;
// Custom constructor
public Map(Transform bone, Transform target)
{
this.bone = bone;
this.target = target;
StoreDefaultState();
}
public void StoreDefaultState()
{
defaultLocalPosition = bone.localPosition;
defaultLocalRotation = bone.localRotation;
}
public void StoreCurrentPose()
{
lerpLocalPosition = bone.localPosition;
lerpLocalRotation = bone.localRotation;
}
public void FixTransform()
{
bone.localPosition = defaultLocalPosition;
bone.localRotation = defaultLocalRotation;
}
// Update mapping
public void Update(float localRotationWeight, float localPositionWeight, Vector3 targetAxis1, Vector3 targetAxis2, Vector3 axis1, Vector3 axis2)
{
if (targetAxis1 == axis1 && targetAxis2 == axis2)
{
bone.localRotation = Quaternion.Lerp(bone.localRotation, target.localRotation, localRotationWeight);
}
else
{
Quaternion r = Quaternion.Lerp(bone.localRotation, QuaTools.MatchRotation(target.localRotation, targetAxis1, targetAxis2, axis1, axis2), localRotationWeight);
Quaternion c = QuaTools.MatchRotation(Quaternion.identity, targetAxis1, targetAxis2, axis1, axis2);
bone.localRotation = c * r;
}
//bone.localPosition = Vector3.Lerp(bone.localPosition, target.localPosition, localPositionWeight); //TODO
}
public void BlendFromLastPose(float lerpTimer)
{
bone.localPosition = Vector3.Lerp(lerpLocalPosition, bone.localPosition, lerpTimer);
bone.localRotation = Quaternion.Lerp(lerpLocalRotation, bone.localRotation, lerpTimer);
}
}
[Tooltip("Choose 2 axes of a finger bone. For example 1 pointing towards the next finger and 2 pointing up. Select a finger bone in the InteractionTarget hierarchy and see which local axis points towards the next bone and which local axis points up and set targetAxis1 and targetAxis2 accordingly. Then select a finger in this poser's hierarchy and do the same for axis1 and axis2.")]
public Vector3 targetAxis1 = Vector3.forward, targetAxis2 = Vector3.up, axis1 = Vector3.forward, axis2 = Vector3.up;
[Tooltip("List of bones must match InteractionTarget's list of bones in both array size and hierarchy.")]
public Map[] bones;
public override void AutoMapping() {}
public override void AutoMapping(Transform[] bones)
{
if (bones.Length != this.bones.Length)
{
Debug.LogError("Trying to use UniversalPoser with an InteractionTarget that has a different number of bones. Bones must match with UniversalPoser bones in both array size and hierarchy", transform);
Debug.LogError("InterqactionTarget.bones: " + bones.Length);
for (int i = 0; i < bones.Length; i++)
{
Debug.LogError(" " + i + ": " + bones[i].name);
}
return;
}
for (int i = 0; i < this.bones.Length; i++)
{
this.bones[i].target = bones[i];
}
StoreDefaultState();
}
protected override void InitiatePoser()
{
StoreDefaultState();
}
protected override void UpdatePoser()
{
if (weight <= 0f) return;
if (localPositionWeight <= 0f && localRotationWeight <= 0f) return;
if (poseRoot == null) return;
// Calculate weights
float rW = localRotationWeight * weight;
float pW = localPositionWeight * weight;
// Lerping the localRotation and the localPosition
for (int i = 0; i < bones.Length; i++) bones[i].Update(rW, pW, targetAxis1, targetAxis2, axis1, axis2);
}
protected override void StoreCurrentPose()
{
for (int i = 0; i < bones.Length; i++)
{
bones[i].StoreCurrentPose();
}
}
protected override void BlendFromLastPose(float lerpTimer)
{
for (int i = 0; i < bones.Length; i++)
{
bones[i].BlendFromLastPose(lerpTimer);
}
}
protected override void FixPoserTransforms()
{
for (int i = 0; i < bones.Length; i++)
{
bones[i].FixTransform();
}
}
private void StoreDefaultState()
{
for (int i = 0; i < bones.Length; i++)
{
bones[i].StoreDefaultState();
}
}
// Returns a Transform from the array that has the specified name
private Transform GetTargetNamed(string tName, Transform[] array)
{
for (int i = 0; i < array.Length; i++)
{
if (array[i].name == tName) return array[i];
}
return null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6c38faaae4d939647ae12f04b96e8ef3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: