using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

[AddComponentMenu("Dynamic Bone/Dynamic Bone")]
public class DynamicBone : MonoBehaviour
{
	public bool SerializeWrite(BinaryWriter f_bw)
	{
		Func<DynamicBone.PartialMode, Dictionary<string, float>, bool> func = delegate(DynamicBone.PartialMode f_pmode, Dictionary<string, float> f_dicValueFromBone)
		{
			f_bw.Write((int)f_pmode);
			if (f_pmode != DynamicBone.PartialMode.Partial)
			{
				return false;
			}
			if (this.m_Particles != null)
			{
				f_bw.Write(this.m_Particles.Count);
				for (int j = 0; j < this.m_Particles.Count; j++)
				{
					string text = this.m_Particles[j].m_Transform.name.ToLower();
					f_bw.Write(text);
					f_bw.Write(f_dicValueFromBone[text]);
				}
				return true;
			}
			NDebug.MessageBox("エラー", "PartialMode.Partialの場合は実行中でないと各ボーン名が解らずボーン個別値指定が保存できません。");
			return false;
		};
		f_bw.Write("CM3D21_PHY");
		f_bw.Write(1170);
		if (this.m_Root == null)
		{
			NDebug.MessageBox("エラー", "×物理ルートボーンが設定されていません。");
			return false;
		}
		f_bw.Write(this.m_Root.name);
		func(this.m_EnablePartialDamping, this.m_dicPartialDamping);
		f_bw.Write(this.m_Damping);
		this.SerializeWriteAnimationCurve(f_bw, this.m_DampingDistrib);
		func(this.m_EnablePartialElasticity, this.m_dicPartialElasticity);
		f_bw.Write(this.m_Elasticity);
		this.SerializeWriteAnimationCurve(f_bw, this.m_ElasticityDistrib);
		func(this.m_EnablePartialStiffness, this.m_dicPartialStiffness);
		f_bw.Write(this.m_Stiffness);
		this.SerializeWriteAnimationCurve(f_bw, this.m_StiffnessDistrib);
		func(this.m_EnablePartialInert, this.m_dicPartialInert);
		f_bw.Write(this.m_Inert);
		this.SerializeWriteAnimationCurve(f_bw, this.m_InertDistrib);
		func(this.m_EnablePartialRadius, this.m_dicPartialRadius);
		f_bw.Write(this.m_Radius);
		this.SerializeWriteAnimationCurve(f_bw, this.m_RadiusDistrib);
		f_bw.Write(this.m_EndLength);
		f_bw.Write(this.m_EndOffset.x);
		f_bw.Write(this.m_EndOffset.y);
		f_bw.Write(this.m_EndOffset.z);
		f_bw.Write(this.m_Gravity.x);
		f_bw.Write(this.m_Gravity.y);
		f_bw.Write(this.m_Gravity.z);
		f_bw.Write(this.m_Force.x);
		f_bw.Write(this.m_Force.y);
		f_bw.Write(this.m_Force.z);
		f_bw.Write(Path.GetFileNameWithoutExtension(this.m_ColliderFileName).ToLower());
		f_bw.Write((this.m_Colliders == null) ? 0 : this.m_Colliders.Count);
		if (this.m_Colliders != null)
		{
		}
		f_bw.Write((this.m_Exclusions == null) ? 0 : this.m_Exclusions.Count);
		if (this.m_Exclusions != null)
		{
			for (int i = 0; i < this.m_Exclusions.Count; i++)
			{
			}
		}
		f_bw.Write((int)this.m_FreezeAxis);
		return true;
	}

	private void SerializeWriteAnimationCurve(BinaryWriter f_bw, AnimationCurve f_ac)
	{
		Keyframe[] keys = f_ac.keys;
		f_bw.Write(keys.Length);
		for (int i = 0; i < keys.Length; i++)
		{
			f_bw.Write(keys[i].time);
			f_bw.Write(keys[i].value);
			f_bw.Write(keys[i].inTangent);
			f_bw.Write(keys[i].outTangent);
		}
	}

	public bool SerializeWriteCollider(BinaryWriter f_bw, string f_strFileName)
	{
		f_bw.Write("CM3D21_COL");
		f_bw.Write(1170);
		if (this.m_Colliders == null || this.m_Colliders.Count == 0)
		{
			NDebug.MessageBox("エラー", "×物理Collidersは空です。");
			return false;
		}
		f_bw.Write(this.m_Colliders.Count);
		for (int i = 0; i < this.m_Colliders.Count; i++)
		{
			if (this.m_Colliders[i] == null)
			{
				f_bw.Write("missing");
			}
			else
			{
				f_bw.Write(this.m_Colliders[i].TypeName);
				this.m_Colliders[i].Serialize(f_bw, 1170);
			}
		}
		this.m_ColliderFileName = f_strFileName;
		this.m_strNowReadColliderFileName = f_strFileName;
		return true;
	}

