public MessageWrapper(MessageWrapper inBase, MessengerImpl inTarget) { Target = inTarget; Message = inBase.Message; Metadata = inBase.Metadata; m_RequeuesLeft = inBase.m_RequeuesLeft; m_ID = s_GlobalID++; }
public Manager() { s_Instance = this; m_MessengerRegistry = new Dictionary <int, MessengerImpl>(); m_MessageQueue = new List <MessageWrapper>(); Root = new MessengerImpl(this); #if DEVELOPMENT DebugMode = true; #endif }
public DelegateBlock(MessengerImpl inOwner, Manager inManager, MsgType inType) { m_Manager = inManager; m_Owner = inOwner; m_DebugMode = inManager.DebugMode; m_Metadata = inManager.Database.Find(inType); m_AllowedArgType = m_Metadata.ArgType; if (m_AllowedArgType != null) { m_AllowedArgTypePtr = m_AllowedArgType.TypeHandle.Value; } }
/// <summary> /// Sends a message to the messenger on the given GameObject. /// </summary> public void Send(GameObject inTarget, Message inMessage) { if (m_Manager.DebugMode) { if (m_Destroyed) { throw new InvalidOperationException("Messenger has already been destroyed"); } if (!inMessage.Type) { throw new ArgumentException("Provided MsgType is null."); } if (inTarget == null) { throw new ArgumentNullException(); } } MessengerImpl messenger = m_Manager.Find(inTarget); if (messenger == null) { if (m_Manager.DebugMode) { if (m_Manager.Database.Find(inMessage.Type).HasFlags(MsgFlags.RequireHandler)) { throw new Exception("MsgType " + inMessage.Type.ToString() + " requires a handler"); } } return; } MessageWrapper wrapper = new MessageWrapper(messenger, inMessage); if (m_Manager.DebugMode) { if (wrapper.Metadata.CanLog(LogFlags.Dispatch)) { m_Manager.Log(Owner.name + " sending message " + inMessage.ToString() + " to " + inTarget.name); } } if ((wrapper.Metadata.Dispatch & MsgDispatch.Immediate) != 0) { messenger.TryDispatch(ref wrapper); } else { m_Manager.QueueMessage(ref wrapper); } }
public void Invoke(ref MessageWrapper inMessage) { if (m_Handlers != null) { m_Handlers(inMessage.Message); } if (m_Actions != null) { m_Actions(); } if (m_Typed != null) { m_Typed.Invoke(ref inMessage); } if (m_Children != null) { int prevDispatchChildren = ++m_DispatchChildrenDepthAndVersion; int childLength = m_Children.Count; for (int i = 0; i < childLength; ++i) { MessengerImpl impl = m_Children[i]; if (impl != null) { impl.TryDispatch(ref inMessage); } } --m_DispatchChildrenDepthAndVersion; // Call earliest in the stack will have prevDispatchChildren set to 1. // If this is the earliest call and it's not the expected value of 0 by this point, // that means the list has changed and we should clean up the null children if (prevDispatchChildren == 1 && m_DispatchChildrenDepthAndVersion != 0) { for (int i = m_Children.Count - 1; i >= 0; --i) { if (m_Children[i] == null) { m_Children.RemoveAt(i); } } m_DispatchChildrenDepthAndVersion = 0; } } }
/// <summary> /// Finds or creates a messenger for the given GameObject. /// </summary> public MessengerImpl Require(GameObject inGameObject) { if (!m_Initialized) { Initialize(); } MessengerImpl m = Find(inGameObject); if (m == null) { m = new MessengerImpl(this, inGameObject); } return(m); }
public void Dispose() { m_Owner = null; m_Manager = null; m_DebugMode = false; m_Metadata = null; m_AllowedArgType = null; m_Handlers = null; m_Actions = null; if (m_Typed != null) { m_Typed.Dispose(); m_Typed = null; } }
/// <summary> /// Broadcasts a message from the root messenger. /// </summary> public void Broadcast(Message inMessage) { if (m_Parent == null) { Send(this, inMessage); return; } if (m_Manager.DebugMode) { if (m_Destroyed) { throw new InvalidOperationException("Messenger has already been destroyed"); } if (!inMessage.Type) { throw new ArgumentException("Provided MsgType is null."); } } MessengerImpl root = m_Parent; while (root.m_Parent != null) { root = root.m_Parent; } MessageWrapper wrapper = new MessageWrapper(root, inMessage); if (m_Manager.DebugMode) { if (wrapper.Metadata.CanLog(LogFlags.Dispatch)) { m_Manager.Log(Owner.name + " broadcasting message " + inMessage.ToString()); } } if ((wrapper.Metadata.Dispatch & MsgDispatch.Immediate) != 0) { root.TryDispatch(ref wrapper); } else { m_Manager.QueueMessage(ref wrapper); } }
// Validates that the graph has no loops private void ValidateGraph(MessengerImpl inNewParent) { HashSet <MessengerImpl> visited = new HashSet <MessengerImpl>(); visited.Add(this); MessengerImpl current = inNewParent; while (current != null) { if (visited.Contains(current)) { throw new Exception("Invalid or looping Messenger graph, starting with " + (ReferenceEquals(m_GameObject, null) ? "[Root]" : m_GameObject.name)); } visited.Add(current); current = current.m_Parent; } }
public MessageWrapper(MessengerImpl inTarget, Message inMessage) { Target = inTarget; Message = inMessage; Manager manager = Manager.Get(); Metadata = manager.Database.Find(inMessage.Type); // Argument validation if (manager.DebugMode) { Metadata.Validate(inMessage); } m_RequeuesLeft = Metadata.RequeueLimit; m_ID = s_GlobalID++; }
/// <summary> /// Registers a handler for the given MsgType. /// </summary> public void Register(MsgType inType, MessengerImpl inHandler) { ValidateRegisterArgs(inType, inHandler); DelegateBlock handler; if (m_Handlers.TryGetValue(inType, out handler)) { handler.Register(inHandler); } else { handler = m_Handlers[inType] = new DelegateBlock(this, m_Manager, inType); handler.Register(inHandler); if (m_Parent != null) { m_Parent.Register(inType, this); } } }
/// <summary> /// Deregisters a handler for the given MsgType. /// </summary> public void Deregister(MsgType inType, MessengerImpl inHandler) { ValidateRegisterArgs(inType, inHandler); DelegateBlock handler; if (m_Handlers.TryGetValue(inType, out handler)) { handler.Deregister(inHandler); if (handler.IsEmpty()) { handler.Dispose(); m_Handlers.Remove(inType); if (m_Parent != null) { m_Parent.Deregister(inType, this); } } } }
public void Deregister(MessengerImpl inHandler) { if (m_Children != null) { if (m_DispatchChildrenDepthAndVersion > 0) { int index = m_Children.IndexOf(inHandler); if (index >= 0) { m_Children[index] = null; } // Incrementing this means that we've changed the list ++m_DispatchChildrenDepthAndVersion; } else { m_Children.Remove(inHandler); } } }
/// <summary> /// Sends a message to the given messenger. /// </summary> public void Send(MessengerImpl inTarget, Message inMessage) { if (m_Manager.DebugMode) { if (m_Destroyed) { throw new InvalidOperationException("Messenger has already been destroyed"); } if (!inMessage.Type) { throw new ArgumentException("Provided MsgType is null."); } if (inTarget == null) { throw new ArgumentNullException(); } } MessageWrapper wrapper = new MessageWrapper(inTarget, inMessage); if (m_Manager.DebugMode) { if (wrapper.Metadata.CanLog(LogFlags.Dispatch)) { m_Manager.Log(Owner.name + " sending message " + inMessage.ToString() + " to " + inTarget.Owner.name); } } if ((wrapper.Metadata.Dispatch & MsgDispatch.Immediate) != 0) { inTarget.TryDispatch(ref wrapper); } else { m_Manager.QueueMessage(ref wrapper); } }
/// <summary> /// Destroys the messenger. /// </summary> public void Destroy(bool inbRemove = true) { if (m_Destroyed) { return; } m_Destroyed = true; if (m_Parent != null) { foreach (MsgType type in m_Handlers.Keys) { m_Parent.Deregister(type, this); } m_Parent.m_Children.Remove(this); m_Parent = null; } foreach (var handler in m_Handlers.Values) { handler.Dispose(); } m_Handlers.Clear(); if (inbRemove) { m_Manager.DeregisterMessenger(this); } for (int i = m_Children.Count - 1; i >= 0; --i) { m_Children[i].OnParentDestroyed(); } m_Children.Clear(); }
/// <summary> /// Constructs the root messenger. /// </summary> public MessengerImpl(Manager inManager) { m_Manager = inManager; m_Handlers = new Dictionary <MsgType, DelegateBlock>(64); m_Parent = null; // We can expect the root to have many children, // so we should pre-allocate a larger list to avoid // expanding at runtime m_Children = new List <MessengerImpl>(256); m_ID = 0; m_IsRoot = true; m_Destroyed = false; m_GameObject = null; m_UnityComponent = null; m_UnityActive = true; Interface = new Messenger(this); m_Manager.RegisterMessenger(this); }
public void Initialize(MessengerImpl inMessenger) { Messenger = inMessenger; }
/// <summary> /// Requeues a message to be executed at the end of the frame. /// </summary> public void RequeueMessage(ref MessageWrapper inWrapper, MessengerImpl inTarget) { m_MessageQueue.Add(new MessageWrapper(inWrapper, inTarget)); }
/// <summary> /// Removes a messenger from the registry. /// </summary> public void DeregisterMessenger(MessengerImpl inImpl) { m_MessengerRegistry.Remove(inImpl.ID); }
/// <summary> /// Registers a messenger to the registry. /// </summary> public void RegisterMessenger(MessengerImpl inImpl) { m_MessengerRegistry[inImpl.ID] = inImpl; }
private void OnParentDestroyed() { m_Parent = null; }