예제 #1
0
            //PUBLIC

            /// <summary>
            /// Find the height of a persistent callback object
            /// </summary>
            /// <param name="property">The property that is to have the height calculated for</param>
            /// <returns>Returns the height in pixels that should be reserved for this element</returns>
            public static float GetElementHeight(SerializedProperty property)
            {
                //Get the target objects of the property
                PersistentCallback[] callbacks;
                property.GetPropertyValues(out callbacks);

                //Check that there are values to check
                if (callbacks.Length == 0)
                {
                    return(0f);
                }

                //Get the height that is used for the object/method selection elements
                float height = EditorGUIUtility.singleLineHeight * 2 + (BUFFER_SPACE * 2f);

                //Get the method that is in use by the primary (first) callback
                PersistentMethod primary = PersistentOptionsUtility.GetPersistentMethodFromCallback(callbacks[0]);

                //Check if this method is the same across all selections
                bool isDifferent = false;

                for (int i = 1; i < callbacks.Length; i++)
                {
                    if (primary != PersistentOptionsUtility.GetPersistentMethodFromCallback(callbacks[i]))
                    {
                        isDifferent = true;
                        break;
                    }
                }

                //If the methods are the same then the parameters can be shown
                if (!isDifferent && !callbacks[0].IsDynamic && primary != null)
                {
                    //Calculate the height required for each drawer
                    int ind = 0;
                    foreach (var param in primary.Parameters)
                    {
                        //Get the drawer for the type
                        AParameterDrawer drawer = ParameterDrawers.GetDrawer(primary.ParameterSignature[ind], param.Attribute);

                        //Collate the parameter cache's that are needed for this callback
                        PersistentParameterCache[] current = new PersistentParameterCache[callbacks.Length];
                        for (int i = 0; i < callbacks.Length; i++)
                        {
                            current[i] = callbacks[i].ParameterInfo[ind].ParameterCache;
                        }

                        //Retrieve the height for the drawer
                        height += drawer.GetDrawerHeight(current, param.DisplayLabel) + BUFFER_SPACE;

                        //Increment the progress
                        ++ind;
                    }
                }

                //Return the final completed height
                return(height);
            }
