| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- using Cinemachine.Utility;
- using UnityEngine;
- namespace Cinemachine
- {
- /// <summary>
- /// This is a CinemachineComponent in the Aim section of the component pipeline.
- /// Its job is to aim the camera in response to the user's mouse or joystick input.
- ///
- /// The composer does not change the camera's position. It will only pan and tilt the
- /// camera where it is, in order to get the desired framing. To move the camera, you have
- /// to use the virtual camera's Body section.
- /// </summary>
- [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
- [AddComponentMenu("")] // Don't display in add component menu
- [SaveDuringPlay]
- public class CinemachinePOV : CinemachineComponentBase
- {
- /// <summary>
- /// Defines the recentering target: Recentering goes here
- /// </summary>
- public enum RecenterTargetMode
- {
- /// <summary>
- /// Just go to 0
- /// </summary>
- None,
- /// <summary>
- /// Axis angles are relative to Follow target's forward
- /// </summary>
- FollowTargetForward,
- /// <summary>
- /// Axis angles are relative to LookAt target's forward
- /// </summary>
- LookAtTargetForward
- }
- /// <summary>
- /// Defines the recentering target: recentering goes here
- /// </summary>
- public RecenterTargetMode m_RecenterTarget = RecenterTargetMode.None;
- /// <summary>The Vertical axis. Value is -90..90. Controls the vertical orientation</summary>
- [Tooltip("The Vertical axis. Value is -90..90. Controls the vertical orientation")]
- [AxisStateProperty]
- public AxisState m_VerticalAxis = new AxisState(-70, 70, false, false, 300f, 0.1f, 0.1f, "Mouse Y", true);
- /// <summary>Controls how automatic recentering of the Vertical axis is accomplished</summary>
- [Tooltip("Controls how automatic recentering of the Vertical axis is accomplished")]
- public AxisState.Recentering m_VerticalRecentering = new AxisState.Recentering(false, 1, 2);
- /// <summary>The Horizontal axis. Value is -180..180. Controls the horizontal orientation</summary>
- [Tooltip("The Horizontal axis. Value is -180..180. Controls the horizontal orientation")]
- [AxisStateProperty]
- public AxisState m_HorizontalAxis = new AxisState(-180, 180, true, false, 300f, 0.1f, 0.1f, "Mouse X", false);
- /// <summary>Controls how automatic recentering of the Horizontal axis is accomplished</summary>
- [Tooltip("Controls how automatic recentering of the Horizontal axis is accomplished")]
- public AxisState.Recentering m_HorizontalRecentering = new AxisState.Recentering(false, 1, 2);
- /// <summary>Obsolete - no longer used</summary>
- [HideInInspector]
- [Tooltip("Obsolete - no longer used")]
- public bool m_ApplyBeforeBody;
- /// <summary>True if component is enabled and has a LookAt defined</summary>
- public override bool IsValid { get { return enabled; } }
- /// <summary>Get the Cinemachine Pipeline stage that this component implements.
- /// Always returns the Aim stage</summary>
- public override CinemachineCore.Stage Stage { get { return CinemachineCore.Stage.Aim; } }
- private void OnValidate()
- {
- m_VerticalAxis.Validate();
- m_VerticalRecentering.Validate();
- m_HorizontalAxis.Validate();
- m_HorizontalRecentering.Validate();
- }
- private void OnEnable()
- {
- UpdateInputAxisProvider();
- }
-
- /// <summary>
- /// API for the inspector. Internal use only
- /// </summary>
- public void UpdateInputAxisProvider()
- {
- m_HorizontalAxis.SetInputAxisProvider(0, null);
- m_VerticalAxis.SetInputAxisProvider(1, null);
- if (VirtualCamera != null)
- {
- var provider = VirtualCamera.GetInputAxisProvider();
- if (provider != null)
- {
- m_HorizontalAxis.SetInputAxisProvider(0, provider);
- m_VerticalAxis.SetInputAxisProvider(1, provider);
- }
- }
- }
- /// <summary>Does nothing</summary>
- /// <param name="state"></param>
- /// <param name="deltaTime"></param>
- public override void PrePipelineMutateCameraState(ref CameraState state, float deltaTime) {}
- /// <summary>Applies the axis values and orients the camera accordingly</summary>
- /// <param name="curState">The current camera state</param>
- /// <param name="deltaTime">Used for calculating damping. Not used.</param>
- public override void MutateCameraState(ref CameraState curState, float deltaTime)
- {
- if (!IsValid)
- return;
- // Only read joystick when game is playing
- if (deltaTime >= 0 && CinemachineCore.Instance.IsLive(VirtualCamera))
- {
- if (m_HorizontalAxis.Update(deltaTime))
- m_HorizontalRecentering.CancelRecentering();
- if (m_VerticalAxis.Update(deltaTime))
- m_VerticalRecentering.CancelRecentering();
- var recenterTarget = GetRecenterTarget();
- m_HorizontalRecentering.DoRecentering(ref m_HorizontalAxis, deltaTime, recenterTarget.x);
- m_VerticalRecentering.DoRecentering(ref m_VerticalAxis, deltaTime, recenterTarget.y);
- }
- // If we have a transform parent, then apply POV in the local space of the parent
- Quaternion rot = Quaternion.Euler(m_VerticalAxis.Value, m_HorizontalAxis.Value, 0);
- Transform parent = VirtualCamera.transform.parent;
- if (parent != null)
- rot = parent.rotation * rot;
- rot = Quaternion.FromToRotation(Vector3.up, curState.ReferenceUp) * rot;
- curState.RawOrientation = rot;
- }
- /// <summary>
- /// Get the horizonmtal and vertical angles that correspong to "at rest" position.
- /// </summary>
- /// <returns>X is horizontal angle (rot Y) and Y is vertical angle (rot X)</returns>
- public Vector2 GetRecenterTarget()
- {
- Transform t = null;
- switch (m_RecenterTarget)
- {
- case RecenterTargetMode.FollowTargetForward: t = VirtualCamera.Follow; break;
- case RecenterTargetMode.LookAtTargetForward: t = VirtualCamera.LookAt; break;
- default: break;
- }
- if (t != null)
- {
- var fwd = t.forward;
- Transform parent = VirtualCamera.transform.parent;
- if (parent != null)
- fwd = parent.rotation * fwd;
- var v = Quaternion.FromToRotation(Vector3.forward, fwd).eulerAngles;
- return new Vector2(NormalizeAngle(v.y), NormalizeAngle(v.x));
- }
- return Vector2.zero;
- }
- // Normalize angle value to [-180, 180] degrees.
- static float NormalizeAngle(float angle)
- {
- return ((angle + 180) % 360) - 180;
- }
- /// <summary>
- /// Force the virtual camera to assume a given position and orientation.
- /// Procedural placement then takes over
- /// </summary>
- /// <param name="pos">Worldspace pposition to take</param>
- /// <param name="rot">Worldspace orientation to take</param>
- public override void ForceCameraPosition(Vector3 pos, Quaternion rot)
- {
- SetAxesForRotation(rot);
- }
- /// <summary>Notification that this virtual camera is going live.
- /// Base class implementation does nothing.</summary>
- /// <param name="fromCam">The camera being deactivated. May be null.</param>
- /// <param name="worldUp">Default world Up, set by the CinemachineBrain</param>
- /// <param name="deltaTime">Delta time for time-based effects (ignore if less than or equal to 0)</param>
- /// <param name="transitionParams">Transition settings for this vcam</param>
- /// <returns>True if the vcam should do an internal update as a result of this call</returns>
- public override bool OnTransitionFromCamera(
- ICinemachineCamera fromCam, Vector3 worldUp, float deltaTime,
- ref CinemachineVirtualCameraBase.TransitionParams transitionParams)
- {
- m_HorizontalRecentering.DoRecentering(ref m_HorizontalAxis, -1, 0);
- m_VerticalRecentering.DoRecentering(ref m_VerticalAxis, -1, 0);
- m_HorizontalRecentering.CancelRecentering();
- m_VerticalRecentering.CancelRecentering();
- if (fromCam != null && transitionParams.m_InheritPosition)
- {
- SetAxesForRotation(fromCam.State.RawOrientation);
- return true;
- }
- return false;
- }
- void SetAxesForRotation(Quaternion targetRot)
- {
- Vector3 up = VcamState.ReferenceUp;
- Vector3 fwd = Vector3.forward;
- Transform parent = VirtualCamera.transform.parent;
- if (parent != null)
- fwd = parent.rotation * fwd;
- m_HorizontalAxis.Value = 0;
- m_HorizontalAxis.Reset();
- Vector3 targetFwd = targetRot * Vector3.forward;
- Vector3 a = fwd.ProjectOntoPlane(up);
- Vector3 b = targetFwd.ProjectOntoPlane(up);
- if (!a.AlmostZero() && !b.AlmostZero())
- m_HorizontalAxis.Value = Vector3.SignedAngle(a, b, up);
- m_VerticalAxis.Value = 0;
- m_VerticalAxis.Reset();
- fwd = Quaternion.AngleAxis(m_HorizontalAxis.Value, up) * fwd;
- Vector3 right = Vector3.Cross(up, fwd);
- if (!right.AlmostZero())
- m_VerticalAxis.Value = Vector3.SignedAngle(fwd, targetFwd, right);
- }
- }
- }
|