/// <summary> /// dumps an error to the console if 'options' is set to 'RequireReceiver' /// </summary> public static void OnNoReceiver(string eventName, vp_TargetEventOptions options) { if (!((options & vp_TargetEventOptions.RequireReceiver) == vp_TargetEventOptions.RequireReceiver)) { return; } Debug.LogError("Error: (" + Utility.GetErrorLocation(2) + ") vp_TargetEvent '" + eventName + "' has no receiver!"); }
/// <summary> /// attempts to trigger the pre-registered method or delegate associated /// with 'eventName' and the target object. if the callback successfully /// executes, it will return a value matching its generic signature. if /// 'options' is set to 'vp_TargetEventOptions.RequireReceiver' there /// will be an error if no such callback can be found. /// example signature: 'vp_TargetEventReturn<bool>.Send' (where the /// type represents the return value). /// </summary> public static R Send(object target, string eventName, vp_TargetEventOptions options = vp_TargetEventOptions.DontRequireReceiver) { retry: Delegate callback = vp_TargetEventHandler.GetCallback(target, eventName, false, 4, options); if (callback == null) { vp_TargetEventHandler.OnNoReceiver(eventName, options); return(default(R)); } try { return(((Func <R>)callback).Invoke()); } catch { eventName += "_"; goto retry; } }
/// <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, vp_TargetEventOptions options = vp_TargetEventOptions.DontRequireReceiver) { retry: Delegate callback = vp_TargetEventHandler.GetCallback(target, eventName, true, 0, options); if (callback == null) { vp_TargetEventHandler.OnNoReceiver(eventName, options); return; } try { ((Action)callback).Invoke(); } catch { eventName += "_"; goto retry; } }
/// <summary> /// attempts to trigger the pre-registered method or delegate associated /// with 'eventName' and the target object. if 'options' is set to /// 'vp_TargetEventOptions.RequireReceiver' there will be an error if /// no such callback can be found. /// </summary> public static void Send(object target, string eventName, vp_TargetEventOptions options = vp_TargetEventOptions.DontRequireReceiver) { retry: Delegate callback = vp_TargetEventHandler.GetCallback(target, eventName, false, 0, options); if (callback == null) { vp_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> /// NOTE: this is an internal method. to register target events, /// instead use 'vp_TargetEvent.Register' or 'vp_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, vp_TargetEventOptions options) { #if UNITY_EDITOR if (string.IsNullOrEmpty(eventName)) { Debug.LogError("Error: (" + Utility.GetErrorLocation(2) + ") vp_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 & vp_TargetEventOptions.IncludeInactive) == vp_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); }