CinemachineExtension.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. namespace Cinemachine
  4. {
  5. /// <summary>
  6. /// Base class for a Cinemachine Virtual Camera extension module.
  7. /// Hooks into the Cinemachine Pipeline. Use this to add extra processing
  8. /// to the vcam, modifying its generated state
  9. /// </summary>
  10. [DocumentationSorting(DocumentationSortingAttribute.Level.API)]
  11. public abstract class CinemachineExtension : MonoBehaviour
  12. {
  13. /// <summary>Useful constant for very small floats</summary>
  14. protected const float Epsilon = Utility.UnityVectorExtensions.Epsilon;
  15. /// <summary>Get the CinemachineVirtualCamera to which this extension is attached</summary>
  16. public CinemachineVirtualCameraBase VirtualCamera
  17. {
  18. get
  19. {
  20. if (m_vcamOwner == null)
  21. m_vcamOwner = GetComponent<CinemachineVirtualCameraBase>();
  22. return m_vcamOwner;
  23. }
  24. }
  25. CinemachineVirtualCameraBase m_vcamOwner;
  26. /// <summary>Connect to virtual camera pipeline.
  27. /// Override implementations must call this base implementation</summary>
  28. protected virtual void Awake()
  29. {
  30. ConnectToVcam(true);
  31. }
  32. /// <summary>Does nothing. It's here for the little checkbox in the inspector.</summary>
  33. protected virtual void OnEnable() {}
  34. #if UNITY_EDITOR
  35. [UnityEditor.Callbacks.DidReloadScripts]
  36. static void OnScriptReload()
  37. {
  38. var extensions = Resources.FindObjectsOfTypeAll<CinemachineExtension>();
  39. // Sort by execution order
  40. System.Array.Sort(extensions, (x, y) =>
  41. UnityEditor.MonoImporter.GetExecutionOrder(UnityEditor.MonoScript.FromMonoBehaviour(x))
  42. - UnityEditor.MonoImporter.GetExecutionOrder(UnityEditor.MonoScript.FromMonoBehaviour(y)));
  43. foreach (var e in extensions)
  44. e.ConnectToVcam(true);
  45. }
  46. #endif
  47. /// <summary>Disconnect from virtual camera pipeline.
  48. /// Override implementations must call this base implementation</summary>
  49. protected virtual void OnDestroy()
  50. {
  51. ConnectToVcam(false);
  52. }
  53. internal void EnsureStarted() { ConnectToVcam(true); }
  54. /// <summary>Connect to virtual camera. Implementation must be safe to be called
  55. /// redundantly. Override implementations must call this base implementation</summary>
  56. /// <param name="connect">True if connecting, false if disconnecting</param>
  57. protected virtual void ConnectToVcam(bool connect)
  58. {
  59. if (connect && VirtualCamera == null)
  60. Debug.LogError("CinemachineExtension requires a Cinemachine Virtual Camera component");
  61. if (VirtualCamera != null)
  62. {
  63. if (connect)
  64. VirtualCamera.AddExtension(this);
  65. else
  66. VirtualCamera.RemoveExtension(this);
  67. }
  68. mExtraState = null;
  69. }
  70. /// <summary>Override this to do such things as offset the RefereceLookAt.
  71. /// Base class implementation does nothing.</summary>
  72. /// <param name="vcam">The virtual camera being processed</param>
  73. /// <param name="curState">Input state that must be mutated</param>
  74. /// <param name="deltaTime">The current applicable deltaTime</param>
  75. public virtual void PrePipelineMutateCameraStateCallback(
  76. CinemachineVirtualCameraBase vcam, ref CameraState curState, float deltaTime) {}
  77. /// <summary>Legacy support. This is only here to avoid changing the API
  78. /// to make PostPipelineStageCallback() public</summary>
  79. /// <param name="vcam">The virtual camera being processed</param>
  80. /// <param name="stage">The current pipeline stage</param>
  81. /// <param name="state">The current virtual camera state</param>
  82. /// <param name="deltaTime">The current applicable deltaTime</param>
  83. public void InvokePostPipelineStageCallback(
  84. CinemachineVirtualCameraBase vcam,
  85. CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
  86. {
  87. PostPipelineStageCallback(vcam, stage, ref state, deltaTime);
  88. }
  89. /// <summary>
  90. /// This callback will be called after the virtual camera has implemented
  91. /// each stage in the pipeline. This method may modify the referenced state.
  92. /// If deltaTime less than 0, reset all state info and perform no damping.
  93. /// </summary>
  94. /// <param name="vcam">The virtual camera being processed</param>
  95. /// <param name="stage">The current pipeline stage</param>
  96. /// <param name="state">The current virtual camera state</param>
  97. /// <param name="deltaTime">The current applicable deltaTime</param>
  98. protected abstract void PostPipelineStageCallback(
  99. CinemachineVirtualCameraBase vcam,
  100. CinemachineCore.Stage stage, ref CameraState state, float deltaTime);
  101. /// <summary>This is called to notify the extension that a target got warped,
  102. /// so that the extension can update its internal state to make the camera
  103. /// also warp seamlessy. Base class implementation does nothing.</summary>
  104. /// <param name="target">The object that was warped</param>
  105. /// <param name="positionDelta">The amount the target's position changed</param>
  106. public virtual void OnTargetObjectWarped(Transform target, Vector3 positionDelta) {}
  107. /// <summary>
  108. /// Force the virtual camera to assume a given position and orientation
  109. /// </summary>
  110. /// <param name="pos">Worldspace pposition to take</param>
  111. /// <param name="rot">Worldspace orientation to take</param>
  112. public virtual void ForceCameraPosition(Vector3 pos, Quaternion rot) {}
  113. /// <summary>Notification that this virtual camera is going live.
  114. /// Base class implementation must be called by any overridden method.</summary>
  115. /// <param name="fromCam">The camera being deactivated. May be null.</param>
  116. /// <param name="worldUp">Default world Up, set by the CinemachineBrain</param>
  117. /// <param name="deltaTime">Delta time for time-based effects (ignore if less than or equal to 0)</param>
  118. /// <returns>True to request a vcam update of internal state</returns>
  119. public virtual bool OnTransitionFromCamera(
  120. ICinemachineCamera fromCam, Vector3 worldUp, float deltaTime) { return false; }
  121. /// <summary>
  122. /// Report maximum damping time needed for this extension.
  123. /// Only used in editor for timeline scrubbing.
  124. /// </summary>
  125. /// <returns>Highest damping setting in this extension</returns>
  126. public virtual float GetMaxDampTime() { return 0; }
  127. /// <summary>Extensions that require user input should implement this and return true.</summary>
  128. public virtual bool RequiresUserInput => false;
  129. /// <summary>Because extensions can be placed on manager cams and will in that
  130. /// case be called for all the vcam children, vcam-specific state information
  131. /// should be stored here. Just define a class to hold your state info
  132. /// and use it exclusively when calling this.</summary>
  133. /// /// <typeparam name="T">The type of the extra state class</typeparam>
  134. /// <param name="vcam">The virtual camera being processed</param>
  135. /// <returns>The extra state, cast as type T</returns>
  136. protected T GetExtraState<T>(ICinemachineCamera vcam) where T : class, new()
  137. {
  138. if (mExtraState == null)
  139. mExtraState = new Dictionary<ICinemachineCamera, System.Object>();
  140. System.Object extra = null;
  141. if (!mExtraState.TryGetValue(vcam, out extra))
  142. extra = mExtraState[vcam] = new T();
  143. return extra as T;
  144. }
  145. /// <summary>Inefficient method to get all extra state info for all vcams.
  146. /// Intended for Editor use only, not runtime!
  147. /// </summary>
  148. /// <typeparam name="T">The extra state type</typeparam>
  149. /// <returns>A dynamically-allocated list with all the extra states</returns>
  150. protected List<T> GetAllExtraStates<T>() where T : class, new()
  151. {
  152. var list = new List<T>();
  153. if (mExtraState != null)
  154. foreach (var v in mExtraState)
  155. list.Add(v.Value as T);
  156. return list;
  157. }
  158. private Dictionary<ICinemachineCamera, System.Object> mExtraState;
  159. }
  160. }