Browse Source

Bugfix: Various fixes to get the Category inspector attribute working

BearishSun 6 years ago
parent
commit
71f10b796d

+ 119 - 0
Source/EditorManaged/Windows/Inspector/InspectableCategory.cs

@@ -0,0 +1,119 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System.Collections.Generic;
+using System;
+using System.Reflection;
+using bs;
+
+namespace bs.Editor
+{
+    /** @addtogroup Inspector
+     *  @{
+     */
+
+    /// <summary>
+    /// Helper inspectable type that groups another inspectable fields under a common category.
+    /// </summary>
+    public class InspectableCategory : InspectableField
+    {
+        private const int IndentAmount = 5;
+
+        public GUILayoutY ChildLayout { get; private set; }
+
+        private List<InspectableField> children = new List<InspectableField>();
+
+        private GUILayoutY guiLayout;
+        private GUIPanel guiContentPanel;
+        private bool isExpanded;
+
+        /// <summary>
+        /// Creates a new inspectable category. The category is initially empty and children must be added by calling
+        /// <see cref="AddChild"/>.
+        /// </summary>
+        /// <param name="parent">Parent Inspector this field belongs to.</param>
+        /// <param name="title">Name of the category.</param>
+        /// <param name="path">Full path to the category (includes name of the category and all parent properties).</param>
+        /// <param name="depth">Determines how deep within the inspector nesting hierarchy is this field. 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 elements will be added to.</param>
+        public InspectableCategory(Inspector parent, string title, string path, int depth, InspectableFieldLayout layout)
+            : base(parent, title, "", SerializableProperty.FieldType.Object, depth, layout, null)
+        {
+            isExpanded = parent.Persistent.GetBool(path + "_Expanded");
+        }
+
+        /// <summary>
+        /// Registers a new child field in the category.
+        /// </summary>
+        /// <param name="child">Child field to add to the category. The field must have the category
+        /// <see cref="ChildLayout"/> as its parent.</param>
+        public void AddChild(InspectableField child)
+        {
+            children.Add(child);
+        }
+
+        /// <inheritdoc/>
+        public override InspectableState Refresh(int layoutIndex)
+        {
+            InspectableState state = InspectableState.NotModified;
+            int currentIndex = 0;
+            for (int i = 0; i < children.Count; i++)
+            {
+                state |= children[i].Refresh(currentIndex);
+                currentIndex += children[i].GetNumLayoutElements();
+            }
+
+            return state;
+        }
+
+        /// <inheritdoc/>
+        protected internal override void Initialize(int index)
+        {
+            guiLayout = layout.AddLayoutY(index);
+
+            GUILayoutX guiTitleLayout = guiLayout.AddLayoutX();
+
+            GUIToggle guiFoldout = new GUIToggle(title, EditorStyles.Foldout);
+            guiFoldout.Value = isExpanded;
+            guiFoldout.AcceptsKeyFocus = false;
+            guiFoldout.OnToggled += OnFoldoutToggled;
+            guiTitleLayout.AddElement(guiFoldout);
+
+            GUILayoutX categoryContentLayout = guiLayout.AddLayoutX();
+            categoryContentLayout.AddSpace(IndentAmount);
+
+            guiContentPanel = categoryContentLayout.AddPanel();
+            GUILayoutX guiIndentLayoutX = guiContentPanel.AddLayoutX();
+            guiIndentLayoutX.AddSpace(IndentAmount);
+            GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
+            guiIndentLayoutY.AddSpace(IndentAmount);
+            ChildLayout = 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);
+
+            guiContentPanel.Active = isExpanded;
+        }
+
+        /// <summary>
+        /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
+        /// </summary>
+        /// <param name="expanded">Determines whether the contents were expanded or collapsed.</param>
+        private void OnFoldoutToggled(bool expanded)
+        {
+            parent.Persistent.SetBool(path + "_Expanded", expanded);
+            isExpanded = expanded;
+            guiContentPanel.Active = expanded;
+        }
+    }
+
+    /** @} */
+}

