GameObjectExtensions.cs

Extension methods on GameObject for sending reactive events. Implements SendDirect to dispatch to the object's event handler, SendUp to dispatch up the parent chain stopping on handler request, and SendDown to dispatch to the object then recursively to children.

#if SANDBOX
using Sandbox.Reactivity.Internals;
#if JETBRAINS_ANNOTATIONS
#endif

namespace Sandbox.Reactivity;

#if JETBRAINS_ANNOTATIONS
#endif
public static class GameObjectExtensions
{
	extension(GameObject go)
	{
		/// <summary>
		/// Sends an event to this game object.
		/// </summary>
		/// <param name="eventData">The event to send.</param>
		/// <typeparam name="T">
		/// The type of event to send. Any registered event functions that accept an event that is assignable to this
		/// type will also be called.
		/// </typeparam>
		public void SendDirect<T>(T eventData)
		{
			if (GameObjectEventManager.Get(go) is not { } handler)
			{
				return;
			}

			handler.Dispatch(eventData);
		}

		/// <summary>
		/// Sends an event to this game object and all of its ancestors.
		/// </summary>
		/// <param name="eventData">The event to send.</param>
		/// <typeparam name="T">
		/// The type of event to send. Any registered event functions that accept an event that is assignable to this
		/// type will also be called.
		/// </typeparam>
		/// <remarks>
		/// An event function can stop propagation of this event to its ancestors.
		/// </remarks>
		public void SendUp<T>(T eventData)
		{
			var next = go;

			while (next != null)
			{
				if (GameObjectEventManager.Get(next) is { } handler)
				{
					if (handler.Dispatch(eventData))
					{
						return;
					}
				}

				next = next.Parent;
			}
		}

		/// <summary>
		/// Sends an event to this game object and all of its descendants.
		/// </summary>
		/// <param name="eventData">The event to send.</param>
		/// <typeparam name="T">
		/// The type of event to send. Any registered event functions that accept an event that is assignable to this
		/// type will also be called.
		/// </typeparam>
		/// <remarks>
		/// An event function can stop propagation of this event to its own descendants.
		/// </remarks>
		public void SendDown<T>(T eventData)
		{
			if (GameObjectEventManager.Get(go) is { } handler)
			{
				if (handler.Dispatch(eventData))
				{
					return;
				}
			}

			foreach (var child in go.Children)
			{
				child.SendDown(eventData);
			}
		}
	}
}
#endif