예제 #1
0
        /// <summary>
        /// Creates inspectable fields all the fields/properties of the specified object.
        /// </summary>
        /// <param name="obj">Object whose fields the GUI will be drawn for.</param>
        /// <param name="parent">Parent Inspector to draw in.</param>
        /// <param name="path">Full path to the field this provided object was retrieved from.</param>
        /// <param name="depth">
        /// Determines how deep within the inspector nesting hierarchy is this objects. Some fields may contain other
        /// fields, in which case you should increase this value by one.
        /// </param>
        /// <param name="layout">Parent layout that all the field GUI elements will be added to.</param>
        /// <param name="overrideCallback">
        /// Optional callback that allows you to override the look of individual fields in the object. If non-null the
        /// callback will be called with information about every field in the provided object. If the callback returns
        /// non-null that inspectable field will be used for drawing the GUI, otherwise the default inspector field type
        /// will be used.
        /// </param>
        public static List <InspectableField> CreateFields(SerializableObject obj, Inspector parent, string path,
                                                           int depth, GUILayoutY layout, FieldOverrideCallback overrideCallback = null)
        {
            // Retrieve fields and sort by order
            SerializableField[] fields = obj.Fields;
            Array.Sort(fields,
                       (x, y) =>
            {
                int orderX = x.Flags.HasFlag(SerializableFieldAttributes.Order) ? x.Style.Order : 0;
                int orderY = y.Flags.HasFlag(SerializableFieldAttributes.Order) ? y.Style.Order : 0;

                return(orderX.CompareTo(orderY));
            });

            // Generate per-field GUI while grouping by category
            Dictionary <string, Tuple <int, GUILayoutY> > categories = new Dictionary <string, Tuple <int, GUILayoutY> >();

            int rootIndex = 0;
            List <InspectableField> inspectableFields = new List <InspectableField>();

            foreach (var field in fields)
            {
                if (!field.Flags.HasFlag(SerializableFieldAttributes.Inspectable))
                {
                    continue;
                }

                string category = null;
                if (field.Flags.HasFlag(SerializableFieldAttributes.Category))
                {
                    category = field.Style.CategoryName;
                }

                Tuple <int, GUILayoutY> categoryInfo = null;
                if (!string.IsNullOrEmpty(category))
                {
                    if (!categories.TryGetValue(category, out categoryInfo))
                    {
                        InspectableFieldLayout fieldLayout        = new InspectableFieldLayout(layout);
                        GUILayoutY             categoryRootLayout = fieldLayout.AddLayoutY(rootIndex);
                        GUILayoutX             guiTitleLayout     = categoryRootLayout.AddLayoutX();

                        bool isExpanded = parent.Persistent.GetBool(path + "/[" + category + "]_Expanded");

                        GUIToggle guiFoldout = new GUIToggle(category, EditorStyles.Foldout);
                        guiFoldout.Value           = isExpanded;
                        guiFoldout.AcceptsKeyFocus = false;
                        guiFoldout.OnToggled      += x =>
                        {
                            parent.Persistent.SetBool(path + "/[" + category + "]_Expanded", x);
                        };
                        guiTitleLayout.AddElement(guiFoldout);

                        GUILayoutX categoryContentLayout = categoryRootLayout.AddLayoutX();
                        categoryContentLayout.AddSpace(IndentAmount);

                        GUIPanel   guiContentPanel  = categoryContentLayout.AddPanel();
                        GUILayoutX guiIndentLayoutX = guiContentPanel.AddLayoutX();
                        guiIndentLayoutX.AddSpace(IndentAmount);
                        GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
                        guiIndentLayoutY.AddSpace(IndentAmount);
                        GUILayoutY categoryLayout = guiIndentLayoutY.AddLayoutY();
                        guiIndentLayoutY.AddSpace(IndentAmount);
                        guiIndentLayoutX.AddSpace(IndentAmount);
                        categoryContentLayout.AddSpace(IndentAmount);

                        short  backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
                        string bgPanelStyle    = depth % 2 == 0
                            ? EditorStylesInternal.InspectorContentBgAlternate
                            : EditorStylesInternal.InspectorContentBg;
                        GUIPanel   backgroundPanel    = guiContentPanel.AddPanel(backgroundDepth);
                        GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
                        backgroundPanel.AddElement(inspectorContentBg);

                        categories[category] = new Tuple <int, GUILayoutY>(0, categoryLayout);
                        rootIndex++;
                    }
                }

                int        currentIndex;
                GUILayoutY parentLayout;
                if (categoryInfo != null)
                {
                    currentIndex = categoryInfo.Item1;
                    parentLayout = categoryInfo.Item2;
                }
                else
                {
                    currentIndex = rootIndex;
                    parentLayout = layout;
                }

                string fieldName = field.Name;
                string childPath = string.IsNullOrEmpty(path) ? fieldName : path + "/" + fieldName;

                InspectableField inspectableField = null;

                if (overrideCallback != null)
                {
                    inspectableField = overrideCallback(field, parent, path, new InspectableFieldLayout(parentLayout),
                                                        currentIndex, depth);
                }

                if (inspectableField == null)
                {
                    inspectableField = CreateField(parent, fieldName, childPath,
                                                   currentIndex, depth, new InspectableFieldLayout(parentLayout), field.GetProperty(),
                                                   InspectableFieldStyle.Create(field));
                }

                inspectableFields.Add(inspectableField);
                currentIndex += inspectableField.GetNumLayoutElements();

                if (categoryInfo != null)
                {
                    categories[category] = new Tuple <int, GUILayoutY>(currentIndex, parentLayout);
                }
                else
                {
                    rootIndex = currentIndex;
                }
            }

            return(inspectableFields);
        }