예제 #2
0
            /// <summary>
            /// Display the elements of the property within the designated area on the inspector area
            /// </summary>
            /// <param name="position">The position within the inspector that the property should be drawn to</param>
            /// <param name="property">The property that is to be displayed within the inspector</param>
            /// <param name="dynamicTypes">Defines the types that are designated as dynamic types for operation</param>
            /// <param name="forceDirty">An action that can be raised from the generic menus callback to force a dirty of the current elements</param>
            /// <returns>Returns true if an event occurred that caused changes that need to be saved</returns>
            public static bool DrawLayoutElements(Rect position, SerializedProperty property, Type[] dynamicTypes, Action forceDirty)
            {
                //Get the target objects of the property
                PersistentCallback[] callbacks;

                //Check that there are values to check
                if (!property.GetPropertyValues(out callbacks) || callbacks.Length == 0)
                {
                    return(false);
                }

                //Flag if the height of this object needs to be recalculated
                bool elementsModified = false;

                {
                    //Check if the event state is different for the contained callbacks
                    bool isDifferent = false;
                    for (int i = 1; i < callbacks.Length; i++)
                    {
                        if (callbacks[0].EventState != callbacks[i].EventState)
                        {
                            isDifferent = true;
                            break;
                        }
                    }

                    //Display an option to change the event state of the options
                    using (GUIMixer.PushSegment(isDifferent)) {
                        //Begin checking for UI changes
                        EditorGUI.BeginChangeCheck();

                        //Present the option for changing the event state
                        ERuntimeEventState newState = (ERuntimeEventState)EditorGUI.EnumPopup(GetLineOffsetPosition(position, 0, 1f), GUIContent.none, callbacks[0].EventState);

                        //If the state has changed, apply it to all of the callbacks
                        if (EditorGUI.EndChangeCheck())
                        {
                            for (int i = 0; i < callbacks.Length; i++)
                            {
                                callbacks[i].EventState = newState;
                            }
                        }
                    }
                }

                {
                    //Check if the target object is different for the contained callbacks
                    bool isDifferent = false;

                    //Check there are multiple objects to modify
                    if (callbacks.Length > 1)
                    {
                        //Get the target of the initial object
                        UnityEngine.Object baseTarget = GetBaseTarget(callbacks[0].Target);

                        //Compare the base target against the others
                        for (int i = 1; i < callbacks.Length; i++)
                        {
                            if (baseTarget != GetBaseTarget(callbacks[i].Target))
                            {
                                isDifferent = true;
                                break;
                            }
                        }
                    }

                    //Display a target field for the callback operations
                    using (GUIMixer.PushSegment(isDifferent)) {
                        //Begin checking for UI changes
                        EditorGUI.BeginChangeCheck();

                        //Present the option for changing the target object
                        UnityEngine.Object newTarget = EditorGUI.ObjectField(GetLineOffsetPosition(position, 1, .4f), GUIContent.none, callbacks[0].Target, typeof(UnityEngine.Object), true);

                        //If the target changed
                        if (EditorGUI.EndChangeCheck())
                        {
                            //Apply the new target to all contained elements
                            for (int i = 0; i < callbacks.Length; i++)
                            {
                                callbacks[i].Target = newTarget;
                            }

                            //That can cause massive changes
                            elementsModified = true;
                        }
                    }
                }

                //Store the persistent method that is assigned to the primary
                PersistentMethod primaryMethod = PersistentOptionsUtility.GetPersistentMethodFromCallback(callbacks[0]);

                //Store a flag that indicates if the callbacks have different methods
                bool methodsAreDifferent = false;

                //Allow for the modification of selected function if there is a target set
                using (GUILocker.PushSegment(callbacks[0].Target)) {
                    //Retrieve the Content that will be displayed for the function selection selected option
                    GUIContent selectedDisplay;

                    //If a method match could be found, use its display label
                    if (primaryMethod != null)
                    {
                        selectedDisplay = primaryMethod.DisplayLabel;
                    }

                    //Otherwise, method may be missing
                    else
                    {
                        //Try to retrieve the label for the callback
                        string generatedLabel = PersistentOptionsUtility.GetPersistentMethodLabelFromCallback(callbacks[0]);

                        //If the string is empty, no function has been set yet
                        selectedDisplay = (string.IsNullOrEmpty(generatedLabel) ?
                                           NO_SELECTION_LABEL :
                                           new GUIContent(generatedLabel + " " + MISSING_LABEL)
                                           );
                    }

                    //Check there are multiple callbacks to compare against
                    if (callbacks.Length > 1)
                    {
                        //Check if the selected callbacks for the other callbacks is different
                        for (int i = 1; i < callbacks.Length; i++)
                        {
                            if (primaryMethod != PersistentOptionsUtility.GetPersistentMethodFromCallback(callbacks[i]))
                            {
                                methodsAreDifferent = true;
                                break;
                            }
                        }
                    }

                    //Display the dropdown button for selecting the active callback
                    using (GUIMixer.PushSegment(methodsAreDifferent)) {
                        if (EditorGUI.DropdownButton(GetLineOffsetPosition(position, 1, .6f, .4f), selectedDisplay, FocusType.Passive))
                        {
                            //Retrieve the constructed menu
                            GenericMenu optionsMenu = CreateOptionsSelectionMenu(callbacks[0].Target, callbacks[0].IsValid, callbacks[0].IsDynamic, primaryMethod, dynamicTypes,
                                                                                 //Reset function
                                                                                 () => {
                                //Loop through and reset all of the callback methods
                                for (int i = 0; i < callbacks.Length; i++)
                                {
                                    callbacks[i].ResetMethod();
                                }

                                //Reset the primary method
                                primaryMethod       = null;
                                methodsAreDifferent = false;

                                //Values modified, force the calling object to re-calculate this element
                                forceDirty();
                            },
                                                                                 //Assign method function
                                                                                 (target, method, isDynamic) => {
                                //Apply the new method to the option
                                AssignPersistentCallback(callbacks, target, method, isDynamic);

                                //Methods are now the same
                                primaryMethod       = method;
                                methodsAreDifferent = false;

                                //Values modified, force the calling object to re-calculate this element
                                forceDirty();
                            });

                            //Display the various options
                            optionsMenu.DropDown(GetLineOffsetPosition(position, 1, .6f, .4f));
                        }
                    }
                }

                //If the primary method is consistent across the multiple objects, display the values
                if (!methodsAreDifferent && !callbacks[0].IsDynamic && primaryMethod != null)
                {
                    //Store the rect of the last point
                    Rect displayRect = GetLineOffsetPosition(position, 1, 1f);

                    //Loop through all of the parameters for this method
                    int ind = 0;
                    foreach (var param in primaryMethod.Parameters)
                    {
                        //Retrieve the drawer for this parameter
                        AParameterDrawer drawer = ParameterDrawers.GetDrawer(primaryMethod.ParameterSignature[ind], param.Attribute);

                        //Collate the parameter cache's that are needed for this callback
                        PersistentParameterCache[] current = new PersistentParameterCache[callbacks.Length];
                        for (int i = 0; i < callbacks.Length; i++)
                        {
                            current[i] = callbacks[i].ParameterInfo[ind].ParameterCache;
                        }

                        //Setup the display rect for displaying values correctly given the values
                        displayRect.y     += displayRect.height + BUFFER_SPACE;
                        displayRect.height = drawer.GetDrawerHeight(current, param.DisplayLabel);

                        //Draw the elements to the inspector
                        if (drawer.DisplayParameterValue(displayRect, current, param.DisplayLabel) && !elementsModified)
                        {
                            elementsModified = true;
                        }

                        //Increment the current progress through the parameters
                        ++ind;
                    }
                }

                //Return the re-calculate flag
                return(elementsModified);
            }