/// <summary> /// attempts to trigger the pre-registered method or delegate associated /// with 'eventName' and the target object. if 'options' is set to /// 'TargetEventOptions.RequireReceiver' there will be an error if /// no such callback can be found. /// </summary> public static void Send(object target, string eventName, TargetEventOptions options = TargetEventOptions.DontRequireReceiver) { retry : Delegate callback = TargetEventHandler.GetCallback(target, eventName, false, 0, options); if (callback == null) { TargetEventHandler.OnNoReceiver(eventName, options); return; } // NOTE: if the below 'try' fails, it is likely because we have an event // with the same name and amount of arguments + return value as another // event, in which case the dictionary happily returned an event with an // incompatible parameter signature = BOOM. we catch this and try again // with an underscore appended to the event name. if 'Register' has added // a matching event with underscores in the name we'll find it sooner or // later. if not, 'callback' will end up null and we'll return gracefully // on the above null check (which is also what will happen if the invocation // crashes for any other reason). try { ((Action)callback).Invoke(); } catch { eventName += "_"; goto retry; } }
/// <summary> /// dumps an error to the console if 'options' is set to 'RequireReceiver' /// </summary> public static void OnNoReceiver(string eventName, TargetEventOptions options) { if (!((options & TargetEventOptions.RequireReceiver) == TargetEventOptions.RequireReceiver)) { return; } Log.Error(") TargetEvent '" + eventName + "'has no receiver!"); }
/// <summary> /// This method will send an event to an object of type 'UnityEngine.Component', /// then onward to its transform and all ancestor transforms recursively until /// a callback registered under 'eventName' is found in any of the objects. NOTES: /// 1) only the first matching callback detected will execute. The event will fail /// if the scan reaches the scene root with no match found. 2) it is best to register /// _transforms_ and not other types of component for use with 'SendUpwards', since /// components will be ignored unless the event is sent specifically to the correct /// component. /// </summary> public static void SendUpwards(Component target, string eventName, TargetEventOptions options = TargetEventOptions.DontRequireReceiver) { retry : Delegate callback = TargetEventHandler.GetCallback(target, eventName, true, 0, options); if (callback == null) { TargetEventHandler.OnNoReceiver(eventName, options); return; } try { ((Action)callback).Invoke(); } catch { eventName += "_"; goto retry; } }
/// <summary> /// NOTE: this is an internal method. to register target events, /// instead use 'TargetEvent.Register' or 'TargetEventReturn.Register'. /// (this method looks for an event name registered to the target object and /// - if found - returns the delegate.) /// </summary> public static Delegate GetCallback(object target, string eventName, bool upwards, int d, TargetEventOptions options) { #if UNITY_EDITOR if (string.IsNullOrEmpty(eventName)) { Log.Warning(") TargetEvent.Send : Name is null or empty."); return(null); } #endif if (target == null) { return(null); } if (string.IsNullOrEmpty(eventName)) { return(null); } retry: Delegate callback = null; if (!((options & TargetEventOptions.IncludeInactive) == TargetEventOptions.IncludeInactive)) { GameObject gameObject = target as GameObject; if (gameObject != null) { if (!Utility.IsActive(gameObject)) { if (upwards) { goto recursive; } return(null); } } else { Behaviour component = target as Behaviour; if (component != null) { if (!component.enabled || !Utility.IsActive(component.gameObject)) { if (upwards) { goto recursive; } return(null); } } } } // get list of callbacks for this object Dictionary <string, Delegate> callbacks = null; if (!TargetDict[d].TryGetValue(target, out callbacks)) { if (upwards) { goto recursive; } return(null); } // get specific callback from list of callbacks if (!callbacks.TryGetValue(eventName, out callback)) { if (upwards) { goto recursive; } return(null); } recursive: // if we are sending a message upwards, scan upwards recursively if ((callback == null) && upwards) { // try to find a transform or parent transform target = Utility.GetParent(target as Component); // couldn't find a new target: our work here is done if (target == null) { goto done; } // found a new target: retry! goto retry; } done: return(callback); }