Пример #1
0
        private static Object SerializeObject(object obj, Dictionary <object, Object> serialized, bool skipNoCopyAttribute = false, Action <object, Object> onAfterSerialize = null)
        ///If skipNotCopyAttribute will skip all fields marked with NoCopy attribute
        {
            //null
            if (obj == null)
            {
                return(Object.Null);
            }

            //if (obj is UnityEngine.Object && (UnityEngine.Object)obj == (UnityEngine.Object)null)
            //	return Object.Null;
            //in some cases treats other graph as null. Better skip nulls on deserialize

            //already serialized
            if (serialized.TryGetValue(obj, out Object serObj))
            {
                return(serObj);
            }

            //type ignored
            //if (obj is ) return Object.Null;

            serObj = new Object();
            serialized.Add(obj, serObj);             //adding before calling any other Serialize to prevent infinite loops
            serObj.refId = serialized.Count - 1;

            Type type = obj.GetType();

            serObj.type = type.AssemblyQualifiedName;

            //string
            if (type == typeof(string))
            {
                serObj.special = (string)obj;
            }

            //guid
            if (type == typeof(Guid))
            {
                serObj.special = ((Guid)obj).ToString();
            }

            //unity object
            //else if (type.IsSubclassOf(typeof(UnityEngine.Object))  &&  !type.IsSubclassOf(typeof(UnityEngine.ScriptableObject)))
            else if (type.IsSubclassOf(typeof(UnityEngine.Object)))
            {
                serObj.uniObj = (UnityEngine.Object)obj;
            }

            //serializer
            else if (type == typeof(Object[]))
            {
                throw new Exception("Serializer is trying to serialize serializer objects. This is causing infinite loop.");
            }

            //reflections
            else if (type.IsSubclassOf(typeof(MemberInfo)))
            {
                if (type.IsSubclassOf(typeof(Type)))                 //could be MonoType
                {
                    serObj.special = ((Type)obj).AssemblyQualifiedName;
                }

                else
                {
                    MemberInfo mi = (MemberInfo)obj;
                    serObj.special = mi.Name + ", " + mi.DeclaringType.AssemblyQualifiedName;
                }
            }

            //primitives (if they were assigned to object field)
            else if (type.IsPrimitive)
            {
                serObj.values = new Value[1];
                serObj.values[0].Set(obj, type);
            }

            //animation curve
            else if (type == typeof(AnimationCurve))
            {
                AnimationCurve curve = (AnimationCurve)obj;

                serObj.values    = new Value[3];
                serObj.values[0] = SerializeObject(curve.keys, serialized, onAfterSerialize: onAfterSerialize).refId;
                serObj.values[1].Set((int)curve.preWrapMode, typeof(int));
                serObj.values[2].Set((int)curve.postWrapMode, typeof(int));
            }

            //array
            else if (type.IsArray)
            {
                Array array = (Array)obj;

                serObj.fields = null;
                serObj.values = new Value[array.Length];

                Type elementType            = type.GetElementType();
                bool elementTypeIsPrimitive = elementType.IsPrimitive;

                for (int i = 0; i < array.Length; i++)
                {
                    object val = array.GetValue(i);

                    Value serVal = new Value();
                    if (elementTypeIsPrimitive)
                    {
                        serVal.Set(val, elementType);
                    }
                    else
                    {
                        serVal = SerializeObject(val, serialized, onAfterSerialize: onAfterSerialize).refId;
                    }

                    serObj.values[i] = serVal;
                }
            }

            //another more relable Unity Object null check
            else if (type == typeof(UnityEngine.Object))
            {
                FieldInfo ptrField = type.GetField("m_CachedPtr", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                IntPtr    ptr      = (IntPtr)ptrField.GetValue(obj);
                if (ptr == IntPtr.Zero)
                {
                    return(Object.Null);
                }
            }

            //class/struct
            else
            {
                if (obj is ISerializationCallbackReceiver)
                {
                    ((ISerializationCallbackReceiver)obj).OnBeforeSerialize();
                }

                if (obj is IAlternativeType altTypeObj)
                {
                    serObj.altType = altTypeObj.AlternativeSerializationType.AssemblyQualifiedName;
                }

                FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

                //special cases when derive from list - adding base class values
                if (obj is IList || obj is IDictionary)
                {
                    ArrayTools.Append(ref fields, type.BaseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
                }

                List <FieldInfo> usedFields = new List <FieldInfo>();
                for (int f = 0; f < fields.Length; f++)
                {
                    FieldInfo field = fields[f];

                    if (field.IsLiteral)
                    {
                        continue;                                      //leaving constant fields blank
                    }
                    if (field.FieldType.IsPointer)
                    {
                        continue;                                                //skipping pointers (they make unity crash. Maybe require unsafe)
                    }
                    if (field.IsNotSerialized)
                    {
                        continue;
                    }

                    if (skipNoCopyAttribute)
                    {
                        object[] noCopyAttributes = field.GetCustomAttributes(typeof(NoCopyAttribute), false);
                        if (noCopyAttributes.Length != 0)
                        {
                            continue;                                                        //SOMEDAY: make NoCopy a serializer control attribute with values inside
                        }
                    }

                    usedFields.Add(field);
                }
                int usedFieldsCount = usedFields.Count;

                serObj.fields = new string[usedFieldsCount];
                serObj.values = new Value[usedFieldsCount];

                for (int f = 0; f < usedFieldsCount; f++)
                {
                    FieldInfo field = usedFields[f];

                    serObj.fields[f] = field.Name;

                    object val = field.GetValue(obj);

                    Value serVal = new Value();
                    if (field.FieldType.IsPrimitive)
                    {
                        serVal.Set(val, field.FieldType);
                    }
                    else
                    {
                        serVal = SerializeObject(val, serialized, onAfterSerialize: onAfterSerialize).refId;
                    }

                    serObj.values[f] = serVal;
                }

                if (obj is ICustomSerialization customObj)
                {
                    customObj.PostprocessAfterSerialize(serObj, serialized);
                }
            }

            onAfterSerialize?.Invoke(obj, serObj);

            return(serObj);
        }
Пример #2
0
        public static void SetUserData(this UnityEditor.AssetImporter importer, string param, string[] data, bool reload = false)
        {
            char endline = '\n';             //';'

            string userData = importer.userData;

            string[] userDataSplit = userData.Split('\n', ';');

            //preparing new data line
            if (data == null)
            {
                data = new string[0];
            }
            string newDataString = param + ":" + data.ToStringMemberwise(separator: ",");

            //param line number (-1 if not found)
            int numInSplit = -1;

            for (int i = 0; i < userDataSplit.Length; i++)
            {
                if (userDataSplit[i].StartsWith(param + ":"))
                {
                    numInSplit = i;
                }
            }

            //erasing empty data
            if (numInSplit >= 0 && data.Length == 0)
            {
                ArrayTools.RemoveAt(ref userDataSplit, numInSplit);
            }

            //replacing line
            if (numInSplit >= 0 && data.Length != 0)
            {
                userDataSplit[numInSplit] = newDataString;
            }

            //adding new line
            if (numInSplit == -1 && data.Length != 0)
            {
                ArrayTools.Add(ref userDataSplit, newDataString);
            }

            //to string
            string newUserData = "";

            for (int i = 0; i < userDataSplit.Length; i++)
            {
                if (userDataSplit[i].Length == 0)
                {
                    continue;
                }
                newUserData += userDataSplit[i];
                if (i != userDataSplit.Length - 1)
                {
                    newUserData += endline;
                }
            }

            //writing
            if (newUserData != userData)
            {
                importer.userData = newUserData;

                UnityEditor.EditorUtility.SetDirty(importer);
                UnityEditor.AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath);
                if (reload)
                {
                    UnityEditor.AssetDatabase.Refresh();
                }
            }
        }