/// <summary>
        /// Show dropdown for selecting a UnityEvent to bind to.
        /// </summary>
        protected void ShowEventMenu(
            AbstractMemberBinding targetScript,
            BindableEvent[] events,
            Action <string> propertyValueSetter,
            string curPropertyValue
            )
        {
            var eventNames = events
                             .Select(evt => evt.ComponentType.Name + "." + evt.Name)
                             .ToArray();
            var selectedIndex = Array.IndexOf(eventNames, curPropertyValue);
            var content       = events
                                .Select(evt => new GUIContent(evt.ComponentType.Name + "." + evt.Name))
                                .ToArray();

            var newSelectedIndex = EditorGUILayout.Popup(
                new GUIContent("View event", "Event on the view to bind to."),
                selectedIndex,
                content
                );

            if (newSelectedIndex != selectedIndex)
            {
                var selectedEvent = events[newSelectedIndex];
                UpdateProperty(
                    propertyValueSetter,
                    curPropertyValue,
                    selectedEvent.ComponentType.Name + "." + selectedEvent.Name
                    );
            }
        }
Beispiel #2
0
        /// <summary>
        /// Display a popup menu for selecting a property from a view-model.
        /// </summary>
        protected void ShowViewModelPropertyMenu(
            string label,
            AbstractMemberBinding target,
            PropertyInfo[] bindableProperties,
            Action <string> propertyValueSetter,
            string curPropertyValue,
            Func <PropertyInfo, bool> menuEnabled
            )
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel(label);

            var dropdownPosition = GUILayoutUtility.GetLastRect();

            dropdownPosition.x += dropdownPosition.width;

            if (GUILayout.Button(new GUIContent(curPropertyValue), EditorStyles.popup))
            {
                InspectorUtils.ShowMenu <PropertyInfo>(
                    property => property.ReflectedType + "/" + property.Name + " : " + property.PropertyType.Name,
                    menuEnabled,
                    property => property.ReflectedType.Name + "." + property.Name == curPropertyValue,
                    property => UpdateProperty(
                        propertyValueSetter,
                        curPropertyValue,
                        property.ReflectedType.Name + "." + property.Name
                        ),
                    bindableProperties,
                    dropdownPosition
                    );
            }

            EditorGUILayout.EndHorizontal();
        }
 /// <summary>
 /// Find bindable properties in available view models.
 /// </summary>
 public static PropertyInfo[] FindBindableProperties(AbstractMemberBinding target)
 {
     return(FindAvailableViewModelTypes(target)
            .SelectMany(type => type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            .Where(property => property
                   .GetCustomAttributes(false)
                   .Any(attribute => attribute is BindingAttribute) // Filter out properties that don't have [Binding].
                   )
            .ToArray());
 }
        /// <summary>
        /// Scan up the hierarchy and find all the types that can be bound to
        /// a specified MemberBinding.
        /// </summary>
        private static IEnumerable <Type> FindAvailableViewModelTypes(AbstractMemberBinding memberBinding)
        {
            var foundAtLeastOneBinding = false;

            var trans = memberBinding.transform;

            while (trans != null)
            {
                var components = trans.GetComponents <MonoBehaviour>();
                foreach (var component in components)
                {
                    // Can't bind to self or null
                    if (component == null || component == memberBinding)
                    {
                        continue;
                    }

                    // Case where a ViewModelBinding is used to bind a non-MonoBehaviour class.
                    var viewModelBinding = component as IViewModelProvider;
                    if (viewModelBinding != null)
                    {
                        var viewModelTypeName = viewModelBinding.GetViewModelTypeName();
                        // Ignore view model bindings that haven't been set up yet.
                        if (string.IsNullOrEmpty(viewModelTypeName))
                        {
                            continue;
                        }

                        foundAtLeastOneBinding = true;

                        yield return(GetViewModelType(viewModelBinding.GetViewModelTypeName()));
                    }
                    else if (component.GetType().GetCustomAttributes(typeof(BindingAttribute), false).Any())
                    {
                        // Case where we are binding to an existing MonoBehaviour.
                        foundAtLeastOneBinding = true;

                        yield return(component.GetType());
                    }
                }

                trans = trans.parent;
            }

            if (!foundAtLeastOneBinding)
            {
                Debug.LogError("UI binding " + memberBinding.gameObject.name + " must be placed underneath at least one bindable component.", memberBinding);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Scan up the hierarchy and find all the types that can be bound to
        /// a specified MemberBinding.
        /// </summary>
        public static IEnumerable <Type> GetAvailableViewModelTypes(this AbstractMemberBinding memberBinding)
        {
            bool foundAtLeastOneBinding = false;

            var trans = memberBinding.transform;

            while (trans != null)
            {
                var viewModels = trans.GetComponents <MonoBehaviour>();
                foreach (var viewModel in viewModels)
                {
                    // Can't bind to self
                    if (viewModel == memberBinding)
                    {
                        continue;
                    }

                    // Case where a ViewModelBinding is used to bind a non-MonoBehaviour class.
                    var viewModelBinding = viewModel as IViewModelBinding;
                    if (viewModelBinding != null)
                    {
                        foundAtLeastOneBinding = true;

                        yield return(GetBoundViewType(viewModelBinding));
                    }
                    else if (viewModel.GetType().GetCustomAttributes(typeof(BindingAttribute), false).Any())
                    {
                        // Case where we are binding to an existing MonoBehaviour.
                        foundAtLeastOneBinding = true;

                        yield return(viewModel.GetType());
                    }
                }

                // Stop at the top level
                if (trans.GetComponent <BindingRoot>() != null)
                {
                    break;
                }

                trans = trans.parent;
            }

            if (!foundAtLeastOneBinding)
            {
                Debug.LogError("UI binding " + memberBinding.gameObject.name +
                               " must be placed underneath at least one bindable component.", memberBinding);
            }
        }
        /// <summary>
        /// Shows a dropdown for selecting a property in the UI to bind to.
        /// </summary>
        public void ShowViewPropertyMenu(
            GUIContent label,
            AbstractMemberBinding targetScript,
            BindablePropertyInfo[] properties,
            Action <string> propertyValueSetter,
            string curPropertyValue,
            out Type selectedPropertyType
            )
        {
            var propertyNames = properties
                                .Select(prop => prop.PropertyInfo.ReflectedType.Name + "." + prop.PropertyInfo.Name)
                                .ToArray();
            var selectedIndex = Array.IndexOf(propertyNames, curPropertyValue);
            var content       = properties.Select(prop => new GUIContent(
                                                      prop.PropertyInfo.ReflectedType.Name + "/" +
                                                      prop.PropertyInfo.Name + " : " +
                                                      prop.PropertyInfo.PropertyType.Name
                                                      ))
                                .ToArray();

            var newSelectedIndex = EditorGUILayout.Popup(label, selectedIndex, content);

            if (newSelectedIndex != selectedIndex)
            {
                var newSelectedProperty = properties[newSelectedIndex];

                UpdateProperty(
                    propertyValueSetter,
                    curPropertyValue,
                    newSelectedProperty.PropertyInfo.ReflectedType.Name + "." + newSelectedProperty.PropertyInfo.Name
                    );

                selectedPropertyType = newSelectedProperty.PropertyInfo.PropertyType;
            }
            else
            {
                if (selectedIndex < 0)
                {
                    selectedPropertyType = null;
                    return;
                }

                selectedPropertyType = properties[selectedIndex].PropertyInfo.PropertyType;
            }
        }
Beispiel #7
0
        /// <summary>
        /// Scan up the hierarchy and find all the types that can be bound to
        /// a specified MemberBinding.
        /// </summary>
        private static IEnumerable <Type> FindAvailableViewModelTypes(AbstractMemberBinding memberBinding)
        {
            var foundAtLeastOneBinding = false;

            var trans = memberBinding.transform;

            while (trans != null)
            {
                var components = trans.GetComponents <MonoBehaviour>();
                foreach (var component in components)
                {
                    // Can't bind to self or null
                    if (component == null || component == memberBinding)
                    {
                        continue;
                    }

                    // Case where a ViewModelBinding is used to bind a non-MonoBehaviour class.
                    var viewModelBinding = component as IViewModelProvider;
                    if (viewModelBinding != null)
                    {
                        var viewModelTypeName = viewModelBinding.GetViewModelTypeName();
                        // Ignore view model bindings that haven't been set up yet.
                        if (string.IsNullOrEmpty(viewModelTypeName))
                        {
                            continue;
                        }

                        var viewModelType = GetViewModelType(viewModelBinding.GetViewModelTypeName());
                        if (viewModelType == null)
                        {
                            viewModelType = GetViewModelType_Hotfix(viewModelBinding.GetViewModelTypeName());
                        }

                        if (viewModelType == null)
                        {
                            continue;
                        }
                        foundAtLeastOneBinding = true;
                        yield return(viewModelType);
                    }
                    else if (component.GetType().FullName.Equals("Framework.Hotfix.HotfixMBContainer"))
                    {
                        // Case where a ViewModelBinding is used to bind hotfix class
                        var prop = component.GetType().GetProperty("HotfixName", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
                        if (prop == null)
                        {
                            continue;
                        }

                        string viewModelTypeName = (string)prop.GetValue(component);
                        if (string.IsNullOrEmpty(viewModelTypeName))
                        {
                            continue;
                        }
                        Type viewModelType = GetViewModelType_Hotfix(viewModelTypeName);
                        if (viewModelType == null)
                        {
                            continue;
                        }
                        foundAtLeastOneBinding = true;
                        yield return(viewModelType);
                    }
                    else if (component.GetType().GetCustomAttributes(typeof(BindingAttribute), false).Any())
                    {
                        // Case where we are binding to an existing MonoBehaviour.
                        foundAtLeastOneBinding = true;

                        yield return(component.GetType());
                    }
                }

                trans = trans.parent;
            }

            if (!foundAtLeastOneBinding)
            {
                Debug.LogError("UI binding " + memberBinding.gameObject.name + " must be placed underneath at least one bindable component.", memberBinding);
            }
        }