using UnityEngine; namespace Cinemachine { /// /// An abstract representation of a mutator acting on a Cinemachine Virtual Camera /// [DocumentationSorting(DocumentationSortingAttribute.Level.API)] public abstract class CinemachineComponentBase : MonoBehaviour { /// Useful constant for very small floats protected const float Epsilon = Utility.UnityVectorExtensions.Epsilon; /// Get the associated CinemachineVirtualCameraBase public CinemachineVirtualCameraBase VirtualCamera { get { if (m_vcamOwner == null) m_vcamOwner = GetComponent(); if (m_vcamOwner == null && transform.parent != null) m_vcamOwner = transform.parent.GetComponent(); return m_vcamOwner; } } CinemachineVirtualCameraBase m_vcamOwner; /// Returns the owner vcam's Follow target. public Transform FollowTarget { get { CinemachineVirtualCameraBase vcam = VirtualCamera; return vcam == null ? null : vcam.Follow; } } /// Returns the owner vcam's LookAt target. public Transform LookAtTarget { get { CinemachineVirtualCameraBase vcam = VirtualCamera; return vcam == null ? null : vcam.LookAt; } } private Transform mCachedFollowTarget; private CinemachineVirtualCameraBase mCachedFollowTargetVcam; private ICinemachineTargetGroup mCachedFollowTargetGroup; void UpdateFollowTargetCache() { mCachedFollowTargetVcam = null; mCachedFollowTargetGroup = null; mCachedFollowTarget = FollowTarget; if (mCachedFollowTarget != null) { mCachedFollowTargetVcam = mCachedFollowTarget.GetComponent(); mCachedFollowTargetGroup = mCachedFollowTarget.GetComponent(); } } /// Get Follow target as ICinemachineTargetGroup, or null if target is not a group public ICinemachineTargetGroup AbstractFollowTargetGroup { get { if (FollowTarget != mCachedFollowTarget) UpdateFollowTargetCache(); return mCachedFollowTargetGroup; } } /// Get Follow target as CinemachineTargetGroup, or null if target is not a CinemachineTargetGroup public CinemachineTargetGroup FollowTargetGroup { get { return AbstractFollowTargetGroup as CinemachineTargetGroup; } } /// 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 { Transform target = FollowTarget; if (target != mCachedFollowTarget) UpdateFollowTargetCache(); if (mCachedFollowTargetVcam != null) return mCachedFollowTargetVcam.State.FinalPosition; 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 { Transform target = FollowTarget; if (target != mCachedFollowTarget) { mCachedFollowTargetVcam = null; mCachedFollowTarget = target; if (target != null) mCachedFollowTargetVcam = target.GetComponent(); } if (mCachedFollowTargetVcam != null) return mCachedFollowTargetVcam.State.FinalOrientation; if (target != null) return TargetPositionCache.GetTargetRotation(target); return Quaternion.identity; } } private Transform mCachedLookAtTarget; private CinemachineVirtualCameraBase mCachedLookAtTargetVcam; private ICinemachineTargetGroup mCachedLookAtTargetGroup; void UpdateLookAtTargetCache() { mCachedLookAtTargetVcam = null; mCachedLookAtTargetGroup = null; mCachedLookAtTarget = LookAtTarget; if (mCachedLookAtTarget != null) { mCachedLookAtTargetVcam = mCachedLookAtTarget.GetComponent(); mCachedLookAtTargetGroup = mCachedLookAtTarget.GetComponent(); } } /// Get LookAt target as ICinemachineTargetGroup, or null if target is not a group public ICinemachineTargetGroup AbstractLookAtTargetGroup { get { if (LookAtTarget != mCachedLookAtTarget) UpdateLookAtTargetCache(); return mCachedLookAtTargetGroup; } } /// Get LookAt target as CinemachineTargetGroup, or null if target is not a CinemachineTargetGroup public CinemachineTargetGroup LookAtTargetGroup { get { return AbstractLookAtTargetGroup as CinemachineTargetGroup; } } /// 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 { Transform target = LookAtTarget; if (target != mCachedLookAtTarget) UpdateLookAtTargetCache(); if (mCachedLookAtTargetVcam != null) return mCachedLookAtTargetVcam.State.FinalPosition; 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 { Transform target = LookAtTarget; if (target != mCachedLookAtTarget) UpdateLookAtTargetCache(); if (mCachedLookAtTargetVcam != null) return mCachedLookAtTargetVcam.State.FinalOrientation; 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 RefereceLookAt. /// 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 public abstract CinemachineCore.Stage Stage { get; } /// Special for Body Stage compoments that want to be applied after Aim /// stage because they use the aim as inout for the procedural placement public virtual bool BodyAppliesAfterAim { get { return 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) /// Transition settings for this vcam /// 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, ref CinemachineVirtualCameraBase.TransitionParams transitionParams) { return 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 seamlessy. 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. /// Worldspace pposition to take /// Worldspace 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() { return 0; } } }