Firstborn/Library/PackageCache/com.unity.cinemachine@2.8.9/Runtime/Helpers/CinemachineTriggerAction.cs
Schaken-Mods b486678290 Library -Artifacts
Library -Artifacts
2023-03-28 12:24:16 -05:00

308 lines
13 KiB
C#

#if !UNITY_2019_3_OR_NEWER
#define CINEMACHINE_PHYSICS
#define CINEMACHINE_PHYSICS_2D
#endif
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Playables;
namespace Cinemachine
{
#if !(CINEMACHINE_PHYSICS || CINEMACHINE_PHYSICS_2D)
// Workaround for Unity scripting bug
/// <summary>
/// A multi-purpose script which causes an action to occur when
/// a trigger collider is entered and exited.
/// </summary>
[AddComponentMenu("")] // Hide in menu
public class CinemachineTriggerAction : MonoBehaviour {}
#else
/// <summary>
/// A multi-purpose script which causes an action to occur when
/// a trigger collider is entered and exited.
/// </summary>
[DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
[SaveDuringPlay]
[HelpURL(Documentation.BaseURL + "api/Cinemachine.CinemachineTriggerAction.html")]
public class CinemachineTriggerAction : MonoBehaviour
{
/// <summary>Only triggers generated by objects on these layers will be considered.</summary>
[Header("Trigger Object Filter")]
[Tooltip("Only triggers generated by objects on these layers will be considered")]
public LayerMask m_LayerMask = 1;
/// <summary>If set, only triggers generated by objects with this tag will be considered</summary>
[TagField]
[Tooltip("If set, only triggers generated by objects with this tag will be considered")]
public string m_WithTag = string.Empty;
/// <summary>Triggers generated by objects with this tag will be ignored</summary>
[TagField]
[Tooltip("Triggers generated by objects with this tag will be ignored")]
public string m_WithoutTag = string.Empty;
/// <summary>Skip this many trigger entries before taking action</summary>
[NoSaveDuringPlay]
[Tooltip("Skip this many trigger entries before taking action")]
public int m_SkipFirst = 0;
/// <summary>Repeat the action for all subsequent trigger entries</summary>
[Tooltip("Repeat the action for all subsequent trigger entries")]
public bool m_Repeating = true;
/// <summary>Defines what action to take on trigger enter/exit</summary>
[Serializable]
public struct ActionSettings
{
/// <summary>What action to take</summary>
public enum Mode
{
/// <summary>Use the event only</summary>
Custom,
/// <summary>Boost priority of virtual camera target</summary>
PriorityBoost,
/// <summary>Activate the target GameObject</summary>
Activate,
/// <summary>Decativate target GameObject</summary>
Deactivate,
/// <summary>Enable a component</summary>
Enable,
/// <summary>Disable a component</summary>
Disable,
#if CINEMACHINE_TIMELINE
/// <summary>Start animation on target</summary>
Play,
/// <summary>Stop animation on target</summary>
Stop
#endif
}
/// <summary>Serializable parameterless game event</summary>
[Serializable] public class TriggerEvent : UnityEvent {}
/// <summary>What action to take</summary>
[Tooltip("What action to take")]
public Mode m_Action;
/// <summary>The target object on which to operate. If null, then the current behaviour/GameObject will be used</summary>
[Tooltip("The target object on which to operate. If null, then the current behaviour/GameObject will be used")]
public UnityEngine.Object m_Target;
/// <summary>If PriorityBoost, this amount will be added to the virtual camera's priority</summary>
[Tooltip("If PriorityBoost, this amount will be added to the virtual camera's priority")]
public int m_BoostAmount;
/// <summary>If playing a timeline, start at this time</summary>
[Tooltip("If playing a timeline, start at this time")]
public float m_StartTime;
/// <summary>How to interpret the start time</summary>
public enum TimeMode
{
/// <summary>Offset after the start of the timeline</summary>
FromStart,
/// <summary>Offset before the end of the timeline</summary>
FromEnd,
/// <summary>Offset before the current timeline time</summary>
BeforeNow,
/// <summary>Offset after the current timeline time</summary>
AfterNow
};
/// <summary>How to interpret the start time</summary>
[Tooltip("How to interpret the start time")]
public TimeMode m_Mode;
/// <summary>This event will be invoked</summary>
[Tooltip("This event will be invoked")]
public TriggerEvent m_Event;
/// <summary>Standard Constructor</summary>
/// <param name="action">Action to set</param>
public ActionSettings(Mode action)
{
m_Action = action;
m_Target = null;
m_BoostAmount = 0;
m_StartTime = 0;
m_Mode = TimeMode.FromStart;
m_Event = new TriggerEvent();
}
/// <summary>Invoke the action. Depending on the mode, different action will
/// be performed. The embedded event will always be invoked, in addition to the
/// action specified by the Mode.</summary>
public void Invoke()
{
UnityEngine.Object currentTarget = m_Target;
if (currentTarget != null)
{
GameObject targetGameObject = currentTarget as GameObject;
Behaviour targetBehaviour = currentTarget as Behaviour;
if (targetBehaviour != null)
targetGameObject = targetBehaviour.gameObject;
switch (m_Action)
{
case Mode.Custom:
break;
case Mode.PriorityBoost:
{
CinemachineVirtualCameraBase vcam
= targetGameObject.GetComponent<CinemachineVirtualCameraBase>();
if (vcam != null)
{
vcam.Priority += m_BoostAmount;
vcam.MoveToTopOfPrioritySubqueue();
}
break;
}
case Mode.Activate:
if (targetGameObject != null)
{
targetGameObject.SetActive(true);
CinemachineVirtualCameraBase vcam
= targetGameObject.GetComponent<CinemachineVirtualCameraBase>();
if (vcam != null)
vcam.MoveToTopOfPrioritySubqueue();
}
break;
case Mode.Deactivate:
if (targetGameObject != null)
targetGameObject.SetActive(false);
break;
case Mode.Enable:
{
if (targetBehaviour != null)
targetBehaviour.enabled = true;
break;
}
case Mode.Disable:
{
if (targetBehaviour != null)
targetBehaviour.enabled = false;
break;
}
#if CINEMACHINE_TIMELINE
case Mode.Play:
{
PlayableDirector playable
= targetGameObject.GetComponent<PlayableDirector>();
if (playable != null)
{
double startTime = 0;
double duration = playable.duration;
double current = playable.time;
switch (m_Mode)
{
default:
case TimeMode.FromStart:
startTime += m_StartTime;
break;
case TimeMode.FromEnd:
startTime = duration - m_StartTime;
break;
case TimeMode.BeforeNow:
startTime = current - m_StartTime;
break;
case TimeMode.AfterNow:
startTime = current + m_StartTime;
break;
}
playable.time = startTime;
playable.Play();
}
else
{
Animation ani = targetGameObject.GetComponent<Animation>();
if (ani != null)
ani.Play();
}
break;
}
case Mode.Stop:
{
PlayableDirector playable
= targetGameObject.GetComponent<PlayableDirector>();
if (playable != null)
playable.Stop();
else
{
Animation ani = targetGameObject.GetComponent<Animation>();
if (ani != null)
ani.Stop();
}
break;
}
#endif
}
}
m_Event.Invoke();
}
}
/// <summary>What action to take when an eligible object enters the collider or trigger zone</summary>
public ActionSettings m_OnObjectEnter = new ActionSettings(ActionSettings.Mode.Custom);
/// <summary>What action to take when an eligible object exits the collider or trigger zone</summary>
public ActionSettings m_OnObjectExit = new ActionSettings(ActionSettings.Mode.Custom);
HashSet<GameObject> m_ActiveTriggerObjects = new HashSet<GameObject>();
private bool Filter(GameObject other)
{
if (!enabled)
return false;
if (((1 << other.layer) & m_LayerMask) == 0)
return false;
if (m_WithTag.Length != 0 && !other.CompareTag(m_WithTag))
return false;
if (m_WithoutTag.Length != 0 && other.CompareTag(m_WithoutTag))
return false;
return true;
}
void InternalDoTriggerEnter(GameObject other)
{
if (!Filter(other))
return;
--m_SkipFirst;
if (m_SkipFirst > -1)
return;
if (!m_Repeating && m_SkipFirst != -1)
return;
m_ActiveTriggerObjects.Add(other);
m_OnObjectEnter.Invoke();
}
void InternalDoTriggerExit(GameObject other)
{
if (!m_ActiveTriggerObjects.Contains(other))
return;
m_ActiveTriggerObjects.Remove(other);
if (enabled)
m_OnObjectExit.Invoke();
}
#if CINEMACHINE_PHYSICS
void OnTriggerEnter(Collider other) { InternalDoTriggerEnter(other.gameObject); }
void OnTriggerExit(Collider other) { InternalDoTriggerExit(other.gameObject); }
void OnCollisionEnter(Collision other) { InternalDoTriggerEnter(other.gameObject); }
void OnCollisionExit(Collision other) { InternalDoTriggerExit(other.gameObject); }
#endif
#if CINEMACHINE_PHYSICS_2D
void OnTriggerEnter2D(Collider2D other) { InternalDoTriggerEnter(other.gameObject); }
void OnTriggerExit2D(Collider2D other) { InternalDoTriggerExit(other.gameObject); }
void OnCollisionEnter2D(Collision2D other) { InternalDoTriggerEnter(other.gameObject); }
void OnCollisionExit2D(Collision2D other) { InternalDoTriggerExit(other.gameObject); }
#endif
void OnEnable() {} // For the Enabled checkbox
}
#endif
}