using UnityEngine; using System; using UnityEngine.Events; namespace Unity.Cinemachine { static class Documentation { /// This must be used like /// [HelpURL(Documentation.BaseURL + "api/some-page.html")] /// or /// [HelpURL(Documentation.BaseURL + "manual/some-page.html")] /// It cannot support String.Format nor string interpolation public const string BaseURL = "https://docs.unity3d.com/Packages/com.unity.cinemachine@3.1/"; } /// A singleton that manages complete lists of CinemachineBrain and, /// CinemachineCamera, and the priority queue. Provides /// services to keeping track of whether CinemachineCameras have /// been updated each frame. public static class CinemachineCore { /// Data version string. Used to upgrade from legacy projects internal const int kStreamingVersion = 20230301; /// /// The root directory where Cinemachine is installed /// public const string kPackageRoot = "Packages/com.unity.cinemachine"; /// /// Unit-test support: /// If non-negative, cinemachine will use this value whenever it wants current unscaled game time. /// Usage is for InputAxis in manual update mode, for deterministic behaviour. /// internal static float CurrentUnscaledTimeTimeOverride = -1; /// /// Unit-test support: /// Replacement for Time.unscaledTime, taking CurrentUnscaledTimeTimeOverride into account. /// internal static float CurrentUnscaledTime => CurrentUnscaledTimeTimeOverride >= 0 ? CurrentUnscaledTimeTimeOverride : Time.unscaledTime; /// Unit-test support: Special mode for deterministic unit tests. internal static bool UnitTestMode = false; /// API for the Unity Editor. /// Color used to indicate that a camera is in Solo mode. internal static Color SoloGUIColor() => Color.Lerp(Color.red, Color.yellow, 0.8f); /// /// Stages in the Cinemachine Component pipeline. This enum defines the pipeline order. /// public enum Stage { /// First stage: position the camera in space Body, /// Second stage: orient the camera to point at the target Aim, /// Final pipeline stage: apply noise (this is done separately, in the /// Correction channel of the CameraState) Noise, /// Post-correction stage. This is invoked on all virtual camera /// types, after the pipeline is complete Finalize }; /// Hint for transitioning to and from Cinemachine cameras [Flags] public enum BlendHints { /// Spherical blend about Tracking target position SphericalPosition = 1, /// Cylindrical blend about Tracking target position /// (vertical co-ordinate is linearly interpolated) CylindricalPosition = 2, /// Screen-space blend between LookAt targets instead of /// world space lerp of target position ScreenSpaceAimWhenTargetsDiffer = 4, /// When this virtual camera goes Live, attempt to force /// the position to be the same /// as the current position of the outgoing Camera InheritPosition = 8, /// Do not consider the tracking target when blending, just /// do a spherical interpolation IgnoreTarget = 16, /// When blending out from this camera, use a snapshot of /// its outgoing state instead of a live state FreezeWhenBlendingOut = 32, } /// Delegate for overriding Unity's default input system. Returns the value /// of the named axis. public delegate float AxisInputDelegate(string axisName); /// Delegate for overriding Unity's default input system. /// If you set this, then your delegate will be called instead of /// System.Input.GetAxis(axisName) whenever in-game user input is needed. #if ENABLE_LEGACY_INPUT_MANAGER public static AxisInputDelegate GetInputAxis = UnityEngine.Input.GetAxis; #else public static AxisInputDelegate GetInputAxis = delegate { return 0; }; #endif /// /// If non-negative, cinemachine will update with this uniform delta time. /// Usage is for timelines in manual update mode. /// public static float UniformDeltaTimeOverride = -1; /// /// Replacement for Time.deltaTime, taking UniformDeltaTimeOverride into account. /// public static float DeltaTime => UniformDeltaTimeOverride >= 0 ? UniformDeltaTimeOverride : Time.deltaTime; /// /// If non-negative, cinemachine will use this value whenever it wants current game time. /// Usage is for master timelines in manual update mode, for deterministic behaviour. /// public static float CurrentTimeOverride = -1; /// /// Replacement for Time.time, taking CurrentTimeTimeOverride into account. /// public static float CurrentTime => CurrentTimeOverride >= 0 ? CurrentTimeOverride : Time.time; /// /// Delegate for overriding a blend that is about to be applied to a transition. /// A handler can either return the default blend, or a new blend definition /// specific to current conditions. /// /// The outgoing virtual camera /// Yhe incoming virtual camera /// The blend that would normally be applied /// The context in which the blend is taking place. /// Can be a CinemachineBrain, or CinemachineStateDrivenCamera, or other manager /// object that can initiate a blend /// The blend definition to use for this transition. public delegate CinemachineBlendDefinition GetBlendOverrideDelegate( ICinemachineCamera fromVcam, ICinemachineCamera toVcam, CinemachineBlendDefinition defaultBlend, UnityEngine.Object owner); /// /// Delegate for overriding a blend that is about to be applied to a transition. /// A handler can either return the default blend, or a new blend specific to /// current conditions. /// public static GetBlendOverrideDelegate GetBlendOverride; /// /// Delegate for replacing a standard CinemachineBlend with a custom blender class. /// Return a new instance of a custom blender, or null to use the default blender. /// /// The outgoing camera /// The incoming camera /// A new instance of a custom blender, or null to use the default blender public delegate CinemachineBlend.IBlender GetCustomBlenderDelegate( ICinemachineCamera fromCam, ICinemachineCamera toCam); /// /// Delegate for replacing a standard CinemachineBlend with a custom blender class. /// Returns a new instance of a custom blender, or null to use the default blender. /// public static GetCustomBlenderDelegate GetCustomBlender; /// An event with ICinemachineMixer and ICinemachineCamera parameters. [Serializable] public class CameraEvent : UnityEvent {} /// An Event with CinemachineBrain as parameter. [Serializable] public class BrainEvent : UnityEvent {} /// This event will fire after a brain updates its Camera public static BrainEvent CameraUpdatedEvent = new (); /// This is sent with BlendEvent public struct BlendEventParams { /// The context in which this blend is ocurring public ICinemachineMixer Origin; /// The blend that in question public CinemachineBlend Blend; } /// An Event with BlendEventParams as parameter. [Serializable] public class BlendEvent : UnityEvent {} /// This event will fire when the current camera changes, /// at the start of a blend public static ICinemachineCamera.ActivationEvent CameraActivatedEvent = new (); /// This event will fire immediately after a camera that is /// live in some context stops being live. public static CameraEvent CameraDeactivatedEvent = new (); /// This event will fire when a blend is created. /// Handler can modify the settings of the blend (but not the cameras). /// /// Note: BlendCreatedEvents are NOT sent for timeline blends, as those are expected /// to be controlled 100% by timeline. To modify the blend algorithm for timeline blends, /// you can install a handler for CinemachineCore.GetCustomBlender. /// public static BlendEvent BlendCreatedEvent = new (); /// This event will fire when the current camera completes a blend-in. public static CameraEvent BlendFinishedEvent = new (); /// /// List of all active CinemachineCameras for all brains. /// This list is kept sorted by priority. /// public static int VirtualCameraCount => CameraUpdateManager.VirtualCameraCount; /// Access the priority-sorted array of active ICinemachineCamera in the scene. /// Index of the camera to access, range 0-VirtualCameraCount /// The virtual camera at the specified index public static CinemachineVirtualCameraBase GetVirtualCamera(int index) => CameraUpdateManager.GetVirtualCamera(index); /// /// API for the Unity Editor. /// Show this camera no matter what. This is static, and so affects all Cinemachine brains. /// public static ICinemachineCamera SoloCamera { get => s_SoloCamera; set { if (value != null && !CinemachineCore.IsLive(value)) value.OnCameraActivated(new ICinemachineCamera.ActivationEventParams { Origin = null, OutgoingCamera = null, IncomingCamera = value, IsCut = true, WorldUp = Vector3.up, DeltaTime = DeltaTime }); s_SoloCamera = value; } } static ICinemachineCamera s_SoloCamera; /// /// Is this virtual camera currently actively controlling any Camera? /// /// The virtual camera in question /// True if the vcam is currently driving a Brain public static bool IsLive(ICinemachineCamera vcam) { if (vcam != null) { int numBrains = CinemachineBrain.ActiveBrainCount; for (int i = 0; i < numBrains; ++i) { var b = CinemachineBrain.GetActiveBrain(i); if (b != null && b.IsLiveChild(vcam)) return true; } } return false; } /// /// Checks if the vcam is live as part of an outgoing blend in any active CinemachineBrain. /// Does not check whether the vcam is also the current active vcam. /// /// The virtual camera to check /// True if the virtual camera is part of a live outgoing blend, false otherwise public static bool IsLiveInBlend(ICinemachineCamera vcam) { if (vcam != null) { int numBrains = CinemachineBrain.ActiveBrainCount; for (int i = 0; i < numBrains; ++i) { var b = CinemachineBrain.GetActiveBrain(i); if (b != null && b.IsLiveInBlend(vcam)) return true; } } return false; } /// /// Try to find a CinemachineBrain to associate with a /// CinemachineCamera. The first CinemachineBrain /// in which this CinemachineCamera is live will be used. /// If none, then the first active CinemachineBrain with the correct /// layer filter will be used. /// Brains with OutputCamera == null will not be returned. /// Final result may be null. /// /// Virtual camera whose potential brain we need. /// First CinemachineBrain found that might be /// appropriate for this vcam, or null public static CinemachineBrain FindPotentialTargetBrain(CinemachineVirtualCameraBase vcam) { if (vcam != null) { // If it's live in some brain, that's good enough for us int numBrains = CinemachineBrain.ActiveBrainCount; for (int i = 0; i < numBrains; ++i) { var b = CinemachineBrain.GetActiveBrain(i); if (b != null && b.OutputCamera != null && b.IsLiveChild(vcam)) return b; } // If it's not live anywhere, then where might it become live? var channel = (uint)vcam.OutputChannel; for (int i = 0; i < numBrains; ++i) { var b = CinemachineBrain.GetActiveBrain(i); if (b != null && b.OutputCamera != null && ((uint)b.ChannelMask & channel) != 0) return b; } } return null; } /// Call this to notify all virtual cameras that may be tracking a target /// that the target's position has suddenly warped to somewhere else, so that /// the virtual cameras can update their internal state to make the camera /// warp seamlessly along with the target. /// /// All virtual cameras are iterated so this call will work no matter how many /// are tracking the target, and whether they are active or inactive. /// /// The object that was warped /// The amount the target's position changed public static void OnTargetObjectWarped(Transform target, Vector3 positionDelta) { var numVcams = CameraUpdateManager.VirtualCameraCount; for (int i = 0; i < numVcams; ++i) GetVirtualCamera(i).OnTargetObjectWarped(target, positionDelta); } /// Call this to notify all virtual cameras to forget state from the previous frame. /// This is essentially a reset of all the Cinemachine cameras. It is useful, for example, /// when you want to restart a game level. /// public static void ResetCameraState() { var numVcams = CameraUpdateManager.VirtualCameraCount; for (int i = 0; i < numVcams; ++i) GetVirtualCamera(i).PreviousStateIsValid = false; int numBrains = CinemachineBrain.ActiveBrainCount; for (int i = 0; i < numBrains; ++i) CinemachineBrain.GetActiveBrain(i).ResetState(); } } }