Esempio n. 1
0
        public static UndoActionObject FromJson(string json)
        {
            //
            // Here be dragons. Thou art forewarned
            //
            var serialized = FlaxEngine.Json.JsonSerializer.Deserialize <SerializedUndoActionObject>(json);

            UndoActionObject undoActionObject = (UndoActionObject)System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(UndoActionObject));

            TargetInstanceField.SetValue(undoActionObject, serialized.TargetInstance);
            DataField.SetValue(undoActionObject, serialized.Data);

            var memberInfoPaths = new MemberInfoPath[serialized.MemberStacks.Length];

            for (int i = 0; i < memberInfoPaths.Length; i++)
            {
                // Prepare the stack entries
                var entries = new MemberInfoPath.Entry[serialized.MemberStacks[i].Length];
                for (int j = 0; j < entries.Length; j++)
                {
                    var        serializedEntry = serialized.MemberStacks[i][j];
                    Type       type            = Type.GetType(serializedEntry.AssemblyQualifiedName);
                    MemberInfo memberInfo;
                    if (serializedEntry.MemberInfoType == typeof(MethodInfo))
                    {
                        memberInfo = type.GetMethod(serializedEntry.Path);
                    }
                    else if (serializedEntry.MemberInfoType == typeof(FieldInfo))
                    {
                        memberInfo = type.GetField(serializedEntry.Path);
                    }
                    else if (serializedEntry.MemberInfoType == typeof(PropertyInfo))
                    {
                        memberInfo = type.GetProperty(serializedEntry.Path);
                    }
                    else
                    {
                        throw new Exception("Unexpected MemberInfoType: " + serializedEntry.MemberInfoType);
                    }

                    entries[j] = new MemberInfoPath.Entry(new ScriptMemberInfo(memberInfo), serializedEntry.Index);
                }

                // MemberInfoPath is a struct, we have to jump through some hoops to set a private field
                object boxedMemberInfoPath = memberInfoPaths[i];
                StackField.SetValue(boxedMemberInfoPath, entries);
                memberInfoPaths[i] = (MemberInfoPath)boxedMemberInfoPath;
            }
            MembersField.SetValue(undoActionObject, memberInfoPaths);

            return(undoActionObject);
        }
        // ---------[ UTILITY ]---------
        /// <summary>Generates the MemberInfoPath data for the given MemberInfo.</summary>
        private static List <MemberInfoPath> GenerateMemberInfoPathList(FieldInfo[] fieldInfoArray,
                                                                        PropertyInfo[] propertyInfoArray,
                                                                        string[] membersToIgnore,
                                                                        bool displayEnumerables,
                                                                        bool displayNested,
                                                                        string pathPrefix)
        {
            List <MemberInfoPath> retVal = new List <MemberInfoPath>();
            List <MemberInfoPath> nested = new List <MemberInfoPath>();

            // process root members
            foreach (FieldInfo field in fieldInfoArray)
            {
                // obsolete check
                if (Attribute.IsDefined(field, typeof(ObsoleteAttribute)))
                {
                    continue;
                }

                // enumerable check
                if (!displayEnumerables &&
                    MemberReferenceDropdownDrawer.IsTypeEnumerable(field.FieldType))
                {
                    continue;
                }

                // mask check
                string fullName   = pathPrefix + field.Name;
                bool   skipMember = false;
                for (int i = 0; i < membersToIgnore.Length && !skipMember; ++i)
                {
                    skipMember = (membersToIgnore[i] == fullName);
                }
                if (skipMember)
                {
                    continue;
                }

                // add to list
                MemberInfoPath mip = new MemberInfoPath()
                {
                    pathPrefix = pathPrefix,
                    memberType = field.FieldType,
                    info       = field,
                };
                retVal.Add(mip);

                // add nested?
                if (displayNested &&
                    field.FieldType.IsClass &&
                    field.FieldType != typeof(string))
                {
                    nested.Add(mip);
                }
            }
            // process root members
            foreach (PropertyInfo property in propertyInfoArray)
            {
                // obsolete check
                if (Attribute.IsDefined(property, typeof(ObsoleteAttribute)))
                {
                    continue;
                }

                // enumerable check
                if (!displayEnumerables &&
                    MemberReferenceDropdownDrawer.IsTypeEnumerable(property.PropertyType))
                {
                    continue;
                }

                // mask check
                string fullName   = pathPrefix + property.Name;
                bool   skipMember = false;
                for (int i = 0; i < membersToIgnore.Length && !skipMember; ++i)
                {
                    skipMember = (membersToIgnore[i] == fullName);
                }
                if (skipMember)
                {
                    continue;
                }

                // add to list
                MemberInfoPath mip = new MemberInfoPath()
                {
                    pathPrefix = pathPrefix,
                    memberType = property.PropertyType,
                    info       = property,
                };
                retVal.Add(mip);

                // add nested?
                if (displayNested &&
                    property.PropertyType.IsClass &&
                    property.PropertyType != typeof(string))
                {
                    nested.Add(mip);
                }
            }

            // process nested
            foreach (MemberInfoPath nestedInfo in nested)
            {
                string prefix = pathPrefix + nestedInfo.info.Name + ".";

                FieldInfo[] nestedFields
                    = nestedInfo.memberType.GetFields(BindingFlags.Instance | BindingFlags.Public);
                PropertyInfo[] nestedProperties
                    = nestedInfo.memberType.GetProperties(BindingFlags.Instance | BindingFlags.Public);

                retVal.AddRange(GenerateMemberInfoPathList(nestedFields,
                                                           nestedProperties,
                                                           membersToIgnore,
                                                           displayEnumerables,
                                                           displayNested,
                                                           prefix));
            }

            return(retVal);
        }