	public void SerializeRead(BinaryReader f_br)
	{
		string a;
		Func<Dictionary<string, float>, DynamicBone.PartialMode> func = delegate(Dictionary<string, float> f_dicValueFromBone)
		{
			DynamicBone.PartialMode partialMode = (DynamicBone.PartialMode)f_br.ReadInt32();
			if (partialMode != DynamicBone.PartialMode.Partial)
			{
				return partialMode;
			}
			int num4 = f_br.ReadInt32();
			if (this.m_Particles != null && this.m_Particles.Count != 0)
			{
				if (num4 != this.m_Particles.Count)
				{
					NDebug.Assert("ボーン数が一致していません。", false);
				}
				for (int k = 0; k < num4; k++)
				{
					string strName = f_br.ReadString();
					if (this.m_Particles.Find((DynamicBone.Particle a) => a.m_Transform.name.ToLower() == strName) == null)
					{
						NDebug.Assert("ボーンがありません。", false);
					}
					f_dicValueFromBone[strName] = f_br.ReadSingle();
				}
			}
			else
			{
				for (int l = 0; l < num4; l++)
				{
					string key = f_br.ReadString();
					f_dicValueFromBone[key] = f_br.ReadSingle();
				}
			}
			return partialMode;
		};
		if (this.m_Exclusions != null)
		{
			this.m_Exclusions.Clear();
		}
		this.m_dicPartialStiffness.Clear();
		a = f_br.ReadString();
		if (a != "CM3D21_PHY")
		{
			NDebug.Assert("物理定義ヘッダー不正", false);
		}
		int num = f_br.ReadInt32();
		string text = f_br.ReadString();
		this.m_EnablePartialDamping = func(this.m_dicPartialDamping);
		this.m_Damping = f_br.ReadSingle();
		this.SerializeReadAnimationCurve(f_br, out this.m_DampingDistrib);
		this.m_EnablePartialElasticity = func(this.m_dicPartialElasticity);
		this.m_Elasticity = f_br.ReadSingle();
		this.SerializeReadAnimationCurve(f_br, out this.m_ElasticityDistrib);
		this.m_EnablePartialStiffness = func(this.m_dicPartialStiffness);
		this.m_Stiffness = f_br.ReadSingle();
		this.SerializeReadAnimationCurve(f_br, out this.m_StiffnessDistrib);
		this.m_EnablePartialInert = func(this.m_dicPartialInert);
		this.m_Inert = f_br.ReadSingle();
		this.SerializeReadAnimationCurve(f_br, out this.m_InertDistrib);
		this.m_EnablePartialRadius = func(this.m_dicPartialRadius);
		this.m_Radius = f_br.ReadSingle();
		this.SerializeReadAnimationCurve(f_br, out this.m_RadiusDistrib);
		this.m_EndLength = f_br.ReadSingle();
		this.m_EndOffset.Set(f_br.ReadSingle(), f_br.ReadSingle(), f_br.ReadSingle());
		this.m_Gravity.Set(f_br.ReadSingle(), f_br.ReadSingle(), f_br.ReadSingle());
		this.m_Force.Set(f_br.ReadSingle(), f_br.ReadSingle(), f_br.ReadSingle());
		this.m_ColliderFileName = f_br.ReadString();
		int num2 = f_br.ReadInt32();
		for (int i = 0; i < num2; i++)
		{
			if (this.m_Colliders == null)
			{
				this.m_Colliders = new List<DynamicBoneColliderBase>();
			}
		}
		int num3 = f_br.ReadInt32();
		for (int j = 0; j < num3; j++)
		{
			if (this.m_Exclusions == null)
			{
				this.m_Exclusions = new List<Transform>();
			}
		}
		this.m_FreezeAxis = (DynamicBone.FreezeAxis)f_br.ReadInt32();
		this.InitTransforms();
		this.SetupParticles();
		this.m_bSkipStartSetupParticles = true;
	}

	private void SerializeReadAnimationCurve(BinaryReader f_br, out AnimationCurve f_ac)
	{
		int num = f_br.ReadInt32();
		f_ac = null;
		if (num != 0)
		{
			Keyframe[] array = new Keyframe[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = new Keyframe
				{
					time = f_br.ReadSingle(),
					value = f_br.ReadSingle(),
					inTangent = f_br.ReadSingle(),
					outTangent = f_br.ReadSingle()
				};
			}
			f_ac = new AnimationCurve(array);
		}
	}

