/// <summary> /// Allows the motor to process bones temporarily and removes them once done /// </summary> /// <param name="rBone"></param> protected virtual bool AddTemporaryBone(BoneControllerBone rBone) { if (rBone == null || rBone._Transform == null) { return(false); } if (rBone.Length < _MinBoneLength) { return(false); } if (rBone == mSkeleton.Root) { return(false); } if (mActiveBoneInfo.ContainsKey(rBone)) { return(true); } ImpactMotorBone lBoneInfo = ImpactMotorBone.Allocate(); lBoneInfo.IsTemporary = true; lBoneInfo.EndPosition = rBone._Transform.position + (rBone._Transform.rotation * (rBone.BoneForward * rBone.Length)); mActiveBoneInfo.Add(rBone, lBoneInfo); return(true); }
/// <summary> /// Renders out bone details specific to the motor /// </summary> /// <param name="rIndex"></param> /// <param name="rBone"></param> /// <returns></returns> protected override bool RenderBone(int rIndex, BoneControllerBone rBone) { bool lIsDirty = false; #if UNITY_EDITOR while (rIndex >= _BoneInfo.Count) { ImpactMotorBone lBoneInfo = new ImpactMotorBone(); if (rBone != null && rBone._Transform != null) { lBoneInfo.EndPosition = rBone._Transform.position + (rBone._Transform.rotation * (rBone.BoneForward * rBone.Length)); } _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo); } // Set the bone weight float lOldBoneWeight = (rBone == null ? 0 : _BoneInfo[rIndex].Weight); float lNewBoneWeight = EditorGUILayout.FloatField(new GUIContent("Rotation Weight", "Normalized weight this bone will be responsible for."), lOldBoneWeight); if (lNewBoneWeight != lOldBoneWeight) { if (rBone != null) { lIsDirty = true; _BoneInfo[rIndex].Weight = lNewBoneWeight; } } #endif return(lIsDirty); }
/// <summary> /// Pulls an object from the pool. /// </summary> /// <returns></returns> public static ImpactMotorBone Allocate() { // Grab the next available object ImpactMotorBone lInstance = sPool.Allocate(); // Initialize lInstance.State = 0; lInstance.Time = 0f; lInstance.Change = Vector3.zero; lInstance.EndPosition = Vector3.zero; lInstance.Weight = 1f; return(lInstance); }
/// <summary> /// Allows the motor to process any specific bone logic after /// a bone has been added /// </summary> /// <param name="rIndex">Index position of the new bone</param> /// <param name="rBone">New bone that was added</param> public override void AddBone(BoneControllerBone rBone, bool rIncludeChildren) { base.AddBone(rBone, rIncludeChildren); ImpactMotorBone lBoneInfo = new ImpactMotorBone(); lBoneInfo.IsTemporary = false; if (rBone != null && rBone._Transform != null) { lBoneInfo.EndPosition = rBone._Transform.position + (rBone._Transform.rotation * (rBone.BoneForward * rBone.Length)); } _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo); }
/// <summary> /// Returns an element back to the pool. /// </summary> /// <param name="rEdge"></param> public static void Release(ImpactMotorBone rInstance) { sPool.Release(rInstance); }
/// <summary> /// Process the motor each frame so that it can update the bone rotations. /// This is the function that should be overridden in each motor /// </summary> /// <param name="rDeltaTime">Delta time to use for the update</param> /// <param name="rUpdate">Determines if it is officially time to do the update</param> protected override void Update(float rDeltaTime, bool rUpdate) { mInactiveBoneInfo.Clear(); // Process the results of the solve. We use the enumerator to // avoid garbage from the ForEach Dictionary <BoneControllerBone, ImpactMotorBone> .Enumerator lEnumerator = mActiveBoneInfo.GetEnumerator(); while (lEnumerator.MoveNext()) { BoneControllerBone lBone = lEnumerator.Current.Key; Vector3 lChange = Vector3.zero; ImpactMotorBone lBoneInfo = mActiveBoneInfo[lBone]; // If we're not in a state, move on if (lBoneInfo.State == 0) { continue; } // If we're recovering from the impact, decrease the lerp over time else if (lBoneInfo.State == 1) { lBoneInfo.Time -= rDeltaTime; float lTime = 1f - Mathf.Clamp01(lBoneInfo.Time / _ImpactTime); lChange = lBoneInfo.Change * lTime; if (lBoneInfo.Time <= 0f) { lBoneInfo.State = 2; lBoneInfo.Time = _RecoveryTime; } } else if (lBoneInfo.State == 2) { lBoneInfo.Time -= rDeltaTime; float lTime = Mathf.Clamp01(lBoneInfo.Time / _RecoveryTime); lChange = lBoneInfo.Change * lTime; if (lBoneInfo.Time <= 0f) { lBoneInfo.State = 3; mInactiveBoneInfo.Add(lBone); } } // Set the new position based on the state lBone.SetWorldEndPosition(lBone.WorldEndPosition + lChange, 1f); } //// Report the rotation to reach the new pose //foreach (BoneControllerBone lBone in mActiveBoneInfo.Keys) //{ // Vector3 lChange = Vector3.zero; // ImpactMotorBone lBoneInfo = mActiveBoneInfo[lBone]; // // If we're not in a state, move on // if (lBoneInfo.State == 0) // { // continue; // } // // If we're recovering from the impact, decrease the lerp over time // else if (lBoneInfo.State == 1) // { // lBoneInfo.Time -= rDeltaTime; // float lTime = 1f - Mathf.Clamp01(lBoneInfo.Time / _ImpactTime); // lChange = lBoneInfo.Change * lTime; // if (lBoneInfo.Time <= 0f) // { // lBoneInfo.State = 2; // lBoneInfo.Time = _RecoveryTime; // } // } // else if (lBoneInfo.State == 2) // { // lBoneInfo.Time -= rDeltaTime; // float lTime = Mathf.Clamp01(lBoneInfo.Time / _RecoveryTime); // lChange = lBoneInfo.Change * lTime; // if (lBoneInfo.Time <= 0f) // { // lBoneInfo.State = 3; // mInactiveBoneInfo.Add(lBone); // } // } // // Set the new position based on the state // lBone.SetWorldEndPosition(lBone.WorldEndPosition + lChange, 1f); //} // Clean up ones we need to for (int i = mInactiveBoneInfo.Count - 1; i >= 0; i--) { BoneControllerBone lBone = mInactiveBoneInfo[i]; if (mActiveBoneInfo.ContainsKey(lBone)) { ImpactMotorBone.Release(mActiveBoneInfo[lBone]); mActiveBoneInfo.Remove(lBone); } } }