/// <summary> /// Pulls an object from the pool. /// </summary> /// <returns></returns> public new static MotionMessage Allocate() { // Grab the next available object MotionMessage lInstance = sPool.Allocate(); if (lInstance == null) { lInstance = new MotionMessage(); } // Reset the sent flags. We do this so messages are flagged as 'completed' // by default. lInstance.IsSent = false; lInstance.IsHandled = false; // For this type, guarentee we have something // to hand back tot he caller return(lInstance); }
/// <summary> /// Returns an element back to the pool. /// </summary> /// <param name="rEdge"></param> public static void Release(MotionMessage rInstance) { if (rInstance == null) { return; } // We should never release an instance unless we're // sure we're done with it. So clearing here is fine rInstance.Clear(); // Reset the sent flags. We do this so messages are flagged as 'completed' // and removed by default. rInstance.IsSent = true; rInstance.IsHandled = true; // Make it available to others. sPool.Release(rInstance); }
/// <summary> /// Raised by the controller when a message is received /// </summary> public override void OnMessageReceived(IMessage rMessage) { if (rMessage == null) { return; } MotionMessage lMotionMessage = rMessage as MotionMessage; if (lMotionMessage != null) { // Activate the interaction if (lMotionMessage.ID == MotionMessage.MSG_MOTION_ACTIVATE) { if (!mIsActive) { mActiveForm = (lMotionMessage.Form >= 0 ? lMotionMessage.Form : _Form); Activate(mMotionLayer.ActiveMotion); lMotionMessage.IsHandled = true; lMotionMessage.Recipient = this; } } // Continue with the casting if (lMotionMessage.ID == MotionMessage.MSG_MOTION_CONTINUE) { if (mIsActive) { mMotionController.SetAnimatorMotionPhase(mMotionLayer.AnimatorLayerIndex, PHASE_CONTINUE, 0, 0, true); lMotionMessage.IsHandled = true; lMotionMessage.Recipient = this; } } } }
/// <summary> /// Updates the motions tied to this layer at the variable /// time step (ie Update() not FixedUpdate(). /// </summary> /// <param name="rDeltaTime">Time since the last frame (or fixed update call)</param> /// <param name="rUpdateIndex">Index of the update to help manage dynamic/fixed updates. [0: Invalid update, >=1: Valid update]</param> public void UpdateMotions(float rDeltaTime, int rUpdateIndex) { int lPriorityIndex = -1; float lPriorityValue = float.MinValue; MotionControllerMotion lPrevActiveMotion = mActiveMotion; // Grab the current state info for the layer _AnimatorStateID = mMotionController.State.AnimatorStates[_AnimatorLayerIndex].StateInfo.fullPathHash; _AnimatorStateNormalizedTime = mMotionController.State.AnimatorStates[_AnimatorLayerIndex].StateInfo.normalizedTime; _AnimatorTransitionID = mMotionController.State.AnimatorStates[_AnimatorLayerIndex].TransitionInfo.fullPathHash; _AnimatorTransitionNormalizedTime = mMotionController.State.AnimatorStates[_AnimatorLayerIndex].TransitionInfo.normalizedTime; // Track how long the motion has been playing mActiveMotionDuration += Time.deltaTime; // Clean up the active motion's flag and ensure it's still valid if (mActiveMotion != null) { mActiveMotion.IsActivatedFrame = false; // If we have a current motion, test if it can continue if (!mActiveMotion.TestUpdate()) { mRunDeactivatedUpdate = true; mPrevActiveMotion = mActiveMotion; mActiveMotion.Deactivate(); mActiveMotion = null; } } // First, check if our current motion is interruptible. // If it's not, we know we are simply running it. if (rUpdateIndex == 1 && (mActiveMotion == null || mActiveMotion.IsInterruptible)) { bool lIsQueued = false; // Cycle through the motions to determine which ones were not // active and should be. We'll take the motion with the highest priority for (int i = 0; i < Motions.Count; i++) { MotionControllerMotion lMotion = Motions[i]; // Clean up the activation flag lMotion.IsActivatedFrame = false; // Don't test if the motion is not enabled if (!lMotion.IsEnabled) { continue; } // Don't reactivate this frame if (Time.time - lMotion.DeactivationTime < 0.001f) { continue; } // If we haven't gone past the reactivation delay, move one if (lMotion.ReactivationDelay > 0f && (lMotion.DeactivationTime + lMotion.ReactivationDelay) > Time.time) { continue; } // If we're to force the motion, don't check others if (lMotion.QueueActivation && (mActiveMotion == null || mActiveMotion.TestInterruption(Motions[i]))) { if (_AnimatorTransitionID == 0) { lIsQueued = true; lPriorityIndex = i; lPriorityValue = lMotion.Priority; lMotion.QueueActivation = false; } break; } // If we're dealing with the current motion, test if we continue else if (lMotion == mActiveMotion) { //if (mActiveMotion.TestUpdate()) //{ if (mActiveMotion.Priority >= lPriorityValue) { lPriorityIndex = i; lPriorityValue = mActiveMotion.Priority; } //} //else //{ // mActiveMotion.Deactivate(); //} } // For new motions, check for activation else if (lMotion.IsStartable) { bool lActivate = lMotion.TestActivate(); // Test if we should activate the motion if (lActivate && mMotionController.MotionActivatedEvent != null) { MotionMessage lMessage = MotionMessage.Allocate(); lMessage.ID = EnumMessageID.MSG_MOTION_TEST; lMessage.Motion = lMotion; lMessage.Continue = true; lMessage.Data = lPrevActiveMotion; mMotionController.MotionTestActivateEvent.Invoke(lMessage); lActivate = lMessage.Continue; MotionMessage.Release(lMessage); } // Test if we should activate the motion if (lActivate && mMotionController._ActorCore != null) { MotionMessage lMessage = MotionMessage.Allocate(); lMessage.ID = EnumMessageID.MSG_MOTION_TEST; lMessage.Motion = lMotion; lMessage.Continue = true; lMessage.Data = lPrevActiveMotion; mMotionController._ActorCore.SendMessage(lMessage); lActivate = lMessage.Continue; MotionMessage.Release(lMessage); } //#if USE_MESSAGE_DISPATCHER || OOTII_MD // // Send the message // if (lActivate) // { // MotionMessage lMessage = MotionMessage.Allocate(); // lMessage.ID = EnumMessageID.MSG_MOTION_TEST; // lMessage.Motion = lMotion; // lMessage.Continue = true; // lMessage.Data = lPrevActiveMotion; // MessageDispatcher.SendMessage(lMessage); // lActivate = lMessage.Continue; // MotionMessage.Release(lMessage); // } //#endif if (lActivate) { if (lMotion.Priority >= lPriorityValue) { lPriorityIndex = i; lPriorityValue = lMotion.Priority; } } } } // If we have a newly chosen motion, we need to activate it if (lPriorityIndex >= 0 && lPriorityIndex < Motions.Count) { // Ensure our new motion is valid. if (!lIsQueued && mActiveMotion != null) { // If the "new" motion is the current motion, move on if (mActiveMotion == Motions[lPriorityIndex]) { lPriorityIndex = -1; } // If the current motion has a higher priority (lower value), move on else if (mActiveMotion.Priority > lPriorityValue) { lPriorityIndex = -1; } // If we can't interrupt the current motion, move on else if (mActiveMotion.IsActive && !mActiveMotion.TestInterruption(Motions[lPriorityIndex])) { lPriorityIndex = -1; } } // Look to start the new motion (if we have one) if (lPriorityIndex >= 0) { if (mActiveMotion != null && mActiveMotion.IsActive && mActiveMotion != Motions[lPriorityIndex]) { mRunDeactivatedUpdate = true; mPrevActiveMotion = mActiveMotion; mActiveMotion.Deactivate(); } if (mActiveMotion != Motions[lPriorityIndex]) { Motions[lPriorityIndex].Activate(lPrevActiveMotion); } mActiveMotion = Motions[lPriorityIndex]; mActiveMotionDuration = 0f; } } } // Process any shutdown procedures for motions that are deactivated. if (mRunDeactivatedUpdate && mPrevActiveMotion != null) { mRunDeactivatedUpdate = mPrevActiveMotion.DeactivatedUpdate(rDeltaTime, rUpdateIndex); } // Process any motions that are active. They will die out on thier own for (int i = 0; i < Motions.Count; i++) { if (Motions[i].IsActive) { Motions[i].UpdateMotion(rDeltaTime, rUpdateIndex); // As a safetly, test and set the active motion if (mActiveMotion == null && Motions[i].IsActive) { mActiveMotion = Motions[i]; mActiveMotionDuration = 0f; } } } // Check if we've deactivated the current motion. If so, we // need to remove our reference to it if (mActiveMotion != null && !mActiveMotion.IsActive) { mActiveMotion = null; mActiveMotionDuration = 0f; } // Calculate the velocities of the active motions mAngularVelocity = Vector3.zero; mRotation = Quaternion.identity; mTilt = Quaternion.identity; mVelocity = Vector3.zero; mMovement = Vector3.zero; for (int i = 0; i < Motions.Count; i++) { if (Motions[i].IsActive) { mAngularVelocity += Motions[i].AngularVelocity; mRotation = mRotation * Motions[i].Rotation; mTilt = mTilt * Motions[i].Tilt; mVelocity += Motions[i].Velocity; mMovement += Motions[i].Movement; } } }