You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
5.0 KiB
128 lines
5.0 KiB
using UnityEngine; |
|
using UnityEngine.Playables; |
|
|
|
namespace Timeline.Samples |
|
{ |
|
// The runtime instance of a Tween track. It is responsible for blending and setting |
|
// the final data on the transform binding. |
|
public class TweenMixerBehaviour : PlayableBehaviour |
|
{ |
|
static AnimationCurve s_DefaultCurve = AnimationCurve.Linear(0.0f, 0.0f, 1.0f, 1.0f); |
|
|
|
bool m_ShouldInitializeTransform = true; |
|
Vector3 m_InitialPosition; |
|
Quaternion m_InitialRotation; |
|
|
|
// Performs blend of position and rotation of all clips connected to a track mixer |
|
// The result is applied to the track binding's (playerData) transform. |
|
public override void ProcessFrame(Playable playable, FrameData info, object playerData) |
|
{ |
|
Transform trackBinding = playerData as Transform; |
|
|
|
if (trackBinding == null) |
|
return; |
|
|
|
// Get the initial position and rotation of the track binding, only when ProcessFrame is first called |
|
InitializeIfNecessary(trackBinding); |
|
|
|
Vector3 accumPosition = Vector3.zero; |
|
Quaternion accumRotation = QuaternionUtils.zero; |
|
|
|
float totalPositionWeight = 0.0f; |
|
float totalRotationWeight = 0.0f; |
|
|
|
// Iterate on all mixer's inputs (ie each clip on the track) |
|
int inputCount = playable.GetInputCount(); |
|
for (int i = 0; i < inputCount; i++) |
|
{ |
|
float inputWeight = playable.GetInputWeight(i); |
|
if (inputWeight <= 0) |
|
continue; |
|
|
|
Playable input = playable.GetInput(i); |
|
float normalizedInputTime = (float)(input.GetTime() / input.GetDuration()); |
|
|
|
// get the clip's behaviour and evaluate the progression along the curve |
|
TweenBehaviour tweenInput = GetTweenBehaviour(input); |
|
float tweenProgress = GetCurve(tweenInput).Evaluate(normalizedInputTime); |
|
|
|
// calculate the position's progression along the curve according to the input's (clip) weight |
|
if (tweenInput.shouldTweenPosition) |
|
{ |
|
totalPositionWeight += inputWeight; |
|
accumPosition += TweenPosition(tweenInput, tweenProgress, inputWeight); |
|
} |
|
|
|
// calculate the rotation's progression along the curve according to the input's (clip) weight |
|
if (tweenInput.shouldTweenRotation) |
|
{ |
|
totalRotationWeight += inputWeight; |
|
accumRotation = TweenRotation(tweenInput, accumRotation, tweenProgress, inputWeight); |
|
} |
|
} |
|
|
|
// Apply the final position and rotation values in the track binding |
|
trackBinding.position = accumPosition + m_InitialPosition * (1.0f - totalPositionWeight); |
|
trackBinding.rotation = accumRotation.Blend(m_InitialRotation, 1.0f - totalRotationWeight); |
|
trackBinding.rotation.Normalize(); |
|
} |
|
|
|
void InitializeIfNecessary(Transform transform) |
|
{ |
|
if (m_ShouldInitializeTransform) |
|
{ |
|
m_InitialPosition = transform.position; |
|
m_InitialRotation = transform.rotation; |
|
m_ShouldInitializeTransform = false; |
|
} |
|
} |
|
|
|
Vector3 TweenPosition(TweenBehaviour tweenInput, float progress, float weight) |
|
{ |
|
Vector3 startPosition = m_InitialPosition; |
|
if (tweenInput.startLocation != null) |
|
{ |
|
startPosition = tweenInput.startLocation.position; |
|
} |
|
|
|
Vector3 endPosition = m_InitialPosition; |
|
if (tweenInput.endLocation != null) |
|
{ |
|
endPosition = tweenInput.endLocation.position; |
|
} |
|
|
|
return Vector3.Lerp(startPosition, endPosition, progress) * weight; |
|
} |
|
|
|
Quaternion TweenRotation(TweenBehaviour tweenInput, Quaternion accumRotation, float progress, float weight) |
|
{ |
|
Quaternion startRotation = m_InitialRotation; |
|
if (tweenInput.startLocation != null) |
|
{ |
|
startRotation = tweenInput.startLocation.rotation; |
|
} |
|
|
|
Quaternion endRotation = m_InitialRotation; |
|
if (tweenInput.endLocation != null) |
|
{ |
|
endRotation = tweenInput.endLocation.rotation; |
|
} |
|
|
|
Quaternion desiredRotation = Quaternion.Lerp(startRotation, endRotation, progress); |
|
return accumRotation.Blend(desiredRotation.NormalizeSafe(), weight); |
|
} |
|
|
|
static TweenBehaviour GetTweenBehaviour(Playable playable) |
|
{ |
|
ScriptPlayable<TweenBehaviour> tweenInput = (ScriptPlayable<TweenBehaviour>)playable; |
|
return tweenInput.GetBehaviour(); |
|
} |
|
|
|
static AnimationCurve GetCurve(TweenBehaviour tween) |
|
{ |
|
if (tween == null || tween.curve == null) |
|
return s_DefaultCurve; |
|
return tween.curve; |
|
} |
|
} |
|
}
|
|
|