using UnityEngine; namespace Unity.Cinemachine { /// /// An abstract representation of a mutator acting on a CinemachineCamera /// [ExecuteAlways] public abstract class CinemachineComponentBase : MonoBehaviour { /// Useful constant for very small floats protected const float Epsilon = UnityVectorExtensions.Epsilon; CinemachineVirtualCameraBase m_VcamOwner; /// Get the associated CinemachineVirtualCameraBase public CinemachineVirtualCameraBase VirtualCamera { get { if (m_VcamOwner == null) TryGetComponent(out m_VcamOwner); #if !CINEMACHINE_NO_CM2_SUPPORT if (m_VcamOwner == null && transform.parent != null) transform.parent.TryGetComponent(out m_VcamOwner); #endif return m_VcamOwner; } } /// /// Standard OnEnable call. Derived classes should call the base class implementation. /// Handles pipeline validation. /// protected virtual void OnEnable() { var vcam = VirtualCamera as CinemachineCamera; if (vcam != null) vcam.InvalidatePipelineCache(); } /// /// Standard OnEnable call. Derived classes should call the base class implementation. /// Handles pipeline validation. /// protected virtual void OnDisable() { var vcam = VirtualCamera as CinemachineCamera; if (vcam != null) vcam.InvalidatePipelineCache(); } /// Returns the owner vcam's Follow target. public Transform FollowTarget { get { var vcam = VirtualCamera; return vcam == null ? null : vcam.ResolveFollow(vcam.Follow); } } /// Returns the owner vcam's LookAt target. public Transform LookAtTarget { get { CinemachineVirtualCameraBase vcam = VirtualCamera; return vcam == null ? null : vcam.ResolveLookAt(vcam.LookAt); } } /// Get Follow target as ICinemachineTargetGroup, or null if target is not a group public ICinemachineTargetGroup FollowTargetAsGroup { get { CinemachineVirtualCameraBase vcam = VirtualCamera; return vcam == null ? null : vcam.FollowTargetAsGroup; } } /// Get the position of the Follow target. Special handling: If the Follow target is /// a VirtualCamera, returns the vcam State's position, not the transform's position public Vector3 FollowTargetPosition { get { var vcam = VirtualCamera.FollowTargetAsVcam; if (vcam != null) return vcam.State.GetFinalPosition(); Transform target = FollowTarget; if (target != null) return TargetPositionCache.GetTargetPosition(target); return Vector3.zero; } } /// Get the rotation of the Follow target. Special handling: If the Follow target is /// a VirtualCamera, returns the vcam State's rotation, not the transform's rotation public Quaternion FollowTargetRotation { get { var vcam = VirtualCamera.FollowTargetAsVcam; if (vcam != null) return vcam.State.GetFinalOrientation(); Transform target = FollowTarget; if (target != null) return TargetPositionCache.GetTargetRotation(target); return Quaternion.identity; } } /// Get LookAt target as ICinemachineTargetGroup, or null if target is not a group /// GML todo: rename this public ICinemachineTargetGroup LookAtTargetAsGroup => VirtualCamera.LookAtTargetAsGroup; /// Get the position of the LookAt target. Special handling: If the LookAt target is /// a VirtualCamera, returns the vcam State's position, not the transform's position public Vector3 LookAtTargetPosition { get { var vcam = VirtualCamera.LookAtTargetAsVcam; if (vcam != null) return vcam.State.GetFinalPosition(); Transform target = LookAtTarget; if (target != null) return TargetPositionCache.GetTargetPosition(target); return Vector3.zero; } } /// Get the rotation of the LookAt target. Special handling: If the LookAt target is /// a VirtualCamera, returns the vcam State's rotation, not the transform's rotation public Quaternion LookAtTargetRotation { get { var vcam = VirtualCamera.LookAtTargetAsVcam; if (vcam != null) return vcam.State.GetFinalOrientation(); Transform target = LookAtTarget; if (target != null) return TargetPositionCache.GetTargetRotation(target); return Quaternion.identity; } } /// Returns the owner vcam's CameraState. public CameraState VcamState { get { CinemachineVirtualCameraBase vcam = VirtualCamera; return vcam == null ? CameraState.Default : vcam.State; } } /// Returns true if this object is enabled and set up to produce results. public abstract bool IsValid { get; } /// Override this to do such things as offset the ReferenceLookAt. /// Base class implementation does nothing. /// Input state that must be mutated /// Current effective deltaTime public virtual void PrePipelineMutateCameraState(ref CameraState curState, float deltaTime) {} /// What part of the pipeline this fits into // GML todo: remove this - use attribute public abstract CinemachineCore.Stage Stage { get; } /// Special for Body Stage components that want to be applied after Aim /// stage because they use the aim as inout for the procedural placement public virtual bool BodyAppliesAfterAim => false; /// Mutates the camera state. This state will later be applied to the camera. /// Input state that must be mutated /// Delta time for time-based effects (ignore if less than 0) public abstract void MutateCameraState(ref CameraState curState, float deltaTime); /// Notification that this virtual camera is going live. /// Base class implementation does nothing. /// The camera being deactivated. May be null. /// Default world Up, set by the CinemachineBrain /// Delta time for time-based effects (ignore if less than or equal to 0) /// True if the vcam should do an internal update as a result of this call public virtual bool OnTransitionFromCamera( ICinemachineCamera fromCam, Vector3 worldUp, float deltaTime) => false; /// This is called to notify the component that a target got warped, /// so that the component can update its internal state to make the camera /// also warp seamlessly. Base class implementation does nothing. /// The object that was warped /// The amount the target's position changed public virtual void OnTargetObjectWarped(Transform target, Vector3 positionDelta) {} /// /// Force the virtual camera to assume a given position and orientation. /// Procedural placement then takes over. /// Base class implementation does nothing. /// World-space position to take /// World-space orientation to take public virtual void ForceCameraPosition(Vector3 pos, Quaternion rot) {} /// /// Report maximum damping time needed for this component. /// Only used in editor for timeline scrubbing. /// /// Highest damping setting in this component public virtual float GetMaxDampTime() => 0; /// /// True if this component tries to make the camera look at the Tracking Target. /// Used by inspector to warn the user of potential improper setup. /// internal virtual bool CameraLooksAtTarget { get => false; } } }