//#define EVENTROUTER_THROWEXCEPTIONS #if EVENTROUTER_THROWEXCEPTIONS //#define EVENTROUTER_REQUIRELISTENER // Uncomment this if you want listeners to be required for sending events. #endif using System; using UnityEngine; using UnityEngine.Events; using System.Collections; using System.Collections.Generic; using UnityEngine.Audio; namespace MoreMountains.Tools { /// /// MMGameEvents are used throughout the game for general game events (game started, game ended, life lost, etc.) /// public struct MMGameEvent { public string EventName; public MMGameEvent(string newName) { EventName = newName; } static MMGameEvent e; public static void Trigger(string newName) { e.EventName = newName; MMEventManager.TriggerEvent(e); } } /// /// This class handles event management, and can be used to broadcast events throughout the game, to tell one class (or many) that something's happened. /// Events are structs, you can define any kind of events you want. This manager comes with MMGameEvents, which are /// basically just made of a string, but you can work with more complex ones if you want. /// /// To trigger a new event, from anywhere, do YOUR_EVENT.Trigger(YOUR_PARAMETERS) /// So MMGameEvent.Trigger("Save"); for example will trigger a Save MMGameEvent /// /// you can also call MMEventManager.TriggerEvent(YOUR_EVENT); /// For example : MMEventManager.TriggerEvent(new MMGameEvent("GameStart")); will broadcast an MMGameEvent named GameStart to all listeners. /// /// To start listening to an event from any class, there are 3 things you must do : /// /// 1 - tell that your class implements the MMEventListener interface for that kind of event. /// For example: public class GUIManager : Singleton, MMEventListener /// You can have more than one of these (one per event type). /// /// 2 - On Enable and Disable, respectively start and stop listening to the event : /// void OnEnable() /// { /// this.MMEventStartListening(); /// } /// void OnDisable() /// { /// this.MMEventStopListening(); /// } /// /// 3 - Implement the MMEventListener interface for that event. For example : /// public void OnMMEvent(MMGameEvent gameEvent) /// { /// if (gameEvent.EventName == "GameOver") /// { /// // DO SOMETHING /// } /// } /// will catch all events of type MMGameEvent emitted from anywhere in the game, and do something if it's named GameOver /// [ExecuteAlways] public static class MMEventManager { private static Dictionary> _subscribersList; static MMEventManager() { _subscribersList = new Dictionary>(); } /// /// Adds a new subscriber to a certain event. /// /// listener. /// The event type. public static void AddListener( MMEventListener listener ) where MMEvent : struct { Type eventType = typeof( MMEvent ); if( !_subscribersList.ContainsKey( eventType ) ) _subscribersList[eventType] = new List(); if( !SubscriptionExists( eventType, listener ) ) _subscribersList[eventType].Add( listener ); } /// /// Removes a subscriber from a certain event. /// /// listener. /// The event type. public static void RemoveListener( MMEventListener listener ) where MMEvent : struct { Type eventType = typeof( MMEvent ); if( !_subscribersList.ContainsKey( eventType ) ) { #if EVENTROUTER_THROWEXCEPTIONS throw new ArgumentException( string.Format( "Removing listener \"{0}\", but the event type \"{1}\" isn't registered.", listener, eventType.ToString() ) ); #else return; #endif } List subscriberList = _subscribersList[eventType]; #if EVENTROUTER_THROWEXCEPTIONS bool listenerFound = false; #endif for (int i = 0; i /// Triggers an event. All instances that are subscribed to it will receive it (and will potentially act on it). /// /// The event to trigger. /// The 1st type parameter. public static void TriggerEvent( MMEvent newEvent ) where MMEvent : struct { List list; if( !_subscribersList.TryGetValue( typeof( MMEvent ), out list ) ) #if EVENTROUTER_REQUIRELISTENER throw new ArgumentException( string.Format( "Attempting to send event of type \"{0}\", but no listener for this type has been found. Make sure this.Subscribe<{0}>(EventRouter) has been called, or that all listeners to this event haven't been unsubscribed.", typeof( MMEvent ).ToString() ) ); #else return; #endif for (int i=0; i ).OnMMEvent( newEvent ); } } /// /// Checks if there are subscribers for a certain type of events /// /// true, if exists was subscriptioned, false otherwise. /// Type. /// Receiver. private static bool SubscriptionExists( Type type, MMEventListenerBase receiver ) { List receivers; if( !_subscribersList.TryGetValue( type, out receivers ) ) return false; bool exists = false; for (int i=0; i /// Static class that allows any class to start or stop listening to events /// public static class EventRegister { public delegate void Delegate( T eventType ); public static void MMEventStartListening( this MMEventListener caller ) where EventType : struct { MMEventManager.AddListener( caller ); } public static void MMEventStopListening( this MMEventListener caller ) where EventType : struct { MMEventManager.RemoveListener( caller ); } } /// /// Event listener basic interface /// public interface MMEventListenerBase { }; /// /// A public interface you'll need to implement for each type of event you want to listen to. /// public interface MMEventListener : MMEventListenerBase { void OnMMEvent( T eventType ); } }