/// <summary> /// Подписывает элемент графического интерфейса на получение событий, которые для него доступны. /// /// Например, у стандартного грфического элемента Toggle есть событие onValueChanged, которое принимает делегат UnityAction<bool> /// Пусть у источника данных есть свойство MyToggle, которое связано с соответствующим GuiToggleBind. Тогда подписка на событие может выглядеть так: /// AddEventListener("MyToggle", "onValueChanged", (proxydata, args) => Debug.Log("MyToggle changed: " + (bool)args[0])); /// </summary> public GuiEventData AddEventListener(string bindName, string eventName, UniversalGuiEventDelegate callback) { GuiEventData guiEventData = null; IGuiBindable bindableData = _bindableGuiComponents.SingleOrDefault(data => data.GetBindName() == bindName); if (bindableData != null) { object unityEvent = bindableData.GetGuiComponent() .GetType() .GetProperyOrFieldValue(bindableData.GetGuiComponent(), eventName); if (unityEvent != null) { Type unityEventType = unityEvent.GetType(); UnityActionProxy proxyHandler = UnityActionProxy.Create(unityEventType, callback); guiEventData = new GuiEventData(bindName, eventName, bindableData, proxyHandler); RegisteredEvents.Add(guiEventData); unityEventType.GetMethod("AddListener") .Invoke(unityEvent, new object[] { proxyHandler.UnityActionDelegate }); } } return(guiEventData); }
/// <param name="unityEventType">Любой тип UnityEvent или производный от UnityEvent</param> /// <param name="universalGuiEventHandler">Универсальный делегат для событий</param> public static UnityActionProxy Create(Type unityEventType, UniversalGuiEventDelegate universalGuiEventHandler) { // список параметров делегата, который принимает AddListener ParameterInfo[] callbackParameters = unityEventType.GetMethod("AddListener").GetParameters()[0] .ParameterType.GetMethod("Invoke").GetParameters(); // список типов параметров делегата Type[] parametersTypes = (from arg in callbackParameters select arg.ParameterType).ToArray(); UnityActionProxy proxyHandler = new UnityActionProxy { UniversalGuiEventHandler = universalGuiEventHandler }; // Далее необходимо собрать делегат для конвертирования параметров ParameterExpression[] args = new ParameterExpression[parametersTypes.Length]; // аргументы, соответствующие аргументам UnityAction<> Expression[] convertedArgs = new Expression[parametersTypes.Length]; // конвертированные аргументы в object for (int i = 0; i < args.Length; i++) { args[i] = Expression.Parameter(parametersTypes[i], "arg" + i); convertedArgs[i] = Expression.Convert(args[i], typeof(object)); } Expression[] handlerEventArgs = new Expression[2]; // список параметров для передачи в универсальный делегат handlerEventArgs[0] = Expression.Constant(proxyHandler.Data); handlerEventArgs[1] = Expression.NewArrayInit(typeof(object), convertedArgs); Expression callHandlerExpression; if (universalGuiEventHandler.Target != null) { callHandlerExpression = Expression.Call(Expression.Constant(universalGuiEventHandler.Target), universalGuiEventHandler.Method, handlerEventArgs); } else { callHandlerExpression = Expression.Call(universalGuiEventHandler.Method, handlerEventArgs); } // делегат, который принимает параметры нужных типов, конвертирует их в object и вызывает универсальный делегат Delegate typesConverter = Expression.Lambda(callHandlerExpression, args).Compile(); // конструирование делегата UnityAction<> с телом typesConverter Type unityEventDelegateType = parametersTypes.Length > 0 ? typeof(UnityAction <>).MakeGenericType(parametersTypes) : typeof(UnityAction); proxyHandler.UnityActionDelegate = Delegate.CreateDelegate(unityEventDelegateType, typesConverter.Target, typesConverter.Method); return(proxyHandler); }
public void AddEventListener(string bindName, string eventName, UniversalGuiEventDelegate callback) { _registeredEvents.Add(new EventData(bindName, eventName, callback)); int i = 0; foreach (var guiComponent in this) { GuiComponent.GuiEventData guiEventData = guiComponent.AddEventListener(bindName, eventName, callback); if (guiEventData == null) throw new Exception("eventName or bindName not found"); // TODO custom type exception guiEventData.UnityActionProxy.Data.Index = i++; } }
public void RemoveEventListener(string bindName, string eventName, UniversalGuiEventDelegate callback, bool throwIfEventNotRegistered = false) { EventData ev = _registeredEvents.SingleOrDefault( data => data.BindName == bindName && data.EventName == eventName && data.Callback == callback); if (ev != null) { foreach (var guiComponent in this) guiComponent.RemoveEventListener(bindName, eventName, callback, throwIfEventNotRegistered); _registeredEvents.Remove(ev); } else if (throwIfEventNotRegistered) throw new Exception("Event " + eventName + " isn\'t registered for collection"); // TODO custom type exception }
public void RemoveEventListener(string bindName, string eventName, UniversalGuiEventDelegate callback, bool throwIfEventNotRegistered = false) { var ev = _registeredEvents.SingleOrDefault( data => data.BindName == bindName && data.EventName == eventName && data.UnityActionProxy.UniversalGuiEventHandler == callback); if (ev != null) { CallRemoveListenerOnUnityEvent(ev); _registeredEvents.Remove(ev); } else if (throwIfEventNotRegistered) { throw new Exception("Event " + eventName + " not registered"); // TODO custom type exception } }
public EventData(string bindName, string eventName, UniversalGuiEventDelegate callback) { BindName = bindName; EventName = eventName; Callback = callback; }
public void RemoveEventListener(string bindName, string eventName, UniversalGuiEventDelegate callback, bool throwIfEventNotRegistered = false) { _bindableGuiElementCollection.RemoveEventListener(bindName, eventName, callback, throwIfEventNotRegistered); }
public void AddEventListener(string bindName, string eventName, UniversalGuiEventDelegate callback) { _bindableGuiElementCollection.AddEventListener(bindName, eventName, callback); }