using System; using System.Collections.Generic; using UnityEngine; namespace Unity.VisualScripting { /// /// A global container that maps Event names and Component references to actions for registered listeners. /// /// /// It is the EventMachine base class for ScriptMachine and StateMachine that triggers events. /// This overrides almost all Unity callbacks (such as Awake, OnEnable, Update, etc.) and triggers an event /// on the EventBus. /// /// /// The following example shows how to use the EventBus to send a custom event from a script to a node in /// a graph. It also shows how to use the EventBus as a global event manager by executing a callback in a /// script, not just a node. /// /// For more information on how to create custom event nodes refer to the /// User Manual. /// /// In this example we've added some code to a GameObject. This code checks for when the user presses a sequence of /// keys to enable a cheat code, then triggers the CheatCodeActivated event. We register the /// CheatCodeActivated event in the Start method. The Update method triggers the event twice /// with 2 different targets: one for the CheatCodeActivated callback and the other to trigger the /// CheatCodeEnabled Node. /// /// /// /// The CheatCodeEnabled Node: /// /// /// public static class EventBus { static EventBus() { events = new Dictionary>(new EventHookComparer()); } private static readonly Dictionary> events; internal static Dictionary> testAccessEvents => events; public static void Register(EventHook hook, Action handler) { if (!events.TryGetValue(hook, out var handlers)) { handlers = new HashSet(); events.Add(hook, handlers); } handlers.Add(handler); } public static void Unregister(EventHook hook, Delegate handler) { if (events.TryGetValue(hook, out var handlers)) { if (handlers.Remove(handler)) { // Free the key references for GC collection if (handlers.Count == 0) { events.Remove(hook); } } } } public static void Trigger(EventHook hook, TArgs args) { HashSet> handlers = null; if (events.TryGetValue(hook, out var potentialHandlers)) { foreach (var potentialHandler in potentialHandlers) { if (potentialHandler is Action handler) { if (handlers == null) { handlers = HashSetPool>.New(); } handlers.Add(handler); } } } if (handlers != null) { foreach (var handler in handlers) { if (!potentialHandlers.Contains(handler)) { continue; } handler.Invoke(args); } handlers.Free(); } } public static void Trigger(string name, GameObject target, TArgs args) { Trigger(new EventHook(name, target), args); } public static void Trigger(EventHook hook) { Trigger(hook, new EmptyEventArgs()); } public static void Trigger(string name, GameObject target) { Trigger(new EventHook(name, target)); } } }