TransformTweenMixerBehaviour.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Playables;
  4. public class TransformTweenMixerBehaviour : PlayableBehaviour
  5. {
  6. bool m_FirstFrameHappened;
  7. public override void ProcessFrame(Playable playable, FrameData info, object playerData)
  8. {
  9. Transform trackBinding = playerData as Transform;
  10. if(trackBinding == null)
  11. return;
  12. Vector3 defaultPosition = trackBinding.position;
  13. Quaternion defaultRotation = trackBinding.rotation;
  14. int inputCount = playable.GetInputCount ();
  15. float positionTotalWeight = 0f;
  16. float rotationTotalWeight = 0f;
  17. Vector3 blendedPosition = Vector3.zero;
  18. Quaternion blendedRotation = new Quaternion(0f, 0f, 0f, 0f);
  19. for (int i = 0; i < inputCount; i++)
  20. {
  21. ScriptPlayable<TransformTweenBehaviour> playableInput = (ScriptPlayable<TransformTweenBehaviour>)playable.GetInput (i);
  22. TransformTweenBehaviour input = playableInput.GetBehaviour ();
  23. if(input.endLocation == null)
  24. continue;
  25. float inputWeight = playable.GetInputWeight(i);
  26. if (!m_FirstFrameHappened && !input.startLocation)
  27. {
  28. input.startingPosition = defaultPosition;
  29. input.startingRotation = defaultRotation;
  30. }
  31. float normalisedTime = (float)(playableInput.GetTime() / playableInput.GetDuration ());
  32. float tweenProgress = input.EvaluateCurrentCurve(normalisedTime);
  33. if (input.tweenPosition)
  34. {
  35. positionTotalWeight += inputWeight;
  36. blendedPosition += Vector3.Lerp(input.startingPosition, input.endLocation.position, tweenProgress) * inputWeight;
  37. }
  38. if (input.tweenRotation)
  39. {
  40. rotationTotalWeight += inputWeight;
  41. Quaternion desiredRotation = Quaternion.Lerp(input.startingRotation, input.endLocation.rotation, tweenProgress);
  42. desiredRotation = NormalizeQuaternion(desiredRotation);
  43. if (Quaternion.Dot (blendedRotation, desiredRotation) < 0f)
  44. {
  45. desiredRotation = ScaleQuaternion (desiredRotation, -1f);
  46. }
  47. desiredRotation = ScaleQuaternion(desiredRotation, inputWeight);
  48. blendedRotation = AddQuaternions (blendedRotation, desiredRotation);
  49. }
  50. }
  51. blendedPosition += defaultPosition * (1f - positionTotalWeight);
  52. Quaternion weightedDefaultRotation = ScaleQuaternion (defaultRotation, 1f - rotationTotalWeight);
  53. blendedRotation = AddQuaternions (blendedRotation, weightedDefaultRotation);
  54. trackBinding.position = blendedPosition;
  55. trackBinding.rotation = blendedRotation;
  56. m_FirstFrameHappened = true;
  57. }
  58. public override void OnPlayableDestroy (Playable playable)
  59. {
  60. m_FirstFrameHappened = false;
  61. }
  62. static Quaternion AddQuaternions (Quaternion first, Quaternion second)
  63. {
  64. first.w += second.w;
  65. first.x += second.x;
  66. first.y += second.y;
  67. first.z += second.z;
  68. return first;
  69. }
  70. static Quaternion ScaleQuaternion (Quaternion rotation, float multiplier)
  71. {
  72. rotation.w *= multiplier;
  73. rotation.x *= multiplier;
  74. rotation.y *= multiplier;
  75. rotation.z *= multiplier;
  76. return rotation;
  77. }
  78. static float QuaternionMagnitude (Quaternion rotation)
  79. {
  80. return Mathf.Sqrt ((Quaternion.Dot (rotation, rotation)));
  81. }
  82. static Quaternion NormalizeQuaternion (Quaternion rotation)
  83. {
  84. float magnitude = QuaternionMagnitude (rotation);
  85. if (magnitude > 0f)
  86. return ScaleQuaternion (rotation, 1f / magnitude);
  87. Debug.LogWarning ("Cannot normalize a quaternion with zero magnitude.");
  88. return Quaternion.identity;
  89. }
  90. }