Просмотр исходного кода

Array and list entries can now also be animated

BearishSun 9 лет назад
Родитель
Сommit
87c5aec53e

+ 155 - 24
Source/MBansheeEditor/Windows/Animation/GUIFieldSelector.cs

@@ -157,6 +157,76 @@ namespace BansheeEditor
             }
         }
 
+        /// <summary>
+        /// Registers a new row in the layout for the provided property. The type of row is determined by the property type.
+        /// </summary>
+        /// <param name="parent">Parent foldout row to which to append the new elements.</param>
+        /// <param name="name">Name of the field the property belongs to.</param>
+        /// <param name="path">Slash separated path to the field from its parent object.</param>
+        /// <param name="property">Property to create the row for.</param>
+        /// <param name="element">Element containing data for the newly created row. Only valid if method returns true.
+        ///                       </param>
+        /// <returns>Returns true if the row was successfully added, false otherwise.</returns>
+        private bool AddPropertyRow(Element parent, string name, string path, SerializableProperty property, 
+            out Element element)
+        {
+            switch (property.Type)
+            {
+                case SerializableProperty.FieldType.Bool:
+                case SerializableProperty.FieldType.Float:
+                case SerializableProperty.FieldType.Int:
+                case SerializableProperty.FieldType.Color:
+                case SerializableProperty.FieldType.Vector2:
+                case SerializableProperty.FieldType.Vector3:
+                case SerializableProperty.FieldType.Vector4:
+                    element = AddFieldRow(parent.childLayout, name, parent.so, parent.comp, path, property.Type);
+                    return true;
+                case SerializableProperty.FieldType.Object:
+                    {
+                        Action<Element, bool> toggleCallback =
+                            (toggleParent, expand) =>
+                            {
+                                SerializableObject childObject = new SerializableObject(property.InternalType, null);
+                                ToggleObjectFoldout(toggleParent, childObject, expand);
+                            };
+
+                        element = AddFoldoutRow(parent.childLayout, null, name, parent.so, parent.comp, path, toggleCallback);
+                    }
+                    return true;
+                case SerializableProperty.FieldType.Array:
+                    {
+                        Action<Element, bool> toggleCallback =
+                            (toggleParent, expand) =>
+                            {
+                                SerializableArray childObject = property.GetArray();
+
+                                if (childObject != null)
+                                    ToggleArrayFoldout(toggleParent, childObject, expand);
+                            };
+
+                        element = AddFoldoutRow(parent.childLayout, null, name, parent.so, parent.comp, path, toggleCallback);
+                    }
+                    return true;
+                case SerializableProperty.FieldType.List:
+                    {
+                        Action<Element, bool> toggleCallback =
+                            (toggleParent, expand) =>
+                            {
+                                SerializableList childObject = property.GetList();
+
+                                if (childObject != null)
+                                    ToggleListFoldout(toggleParent, childObject, expand);
+                            };
+
+                        element = AddFoldoutRow(parent.childLayout, null, name, parent.so, parent.comp, path, toggleCallback);
+                    }
+                    return true;
+            }
+
+            element = new Element();
+            return false;
+        }
+
         /// <summary>
         /// Registers a set of rows for all child fields of the provided object.
         /// </summary>
@@ -172,28 +242,9 @@ namespace BansheeEditor
 
                 string propertyPath = parent.path + "/" + field.Name;
 
-                switch (field.Type)
-                {
-                    case SerializableProperty.FieldType.Bool:
-                    case SerializableProperty.FieldType.Float:
-                    case SerializableProperty.FieldType.Int:
-                    case SerializableProperty.FieldType.Color:
-                    case SerializableProperty.FieldType.Vector2:
-                    case SerializableProperty.FieldType.Vector3:
-                    case SerializableProperty.FieldType.Vector4:
-                        elements.Add(AddFieldRow(parent.childLayout, field.Name, parent.so, parent.comp, propertyPath, field.Type));
-                        break;
-                    case SerializableProperty.FieldType.Object:
-                        Action<Element, bool> toggleCallback = 
-                            (toggleParent, expand) =>
-                        {
-                            SerializableObject childObject = new SerializableObject(field.InternalType, null);
-                            ToggleObjectFoldout(toggleParent, childObject, expand);
-                        };
-                        elements.Add(AddFoldoutRow(parent.childLayout, null, field.Name, parent.so, parent.comp, 
-                            propertyPath, toggleCallback));
-                        break;
-                }
+                Element element;
+                if(AddPropertyRow(parent, field.Name, propertyPath, field.GetProperty(), out element))
+                    elements.Add(element);
             }
 
             // Handle special fields
@@ -247,6 +298,52 @@ namespace BansheeEditor
             parent.children = elements.ToArray();
         }
 
+        /// <summary>
+        /// Registers a set of rows for all entries of the provided array.
+        /// </summary>
+        /// <param name="parent">Parent foldout row to which to append the new elements.</param>
+        /// <param name="serializableArray">Array whose fields to display.</param>
+        private void AddArrayRows(Element parent, SerializableArray serializableArray)
+        {
+            List<Element> elements = new List<Element>();
+
+            int length = serializableArray.GetLength();
+            for (int i = 0; i < length; i++)
+            {
+                string name = "[" + i + "]";
+                string propertyPath = parent.path + name;
+
+                Element element;
+                if (AddPropertyRow(parent, name, propertyPath, serializableArray.GetProperty(i), out element))
+                    elements.Add(element);
+            }
+
+            parent.children = elements.ToArray();
+        }
+
+        /// <summary>
+        /// Registers a set of rows for all entries of the provided list.
+        /// </summary>
+        /// <param name="parent">Parent foldout row to which to append the new elements.</param>
+        /// <param name="serializableList">List whose fields to display.</param>
+        private void AddListRows(Element parent, SerializableList serializableList)
+        {
+            List<Element> elements = new List<Element>();
+
+            int length = serializableList.GetLength();
+            for (int i = 0; i < length; i++)
+            {
+                string name = "[" + i + "]";
+                string propertyPath = parent.path + name;
+
+                Element element;
+                if (AddPropertyRow(parent, name, propertyPath, serializableList.GetProperty(i), out element))
+                    elements.Add(element);
+            }
+
+            parent.children = elements.ToArray();
+        }
+
         /// <summary>
         /// Registers a new row in the layout. The row cannot have any further children and can be selected as the output
         /// field.
