| 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"/> | |
| [] | |
| public class SignalReceiver : MonoBehaviour, INotificationReceiver | |
| { | |
| [] | |
| 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() | |
| { | |
| } | |
| [] | |
| class EventKeyValue | |
| { | |
| [] | |
| List<SignalAsset> m_Signals = new List<SignalAsset>(); | |
| [] | |
| 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; } | |
| } | |
| } | |
| } | |
| } | |