	public void SerializeReadCollider(BinaryReader f_br, Transform f_trBodyBoneRoot, string f_strFileName, Maid f_maid)
	{
		if (this.m_Colliders == null)
		{
			this.m_Colliders = new List<DynamicBoneColliderBase>();
		}
		if (this.m_Colliders != null)
		{
			if (Application.isPlaying)
			{
				for (int i = 0; i < this.m_Colliders.Count; i++)
				{
					if (this.m_Colliders[i] != null)
					{
						UnityEngine.Object.DestroyImmediate(this.m_Colliders[i].gameObject);
					}
				}
			}
			this.m_Colliders.Clear();
		}
		string a = f_br.ReadString();
		if (a != "CM3D21_COL")
		{
			NDebug.Assert("物理Colliderヘッダー不正", false);
		}
		int f_nVersion = f_br.ReadInt32();
		int num = f_br.ReadInt32();
		for (int j = 0; j < num; j++)
		{
			GameObject gameObject = new GameObject();
			string text = f_br.ReadString();
			if (text == "dbc")
			{
				DynamicBoneCollider dynamicBoneCollider = gameObject.AddComponent<DynamicBoneCollider>();
				dynamicBoneCollider.Deserialize(f_br, f_nVersion, f_trBodyBoneRoot);
				this.m_Colliders.Add(dynamicBoneCollider);
			}
			else if (text == "dpc")
			{
				DynamicBonePlaneCollider dynamicBonePlaneCollider = gameObject.AddComponent<DynamicBonePlaneCollider>();
				dynamicBonePlaneCollider.Deserialize(f_br, f_nVersion, f_trBodyBoneRoot);
				this.m_Colliders.Add(dynamicBonePlaneCollider);
			}
			else if (text == "dbm")
			{
				DynamicBoneMuneCollider dynamicBoneMuneCollider = gameObject.AddComponent<DynamicBoneMuneCollider>();
				dynamicBoneMuneCollider.m_maid = f_maid;
				dynamicBoneMuneCollider.Deserialize(f_br, f_nVersion, f_trBodyBoneRoot);
				this.m_Colliders.Add(dynamicBoneMuneCollider);
			}
			else if (!(text == "missing"))
			{
				NDebug.Assert("不正なColliderです。" + text, false);
			}
		}
		this.m_ColliderFileName = f_strFileName;
		this.m_strNowReadColliderFileName = f_strFileName;
	}

	private void Start()
	{
		if (!this.m_bSkipStartSetupParticles)
		{
			this.SetupParticles();
		}
		this.m_fRealTimeBefore = Time.realtimeSinceStartup;
	}

	private void FixedUpdate()
	{
		if (this.m_UpdateMode == DynamicBone.UpdateMode.AnimatePhysics)
		{
			this.PreUpdate();
		}
	}

	private void Update()
	{
		if (this.m_UpdateMode != DynamicBone.UpdateMode.AnimatePhysics)
		{
			this.PreUpdate();
		}
	}

	private void LateUpdate()
	{
		if (this.m_DistantDisable)
		{
			this.CheckDistance();
		}
		if (this.m_Weight > 0f && (!this.m_DistantDisable || !this.m_DistantDisabled))
		{
			float t;
			if (this.m_UpdateMode == DynamicBone.UpdateMode.UnscaledTime)
			{
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				t = realtimeSinceStartup - this.m_fRealTimeBefore;
				this.m_fRealTimeBefore = realtimeSinceStartup;
			}
			else
			{
				t = Time.deltaTime;
			}
			this.UpdateDynamicBones(t);
		}
	}

	private void PreUpdate()
	{
		if (this.m_Weight > 0f && (!this.m_DistantDisable || !this.m_DistantDisabled))
		{
			this.InitTransforms();
		}
	}

	private void CheckDistance()
	{
		Transform transform = this.m_ReferenceObject;
		if (transform == null && Camera.main != null)
		{
			transform = Camera.main.transform;
		}
		if (transform != null)
		{
			float sqrMagnitude = (transform.position - base.transform.position).sqrMagnitude;
			bool flag = sqrMagnitude > this.m_DistanceToObject * this.m_DistanceToObject;
			if (flag != this.m_DistantDisabled)
			{
				if (!flag)
				{
					this.ResetParticlesPosition();
				}
				this.m_DistantDisabled = flag;
			}
		}
	}