예제 #2
0
        /// <summary>
        /// Rebuilds the GUI object header if needed.
        /// </summary>
        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
        protected void BuildGUI(int layoutIndex)
        {
            Action BuildEmptyGUI = () =>
            {
                guiInternalTitleLayout = guiTitleLayout.InsertLayoutX(0);

                guiInternalTitleLayout.AddElement(new GUILabel(title));
                guiInternalTitleLayout.AddElement(new GUILabel("Empty", GUIOption.FixedWidth(100)));

                if (!property.IsValueType)
                {
                    GUIContent createIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Create),
                                                           new LocEdString("Create"));
                    guiCreateBtn          = new GUIButton(createIcon, GUIOption.FixedWidth(30));
                    guiCreateBtn.OnClick += OnCreateButtonClicked;
                    guiInternalTitleLayout.AddElement(guiCreateBtn);
                }
            };

            Action BuildFilledGUI = () =>
            {
                guiInternalTitleLayout = guiTitleLayout.InsertLayoutX(0);

                GUIToggle guiFoldout = new GUIToggle(title, EditorStyles.Foldout);
                guiFoldout.Value           = isExpanded;
                guiFoldout.AcceptsKeyFocus = false;
                guiFoldout.OnToggled      += OnFoldoutToggled;
                guiInternalTitleLayout.AddElement(guiFoldout);

                if (!style.StyleFlags.HasFlag(InspectableFieldStyleFlags.NotNull))
                {
                    GUIContent clearIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Clear),
                                                          new LocEdString("Clear"));
                    GUIButton clearBtn = new GUIButton(clearIcon, GUIOption.FixedWidth(20));
                    clearBtn.OnClick += OnClearButtonClicked;
                    guiInternalTitleLayout.AddElement(clearBtn);
                }

                if (isExpanded)
                {
                    SerializableObject  serializableObject = property.GetObject();
                    SerializableField[] fields             = serializableObject.Fields;

                    if (fields.Length > 0)
                    {
                        guiChildLayout = guiLayout.AddLayoutX();
                        guiChildLayout.AddSpace(IndentAmount);

                        GUIPanel   guiContentPanel  = guiChildLayout.AddPanel();
                        GUILayoutX guiIndentLayoutX = guiContentPanel.AddLayoutX();
                        guiIndentLayoutX.AddSpace(IndentAmount);
                        GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
                        guiIndentLayoutY.AddSpace(IndentAmount);
                        GUILayoutY guiContentLayout = guiIndentLayoutY.AddLayoutY();
                        guiIndentLayoutY.AddSpace(IndentAmount);
                        guiIndentLayoutX.AddSpace(IndentAmount);
                        guiChildLayout.AddSpace(IndentAmount);

                        short  backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
                        string bgPanelStyle    = depth % 2 == 0
                           ? EditorStylesInternal.InspectorContentBgAlternate
                           : EditorStylesInternal.InspectorContentBg;
                        GUIPanel   backgroundPanel    = guiContentPanel.AddPanel(backgroundDepth);
                        GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
                        backgroundPanel.AddElement(inspectorContentBg);

                        int currentIndex = 0;
                        foreach (var field in fields)
                        {
                            if (!field.Flags.HasFlag(SerializableFieldAttributes.Inspectable))
                            {
                                continue;
                            }

                            string childPath = path + "/" + field.Name;

                            InspectableField inspectable = CreateInspectable(parent, field.Name, childPath,
                                                                             currentIndex, depth + 1, new InspectableFieldLayout(guiContentLayout), field.GetProperty(), InspectableFieldStyle.Create(field));

                            children.Add(inspectable);
                            currentIndex += inspectable.GetNumLayoutElements();
                        }
                    }
                }
                else
                {
                    guiChildLayout = null;
                }
            };

            if (state == State.None)
            {
                if (propertyValue != null)
                {
                    BuildFilledGUI();
                    state = State.Filled;
                }
                else
                {
                    BuildEmptyGUI();

                    state = State.Empty;
                }
            }
            else if (state == State.Empty)
            {
                if (propertyValue != null)
                {
                    guiInternalTitleLayout.Destroy();
                    guiCreateBtn = null;

                    BuildFilledGUI();
                    state = State.Filled;
                }
            }
            else if (state == State.Filled)
            {
                foreach (var child in children)
                {
                    child.Destroy();
                }

                children.Clear();
                guiInternalTitleLayout.Destroy();
                guiCreateBtn = null;

                if (guiChildLayout != null)
                {
                    guiChildLayout.Destroy();
                    guiChildLayout = null;
                }

                if (propertyValue == null)
                {
                    BuildEmptyGUI();
                    state = State.Empty;
                }
                else
                {
                    BuildFilledGUI();
                }
            }
        }
예제 #3
0
        /// <inheritdoc/>
        protected internal override void Initialize()
        {
            if (InspectedObject == null)
            {
                LoadResource();
            }

            if (InspectedObject != null)
            {
                int currentIndex = 0;
                SerializableObject serializableObject = new SerializableObject(InspectedObject.GetType(), InspectedObject);
                foreach (var field in serializableObject.Fields)
                {
                    if (!field.Inspectable)
                    {
                        continue;
                    }

                    string           path             = field.Name;
                    InspectableField inspectableField = InspectableField.CreateInspectable(this, field.Name, path,
                                                                                           currentIndex, 0, new InspectableFieldLayout(Layout), field.GetProperty(), InspectableFieldStyle.Create(field));

                    inspectableFields.Add(inspectableField);
                    isEmpty = false;

                    currentIndex += inspectableField.GetNumLayoutElements();
                }

                base.SetVisible(!isEmpty);
            }
        }