119 lines
4.0 KiB
C#
119 lines
4.0 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Playables;
|
|
|
|
public class TransformTweenMixerBehaviour : PlayableBehaviour
|
|
{
|
|
bool m_FirstFrameHappened;
|
|
|
|
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
|
|
{
|
|
Transform trackBinding = playerData as Transform;
|
|
|
|
if(trackBinding == null)
|
|
return;
|
|
|
|
Vector3 defaultPosition = trackBinding.position;
|
|
Quaternion defaultRotation = trackBinding.rotation;
|
|
|
|
int inputCount = playable.GetInputCount ();
|
|
|
|
float positionTotalWeight = 0f;
|
|
float rotationTotalWeight = 0f;
|
|
|
|
Vector3 blendedPosition = Vector3.zero;
|
|
Quaternion blendedRotation = new Quaternion(0f, 0f, 0f, 0f);
|
|
|
|
for (int i = 0; i < inputCount; i++)
|
|
{
|
|
ScriptPlayable<TransformTweenBehaviour> playableInput = (ScriptPlayable<TransformTweenBehaviour>)playable.GetInput (i);
|
|
TransformTweenBehaviour input = playableInput.GetBehaviour ();
|
|
|
|
if(input.endLocation == null)
|
|
continue;
|
|
|
|
float inputWeight = playable.GetInputWeight(i);
|
|
|
|
if (!m_FirstFrameHappened && !input.startLocation)
|
|
{
|
|
input.startingPosition = defaultPosition;
|
|
input.startingRotation = defaultRotation;
|
|
}
|
|
|
|
float normalisedTime = (float)(playableInput.GetTime() / playableInput.GetDuration ());
|
|
float tweenProgress = input.EvaluateCurrentCurve(normalisedTime);
|
|
|
|
if (input.tweenPosition)
|
|
{
|
|
positionTotalWeight += inputWeight;
|
|
|
|
blendedPosition += Vector3.Lerp(input.startingPosition, input.endLocation.position, tweenProgress) * inputWeight;
|
|
}
|
|
|
|
if (input.tweenRotation)
|
|
{
|
|
rotationTotalWeight += inputWeight;
|
|
|
|
Quaternion desiredRotation = Quaternion.Lerp(input.startingRotation, input.endLocation.rotation, tweenProgress);
|
|
desiredRotation = NormalizeQuaternion(desiredRotation);
|
|
|
|
if (Quaternion.Dot (blendedRotation, desiredRotation) < 0f)
|
|
{
|
|
desiredRotation = ScaleQuaternion (desiredRotation, -1f);
|
|
}
|
|
|
|
desiredRotation = ScaleQuaternion(desiredRotation, inputWeight);
|
|
|
|
blendedRotation = AddQuaternions (blendedRotation, desiredRotation);
|
|
}
|
|
}
|
|
|
|
blendedPosition += defaultPosition * (1f - positionTotalWeight);
|
|
Quaternion weightedDefaultRotation = ScaleQuaternion (defaultRotation, 1f - rotationTotalWeight);
|
|
blendedRotation = AddQuaternions (blendedRotation, weightedDefaultRotation);
|
|
|
|
trackBinding.position = blendedPosition;
|
|
trackBinding.rotation = blendedRotation;
|
|
|
|
m_FirstFrameHappened = true;
|
|
}
|
|
|
|
public override void OnPlayableDestroy (Playable playable)
|
|
{
|
|
m_FirstFrameHappened = false;
|
|
}
|
|
|
|
static Quaternion AddQuaternions (Quaternion first, Quaternion second)
|
|
{
|
|
first.w += second.w;
|
|
first.x += second.x;
|
|
first.y += second.y;
|
|
first.z += second.z;
|
|
return first;
|
|
}
|
|
|
|
static Quaternion ScaleQuaternion (Quaternion rotation, float multiplier)
|
|
{
|
|
rotation.w *= multiplier;
|
|
rotation.x *= multiplier;
|
|
rotation.y *= multiplier;
|
|
rotation.z *= multiplier;
|
|
return rotation;
|
|
}
|
|
|
|
static float QuaternionMagnitude (Quaternion rotation)
|
|
{
|
|
return Mathf.Sqrt ((Quaternion.Dot (rotation, rotation)));
|
|
}
|
|
|
|
static Quaternion NormalizeQuaternion (Quaternion rotation)
|
|
{
|
|
float magnitude = QuaternionMagnitude (rotation);
|
|
|
|
if (magnitude > 0f)
|
|
return ScaleQuaternion (rotation, 1f / magnitude);
|
|
|
|
Debug.LogWarning ("Cannot normalize a quaternion with zero magnitude.");
|
|
return Quaternion.identity;
|
|
}
|
|
} |