// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus). // It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE) using UnityEngine; using System.Collections.Generic; using System; namespace Fungus { /// <summary> /// A simple efficient event dispatcher with logging support. /// </summary> public class EventDispatcher : MonoBehaviour { protected readonly Dictionary<Type, List<Delegate>> delegates = new Dictionary<Type, List<Delegate>>(); protected virtual event Action<string> onLog; /// <summary> /// Gets the delegate list copy. /// </summary> /// <remarks> /// As listener can modify the list while iterating it, it is better to iterate a copy of the delegates list instead of a reference. /// </remarks> /// <returns>A copy of the delegates list if found. Null if the dictionary does not contain a delegate list for this event.</returns> /// <param name="evt">Event instance.</param> /// <typeparam name="T">Type of the received event.</typeparam> protected virtual List<Delegate> GetDelegateListCopy<T>(T evt) { var type = typeof(T); return delegates.ContainsKey(type) ? new List<Delegate>(delegates[type]) : null; } protected virtual void Log(string message) { if(onLog != null) { onLog(message); } } #region Public members /// <summary> /// A typed delegate which contains information about the event. /// </summary> public delegate void TypedDelegate<T>(T e) where T : class; /// <summary> /// Adds a log callback action. /// </summary> public virtual void AddLog(Action<string> log) { onLog += log; } /// <summary> /// Removes a log callback action. /// </summary> public virtual void RemoveLog(Action<string> log) { onLog -= log; } /// <summary> /// Adds a listener for a specified event type. /// </summary> public virtual void AddListener<T>(TypedDelegate<T> listener) where T : class { var type = typeof(T); if(!delegates.ContainsKey(type)) { delegates.Add(type, new List<Delegate>()); } var list = delegates[type]; if(!list.Contains(listener)) { list.Add(listener); } } /// <summary> /// Removes a listener for a specified event type. /// </summary> public virtual void RemoveListener<T>(TypedDelegate<T> listener) where T : class { var type = typeof(T); if(delegates.ContainsKey(type)) { delegates[type].Remove(listener); return; } } /// <summary> /// Raise an event of a specified type. /// </summary> public virtual void Raise<T>(T evt) where T : class { if(evt == null) { Log("Raised a null event"); return; } var list = GetDelegateListCopy(evt); if(list == null || list.Count < 1) { Log("Raised an event with no listeners"); return; } for(int i = 0; i < list.Count; ++i) { var callback = list[i] as TypedDelegate<T>; if(callback != null) { try { callback(evt); } catch(Exception gotcha) { Log(gotcha.Message); } } } } /// <summary> /// Raise an event of a specified type, creates an instance of the type automatically. /// </summary> public virtual void Raise<T>() where T : class, new() { Raise<T>(new T()); } /// <summary> /// Unregisters all event listeners. /// </summary> public virtual void UnregisterAll() { delegates.Clear(); } #endregion } }