Skip to content

Instantly share code, notes, and snippets.

@grahamboree
Last active August 29, 2015 14:19
Show Gist options
  • Save grahamboree/36a815a7aeba50a2c1f2 to your computer and use it in GitHub Desktop.
Save grahamboree/36a815a7aeba50a2c1f2 to your computer and use it in GitHub Desktop.
Unity Messenger
using System;
using System.Collections.Generic;
using UnityEngine;
public enum EventType {
// Add events here.
testOne,
testTwo,
testThree
}
public enum MessengerMode {
DONT_REQUIRE_LISTENER,
REQUIRE_LISTENER,
DEFAULT = DONT_REQUIRE_LISTENER,
}
/// No parameters
public static class Messenger {
public static void AddListener(EventType eventName, Action handler) {
MessengerInternal.OnListenerAdding(eventName, handler);
MessengerInternal.eventTable[eventName] = (Action)MessengerInternal.eventTable[eventName] + handler;
}
public static void RemoveListener(EventType eventName, Action handler) {
MessengerInternal.OnListenerRemoving(eventName, handler);
MessengerInternal.eventTable[eventName] = (Action)MessengerInternal.eventTable[eventName] - handler;
MessengerInternal.OnListenerRemoved(eventName);
}
public static void Broadcast(EventType eventName, MessengerMode mode = MessengerMode.DEFAULT) {
MessengerInternal.OnBroadcasting(eventName, mode);
Delegate d;
if (MessengerInternal.eventTable.TryGetValue(eventName, out d)) {
Action callback = d as Action;
if (callback != null) {
callback();
} else {
MessengerInternal.BroadcastSignatureError(eventName);
}
}
}
}
/// One parameter
public static class Messenger<T> {
public static void AddListener(EventType eventName, Action<T> handler) {
MessengerInternal.OnListenerAdding(eventName, handler);
MessengerInternal.eventTable[eventName] = (Action<T>)MessengerInternal.eventTable[eventName] + handler;
}
public static void RemoveListener(EventType eventName, Action<T> handler) {
MessengerInternal.OnListenerRemoving(eventName, handler);
MessengerInternal.eventTable[eventName] = (Action<T>)MessengerInternal.eventTable[eventName] - handler;
MessengerInternal.OnListenerRemoved(eventName);
}
public static void Broadcast(EventType eventName, T arg1, MessengerMode mode = MessengerMode.DEFAULT) {
MessengerInternal.OnBroadcasting(eventName, mode);
Delegate d;
if (MessengerInternal.eventTable.TryGetValue(eventName, out d)) {
Action<T> callback = d as Action<T>;
if (callback != null) {
callback(arg1);
} else {
MessengerInternal.BroadcastSignatureError(eventName);
}
}
}
}
/// Two parameters
public static class Messenger<T, U> {
public static void AddListener(EventType eventName, Action<T, U> handler) {
MessengerInternal.OnListenerAdding(eventName, handler);
MessengerInternal.eventTable[eventName] = (Action<T, U>)MessengerInternal.eventTable[eventName] + handler;
}
public static void RemoveListener(EventType eventName, Action<T, U> handler) {
MessengerInternal.OnListenerRemoving(eventName, handler);
MessengerInternal.eventTable[eventName] = (Action<T, U>)MessengerInternal.eventTable[eventName] - handler;
MessengerInternal.OnListenerRemoved(eventName);
}
public static void Broadcast(EventType eventName, T arg1, U arg2, MessengerMode mode = MessengerMode.DEFAULT) {
MessengerInternal.OnBroadcasting(eventName, mode);
Delegate d;
if (MessengerInternal.eventTable.TryGetValue(eventName, out d)) {
Action<T, U> callback = d as Action<T, U>;
if (callback != null) {
callback(arg1, arg2);
} else {
MessengerInternal.BroadcastSignatureError(eventName);
}
}
}
}
/// Three parameters
public static class Messenger<T, U, V> {
public static void AddListener(EventType eventName, Action<T, U, V> handler) {
MessengerInternal.OnListenerAdding(eventName, handler);
MessengerInternal.eventTable[eventName] = (Action<T, U, V>)MessengerInternal.eventTable[eventName] + handler;
}
public static void RemoveListener(EventType eventName, Action<T, U, V> handler) {
MessengerInternal.OnListenerRemoving(eventName, handler);
MessengerInternal.eventTable[eventName] = (Action<T, U, V>)MessengerInternal.eventTable[eventName] - handler;
MessengerInternal.OnListenerRemoved(eventName);
}
public static void Broadcast(EventType eventName, T arg1, U arg2, V arg3, MessengerMode mode = MessengerMode.DEFAULT) {
MessengerInternal.OnBroadcasting(eventName, mode);
Delegate d;
if (MessengerInternal.eventTable.TryGetValue(eventName, out d)) {
Action<T, U, V> callback = d as Action<T, U, V>;
if (callback != null) {
callback(arg1, arg2, arg3);
} else {
MessengerInternal.BroadcastSignatureError(eventName);
}
}
}
}
internal static class MessengerInternal {
/// Maps event names to delegate chains.
public static Dictionary<EventType, Delegate> eventTable = new Dictionary<EventType, Delegate>();
#region Methods.
public static void OnListenerAdding(EventType eventName, Delegate callback) {
if (!eventTable.ContainsKey(eventName)) {
eventTable.Add(eventName, null);
}
Delegate d = eventTable[eventName];
if (d != null && d.GetType() != callback.GetType()) {
Debug.LogError(string.Format("Attempting to add listener with inconsistent signature for event type {0}. " +
"Current listeners have type {1} and listener being added has type {2}",
eventName,
d.GetType().Name,
callback.GetType().Name));
}
}
public static void OnListenerRemoving(EventType eventName, Delegate listenerBeingRemoved) {
if (eventTable.ContainsKey(eventName)) {
Delegate d = eventTable[eventName];
if (d == null) {
Debug.LogError(string.Format(
"Attempting to remove listener with for event type {0} but current listener is null.", eventName));
}
if (d.GetType() != listenerBeingRemoved.GetType()) {
Debug.LogError(string.Format("Attempting to remove listener with inconsistent signature for event " +
"type {0}. Current listeners have type {1} and listener being removed has type {2}",
eventName,
d.GetType().Name,
listenerBeingRemoved.GetType().Name));
}
} else {
Debug.LogError(string.Format("Attempting to remove listener for type {0} but Messenger doesn't know " +
"about this event type.", eventName));
}
}
public static void OnListenerRemoved(EventType eventName) {
if (eventTable[eventName] == null) {
eventTable.Remove(eventName);
}
}
public static void OnBroadcasting(EventType eventName, MessengerMode mode) {
if (mode == MessengerMode.REQUIRE_LISTENER && !eventTable.ContainsKey(eventName)) {
Debug.LogError(string.Format("Broadcasting message {0} but no listener found.", eventName));
}
}
public static void BroadcastSignatureError(EventType eventName) {
Debug.LogError(string.Format(
"Broadcasting message {0} but listeners have a different signature than the broadcaster.", eventName));
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment