private static extern void Internal_CreateInstance(SerializableProperty instance, Type type);
示例#2
0
        /// <summary>
        /// Builds a list of properties that will be animated using float animation curves.
        /// </summary>
        /// <param name="clip">Clip to retrieve the float animation curves from.</param>
        partial void RebuildFloatProperties(RRef <AnimationClip> clip)
        {
            if (clip == null)
            {
                floatProperties = null;
                return;
            }

            AnimationCurves curves = clip.Value.Curves;

            List <FloatCurvePropertyInfo> newFloatProperties = new List <FloatCurvePropertyInfo>();

            for (int i = 0; i < curves.Generic.Length; i++)
            {
                bool isMorphCurve = curves.Generic[i].flags.HasFlag(AnimationCurveFlags.MorphWeight) ||
                                    curves.Generic[i].flags.HasFlag(AnimationCurveFlags.MorphFrame);

                if (isMorphCurve)
                {
                    continue;
                }

                string suffix;
                SerializableProperty property = FindProperty(SceneObject, curves.Generic[i].name, out suffix);
                if (property == null)
                {
                    continue;
                }

                int elementIdx = 0;
                if (!string.IsNullOrEmpty(suffix))
                {
                    PropertySuffixInfo suffixInfo;
                    if (PropertySuffixInfos.TryGetValue(suffix, out suffixInfo))
                    {
                        elementIdx = suffixInfo.elementIdx;
                    }
                }

                Action <float> setter = null;

                Type internalType = property.InternalType;
                switch (property.Type)
                {
                case SerializableProperty.FieldType.Vector2:
                    if (internalType == typeof(Vector2))
                    {
                        setter = f =>
                        {
                            Vector2 value = property.GetValue <Vector2>();
                            value[elementIdx] = f;
                            property.SetValue(value);
                        };
                    }

                    break;

                case SerializableProperty.FieldType.Vector3:
                    if (internalType == typeof(Vector3))
                    {
                        setter = f =>
                        {
                            Vector3 value = property.GetValue <Vector3>();
                            value[elementIdx] = f;
                            property.SetValue(value);
                        };
                    }
                    break;

                case SerializableProperty.FieldType.Vector4:
                    if (internalType == typeof(Vector4))
                    {
                        setter = f =>
                        {
                            Vector4 value = property.GetValue <Vector4>();
                            value[elementIdx] = f;
                            property.SetValue(value);
                        };
                    }
                    else if (internalType == typeof(Quaternion))
                    {
                        setter = f =>
                        {
                            Quaternion value = property.GetValue <Quaternion>();
                            value[elementIdx] = f;
                            property.SetValue(value);
                        };
                    }
                    break;

                case SerializableProperty.FieldType.Color:
                    if (internalType == typeof(Color))
                    {
                        setter = f =>
                        {
                            Color value = property.GetValue <Color>();
                            value[elementIdx] = f;
                            property.SetValue(value);
                        };
                    }
                    break;

                case SerializableProperty.FieldType.Bool:
                    setter = f =>
                    {
                        bool value = f > 0.0f;
                        property.SetValue(value);
                    };
                    break;

                case SerializableProperty.FieldType.Int:
                    setter = f =>
                    {
                        int value = (int)f;
                        property.SetValue(value);
                    };
                    break;

                case SerializableProperty.FieldType.Float:
                    setter = f =>
                    {
                        property.SetValue(f);
                    };
                    break;
                }

                if (setter == null)
                {
                    continue;
                }

                FloatCurvePropertyInfo propertyInfo = new FloatCurvePropertyInfo();
                propertyInfo.curveIdx = i;
                propertyInfo.setter   = setter;

                newFloatProperties.Add(propertyInfo);
            }

            floatProperties = newFloatProperties.ToArray();
        }
 /// <summary>
 /// Constructor for use by the runtime only.
 /// </summary>
 /// <param name="elementType">C# type of the elements in the array.</param>
 /// <param name="parentProperty">Property used for retrieving this entry.</param>
 private SerializableArray(Type elementType, SerializableProperty parentProperty)
 {
     this.parentProperty = parentProperty;
     this.elementType    = elementType;
     elementPropertyType = SerializableProperty.DetermineFieldType(elementType);
 }