	private void OnEnable()
	{
		this.ResetParticlesPosition();
	}

	private void OnDisable()
	{
		this.InitTransforms();
	}

	private void OnValidate()
	{
		this.m_UpdateRate = Mathf.Max(this.m_UpdateRate, 0f);
		this.m_Damping = Mathf.Clamp01(this.m_Damping);
		this.m_Elasticity = Mathf.Clamp01(this.m_Elasticity);
		this.m_Stiffness = Mathf.Clamp01(this.m_Stiffness);
		this.m_Inert = Mathf.Clamp01(this.m_Inert);
		this.m_Radius = Mathf.Max(this.m_Radius, 0f);
		if (Application.isEditor && Application.isPlaying)
		{
			this.InitTransforms();
			this.SetupParticles();
		}
	}

	public void SetWeight(float w)
	{
		if (this.m_Weight != w)
		{
			if (w == 0f)
			{
				this.InitTransforms();
			}
			else if (this.m_Weight == 0f)
			{
				this.ResetParticlesPosition();
			}
			this.m_Weight = w;
		}
	}

	public float GetWeight()
	{
		return this.m_Weight;
	}

	private void UpdateDynamicBones(float t)
	{
		if (this.m_Root == null)
		{
			return;
		}
		this.m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x);
		this.m_ObjectMove = base.transform.position - this.m_ObjectPrevPosition;
		this.m_ObjectPrevPosition = base.transform.position;
		int num = 1;
		if (this.m_UpdateRate > 0f)
		{
			float num2 = 1f / this.m_UpdateRate;
			this.m_Time += t;
			num = 0;
			while (this.m_Time >= num2)
			{
				this.m_Time -= num2;
				if (++num >= 3)
				{
					this.m_Time = 0f;
					break;
				}
			}
		}
		if (num > 0)
		{
			for (int i = 0; i < num; i++)
			{
				this.UpdateParticles1();
				this.UpdateParticles2();
				this.m_ObjectMove = Vector3.zero;
			}
		}
		else
		{
			this.SkipUpdateParticles();
		}
		this.ApplyParticlesToTransforms();
	}

	private void SetupParticles()
	{
		this.m_Particles.Clear();
		if (this.m_Root == null)
		{
			return;
		}
		this.m_LocalGravity = this.m_Root.InverseTransformDirection(this.m_Gravity);
		this.m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x);
		this.m_ObjectPrevPosition = base.transform.position;
		this.m_ObjectMove = Vector3.zero;
		this.m_BoneTotalLength = 0f;
		this.AppendParticles(this.m_Root, -1, 0f);
		this.UpdateParameters();
	}

	private void AppendParticles(Transform b, int parentIndex, float boneLength)
	{
		DynamicBone.Particle particle = new DynamicBone.Particle();
		particle.m_Transform = b;
		particle.m_ParentIndex = parentIndex;
		if (b != null)
		{
			particle.m_Position = (particle.m_PrevPosition = b.position);
			particle.m_InitLocalPosition = b.localPosition;
			particle.m_InitLocalRotation = b.localRotation;
		}
		else
		{
			Transform transform = this.m_Particles[parentIndex].m_Transform;
			if (this.m_EndLength > 0f)
			{
				Transform parent = transform.parent;
				if (parent != null)
				{
					particle.m_EndOffset = transform.InverseTransformPoint(transform.position * 2f - parent.position) * this.m_EndLength;
				}
				else
				{
					particle.m_EndOffset = new Vector3(this.m_EndLength, 0f, 0f);
				}
			}
			else
			{
				particle.m_EndOffset = transform.InverseTransformPoint(base.transform.TransformDirection(this.m_EndOffset) + transform.position);
			}
			particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset));
		}
		if (parentIndex >= 0)
		{
			boneLength += (this.m_Particles[parentIndex].m_Transform.position - particle.m_Position).magnitude;
			particle.m_BoneLength = boneLength;
			this.m_BoneTotalLength = Mathf.Max(this.m_BoneTotalLength, boneLength);
		}
		int count = this.m_Particles.Count;
		this.m_Particles.Add(particle);
		if (b != null)
		{
			for (int i = 0; i < b.childCount; i++)
			{
				bool flag = false;
				if (this.m_Exclusions != null)
				{
					for (int j = 0; j < this.m_Exclusions.Count; j++)
					{
						Transform x = this.m_Exclusions[j];
						if (x == b.GetChild(i))
						{
							flag = true;
							break;
						}
					}
				}
				if (!flag)
				{
					this.AppendParticles(b.GetChild(i), count, boneLength);
				}
				else if (this.m_EndLength > 0f || this.m_EndOffset != Vector3.zero)
				{
					this.AppendParticles(null, count, boneLength);
				}
			}
			if (b.childCount == 0 && (this.m_EndLength > 0f || this.m_EndOffset != Vector3.zero))
			{
				this.AppendParticles(null, count, boneLength);
			}
		}
	}

	private void TryGetValueFromBone(DynamicBone.PartialMode f_mode, Dictionary<string, float> f_def, DynamicBone.SaveType f_type, string f_name, ref float f_value)
	{
		if (f_mode == DynamicBone.PartialMode.Partial)
		{
			if (!f_def.TryGetValue(f_name, out f_value))
			{
				float num = 0f;
				f_def[f_name] = num;
				f_value = num;
			}
		}
		else if (f_mode == DynamicBone.PartialMode.FromBoneName)
		{
			if (f_name.Contains("_h_"))
			{
				f_value = this.m_ValueFromBone[(int)f_type, 0];
			}
			else if (f_name.Contains("_h50_"))
			{
				f_value = this.m_ValueFromBone[(int)f_type, 1];
			}
			else
			{
				f_value = this.m_ValueFromBone[(int)f_type, 2];
			}
		}
	}

	public void UpdateParameters()
	{
		if (this.m_Root == null)
		{
			return;
		}
		this.m_LocalGravity = this.m_Root.InverseTransformDirection(this.m_Gravity);
		for (int i = 0; i < this.m_Particles.Count; i++)
		{
			DynamicBone.Particle particle = this.m_Particles[i];
			particle.m_Damping = this.m_Damping;
			particle.m_Elasticity = this.m_Elasticity;
			particle.m_Stiffness = this.m_Stiffness;
			particle.m_Inert = this.m_Inert;
			particle.m_Radius = this.m_Radius;
			if (this.m_BoneTotalLength > 0f)
			{
				float time = particle.m_BoneLength / this.m_BoneTotalLength;
				if (this.m_EnablePartialDamping == DynamicBone.PartialMode.StaticOrCurve && this.m_DampingDistrib != null && this.m_DampingDistrib.keys.Length > 0)
				{
					particle.m_Damping *= this.m_DampingDistrib.Evaluate(time);
				}
				if (this.m_EnablePartialElasticity == DynamicBone.PartialMode.StaticOrCurve && this.m_ElasticityDistrib != null && this.m_ElasticityDistrib.keys.Length > 0)
				{
					particle.m_Elasticity *= this.m_ElasticityDistrib.Evaluate(time);
				}
				if (this.m_EnablePartialStiffness == DynamicBone.PartialMode.StaticOrCurve && this.m_StiffnessDistrib != null && this.m_StiffnessDistrib.keys.Length > 0)
				{
					particle.m_Stiffness *= this.m_StiffnessDistrib.Evaluate(time);
				}
				if (this.m_EnablePartialInert == DynamicBone.PartialMode.StaticOrCurve && this.m_InertDistrib != null && this.m_InertDistrib.keys.Length > 0)
				{
					particle.m_Inert *= this.m_InertDistrib.Evaluate(time);
				}
				if (this.m_EnablePartialRadius == DynamicBone.PartialMode.StaticOrCurve && this.m_RadiusDistrib != null && this.m_RadiusDistrib.keys.Length > 0)
				{
					particle.m_Radius *= this.m_RadiusDistrib.Evaluate(time);
				}
			}
			string f_name = particle.m_Transform.name.ToLower();
			this.TryGetValueFromBone(this.m_EnablePartialDamping, this.m_dicPartialDamping, DynamicBone.SaveType.Damping, f_name, ref particle.m_Damping);
			this.TryGetValueFromBone(this.m_EnablePartialElasticity, this.m_dicPartialElasticity, DynamicBone.SaveType.Elasticity, f_name, ref particle.m_Elasticity);
			this.TryGetValueFromBone(this.m_EnablePartialStiffness, this.m_dicPartialStiffness, DynamicBone.SaveType.Stiffness, f_name, ref particle.m_Stiffness);
			this.TryGetValueFromBone(this.m_EnablePartialInert, this.m_dicPartialInert, DynamicBone.SaveType.Inert, f_name, ref particle.m_Inert);
			this.TryGetValueFromBone(this.m_EnablePartialRadius, this.m_dicPartialRadius, DynamicBone.SaveType.Radius, f_name, ref particle.m_Radius);
			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 InitTransforms()
	{
		for (int i = 0; i < this.m_Particles.Count; i++)
		{
			DynamicBone.Particle particle = this.m_Particles[i];
			if (particle.m_Transform != null)
			{
				particle.m_Transform.localPosition = particle.m_InitLocalPosition;
				particle.m_Transform.localRotation = particle.m_InitLocalRotation;
			}
		}
	}

	private void ResetParticlesPosition()
	{
		for (int i = 0; i < this.m_Particles.Count; i++)
		{
			DynamicBone.Particle particle = this.m_Particles[i];
			if (particle.m_Transform != null)
			{
				particle.m_Position = (particle.m_PrevPosition = particle.m_Transform.position);
			}
			else
			{
				Transform transform = this.m_Particles[particle.m_ParentIndex].m_Transform;
				particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset));
			}
		}
		this.m_ObjectPrevPosition = base.transform.position;
	}

	private void UpdateParticles1()
	{
		Vector3 vector = this.m_Gravity;
		Vector3 normalized = this.m_Gravity.normalized;
		Vector3 lhs = this.m_Root.TransformDirection(this.m_LocalGravity);
		Vector3 b = normalized * Mathf.Max(Vector3.Dot(lhs, normalized), 0f);
		vector -= b;
		vector = (vector + this.m_Force) * this.m_ObjectScale;
		for (int i = 0; i < this.m_Particles.Count; i++)
		{
			DynamicBone.Particle particle = this.m_Particles[i];
			if (particle.m_ParentIndex >= 0)
			{
				Vector3 a = particle.m_Position - particle.m_PrevPosition;
				Vector3 b2 = this.m_ObjectMove * particle.m_Inert;
				particle.m_PrevPosition = particle.m_Position + b2;
				particle.m_Position += a * (1f - particle.m_Damping) + vector + b2;
			}
			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 < this.m_Particles.Count; i++)
		{
			DynamicBone.Particle particle = this.m_Particles[i];
			DynamicBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex];
			float magnitude;
			if (particle.m_Transform != null)
			{
				magnitude = (particle2.m_Transform.position - particle.m_Transform.position).magnitude;
			}
			else
			{
				magnitude = particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude;
			}
			float num = Mathf.Lerp(1f, particle.m_Stiffness, this.m_Weight);
			if (num > 0f || particle.m_Elasticity > 0f)
			{
				Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix;
				localToWorldMatrix.SetColumn(3, particle2.m_Position);
				Vector3 a;
				if (particle.m_Transform != null)
				{
					a = localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition);
				}
				else
				{
					a = localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset);
				}
				Vector3 a2 = a - particle.m_Position;
				particle.m_Position += a2 * particle.m_Elasticity;
				if (num > 0f)
				{
					a2 = a - particle.m_Position;
					float magnitude2 = a2.magnitude;
					float num2 = magnitude * (1f - num) * 2f;
					if (magnitude2 > num2)
					{
						particle.m_Position += a2 * ((magnitude2 - num2) / magnitude2);
					}
				}
			}
			if (this.m_Colliders != null)
			{
				float particleRadius = particle.m_Radius * this.m_ObjectScale;
				for (int j = 0; j < this.m_Colliders.Count; j++)
				{
					DynamicBoneColliderBase dynamicBoneColliderBase = this.m_Colliders[j];
					if (dynamicBoneColliderBase != null && dynamicBoneColliderBase.enabled)
					{
						dynamicBoneColliderBase.Collide(ref particle.m_Position, particleRadius);
					}
				}
				if (this.m_hitFloorPlane != null)
				{
					this.m_hitFloorPlane.Collide(ref particle.m_Position, particleRadius);
				}
			}
			if (this.m_FreezeAxis != DynamicBone.FreezeAxis.None)
			{
				DynamicBone.FreezeAxis freezeAxis = this.m_FreezeAxis;
				if (freezeAxis != DynamicBone.FreezeAxis.X)
				{
					if (freezeAxis != DynamicBone.FreezeAxis.Y)
					{
						if (freezeAxis == DynamicBone.FreezeAxis.Z)
						{
							plane.SetNormalAndPosition(particle2.m_Transform.forward, particle2.m_Position);
						}
					}
					else
					{
						plane.SetNormalAndPosition(particle2.m_Transform.up, particle2.m_Position);
					}
				}
				else
				{
					plane.SetNormalAndPosition(particle2.m_Transform.right, particle2.m_Position);
				}
				particle.m_Position -= plane.normal * plane.GetDistanceToPoint(particle.m_Position);
			}
			Vector3 a3 = particle2.m_Position - particle.m_Position;
			float magnitude3 = a3.magnitude;
			if (magnitude3 > 0f)
			{
				particle.m_Position += a3 * ((magnitude3 - magnitude) / magnitude3);
			}
		}
	}

	private void SkipUpdateParticles()
	{
		for (int i = 0; i < this.m_Particles.Count; i++)
		{
			DynamicBone.Particle particle = this.m_Particles[i];
			if (particle.m_ParentIndex >= 0)
			{
				particle.m_PrevPosition += this.m_ObjectMove;
				particle.m_Position += this.m_ObjectMove;
				DynamicBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex];
				float magnitude;
				if (particle.m_Transform != null)
				{
					magnitude = (particle2.m_Transform.position - particle.m_Transform.position).magnitude;
				}
				else
				{
					magnitude = particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude;
				}
				float num = Mathf.Lerp(1f, particle.m_Stiffness, this.m_Weight);
				if (num > 0f)
				{
					Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix;
					localToWorldMatrix.SetColumn(3, particle2.m_Position);
					Vector3 a;
					if (particle.m_Transform != null)
					{
						a = localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition);
					}
					else
					{
						a = localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset);
					}
					Vector3 a2 = a - particle.m_Position;
					float magnitude2 = a2.magnitude;
					float num2 = magnitude * (1f - num) * 2f;
					if (magnitude2 > num2)
					{
						particle.m_Position += a2 * ((magnitude2 - num2) / magnitude2);
					}
				}
				Vector3 a3 = particle2.m_Position - particle.m_Position;
				float magnitude3 = a3.magnitude;
				if (magnitude3 > 0f)
				{
					particle.m_Position += a3 * ((magnitude3 - magnitude) / magnitude3);
				}
			}
			else
			{
				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 < this.m_Particles.Count; i++)
		{
			DynamicBone.Particle particle = this.m_Particles[i];
			DynamicBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex];
			if (particle2.m_Transform.childCount <= 1)
			{
				Vector3 direction;
				if (particle.m_Transform != null)
				{
					direction = particle.m_Transform.localPosition;
				}
				else
				{
					direction = particle.m_EndOffset;
				}
				Vector3 toDirection = particle.m_Position - particle2.m_Position;
				Quaternion lhs = Quaternion.FromToRotation(particle2.m_Transform.TransformDirection(direction), toDirection);
				particle2.m_Transform.rotation = lhs * particle2.m_Transform.rotation;
			}
			if (particle.m_Transform != null)
			{
				particle.m_Transform.position = particle.m_Position;
			}
		}
	}

	[ReadOnly]
	public string m_strNowReadPhysicsFileName;

	[Tooltip("The root of the transform hierarchy to apply physics.")]
	public Transform m_Root;

	[Tooltip("Internal physics simulation rate.")]
	public float m_UpdateRate;

	public DynamicBone.UpdateMode m_UpdateMode = DynamicBone.UpdateMode.UnscaledTime;

	[Header("■減衰率 設定タイプ")]
	[Tooltip("StaticOrCurve=下記の設定を使う。\nPartial=ボーン個別にToolで設定する。\nFromBoneName=旧仕様ボーン名から自動で設定する。")]
	public DynamicBone.PartialMode m_EnablePartialDamping;

	public Dictionary<string, float> m_dicPartialDamping = new Dictionary<string, float>();

	[Header("減衰率")]
	[Tooltip("How much the bones slowed down.")]
	[Range(0f, 1f)]
	public float m_Damping = 0.5f;

	public AnimationCurve m_DampingDistrib;

	[Header("■復元率 設定タイプ")]
	[Tooltip("StaticOrCurve=下記の設定を使う。\nPartial=ボーン個別にToolで設定する。\nFromBoneName=旧仕様ボーン名から自動で設定する。")]
	public DynamicBone.PartialMode m_EnablePartialElasticity;

	public Dictionary<string, float> m_dicPartialElasticity = new Dictionary<string, float>();

	[Header("復元率")]
	[Tooltip("How much the force applied to return each bone to original orientation.")]
	[Range(0f, 1f)]
	public float m_Elasticity = 0.1f;

	public AnimationCurve m_ElasticityDistrib;

	[Header("■元の向きの影響力 設定タイプ")]
	[Tooltip("StaticOrCurve=下記の設定を使う。\nPartial=ボーン個別にToolで設定する。\nFromBoneName=旧仕様ボーン名から自動で設定する。")]
	public DynamicBone.PartialMode m_EnablePartialStiffness;

	public Dictionary<string, float> m_dicPartialStiffness = new Dictionary<string, float>();

	[Header("元の向きの影響力(StaticOrCurve)")]
	[Tooltip("How much bone's original orientation are preserved.")]
	[Range(0f, 1f)]
	public float m_Stiffness = 0.1f;

	public AnimationCurve m_StiffnessDistrib;

	[Header("■移動距離による物理無視率 設定タイプ")]
	[Tooltip("StaticOrCurve=下記の設定を使う。\nPartial=ボーン個別にToolで設定する。\nFromBoneName=旧仕様ボーン名から自動で設定する。")]
	public DynamicBone.PartialMode m_EnablePartialInert;

	public Dictionary<string, float> m_dicPartialInert = new Dictionary<string, float>();

	[Header("移動距離による物理無視率")]
	[Tooltip("How much character's position change is ignored in physics simulation.")]
	[Range(0f, 1f)]
	public float m_Inert;

	public AnimationCurve m_InertDistrib;

	[Header("■各ノードの当たり判定半径 設定タイプ")]
	[Tooltip("StaticOrCurve=下記の設定を使う。\nPartial=ボーン個別にToolで設定する。\nFromBoneName=旧仕様ボーン名から自動で設定する。")]
	public DynamicBone.PartialMode m_EnablePartialRadius;

	[SerializeField]
	public Dictionary<string, float> m_dicPartialRadius = new Dictionary<string, float>();

	[Header("各ノードの当たり判定半径")]
	[Tooltip("Each bone can be a sphere to collide with colliders. Radius describe sphere's size.")]
	public float m_Radius;

	public AnimationCurve m_RadiusDistrib;

	[Header("先端に余分ボーンの追加")]
	[Tooltip("If End Length is not zero, an extra bone is generated at the end of transform hierarchy.")]
	public float m_EndLength;

	[Tooltip("If End Offset is not zero, an extra bone is generated at the end of transform hierarchy.")]
	[Header("先端に余分ボーンのオフセット座標")]
	public Vector3 m_EndOffset = Vector3.zero;

	[Tooltip("力は骨に適用されます。キャラクターの初期ポーズに適用される部分的な力は相殺されます。The force apply to bones. Partial force apply to character's initial pose is cancelled out.")]
	public Vector3 m_Gravity = new Vector3(0f, 0f, 0f);

	[Header("力を加える")]
	[Tooltip("The force apply to bones.")]
	public Vector3 m_Force = new Vector3(0f, -0.01f, 0f);

	[Header("衝突相手ファイル")]
	public string m_ColliderFileName;

	[ReadOnly]
	public string m_strNowReadColliderFileName;

	public bool m_ViewColliderGizmo;

	[Header("各ノードが衝突する相手(実機では[衝突相手ファイル]により適用される)")]
	[Tooltip("Collider objects interact with the bones.")]
	public List<DynamicBoneColliderBase> m_Colliders;

	[Header("物理計算から特別に除外するノード(子供も動かなくなる)")]
	[Tooltip("Bones exclude from physics simulation.")]
	public List<Transform> m_Exclusions;

	[Tooltip("Constrain bones to move on specified plane.")]
	public DynamicBone.FreezeAxis m_FreezeAxis;

	[Header("距離による物理自動無効化")]
	[Tooltip("キャラクターがカメラやプレーヤーから遠い場合、物理シミュレーションを自動的に無効にします。")]
	public bool m_DistantDisable;

	public Transform m_ReferenceObject;

	public float m_DistanceToObject = 20f;

	[HideInInspector]
	[NonSerialized]
	public DynamicBonePlaneCollider m_hitFloorPlane;

	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 float m_fRealTimeBefore;

	public float[,] m_ValueFromBone = new float[,]
	{
		{
			0.5f,
			0.5f,
			0.5f
		},
		{
			0.03f,
			0.03f,
			0.03f
		},
		{
			0.95f,
			0.8f,
			0.5f
		},
		{
			0f,
			0f,
			0f
		},
		{
			0.3f,
			0.3f,
			0.3f
		}
	};

	public List<DynamicBone.Particle> m_Particles = new List<DynamicBone.Particle>();

	private bool m_bSkipStartSetupParticles;

	public enum UpdateMode
	{
		Normal,
		AnimatePhysics,
		UnscaledTime
	}

	public enum PartialMode
	{
		StaticOrCurve,
		Partial,
		FromBoneName
	}

	public enum FreezeAxis
	{
		None,
		X,
		Y,
		Z
	}

	public enum SaveType
	{
		Damping,
		Elasticity,
		Stiffness,
		Inert,
		Radius,
		MAX
	}

	public 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;
	}
}