+ 31 - 54
Source/EditorManaged/Windows/Inspector/InspectableField.cs

@@ -36,10 +36,7 @@ namespace bs.Editor
             get { return property; }
             set
             {
-                if (value == null)
-                    throw new ArgumentException("Cannot assign a null property to an inspectable field.");
-
-                if (value.Type != type)
+                if (value != null && value.Type != type)
                 {
                     throw new ArgumentException(
                         "Attempting to initialize an inspectable field with a property of invalid type.");
@@ -170,71 +167,47 @@ namespace bs.Editor
                 });
 
             // Generate per-field GUI while grouping by category
-            Dictionary<string, Tuple<int, GUILayoutY>> categories = new Dictionary<string, Tuple<int, GUILayoutY>>();
-
             int rootIndex = 0;
+            int categoryIndex = 0;
+            string categoryName = null;
+            InspectableCategory category = null;
+
             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))
+                    string newCategory = field.Style.CategoryName;
+                    if (!string.IsNullOrEmpty(newCategory) && categoryName != newCategory)
                     {
-                        InspectableFieldLayout fieldLayout = new InspectableFieldLayout(layout);
-                        GUILayoutY categoryRootLayout = fieldLayout.AddLayoutY(rootIndex);
-                        GUILayoutX guiTitleLayout = categoryRootLayout.AddLayoutX();
+                        string categoryPath = path + "/[" + newCategory + "]";
+                        category = new InspectableCategory(parent, newCategory, categoryPath, depth, new InspectableFieldLayout(layout));
 
-                        bool isExpanded = parent.Persistent.GetBool(path + "/[" + category + "]_Expanded");
+                        category.Initialize(rootIndex);
+                        category.Refresh(rootIndex);
+                        rootIndex += category.GetNumLayoutElements();
 
-                        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++;
+                        inspectableFields.Add(category);
+
+                        categoryName = newCategory;
+                        categoryIndex = 0;
+                    }
+                    else
+                    {
+                        categoryName = null;
+                        category = null;
                     }
                 }
 
                 int currentIndex;
                 GUILayoutY parentLayout;
-                if (categoryInfo != null)
+                if (category != null)
                 {
-                    currentIndex = categoryInfo.Item1;
-                    parentLayout = categoryInfo.Item2;
+                    currentIndex = categoryIndex;
+                    parentLayout = category.ChildLayout;
                 }
                 else
                 {
@@ -258,11 +231,15 @@ namespace bs.Editor
                         InspectableFieldStyle.Create(field));
                 }
 
-                inspectableFields.Add(inspectableField);
+                if (category != null)
+                    category.AddChild(inspectableField);
+                else
+                    inspectableFields.Add(inspectableField);
+
                 currentIndex += inspectableField.GetNumLayoutElements();
 
-                if (categoryInfo != null)
-                    categories[category] = new Tuple<int, GUILayoutY>(currentIndex, parentLayout);
+                if (category != null)
+                    categoryIndex = currentIndex;
                 else
                     rootIndex = currentIndex;
             }

+ 1 - 1
Source/EditorManaged/Windows/Inspector/InspectableObject.cs

@@ -36,7 +36,7 @@ namespace bs.Editor
         private Type[] instantiableTypes;
 
         /// <summary>
-        /// Creates a new inspectable array GUI for the specified property.
+        /// Creates a new inspectable object GUI for the specified property.
         /// </summary>
         /// <param name="parent">Parent Inspector this field belongs to.</param>
         /// <param name="title">Name of the property, or some other value to set as the title.</param>

+ 1 - 1
Source/bsf

@@ -1 +1 @@
-Subproject commit 386ade7f55e668462c2da0f858415067ac6ead94
+Subproject commit 46329459451dedf29514cf9c5d324a10b0b7b8ff