r2mods/ilspy_dump/ror2_csproj/DynamicBone.cs

614 lines
15 KiB
C#
Raw Normal View History

2024-10-04 07:26:37 +00:00
using System.Collections.Generic;
using UnityEngine;
[AddComponentMenu("Dynamic Bone/Dynamic Bone")]
public class DynamicBone : MonoBehaviour
{
public enum UpdateMode
{
Normal,
AnimatePhysics,
UnscaledTime
}
public enum FreezeAxis
{
None,
X,
Y,
Z
}
private class Particle
{
public Transform m_Transform;
public int m_ParentIndex = -1;
public float m_Damping;
public float m_Elasticity;
public float m_Stiffness;
public float m_Inert;
public float m_Radius;
public float m_BoneLength;
public Vector3 m_Position = Vector3.zero;
public Vector3 m_PrevPosition = Vector3.zero;
public Vector3 m_EndOffset = Vector3.zero;
public Vector3 m_InitLocalPosition = Vector3.zero;
public Quaternion m_InitLocalRotation = Quaternion.identity;
}
public Transform m_Root;
public float m_UpdateRate = 60f;
public UpdateMode m_UpdateMode;
[Range(0f, 1f)]
public float m_Damping = 0.1f;
public AnimationCurve m_DampingDistrib;
[Range(0f, 1f)]
public float m_Elasticity = 0.1f;
public AnimationCurve m_ElasticityDistrib;
[Range(0f, 1f)]
public float m_Stiffness = 0.1f;
public AnimationCurve m_StiffnessDistrib;
[Range(0f, 1f)]
public float m_Inert;
public AnimationCurve m_InertDistrib;
public float m_Radius;
public AnimationCurve m_RadiusDistrib;
public float m_EndLength;
public Vector3 m_EndOffset = Vector3.zero;
public Vector3 m_Gravity = Vector3.zero;
public Vector3 m_Force = Vector3.zero;
public List<DynamicBoneCollider> m_Colliders;
public List<Transform> m_Exclusions;
public FreezeAxis m_FreezeAxis;
public bool m_DistantDisable;
public Transform m_ReferenceObject;
public float m_DistanceToObject = 20f;
[Tooltip("Check this if you want the bone to be dynamic even on low performance HW")]
public bool neverOptimize;
private Vector3 m_LocalGravity = Vector3.zero;
private Vector3 m_ObjectMove = Vector3.zero;
private Vector3 m_ObjectPrevPosition = Vector3.zero;
private float m_BoneTotalLength;
private float m_ObjectScale = 1f;
private float m_Time;
private float m_Weight = 1f;
private bool m_DistantDisabled;
private List<Particle> m_Particles = new List<Particle>();
private void Start()
{
SetupParticles();
}
private void FixedUpdate()
{
if (m_UpdateMode == UpdateMode.AnimatePhysics)
{
PreUpdate();
}
}
private void Update()
{
if (m_UpdateMode != UpdateMode.AnimatePhysics)
{
PreUpdate();
}
}
private void LateUpdate()
{
if (m_DistantDisable)
{
CheckDistance();
}
if (m_Weight > 0f && (!m_DistantDisable || !m_DistantDisabled))
{
float deltaTime = Time.deltaTime;
UpdateDynamicBones(deltaTime);
}
}
private void PreUpdate()
{
if (m_Weight > 0f && (!m_DistantDisable || !m_DistantDisabled))
{
InitTransforms();
}
}
private void CheckDistance()
{
Transform referenceObject = m_ReferenceObject;
if (referenceObject == null && (bool)Camera.main)
{
referenceObject = Camera.main.transform;
}
if (!referenceObject)
{
return;
}
bool flag = (referenceObject.position - base.transform.position).sqrMagnitude > m_DistanceToObject * m_DistanceToObject;
if (flag != m_DistantDisabled)
{
if (!flag)
{
ResetParticlesPosition();
}
m_DistantDisabled = flag;
}
}
private void OnEnable()
{
ResetParticlesPosition();
}
private void OnDisable()
{
InitTransforms();
}
private void OnValidate()
{
m_UpdateRate = Mathf.Max(m_UpdateRate, 0f);
m_Damping = Mathf.Clamp01(m_Damping);
m_Elasticity = Mathf.Clamp01(m_Elasticity);
m_Stiffness = Mathf.Clamp01(m_Stiffness);
m_Inert = Mathf.Clamp01(m_Inert);
m_Radius = Mathf.Max(m_Radius, 0f);
if (Application.isEditor && Application.isPlaying)
{
InitTransforms();
SetupParticles();
}
}
private void OnDrawGizmosSelected()
{
if (!base.enabled || m_Root == null)
{
return;
}
if (Application.isEditor && !Application.isPlaying && base.transform.hasChanged)
{
InitTransforms();
SetupParticles();
}
Gizmos.color = Color.white;
for (int i = 0; i < m_Particles.Count; i++)
{
Particle particle = m_Particles[i];
if (particle.m_ParentIndex >= 0)
{
Particle particle2 = m_Particles[particle.m_ParentIndex];
Gizmos.DrawLine(particle.m_Position, particle2.m_Position);
}
if (particle.m_Radius > 0f)
{
Gizmos.DrawWireSphere(particle.m_Position, particle.m_Radius * m_ObjectScale);
}
}
}
public void SetWeight(float w)
{
if (m_Weight != w)
{
if (w == 0f)
{
InitTransforms();
}
else if (m_Weight == 0f)
{
ResetParticlesPosition();
}
m_Weight = w;
}
}
public float GetWeight()
{
return m_Weight;
}
private void UpdateDynamicBones(float t)
{
if (m_Root == null)
{
return;
}
m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x);
m_ObjectMove = base.transform.position - m_ObjectPrevPosition;
m_ObjectPrevPosition = base.transform.position;
int num = 1;
if (m_UpdateRate > 0f)
{
float num2 = 1f / m_UpdateRate;
m_Time += t;
num = 0;
while (m_Time >= num2)
{
m_Time -= num2;
if (++num >= 3)
{
m_Time = 0f;
break;
}
}
}
if (num > 0)
{
for (int i = 0; i < num; i++)
{
UpdateParticles1();
UpdateParticles2();
m_ObjectMove = Vector3.zero;
}
}
else
{
SkipUpdateParticles();
}
ApplyParticlesToTransforms();
}
private void SetupParticles()
{
m_Particles.Clear();
if (m_Root == null)
{
return;
}
m_LocalGravity = m_Root.InverseTransformDirection(m_Gravity);
m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x);
m_ObjectPrevPosition = base.transform.position;
m_ObjectMove = Vector3.zero;
m_BoneTotalLength = 0f;
AppendParticles(m_Root, -1, 0f);
for (int i = 0; i < m_Particles.Count; i++)
{
Particle particle = m_Particles[i];
particle.m_Damping = m_Damping;
particle.m_Elasticity = m_Elasticity;
particle.m_Stiffness = m_Stiffness;
particle.m_Inert = m_Inert;
particle.m_Radius = m_Radius;
if (m_BoneTotalLength > 0f)
{
float time = particle.m_BoneLength / m_BoneTotalLength;
if (m_DampingDistrib != null && m_DampingDistrib.keys.Length != 0)
{
particle.m_Damping *= m_DampingDistrib.Evaluate(time);
}
if (m_ElasticityDistrib != null && m_ElasticityDistrib.keys.Length != 0)
{
particle.m_Elasticity *= m_ElasticityDistrib.Evaluate(time);
}
if (m_StiffnessDistrib != null && m_StiffnessDistrib.keys.Length != 0)
{
particle.m_Stiffness *= m_StiffnessDistrib.Evaluate(time);
}
if (m_InertDistrib != null && m_InertDistrib.keys.Length != 0)
{
particle.m_Inert *= m_InertDistrib.Evaluate(time);
}
if (m_RadiusDistrib != null && m_RadiusDistrib.keys.Length != 0)
{
particle.m_Radius *= m_RadiusDistrib.Evaluate(time);
}
}
particle.m_Damping = Mathf.Clamp01(particle.m_Damping);
particle.m_Elasticity = Mathf.Clamp01(particle.m_Elasticity);
particle.m_Stiffness = Mathf.Clamp01(particle.m_Stiffness);
particle.m_Inert = Mathf.Clamp01(particle.m_Inert);
particle.m_Radius = Mathf.Max(particle.m_Radius, 0f);
}
}
private void AppendParticles(Transform b, int parentIndex, float boneLength)
{
Particle particle = new Particle();
particle.m_Transform = b;
particle.m_ParentIndex = parentIndex;
if ((bool)b)
{
particle.m_Position = (particle.m_PrevPosition = b.position);
particle.m_InitLocalPosition = b.localPosition;
particle.m_InitLocalRotation = b.localRotation;
}
else
{
Transform transform = m_Particles[parentIndex].m_Transform;
if (m_EndLength > 0f)
{
Transform parent = transform.parent;
if ((bool)parent)
{
particle.m_EndOffset = transform.InverseTransformPoint(transform.position * 2f - parent.position) * m_EndLength;
}
else
{
particle.m_EndOffset = new Vector3(m_EndLength, 0f, 0f);
}
}
else
{
particle.m_EndOffset = transform.InverseTransformPoint(base.transform.TransformDirection(m_EndOffset) + transform.position);
}
particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset));
}
if (parentIndex >= 0)
{
boneLength += (m_Particles[parentIndex].m_Transform.position - particle.m_Position).magnitude;
particle.m_BoneLength = boneLength;
m_BoneTotalLength = Mathf.Max(m_BoneTotalLength, boneLength);
}
int count = m_Particles.Count;
m_Particles.Add(particle);
if (!b)
{
return;
}
for (int i = 0; i < b.childCount; i++)
{
bool flag = false;
if (m_Exclusions != null)
{
for (int j = 0; j < m_Exclusions.Count; j++)
{
if (m_Exclusions[j] == b.GetChild(i))
{
flag = true;
break;
}
}
}
if (!flag)
{
AppendParticles(b.GetChild(i), count, boneLength);
}
}
if (b.childCount == 0 && (m_EndLength > 0f || m_EndOffset != Vector3.zero))
{
AppendParticles(null, count, boneLength);
}
}
private void InitTransforms()
{
for (int i = 0; i < m_Particles.Count; i++)
{
Particle particle = m_Particles[i];
if ((bool)particle.m_Transform)
{
particle.m_Transform.localPosition = particle.m_InitLocalPosition;
particle.m_Transform.localRotation = particle.m_InitLocalRotation;
}
}
}
private void ResetParticlesPosition()
{
for (int i = 0; i < m_Particles.Count; i++)
{
Particle particle = m_Particles[i];
if ((bool)particle.m_Transform)
{
particle.m_Position = (particle.m_PrevPosition = particle.m_Transform.position);
continue;
}
Transform transform = m_Particles[particle.m_ParentIndex].m_Transform;
particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset));
}
m_ObjectPrevPosition = base.transform.position;
}
private void UpdateParticles1()
{
Vector3 gravity = m_Gravity;
Vector3 normalized = m_Gravity.normalized;
Vector3 lhs = m_Root.TransformDirection(m_LocalGravity);
Vector3 vector = normalized * Mathf.Max(Vector3.Dot(lhs, normalized), 0f);
gravity -= vector;
gravity = (gravity + m_Force) * m_ObjectScale;
for (int i = 0; i < m_Particles.Count; i++)
{
Particle particle = m_Particles[i];
if (particle.m_ParentIndex >= 0)
{
Vector3 vector2 = particle.m_Position - particle.m_PrevPosition;
Vector3 vector3 = m_ObjectMove * particle.m_Inert;
particle.m_PrevPosition = particle.m_Position + vector3;
particle.m_Position += vector2 * (1f - particle.m_Damping) + gravity + vector3;
}
else
{
particle.m_PrevPosition = particle.m_Position;
particle.m_Position = particle.m_Transform.position;
}
}
}
private void UpdateParticles2()
{
Plane plane = default(Plane);
for (int i = 1; i < m_Particles.Count; i++)
{
Particle particle = m_Particles[i];
Particle particle2 = m_Particles[particle.m_ParentIndex];
if (!particle2.m_Transform)
{
continue;
}
float num = ((!particle.m_Transform) ? particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude : (particle2.m_Transform.position - particle.m_Transform.position).magnitude);
float num2 = Mathf.Lerp(1f, particle.m_Stiffness, m_Weight);
if (num2 > 0f || particle.m_Elasticity > 0f)
{
Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix;
localToWorldMatrix.SetColumn(3, particle2.m_Position);
Vector3 vector = ((!particle.m_Transform) ? localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset) : localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition));
Vector3 vector2 = vector - particle.m_Position;
particle.m_Position += vector2 * particle.m_Elasticity;
if (num2 > 0f)
{
vector2 = vector - particle.m_Position;
float magnitude = vector2.magnitude;
float num3 = num * (1f - num2) * 2f;
if (magnitude > num3)
{
particle.m_Position += vector2 * ((magnitude - num3) / magnitude);
}
}
}
if (m_Colliders != null)
{
float particleRadius = particle.m_Radius * m_ObjectScale;
for (int j = 0; j < m_Colliders.Count; j++)
{
DynamicBoneCollider dynamicBoneCollider = m_Colliders[j];
if ((bool)dynamicBoneCollider && dynamicBoneCollider.enabled)
{
dynamicBoneCollider.Collide(ref particle.m_Position, particleRadius);
}
}
}
if (m_FreezeAxis != 0)
{
switch (m_FreezeAxis)
{
case FreezeAxis.X:
plane.SetNormalAndPosition(particle2.m_Transform.right, particle2.m_Position);
break;
case FreezeAxis.Y:
plane.SetNormalAndPosition(particle2.m_Transform.up, particle2.m_Position);
break;
case FreezeAxis.Z:
plane.SetNormalAndPosition(particle2.m_Transform.forward, particle2.m_Position);
break;
}
particle.m_Position -= plane.normal * plane.GetDistanceToPoint(particle.m_Position);
}
Vector3 vector3 = particle2.m_Position - particle.m_Position;
float magnitude2 = vector3.magnitude;
if (magnitude2 > 0f)
{
particle.m_Position += vector3 * ((magnitude2 - num) / magnitude2);
}
}
}
private void SkipUpdateParticles()
{
for (int i = 0; i < m_Particles.Count; i++)
{
Particle particle = m_Particles[i];
if (particle.m_ParentIndex >= 0)
{
particle.m_PrevPosition += m_ObjectMove;
particle.m_Position += m_ObjectMove;
Particle particle2 = m_Particles[particle.m_ParentIndex];
if (!particle2.m_Transform)
{
continue;
}
float num = ((!particle.m_Transform) ? particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude : (particle2.m_Transform.position - particle.m_Transform.position).magnitude);
float num2 = Mathf.Lerp(1f, particle.m_Stiffness, m_Weight);
if (num2 > 0f)
{
Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix;
localToWorldMatrix.SetColumn(3, particle2.m_Position);
Vector3 vector = ((!particle.m_Transform) ? localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset) : localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition));
Vector3 vector2 = vector - particle.m_Position;
float magnitude = vector2.magnitude;
float num3 = num * (1f - num2) * 2f;
if (magnitude > num3)
{
particle.m_Position += vector2 * ((magnitude - num3) / magnitude);
}
}
Vector3 vector3 = particle2.m_Position - particle.m_Position;
float magnitude2 = vector3.magnitude;
if (magnitude2 > 0f)
{
particle.m_Position += vector3 * ((magnitude2 - num) / magnitude2);
}
}
else if ((bool)particle.m_Transform)
{
particle.m_PrevPosition = particle.m_Position;
particle.m_Position = particle.m_Transform.position;
}
}
}
private static Vector3 MirrorVector(Vector3 v, Vector3 axis)
{
return v - axis * (Vector3.Dot(v, axis) * 2f);
}
private void ApplyParticlesToTransforms()
{
for (int i = 1; i < m_Particles.Count; i++)
{
Particle particle = m_Particles[i];
Particle particle2 = m_Particles[particle.m_ParentIndex];
if (particle2.m_Transform.childCount <= 1)
{
Vector3 direction = ((!particle.m_Transform) ? particle.m_EndOffset : particle.m_Transform.localPosition);
Vector3 toDirection = particle.m_Position - particle2.m_Position;
Quaternion quaternion = Quaternion.FromToRotation(particle2.m_Transform.TransformDirection(direction), toDirection);
particle2.m_Transform.rotation = quaternion * particle2.m_Transform.rotation;
}
if ((bool)particle.m_Transform)
{
particle.m_Transform.position = particle.m_Position;
}
}
}
}