You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
9.1 KiB
252 lines
9.1 KiB
using System; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
using UnityEngine.Events; |
|
using UnityEngine.Playables; |
|
|
|
namespace UnityEngine.Timeline |
|
{ |
|
/// <summary> |
|
/// Listens for emitted signals and reacts depending on its defined reactions. |
|
/// </summary> |
|
/// A SignalReceiver contains a list of reactions. Each reaction is bound to a SignalAsset. |
|
/// When a SignalEmitter emits a signal, the SignalReceiver invokes the corresponding reaction. |
|
/// <seealso cref="UnityEngine.Timeline.SignalEmitter"/> |
|
/// <seealso cref="UnityEngine.Timeline.SignalAsset"/> |
|
[TimelineHelpURL(typeof(SignalReceiver))] |
|
public class SignalReceiver : MonoBehaviour, INotificationReceiver |
|
{ |
|
[SerializeField] |
|
EventKeyValue m_Events = new EventKeyValue(); |
|
|
|
/// <summary> |
|
/// Called when a notification is sent. |
|
/// </summary> |
|
/// <param name="origin">The playable that sent the notification.</param> |
|
/// <param name="notification">The received notification. Only notifications of type <see cref="SignalEmitter"/> will be processed.</param> |
|
/// <param name="context">User defined data that depends on the type of notification. Uses this to pass necessary information that can change with each invocation.</param> |
|
public void OnNotify(Playable origin, INotification notification, object context) |
|
{ |
|
var signal = notification as SignalEmitter; |
|
if (signal != null && signal.asset != null) |
|
{ |
|
UnityEvent evt; |
|
if (m_Events.TryGetValue(signal.asset, out evt) && evt != null) |
|
{ |
|
evt.Invoke(); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Defines a new reaction for a SignalAsset. |
|
/// </summary> |
|
/// <param name="asset">The SignalAsset for which the reaction is being defined.</param> |
|
/// <param name="reaction">The UnityEvent that describes the reaction.</param> |
|
/// <exception cref="ArgumentNullException">Thrown when the asset is null.</exception> |
|
/// <exception cref="ArgumentException">Thrown when the SignalAsset is already registered with this receiver.</exception> |
|
public void AddReaction(SignalAsset asset, UnityEvent reaction) |
|
{ |
|
if (asset == null) |
|
throw new ArgumentNullException("asset"); |
|
|
|
if (m_Events.signals.Contains(asset)) |
|
throw new ArgumentException("SignalAsset already used."); |
|
m_Events.Append(asset, reaction); |
|
} |
|
|
|
/// <summary> |
|
/// Appends a null SignalAsset with a reaction specified by the UnityEvent. |
|
/// </summary> |
|
/// <param name="reaction">The new reaction to be appended.</param> |
|
/// <returns>The index of the appended reaction.</returns> |
|
/// <remarks>Multiple null assets are valid.</remarks> |
|
public int AddEmptyReaction(UnityEvent reaction) |
|
{ |
|
m_Events.Append(null, reaction); |
|
return m_Events.events.Count - 1; |
|
} |
|
|
|
/// <summary> |
|
/// Removes the first occurrence of a SignalAsset. |
|
/// </summary> |
|
/// <param name="asset">The SignalAsset to be removed.</param> |
|
public void Remove(SignalAsset asset) |
|
{ |
|
if (!m_Events.signals.Contains(asset)) |
|
{ |
|
throw new ArgumentException("The SignalAsset is not registered with this receiver."); |
|
} |
|
|
|
m_Events.Remove(asset); |
|
} |
|
|
|
/// <summary> |
|
/// Gets a list of all registered SignalAssets. |
|
/// </summary> |
|
/// <returns>Returns a list of SignalAssets.</returns> |
|
public IEnumerable<SignalAsset> GetRegisteredSignals() |
|
{ |
|
return m_Events.signals; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the first UnityEvent associated with a SignalAsset. |
|
/// </summary> |
|
/// <param name="key">A SignalAsset defining the signal.</param> |
|
/// <returns>Returns the reaction associated with a SignalAsset. Returns null if the signal asset does not exist.</returns> |
|
public UnityEvent GetReaction(SignalAsset key) |
|
{ |
|
UnityEvent ret; |
|
if (m_Events.TryGetValue(key, out ret)) |
|
{ |
|
return ret; |
|
} |
|
|
|
return null; |
|
} |
|
|
|
/// <summary> |
|
/// Returns the count of registered SignalAssets. |
|
/// </summary> |
|
/// <returns></returns> |
|
public int Count() |
|
{ |
|
return m_Events.signals.Count; |
|
} |
|
|
|
/// <summary> |
|
/// Replaces the SignalAsset associated with a reaction at a specific index. |
|
/// </summary> |
|
/// <param name="idx">The index of the reaction.</param> |
|
/// <param name="newKey">The replacement SignalAsset.</param> |
|
/// <exception cref="ArgumentException">Thrown when the replacement SignalAsset is already registered to this SignalReceiver.</exception> |
|
/// <remarks>The new SignalAsset can be null.</remarks> |
|
public void ChangeSignalAtIndex(int idx, SignalAsset newKey) |
|
{ |
|
if (idx < 0 || idx > m_Events.signals.Count - 1) |
|
throw new IndexOutOfRangeException(); |
|
|
|
if (m_Events.signals[idx] == newKey) |
|
return; |
|
var alreadyUsed = m_Events.signals.Contains(newKey); |
|
if (newKey == null || m_Events.signals[idx] == null || !alreadyUsed) |
|
m_Events.signals[idx] = newKey; |
|
|
|
if (newKey != null && alreadyUsed) |
|
throw new ArgumentException("SignalAsset already used."); |
|
} |
|
|
|
/// <summary> |
|
/// Removes the SignalAsset and reaction at a specific index. |
|
/// </summary> |
|
/// <param name="idx">The index of the SignalAsset to be removed.</param> |
|
public void RemoveAtIndex(int idx) |
|
{ |
|
if (idx < 0 || idx > m_Events.signals.Count - 1) |
|
throw new IndexOutOfRangeException(); |
|
m_Events.Remove(idx); |
|
} |
|
|
|
/// <summary> |
|
/// Replaces the reaction at a specific index with a new UnityEvent. |
|
/// </summary> |
|
/// <param name="idx">The index of the reaction to be replaced.</param> |
|
/// <param name="reaction">The replacement reaction.</param> |
|
/// <exception cref="ArgumentNullException">Thrown when the replacement reaction is null.</exception> |
|
public void ChangeReactionAtIndex(int idx, UnityEvent reaction) |
|
{ |
|
if (idx < 0 || idx > m_Events.events.Count - 1) |
|
throw new IndexOutOfRangeException(); |
|
|
|
m_Events.events[idx] = reaction; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the reaction at a specific index. |
|
/// </summary> |
|
/// <param name="idx">The index of the reaction.</param> |
|
/// <returns>Returns a reaction.</returns> |
|
public UnityEvent GetReactionAtIndex(int idx) |
|
{ |
|
if (idx < 0 || idx > m_Events.events.Count - 1) |
|
throw new IndexOutOfRangeException(); |
|
return m_Events.events[idx]; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the SignalAsset at a specific index |
|
/// </summary> |
|
/// <param name="idx">The index of the SignalAsset.</param> |
|
/// <returns>Returns a SignalAsset.</returns> |
|
public SignalAsset GetSignalAssetAtIndex(int idx) |
|
{ |
|
if (idx < 0 || idx > m_Events.signals.Count - 1) |
|
throw new IndexOutOfRangeException(); |
|
return m_Events.signals[idx]; |
|
} |
|
|
|
// Required by Unity for the MonoBehaviour to have an enabled state |
|
private void OnEnable() |
|
{ |
|
} |
|
|
|
[Serializable] |
|
class EventKeyValue |
|
{ |
|
[SerializeField] |
|
List<SignalAsset> m_Signals = new List<SignalAsset>(); |
|
|
|
[SerializeField, CustomSignalEventDrawer] |
|
List<UnityEvent> m_Events = new List<UnityEvent>(); |
|
|
|
public bool TryGetValue(SignalAsset key, out UnityEvent value) |
|
{ |
|
var index = m_Signals.IndexOf(key); |
|
if (index != -1) |
|
{ |
|
value = m_Events[index]; |
|
return true; |
|
} |
|
|
|
value = null; |
|
return false; |
|
} |
|
|
|
public void Append(SignalAsset key, UnityEvent value) |
|
{ |
|
m_Signals.Add(key); |
|
m_Events.Add(value); |
|
} |
|
|
|
public void Remove(int idx) |
|
{ |
|
if (idx != -1) |
|
{ |
|
m_Signals.RemoveAt(idx); |
|
m_Events.RemoveAt(idx); |
|
} |
|
} |
|
|
|
public void Remove(SignalAsset key) |
|
{ |
|
var idx = m_Signals.IndexOf(key); |
|
if (idx != -1) |
|
{ |
|
m_Signals.RemoveAt(idx); |
|
m_Events.RemoveAt(idx); |
|
} |
|
} |
|
|
|
public List<SignalAsset> signals |
|
{ |
|
get { return m_Signals; } |
|
} |
|
|
|
public List<UnityEvent> events |
|
{ |
|
get { return m_Events; } |
|
} |
|
} |
|
} |
|
}
|
|
|