コード例 #1
0
        /// <summary>
        /// Подписывает элемент графического интерфейса на получение событий, которые для него доступны.
        ///
        /// Например, у стандартного грфического элемента Toggle есть событие onValueChanged, которое принимает делегат UnityAction&lt;bool&gt;
        /// Пусть у источника данных есть свойство 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);
        }
コード例 #2
0
 public GuiEventData(string bindName, string eventName, IGuiBindable guiBindableData, UnityActionProxy unityActionProxy)
 {
     BindName         = bindName;
     EventName        = eventName;
     GuiBindableData  = guiBindableData;
     UnityActionProxy = unityActionProxy;
 }
コード例 #3
0
        /// <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);
        }