示例#4
0
        /// <summary>
        /// Searches the scene object hierarchy to find a property at the given path.
        /// </summary>
        /// <param name="root">Root scene object to which the path is relative to.</param>
        /// <param name="path">Path to the property, where each element of the path is separated with "/".
        ///
        ///                    Path elements prefixed with "!" signify names of child scene objects (first one relative to
        ///                    <paramref name="root"/>. Name of the root element should not be included in the path.
        ///
        ///                    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
        ///                    "Position", "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.
        ///
        ///                    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 the root object)
        ///                     :MyComponent/myArray[0] (path to first element of myArray on the same component as above)
        ///                     !childSO/:MyComponent/myInt (path to myInt variable on a child scene object)
        ///                     !childSO/Position (path to the scene object position)
        ///                     :MyComponent/myVector.z (path to the z component of myVector on the root object)
        /// </param>
        /// <param name="suffix">Suffix of the last field entry, if it has any. Contains the suffix separator ".".</param>
        /// <returns>If found, property object you can use for setting and getting the value from the property, otherwise
        ///          null.</returns>
        internal static SerializableProperty FindProperty(SceneObject root, string path, out string suffix)
        {
            suffix = null;

            if (string.IsNullOrEmpty(path) || root == null)
            {
                return(null);
            }

            string trimmedPath = path.Trim('/');

            string[] entries = trimmedPath.Split('/');

            // Find scene object referenced by the path
            SceneObject so      = root;
            int         pathIdx = 0;

            for (; pathIdx < entries.Length; pathIdx++)
            {
                string entry = entries[pathIdx];

                if (string.IsNullOrEmpty(entry))
                {
                    continue;
                }

                // Not a scene object, break
                if (entry[0] != '!')
                {
                    break;
                }

                string childName = entry.Substring(1, entry.Length - 1);
                so = so.FindChild(childName);

                if (so == null)
                {
                    break;
                }
            }

            // Child scene object couldn't be found
            if (so == null)
            {
                return(null);
            }

            // Path too short, no field entry
            if (pathIdx >= entries.Length)
            {
                return(null);
            }

            // Check if path is referencing a component, and if so find it
            Component component = null;

            {
                string entry = entries[pathIdx];
                if (entry[0] == ':')
                {
                    string componentName = entry.Substring(1, entry.Length - 1);

                    Component[] components = so.GetComponents();
                    component = Array.Find(components, x => x.GetType().Name == componentName);

                    // Cannot find component with specified type
                    if (component == null)
                    {
                        return(null);
                    }
                }
            }

            // Look for a field within a component
            if (component != null)
            {
                pathIdx++;
                if (pathIdx >= entries.Length)
                {
                    return(null);
                }

                SerializableObject componentObj = new SerializableObject(component);

                StringBuilder pathBuilder = new StringBuilder();
                for (; pathIdx < entries.Length - 1; pathIdx++)
                {
                    pathBuilder.Append(entries[pathIdx] + "/");
                }

                // Check last path entry for suffix and remove it
                int suffixIdx = entries[pathIdx].LastIndexOf(".");
                if (suffixIdx != -1)
                {
                    string entryNoSuffix = entries[pathIdx].Substring(0, suffixIdx);
                    suffix = entries[pathIdx].Substring(suffixIdx, entries[pathIdx].Length - suffixIdx);

                    pathBuilder.Append(entryNoSuffix);
                }
                else
                {
                    pathBuilder.Append(entries[pathIdx]);
                }

                return(componentObj.FindProperty(pathBuilder.ToString()));
            }
            else // Field is one of the builtin ones on the SceneObject itself
            {
                if ((pathIdx + 1) < entries.Length)
                {
                    return(null);
                }

                string entry = entries[pathIdx];
                if (entry == "Position")
                {
                    SerializableProperty property = new SerializableProperty(
                        SerializableProperty.FieldType.Vector3,
                        typeof(Vector3),
                        () => so.LocalPosition,
                        (x) => so.LocalPosition = (Vector3)x);

                    return(property);
                }
                else if (entry == "Rotation")
                {
                    SerializableProperty property = new SerializableProperty(
                        SerializableProperty.FieldType.Vector3,
                        typeof(Vector3),
                        () => so.LocalRotation.ToEuler(),
                        (x) => so.LocalRotation = Quaternion.FromEuler((Vector3)x));

                    return(property);
                }
                else if (entry == "Scale")
                {
                    SerializableProperty property = new SerializableProperty(
                        SerializableProperty.FieldType.Vector3,
                        typeof(Vector3),
                        () => so.LocalScale,
                        (x) => so.LocalScale = (Vector3)x);

                    return(property);
                }

                return(null);
            }
        }
示例#5
0
        /// <summary>
        /// Uses the provided path elements to find an dictionary element with the specified key, and returns a property
        /// to the element, or to a child property of that element.
        /// </summary>
        /// <param name="pathElements">Path elements representing field names and keys to look for.</param>
        /// <param name="elementIdx">Index in the <paramref name="pathElements"/> array to start the search at.</param>
        /// <returns>Property representing the final path element, or null if not found (key or property with that path
        ///          doesn't exist).</returns>
        internal SerializableProperty FindProperty(PropertyPathElement[] pathElements, int elementIdx)
        {
            if (pathElements[elementIdx].key == null)
            {
                return(null);
            }

            object key = null;

            switch (KeyPropertyType)
            {
            case SerializableProperty.FieldType.String:
                key = pathElements[elementIdx].key;
                break;

            case SerializableProperty.FieldType.Bool:
                bool boolKey;
                if (bool.TryParse(pathElements[elementIdx].key, out boolKey))
                {
                    key = boolKey;
                }

                break;

            case SerializableProperty.FieldType.Int:
                int intKey;
                if (int.TryParse(pathElements[elementIdx].key, out intKey))
                {
                    key = intKey;
                }

                break;

            case SerializableProperty.FieldType.Float:
                float floatKey;
                if (float.TryParse(pathElements[elementIdx].key, out floatKey))
                {
                    key = floatKey;
                }

                break;
            }

            if (key == null)
            {
                return(null);
            }

            SerializableProperty property = GetProperty(key).Value;

            if (elementIdx == (pathElements.Length - 1))
            {
                return(property);
            }

            if (property != null)
            {
                return(property.FindProperty(pathElements, elementIdx + 1));
            }

            return(null);
        }