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();
}
}
}