@@ -395,9 +492,7 @@ namespace BansheeEditor
             parent.indentLayout.Active = expand;
 
             if (expand)
-            {
                 AddSceneObjectRows(parent);
-            }
         }
 
         /// <summary>
@@ -418,6 +513,42 @@ namespace BansheeEditor
                 AddObjectRows(parent, obj);
         }
 
+        /// <summary>
+        /// Expands or collapses the set of rows displaying all entries of a serializable array.
+        /// </summary>
+        /// <param name="parent">Parent row element whose children to expand/collapse.</param>
+        /// <param name="obj">Object describing the array whose entries to display.</param>
+        /// <param name="expand">True to expand, false to collapse.</param>
+        private void ToggleArrayFoldout(Element parent, SerializableArray obj,
+            bool expand)
+        {
+            parent.childLayout.Clear();
+            parent.children = null;
+
+            parent.indentLayout.Active = expand;
+
+            if (expand)
+                AddArrayRows(parent, obj);
+        }
+
+        /// <summary>
+        /// Expands or collapses the set of rows displaying all entries of a serializable list.
+        /// </summary>
+        /// <param name="parent">Parent row element whose children to expand/collapse.</param>
+        /// <param name="obj">Object describing the list whose entries to display.</param>
+        /// <param name="expand">True to expand, false to collapse.</param>
+        private void ToggleListFoldout(Element parent, SerializableList obj,
+            bool expand)
+        {
+            parent.childLayout.Clear();
+            parent.children = null;
+
+            parent.indentLayout.Active = expand;
+
+            if (expand)
+                AddListRows(parent, obj);
+        }
+
         /// <summary>
         /// Triggered when the user selects a field.
         /// </summary>

+ 8 - 2
Source/MBansheeEngine/Animation/Animation.cs

@@ -531,16 +531,22 @@ namespace BansheeEngine
         /// 
         ///                    Path element prefixed with ":" signify names of components. If a path doesn't have a
         ///                    component element, it is assumed the field is relative to the scene object itself (only 
-        ///                    "Translation", "Rotation" and "Scale fields are supported in such case). Only one component
+        ///                    "Translation", "Rotation" and "Scale" fields are supported in such case). Only one component
         ///                    path element per path is allowed.
         /// 
         ///                    Path entries with no prefix are considered regular script object fields. Each path must have
-        ///                    at least one such entry. Last field entry can optionally have a suffix separated from the
+        ///                    at least one such entry. 
+        /// 
+        ///                    A field path can be followed by an indexer [n] where n is a zero-based index. Such paths
+        ///                    are assumed to be referencing an index within an array or a list.
+        /// 
+        ///                    A field path can also be followed by a suffix (after the indexer, if any) separated from the
         ///                    path name with ".". This suffix is not parsed internally, but will be returned as 
         ///                    <paramref name="suffix"/>.
         /// 
         ///                    Path examples:
         ///                     :MyComponent/myInt (path to myInt variable on a component attached to this object)
+        ///                     :MyComponent/myArray[0] (path to first element of myArray on the same component)
         ///                     !childSO/:MyComponent/myInt (path to myInt variable on a child scene object)
         ///                     !childSO/Translation (path to the scene object translation)
         ///                     :MyComponent/myVector.z (path to the z component of myVector on this object)

+ 16 - 5
Source/MBansheeEngine/Serialization/SerializableObject.cs

@@ -119,23 +119,34 @@ namespace BansheeEngine
                     return null;
 
                 pathElements[i] = new PropertyPathElement();
+
+                int startIdx = 0;
+                int nameEndIdx = 0;
+                int endIdx = entry.Length - 1;
                 if (entry[entry.Length - 1] == ']')
                 {
                     bool foundKey = false;
-                    int j = entry.Length - 2;
-                    for (; j >= 0; j--)
+                    for (int j = 0; j < entry.Length - 1; j++)
                     {
                         if (entry[j] == '[')
                         {
+                            startIdx = j;
+                            nameEndIdx = j;
                             foundKey = true;
-                            break;
                         }
                     }
 
+                    // Trim string quotes, if they exist
+                    if (startIdx < (endIdx - 1) && entry[startIdx + 1] == '"')
+                        startIdx++;
+
+                    if (endIdx > (startIdx + 1) && entry[endIdx - 1] == '"')
+                        endIdx--;
+                    
                     if (foundKey)
                     {
-                        pathElements[i].name = entry.Substring(0, j);
-                        pathElements[i].key = entry.Substring(j + 1, (entry.Length - 1) - (j + 1));
+                        pathElements[i].name = entry.Substring(0, nameEndIdx);
+                        pathElements[i].key = entry.Substring(startIdx + 1, endIdx - (startIdx + 1));
                     }
                     else
                         pathElements[i].name = entry;