private void DrawToolbar() { SirenixEditorGUI.BeginHorizontalToolbar(); { // Label if (info.DropZone != null && DragAndDropManager.IsDragInProgress && info.DropZone.IsAccepted == false) { GUIHelper.PushGUIEnabled(false); } if (info.Property.ValueEntry.ListLengthChangedFromPrefab) { GUIHelper.PushIsBoldLabel(true); } if (info.ListConfig.HideFoldoutWhileEmpty && info.IsEmpty || info.CustomListDrawerOptions.Expanded) { GUILayout.Label(info.Label, GUILayoutOptions.ExpandWidth(false)); } else { info.Toggled.Value = SirenixEditorGUI.Foldout(info.Toggled.Value, info.Label ?? GUIContent.none); } if (info.Property.ValueEntry.ListLengthChangedFromPrefab) { GUIHelper.PopIsBoldLabel(); } if (info.CustomListDrawerOptions.Expanded) { info.Toggled.Value = true; } if (info.DropZone != null && DragAndDropManager.IsDragInProgress && info.DropZone.IsAccepted == false) { GUIHelper.PopGUIEnabled(); } GUILayout.FlexibleSpace(); // Item Count if (info.CustomListDrawerOptions.ShowItemCountHasValue ? info.CustomListDrawerOptions.ShowItemCount : info.ListConfig.ShowItemCount) { if (info.Property.ValueEntry.ValueState == PropertyValueState.CollectionLengthConflict) { GUILayout.Label(info.Count + " / " + info.CollectionResolver.MaxCollectionLength + " items", EditorStyles.centeredGreyMiniLabel); } else { GUILayout.Label(info.IsEmpty ? "Empty" : info.Count + " items", EditorStyles.centeredGreyMiniLabel); } } bool paging = info.CustomListDrawerOptions.PagingHasValue ? info.CustomListDrawerOptions.ShowPaging : true; bool hidePaging = info.ListConfig.HidePagingWhileCollapsed && info.Toggled.Value == false || info.ListConfig.HidePagingWhileOnlyOnePage && info.Count <= info.NumberOfItemsPerPage; int numberOfItemsPrPage = Math.Max(1, info.NumberOfItemsPerPage); int numberOfPages = Mathf.CeilToInt(info.Count / (float)numberOfItemsPrPage); int pageIndex = info.Count == 0 ? 0 : (info.StartIndex / numberOfItemsPrPage) % info.Count; // Paging if (paging) { bool disablePaging = paging && !hidePaging && (DragAndDropManager.IsDragInProgress || info.ShowAllWhilePaging || info.Toggled.Value == false); if (disablePaging) { GUIHelper.PushGUIEnabled(false); } if (!hidePaging) { if (pageIndex == 0) { GUIHelper.PushGUIEnabled(false); } if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleLeft, true)) { if (Event.current.button == 0) { info.StartIndex -= numberOfItemsPrPage; } else { info.StartIndex = 0; } } if (pageIndex == 0) { GUIHelper.PopGUIEnabled(); } var userPageIndex = EditorGUILayout.IntField((numberOfPages == 0 ? 0 : (pageIndex + 1)), GUILayoutOptions.Width(10 + numberOfPages.ToString(CultureInfo.InvariantCulture).Length * 10)) - 1; if (pageIndex != userPageIndex) { info.StartIndex = userPageIndex * numberOfItemsPrPage; } GUILayout.Label("/ " + numberOfPages); if (pageIndex == numberOfPages - 1) { GUIHelper.PushGUIEnabled(false); } if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleRight, true)) { if (Event.current.button == 0) { info.StartIndex += numberOfItemsPrPage; } else { info.StartIndex = numberOfItemsPrPage * numberOfPages; } } if (pageIndex == numberOfPages - 1) { GUIHelper.PopGUIEnabled(); } } pageIndex = info.Count == 0 ? 0 : (info.StartIndex / numberOfItemsPrPage) % info.Count; var newStartIndex = Mathf.Clamp(pageIndex * numberOfItemsPrPage, 0, Mathf.Max(0, info.Count - 1)); if (newStartIndex != info.StartIndex) { info.StartIndex = newStartIndex; var newPageIndex = info.Count == 0 ? 0 : (info.StartIndex / numberOfItemsPrPage) % info.Count; if (pageIndex != newPageIndex) { pageIndex = newPageIndex; info.StartIndex = Mathf.Clamp(pageIndex * numberOfItemsPrPage, 0, Mathf.Max(0, info.Count - 1)); } } info.EndIndex = Mathf.Min(info.StartIndex + numberOfItemsPrPage, info.Count); if (disablePaging) { GUIHelper.PopGUIEnabled(); } } else { info.StartIndex = 0; info.EndIndex = info.Count; } if (paging && hidePaging == false && info.ListConfig.ShowExpandButton) { if (info.Count < 300) { if (SirenixEditorGUI.ToolbarButton(info.ShowAllWhilePaging ? EditorIcons.TriangleUp : EditorIcons.TriangleDown, true)) { info.ShowAllWhilePaging = !info.ShowAllWhilePaging; } } else { info.ShowAllWhilePaging = false; } } // Add Button if (info.IsReadOnly == false && !info.HideAddButton) { info.ObjectPicker = ObjectPicker.GetObjectPicker(info, info.CollectionResolver.ElementType); var superHackyAddFunctionWeSeriouslyNeedANewListDrawer = CollectionDrawerStaticInfo.NextCustomAddFunction; CollectionDrawerStaticInfo.NextCustomAddFunction = null; if (SirenixEditorGUI.ToolbarButton(EditorIcons.Plus)) { if (superHackyAddFunctionWeSeriouslyNeedANewListDrawer != null) { superHackyAddFunctionWeSeriouslyNeedANewListDrawer(); } else if (info.GetCustomAddFunction != null) { var objs = new object[info.Property.Tree.WeakTargets.Count]; for (int i = 0; i < objs.Length; i++) { objs[i] = info.GetCustomAddFunction(info.Property.ParentValues[i]); } info.CollectionResolver.QueueAdd(objs); } else if (info.GetCustomAddFunctionVoid != null) { info.GetCustomAddFunctionVoid(info.Property.ParentValues[0]); this.Property.ValueEntry.WeakValues.ForceMarkDirty(); } else if (info.CustomListDrawerOptions.AlwaysAddDefaultValue) { var objs = new object[info.Property.Tree.WeakTargets.Count]; if (info.Property.ValueEntry.SerializationBackend == SerializationBackend.Unity) { for (int i = 0; i < objs.Length; i++) { objs[i] = UnitySerializationUtility.CreateDefaultUnityInitializedObject(info.CollectionResolver.ElementType); } } else { for (int i = 0; i < objs.Length; i++) { if (info.CollectionResolver.ElementType.IsValueType) { objs[i] = Activator.CreateInstance(info.CollectionResolver.ElementType); } else { objs[i] = null; } } } //info.ListValueChanger.AddListElement(objs, "Add default value"); info.CollectionResolver.QueueAdd(objs); } else if (info.CollectionResolver.ElementType.InheritsFrom <UnityEngine.Object>() && Event.current.modifiers == EventModifiers.Control) { info.CollectionResolver.QueueAdd(new object[info.Property.Tree.WeakTargets.Count]); } else { info.ObjectPicker.ShowObjectPicker( null, info.Property.GetAttribute <AssetsOnlyAttribute>() == null, GUIHelper.GetCurrentLayoutRect(), info.Property.ValueEntry.SerializationBackend == SerializationBackend.Unity); } } info.JumpToNextPageOnAdd = paging && (info.Count % numberOfItemsPrPage == 0) && (pageIndex + 1 == numberOfPages); } if (info.OnTitleBarGUI != null) { info.OnTitleBarGUI(info.Property.ParentValues[0]); } } SirenixEditorGUI.EndHorizontalToolbar(); }
void ISerializationCallbackReceiver.OnBeforeSerialize() { UnitySerializationUtility.SerializeUnityObject((UnityEngine.Object) this, ref this.serializationData, false, (SerializationContext)null); }
public virtual void ValidateUnityObjectRecursively(UnityEngine.Object value, ref List <ValidationResult> results) { if (results == null) { results = new List <ValidationResult>(); } if (object.ReferenceEquals(value, null)) { return; } var type = value.GetType(); bool odinSerialized = type.IsDefined <ShowOdinSerializedPropertiesInInspectorAttribute>(inherit: true); bool odinSerializesUnityMembers = false; IMemberSelector selector; if (odinSerialized) { var policyOverride = value as IOverridesSerializationPolicy; if (policyOverride != null) { selector = new SerializationPolicyMemberSelector(policyOverride.SerializationPolicy ?? SerializationPolicies.Unity); odinSerializesUnityMembers = policyOverride.OdinSerializesUnityFields; } else { selector = OdinMemberSelector; } } else { selector = UnityMemberSelector; } this.ValidateValue(value, value, ref results); HashSet <object> seenReferences = new HashSet <object>(ReferenceEqualityComparer <object> .Default); HashSet <MemberInfo> seenMembers = new HashSet <MemberInfo>(FastMemberComparer.Instance); foreach (var member in selector.SelectMembers(type)) { IMemberSelector childSelector = selector; if (odinSerialized && !odinSerializesUnityMembers && UnitySerializationUtility.GuessIfUnityWillSerialize(member)) { childSelector = UnityMemberSelector; } var memberValue = GetMemberValue(member, value, results); var memberValueType = memberValue == null?member.GetReturnType() : memberValue.GetType(); ValidateMemberRecursive(value, member, memberValue, memberValueType, childSelector, value, new List <ValidationPathStep>() { new ValidationPathStep() { Value = memberValue, Member = member, StepString = member.Name } }, seenReferences, seenMembers, results, 0); } }
public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) { FieldDeclarationSyntax fieldDeclaration = (FieldDeclarationSyntax)base.VisitFieldDeclaration(node); var typeInfo = model.GetTypeInfo(node.Declaration.Type); if (typeInfo.Type == null) { UdonSharpUtils.LogWarning($"Could not find symbol for {node}"); return(fieldDeclaration); } ITypeSymbol rootType = typeInfo.Type; while (rootType.TypeKind == TypeKind.Array) { rootType = ((IArrayTypeSymbol)rootType).ElementType; } if (rootType.TypeKind == TypeKind.Error || rootType.TypeKind == TypeKind.Unknown) { UdonSharpUtils.LogWarning($"Type {typeInfo.Type} for field '{fieldDeclaration.Declaration}' is invalid"); return(fieldDeclaration); } IFieldSymbol firstFieldSymbol = (IFieldSymbol)model.GetDeclaredSymbol(node.Declaration.Variables.First()); rootType = firstFieldSymbol.Type; // If the field is not serialized or is using Odin already, we don't need to do anything. if (!IsFieldSerializedWithoutOdin(firstFieldSymbol)) { return(fieldDeclaration); } // Getting the type may fail if it's a user type that hasn't compiled on the C# side yet. For now we skip it, but we should do a simplified check for jagged arrays if (!TypeSymbol.TryGetSystemType(rootType, out Type systemType)) { return(fieldDeclaration); } // If Unity can serialize the type, we're good if (UnitySerializationUtility.GuessIfUnityWillSerialize(systemType)) { return(fieldDeclaration); } // Common type that gets picked up as serialized but shouldn't be // todo: Add actual checking for if a type is serializable, which isn't consistent. Unity/System library types in large part are serializable but don't have the System.Serializable tag, but types outside those assemblies need the tag to be serialized. if (systemType == typeof(VRCPlayerApi) || systemType == typeof(VRCPlayerApi[])) { return(fieldDeclaration); } Modified = true; NameSyntax odinSerializeName = IdentifierName("VRC"); odinSerializeName = QualifiedName(odinSerializeName, IdentifierName("Udon")); odinSerializeName = QualifiedName(odinSerializeName, IdentifierName("Serialization")); odinSerializeName = QualifiedName(odinSerializeName, IdentifierName("OdinSerializer")); odinSerializeName = QualifiedName(odinSerializeName, IdentifierName("OdinSerialize")); // Somehow it seems like there's literally no decent way to maintain the indent on inserted code so we'll just inline the comment because Roslyn is dumb SyntaxTrivia commentTrivia = Comment(" /* UdonSharp auto-upgrade: serialization */ "); AttributeListSyntax newAttribList = AttributeList(SeparatedList(new [] { Attribute(odinSerializeName) })).WithTrailingTrivia(commentTrivia); SyntaxList <AttributeListSyntax> attributeList = fieldDeclaration.AttributeLists; if (attributeList.Count > 0) { SyntaxTriviaList trailingTrivia = attributeList.Last().GetTrailingTrivia(); trailingTrivia = trailingTrivia.Insert(0, commentTrivia); attributeList.Replace(attributeList[attributeList.Count - 1], attributeList[attributeList.Count - 1].WithoutTrailingTrivia()); newAttribList = newAttribList.WithTrailingTrivia(trailingTrivia); } else { newAttribList = newAttribList.WithLeadingTrivia(fieldDeclaration.GetLeadingTrivia()); fieldDeclaration = fieldDeclaration.WithoutLeadingTrivia(); } attributeList = attributeList.Add(newAttribList); return(fieldDeclaration.WithAttributeLists(attributeList)); }
public bool ScanScenes(string[] scenePaths, bool includeSceneDependencies, bool showProgressBar) { if (scenePaths.Length == 0) { return(true); } bool formerForceEditorModeSerialization = UnitySerializationUtility.ForceEditorModeSerialization; try { UnitySerializationUtility.ForceEditorModeSerialization = true; bool hasDirtyScenes = false; for (int i = 0; i < EditorSceneManager.sceneCount; i++) { if (EditorSceneManager.GetSceneAt(i).isDirty) { hasDirtyScenes = true; break; } } if (hasDirtyScenes && !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { return(false); } var oldSceneSetup = EditorSceneManager.GetSceneManagerSetup(); try { for (int i = 0; i < scenePaths.Length; i++) { var scenePath = scenePaths[i]; if (showProgressBar && EditorUtility.DisplayCancelableProgressBar("Scanning scenes for AOT support", "Scene " + (i + 1) + "/" + scenePaths.Length + " - " + scenePath, (float)i / scenePaths.Length)) { return(false); } EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single); var sceneGOs = UnityEngine.Object.FindObjectsOfType <GameObject>(); foreach (var go in sceneGOs) { if ((go.hideFlags & HideFlags.DontSaveInBuild) == 0) { foreach (var component in go.GetComponents <ISerializationCallbackReceiver>()) { try { this.allowRegisteringScannedTypes = true; component.OnBeforeSerialize(); var prefabSupporter = component as ISupportsPrefabSerialization; if (prefabSupporter != null) { // Also force a serialization of the object's prefab modifications, in case there are unknown types in there List <UnityEngine.Object> objs = null; var mods = UnitySerializationUtility.DeserializePrefabModifications(prefabSupporter.SerializationData.PrefabModifications, prefabSupporter.SerializationData.PrefabModificationsReferencedUnityObjects); UnitySerializationUtility.SerializePrefabModifications(mods, ref objs); } } finally { this.allowRegisteringScannedTypes = false; } } } } } // Load a new empty scene that will be unloaded immediately, just to be sure we completely clear all changes made by the scan EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); } finally { if (oldSceneSetup != null && oldSceneSetup.Length > 0) { if (showProgressBar) { EditorUtility.DisplayProgressBar("Restoring scene setup", "", 1.0f); } EditorSceneManager.RestoreSceneManagerSetup(oldSceneSetup); } } if (includeSceneDependencies) { for (int i = 0; i < scenePaths.Length; i++) { var scenePath = scenePaths[i]; if (showProgressBar && EditorUtility.DisplayCancelableProgressBar("Scanning scene dependencies for AOT support", "Scene " + (i + 1) + "/" + scenePaths.Length + " - " + scenePath, (float)i / scenePaths.Length)) { return(false); } string[] dependencies = AssetDatabase.GetDependencies(scenePath, recursive: true); foreach (var dependency in dependencies) { this.ScanAsset(dependency, includeAssetDependencies: false); // All dependencies of this asset were already included recursively by Unity } } } return(true); } finally { if (showProgressBar) { EditorUtility.ClearProgressBar(); } UnitySerializationUtility.ForceEditorModeSerialization = formerForceEditorModeSerialization; } }
void ISerializationCallbackReceiver.OnAfterDeserialize() { UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData); this.OnAfterDeserialize(); }
/// <summary> /// Draws The Property. /// </summary> protected override void DrawPropertyLayout(InspectorProperty property, OdinSerializeAttribute attribute, GUIContent label) { if (GlobalSerializationConfig.Instance.HideOdinSerializeAttributeWarningMessages || property.Parent != null) { this.CallNextDrawer(property, label); return; } PropertyContext <string> msg; if (property.Context.Get(this, "Message", out msg)) { if (property.Info.PropertyType == PropertyType.ValueType || property.Info.PropertyType == PropertyType.ReferenceType) { string message = null; if (property.ValueEntry.SerializationBackend == SerializationBackend.None) { message = "The following property is marked with the [OdinSerialize] attribute, " + "but the property is not part of any object that uses the ODIN Serialization Protocol. \n\n" + "Are you perhaps forgetting to inherit from one of our serialized base classes such as SerializedMonoBehaviour or SerializedScriptableObject? \n\n"; var fieldInfo = property.Info.MemberInfo as System.Reflection.FieldInfo; if (fieldInfo != null && fieldInfo.IsPublic && property.Info.GetAttribute <System.NonSerializedAttribute>() == null) { message += "ODIN will also serialize public fields by default, so are you sure you need to mark the field with the [OdinSerialize] attribute?\n\n"; } } // We need a way to find out if Unity will also serialize it. else if (property.ValueEntry.SerializationBackend == SerializationBackend.ODIN && UnitySerializationUtility.GuessIfUnityWillSerialize(property.Info.MemberInfo)) { message = "The following property is marked with the [OdinSerialize] attribute, but Unity is also serializing it. " + "You can either remove the [OdinSerialize] attribute and let Unity serialize it, or you can use the [NonSerialized] " + "attribute together with the [OdinSerialize] attribute if you want ODIN to serialize it instead of Unity.\n\n"; bool isCustomSerializableType = property.Info.MemberInfo.DeclaringType.GetAttribute <System.SerializableAttribute>() != null && (property.Info.MemberInfo.DeclaringType.Assembly.GetAssemblyTypeFlag() & AssemblyTypeFlags.CustomTypes) != 0; if (isCustomSerializableType) { message += "ODIN's default serialization protocol does not require a type to be marked with the [Serializable] attribute in order for it to be serialized, which Unity does. " + "Therefore you could remove the System.Serializable attribute from " + property.Info.MemberInfo.DeclaringType.GetNiceFullName() + " if you want Unity never to serialize the type.\n\n"; } } if (message != null) { message += "Check out our online manual for more information.\n\n"; message += "This message can be disabled in the 'Tools > ODIN Inspector > Preferences > Serialization' window, but it is recommended that you don't."; } msg.Value = message; } } if (msg.Value != null) { AllEditorGUI.WarningMessageBox(msg.Value); } this.CallNextDrawer(property, label); }
public void OnAfterDeserialize() { UnitySerializationUtility.DeserializeUnityObject(this, ref serializationData); }
private static MemberSerializationInfo CreateInfoFor(MemberInfo member, SerializationBackendFlags serializationBackend) { SerializationFlags flags = 0; // Is the member a field, property or auto-property? if (member is FieldInfo) { var f = member as FieldInfo; flags |= SerializationFlags.Field; if (f.IsPublic) { flags |= SerializationFlags.Public; } } else if (member is PropertyInfo) { var p = member as PropertyInfo; flags |= SerializationFlags.Property; if (p.GetGetMethod() != null && p.GetGetMethod().IsPublic || p.GetSetMethod() != null && p.GetSetMethod().IsPublic) { flags |= SerializationFlags.Public; } if (p.IsAutoProperty()) { flags |= SerializationFlags.AutoProperty; } } // Will Unity serialize the member? if ((serializationBackend & SerializationBackendFlags.Unity) != 0 && UnitySerializationUtility.GuessIfUnityWillSerialize(member)) { flags |= SerializationFlags.SerializedByUnity; } // Will Odin serialize the member? if ((serializationBackend & SerializationBackendFlags.Odin) != 0 && UnitySerializationUtility.OdinWillSerialize(member, false)) { flags |= SerializationFlags.SerializedByOdin; } // Does the member have a SerializeField attribute? if (member.HasCustomAttribute <SerializeField>()) { flags |= SerializationFlags.SerializeFieldAttribute; } // Does the member have a OdinSerialize attribute? if (member.HasCustomAttribute <OdinSerializeAttribute>()) { flags |= SerializationFlags.OdinSerializeAttribute; } // Does the member have a NonSerialized attribute? if (member.HasCustomAttribute <NonSerializedAttribute>()) { flags |= SerializationFlags.NonSerializedAttribute; } // Does Unity support serializing the type? if (serializationBackend.HasAll(SerializationBackendFlags.Unity) && UnitySerializationUtility.GuessIfUnityWillSerialize(member.GetReturnType())) { flags |= SerializationFlags.TypeSupportedByUnity; } return(new MemberSerializationInfo(member, CreateNotes(member, flags, serializationBackend), flags, serializationBackend)); }
static DrawerLocator() { // This method is *very* expensive performance-wise and generates lots of garbage due to liberal use of LINQ for readability. // This is acceptable, as it only runs once per AppDomain reload, and only ever in the editor. // // First, get all relevant types // var allTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes | AssemblyTypeFlags.UnityEditorTypes) .Where(type => type.IsAbstract == false && type.IsClass && (typeof(OdinDrawer).IsAssignableFrom(type) || (typeof(GUIDrawer).IsAssignableFrom(type) && (!(type.Namespace ?? "").StartsWith("Unity", StringComparison.InvariantCulture) || !ExcludeUnityDrawers.Contains(type.Name))))) .ToArray(); // // Find all regular Unity property and decorator drawers and create alias drawers for them // IEnumerable <Type> unityPropertyDrawers; IEnumerable <Type> unityPropertyAttributeDrawers; IEnumerable <Type> unityDecoratorDrawers; if (DrawerLocator.CustomPropertyDrawerTypeField != null && DrawerLocator.CustomPropertyDrawerUseForChildrenField != null) { unityPropertyDrawers = allTypes.Where(type => type.IsGenericTypeDefinition == false && typeof(PropertyDrawer).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null) .SelectMany(type => type.GetCustomAttributes <CustomPropertyDrawer>(true).Select(attr => new { Type = type, Attribute = attr })) .Where(n => { if (n.Attribute != null) { var drawnType = CustomPropertyDrawerTypeField.GetValue(n.Attribute) as Type; if (drawnType != null && !typeof(PropertyAttribute).IsAssignableFrom(drawnType) && UnitySerializationUtility.GuessIfUnityWillSerialize(drawnType)) { return(true); } } return(false); }) .Select(n => { var drawnType = (Type)CustomPropertyDrawerTypeField.GetValue(n.Attribute); if (drawnType.IsAbstract || (bool)DrawerLocator.CustomPropertyDrawerUseForChildrenField.GetValue(n.Attribute)) { var tArg = typeof(AbstractTypeUnityPropertyDrawer <, ,>).GetGenericArguments()[2]; return(typeof(AbstractTypeUnityPropertyDrawer <, ,>).MakeGenericType(n.Type, drawnType, tArg)); } else { return(typeof(UnityPropertyDrawer <,>).MakeGenericType(n.Type, drawnType)); } }); unityPropertyAttributeDrawers = allTypes.Where(type => type.IsGenericTypeDefinition == false && typeof(PropertyDrawer).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null) .SelectMany(type => type.GetCustomAttributes <CustomPropertyDrawer>(true).Select(attr => new { Type = type, Attribute = attr })) .Where(n => { if (n.Attribute != null) { var drawnType = CustomPropertyDrawerTypeField.GetValue(n.Attribute) as Type; if (drawnType != null && typeof(PropertyAttribute).IsAssignableFrom(drawnType)) { return(true); } } return(false); }) .Select(n => { Type drawnType = (Type)CustomPropertyDrawerTypeField.GetValue(n.Attribute); if ((bool)DrawerLocator.CustomPropertyDrawerUseForChildrenField.GetValue(n.Attribute)) { var tAttributeArgParam = typeof(UnityPropertyAttributeDrawer <, ,>).GetGenericArguments()[1]; return(typeof(UnityPropertyAttributeDrawer <, ,>).MakeGenericType(n.Type, tAttributeArgParam, drawnType)); } else { return(typeof(UnityPropertyAttributeDrawer <, ,>).MakeGenericType(n.Type, drawnType, typeof(PropertyAttribute))); } }); unityDecoratorDrawers = allTypes.Where(type => type.IsGenericTypeDefinition == false && typeof(DecoratorDrawer).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null) .Select(type => new { Type = type, Attribute = type.GetCustomAttribute <CustomPropertyDrawer>(true) }) .Where(n => n.Attribute != null) .Select(n => new { Type = n.Type, Attribute = n.Attribute, DrawnType = CustomPropertyDrawerTypeField.GetValue(n.Attribute) as Type }) .Where(n => n.DrawnType != null && typeof(PropertyAttribute).IsAssignableFrom(n.DrawnType)) .Select(n => { if ((bool)DrawerLocator.CustomPropertyDrawerUseForChildrenField.GetValue(n.Attribute)) { var tAttributeArgParam = typeof(UnityDecoratorAttributeDrawer <, ,>).GetGenericArguments()[1]; return(typeof(UnityDecoratorAttributeDrawer <, ,>).MakeGenericType(n.Type, tAttributeArgParam, n.DrawnType)); } else { return(typeof(UnityDecoratorAttributeDrawer <, ,>).MakeGenericType(n.Type, n.DrawnType, typeof(PropertyAttribute))); } }); } else { Debug.LogWarning("Could not find internal fields 'm_Type' and/or 'm_UseForChildren' in type CustomPropertyDrawer; Unity PropertyDrawers and DecoratorDrawers have been disabled in the inspector."); unityPropertyDrawers = Enumerable.Empty <Type>(); unityPropertyAttributeDrawers = Enumerable.Empty <Type>(); unityDecoratorDrawers = Enumerable.Empty <Type>(); } // // Find, group and sort all defined property drawer types // DrawerLocator.PropertyDrawerInfos = allTypes.Where(type => type.ImplementsOpenGenericClass(typeof(OdinValueDrawer <>)) && type.GetConstructor(Type.EmptyTypes) != null && type.IsDefined <OdinDrawerAttribute>(false)) .Append(unityPropertyDrawers) .Select(drawerType => { Type drawnType; if (!DrawerIsValid(drawerType, out drawnType) || drawnType == null) { return(null); } return(new DrawerInfo(drawerType, drawnType, null, drawerType.GetAttribute <OdinDrawerAttribute>(false))); }) .Where(info => info != null) .Distinct() .OrderByDescending(info => info.Priority) .ToList(); DrawerLocator.AttributeDrawerInfos = allTypes.Where(type => type.ImplementsOpenGenericClass(typeof(OdinAttributeDrawer <>)) && type.GetConstructor(Type.EmptyTypes) != null && type.IsDefined <OdinDrawerAttribute>(false)) .Append(unityDecoratorDrawers) .Append(unityPropertyAttributeDrawers) .Select(type => { if (type.ImplementsOpenGenericClass(typeof(OdinAttributeDrawer <,>))) { Type drawnType; if (!DrawerIsValid(type, out drawnType)) { return(null); } Type[] args = type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinAttributeDrawer <,>)); return(new DrawerInfo(type, drawnType, args[0], type.GetAttribute <OdinDrawerAttribute>(false))); } else { return(new DrawerInfo(type, null, type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinAttributeDrawer <>))[0], type.GetAttribute <OdinDrawerAttribute>(false))); } }) .Where(info => info != null) .Distinct() .OrderByDescending(info => info.Priority) .ToList(); DrawerLocator.GroupDrawerInfos = allTypes.Where(type => type.IsGenericTypeDefinition == false && type.IsGenericType == false && type.ImplementsOpenGenericClass(typeof(OdinGroupDrawer <>)) && type.GetConstructor(Type.EmptyTypes) != null) .Select(type => new DrawerInfo(type, null, type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinGroupDrawer <>))[0], type.GetAttribute <OdinDrawerAttribute>(false))) .Where(info => info.OdinDrawerAttribute != null) .Distinct() .OrderByDescending(info => info.Priority) .ToList(); // // Register found drawers in various dictionaries // for (int i = 0; i < DrawerLocator.PropertyDrawerInfos.Count; i++) { var info = DrawerLocator.PropertyDrawerInfos[i]; DrawerLocator.DrawerTypePriorityLookup[info.DrawerType] = info.Priority; //Debug.Log("Found value drawer: " + info); } for (int i = 0; i < DrawerLocator.AttributeDrawerInfos.Count; i++) { var info = DrawerLocator.AttributeDrawerInfos[i]; DrawerLocator.DrawerTypePriorityLookup[info.DrawerType] = info.Priority; //Debug.Log("Found attribute drawer: " + info); // Also register in attribute value drawer maps if (info.DrawnValueType != null) { List <DrawerInfo> list; if (!DrawerLocator.AttributeDrawerMap.TryGetValue(info.DrawnAttributeType, out list)) { list = new List <DrawerInfo>(); DrawerLocator.AttributeDrawerMap.Add(info.DrawnAttributeType, list); } list.Add(info); } } }
public void OnBeforeSerialize() { UnitySerializationUtility.SerializeUnityObject(this, ref serializationData); }
public void LoadData() { UnitySerializationUtility.DeserializeUnityObject(this, ref this.serialization_data); //Debug.Log("LoadData"); }
public static bool GuessIfUnityWillSerialize([NotNull] System.Reflection.MemberInfo memberInfo, [CanBeNull] object value) { #if DONT_USE_ODIN_SERIALIZER if (memberInfo.IsStatic()) { return(false); } var declaringType = memberInfo.DeclaringType; if (!(memberInfo is System.Reflection.FieldInfo)) { return(false); } if (!declaringType.IsSerializable) { return(false); } if (declaringType.IsGenericType) { if (declaringType.IsGenericTypeDefinition) { return(false); } return(declaringType.GetGenericTypeDefinition() == Types.List); } return(declaringType.IsSerializable && memberInfo is System.Reflection.FieldInfo); #else var field = memberInfo as System.Reflection.FieldInfo; if (field != null && field.IsInitOnly) { return(false); } var fieldType = memberInfo.DeclaringType; // Generic types are not supported, even with the SerializeReference attribute - with the exceptin of List<>. if (fieldType.IsGenericType) { return(fieldType.GetGenericTypeDefinition() == Types.List); } #if UNITY_2019_3_OR_NEWER // With SerializeReference attribute Unity can serialize interface values if value does not derive from UnityEngine.Object if (memberInfo.GetCustomAttributes(typeof(SerializeReference), false).Length > 0) { return(value == null || !Types.UnityObject.IsAssignableFrom(value.GetType())); } #endif if (fieldType.IsAbstract) { return(false); } if (fieldType == Types.SystemObject) { return(false); } return(UnitySerializationUtility.GuessIfUnityWillSerialize(memberInfo)); #endif }
public void LoadData() { UnitySerializationUtility.DeserializeUnityObject(this, ref this.serialization_data); FixNullGraphInstace(!is_ready); is_ready = true; }
private bool ProcessScenes() { var scenePaths = AssetDatabase.FindAssets("t:Scene") .Select(n => AssetDatabase.GUIDToAssetPath(n)) .ToList(); bool hasDirtyScenes = false; for (int i = 0; i < EditorSceneManager.sceneCount; i++) { if (EditorSceneManager.GetSceneAt(i).isDirty) { hasDirtyScenes = true; break; } } if (hasDirtyScenes && !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { return(false); } var oldSceneSetup = EditorSceneManager.GetSceneManagerSetup(); try { for (int i = 0; i < scenePaths.Count; i++) { var scenePath = scenePaths[i]; if (EditorUtility.DisplayCancelableProgressBar("Scanning Scenes", "Scene " + (i + 1) + "/" + scenePaths.Count + " - " + scenePath, (float)i / scenePaths.Count)) { return(false); } EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single); var sceneGOs = UnityEngine.Object.FindObjectsOfType <GameObject>(); foreach (var go in sceneGOs) { if ((go.hideFlags & HideFlags.DontSaveInBuild) == 0) { foreach (var component in go.GetComponents <ISerializationCallbackReceiver>()) { component.OnBeforeSerialize(); var prefabSupporter = component as ISupportsPrefabSerialization; if (prefabSupporter != null) { // Also force a serialization of the object's prefab modifications, in case there are unknown types in there List <UnityEngine.Object> objs = null; var mods = UnitySerializationUtility.DeserializePrefabModifications(prefabSupporter.SerializationData.PrefabModifications, prefabSupporter.SerializationData.PrefabModificationsReferencedUnityObjects); UnitySerializationUtility.SerializePrefabModifications(mods, ref objs); } } } } } // Load a new empty scene that will be unloaded immediately, just to be sure we completely clear all changes made by the scan EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); } finally { try { EditorUtility.DisplayProgressBar("Restoring scene setup", "", 0.5f); EditorSceneManager.RestoreSceneManagerSetup(oldSceneSetup); } finally { EditorUtility.ClearProgressBar(); } } return(true); }
private static string[] CreateNotes(MemberInfo member, SerializationFlags flags, SerializationBackendFlags serializationBackend) { List <string> notes = new List <string>(); StringBuilder buffer = new StringBuilder(); // Member type if (flags.HasAll(SerializationFlags.Property | SerializationFlags.AutoProperty)) { buffer.AppendFormat("The auto property {0} ", member.GetNiceName()); } else if (flags.HasAll(SerializationFlags.Property)) { buffer.AppendFormat("The non-auto property {0} ", member.GetNiceName()); } else { if (flags.HasAll(SerializationFlags.Public)) { buffer.AppendFormat("The public field {0} ", member.GetNiceName()); } else { buffer.AppendFormat("The field {0} ", member.GetNiceName()); } } // Is the member serialized? if (flags.HasAny(SerializationFlags.SerializedByOdin | SerializationFlags.SerializedByUnity)) { buffer.Append("is serialized by "); // Who? if (flags.HasAll(SerializationFlags.SerializedByUnity | SerializationFlags.SerializedByOdin)) { buffer.Append("both Unity and Odin "); } else if (flags.HasAll(SerializationFlags.SerializedByUnity)) { buffer.Append("Unity "); } else { buffer.Append("Odin "); } buffer.Append("because "); // Why? var relevant = flags & (SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute | SerializationFlags.NonSerializedAttribute); if (flags.HasAll(SerializationFlags.OdinSerializeAttribute) && serializationBackend.HasAll(SerializationBackendFlags.Odin)) // The OdinSerialize attribute is only relevant when the Odin serialization backend is available. { relevant |= SerializationFlags.OdinSerializeAttribute; } switch (relevant) { case SerializationFlags.Public: buffer.Append("its access modifier is public. "); break; case SerializationFlags.SerializeFieldAttribute: buffer.Append("it has the [SerializeField] attribute. "); break; case SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute: buffer.Append("it has the [SerializeField] attribute, and it's public. "); break; case SerializationFlags.OdinSerializeAttribute: buffer.Append("it has the [OdinSerialize] attribute. "); break; case SerializationFlags.Public | SerializationFlags.OdinSerializeAttribute: buffer.Append("it has the [OdinSerialize] attribute, and it's public."); break; case SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute: buffer.Append("it has the [SerializeField] and [OdinSerialize] attribute. "); break; case SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute: buffer.Append("its access modifier is public and has the [SerializeField] and [OdinSerialize] attribute. "); break; case SerializationFlags.OdinSerializeAttribute | SerializationFlags.NonSerializedAttribute: case SerializationFlags.Public | SerializationFlags.OdinSerializeAttribute | SerializationFlags.NonSerializedAttribute: case SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute | SerializationFlags.NonSerializedAttribute: case SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute | SerializationFlags.NonSerializedAttribute: buffer.Append("it has the [OdinSerialize] and [NonSerialzied] attribute. "); break; default: buffer.Append("(MISSING CASE: " + relevant.ToString() + ")"); break; } // Empty the buffer. if (buffer.Length > 0) { notes.Add(buffer.ToString()); buffer.Length = 0; } // Why is the value not serialized by Unity? if (serializationBackend.HasAll(SerializationBackendFlags.Unity) && flags.HasNone(SerializationFlags.SerializedByUnity)) { buffer.Append("The member is not being serialized by Unity since "); if (flags.HasAll(SerializationFlags.Property)) { buffer.Append("Unity does not serialize properties."); } else if (UnitySerializationUtility.GuessIfUnityWillSerialize(member.GetReturnType()) == false) { buffer.Append("Unity does not support the type."); } else if (flags.HasAll(SerializationFlags.NonSerializedAttribute)) { buffer.Append("the [NonSerialized] attribute is defined."); } else if (flags.HasAny(SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute) == false) { buffer.Append("it is neither a public field or has the [SerializeField] attribute."); } else { buffer.Append("# Missing case, please report: " + flags.ToString()); } } // Empty the buffer. if (buffer.Length > 0) { notes.Add(buffer.ToString()); buffer.Length = 0; } // Why is the value not serialized by Odin? if (flags.HasAll(SerializationFlags.SerializedByOdin) == false) { buffer.Append("Member is not serialized by Odin because "); if ((serializationBackend & SerializationBackendFlags.Odin) != 0) { if (flags.HasAll(SerializationFlags.SerializedByUnity)) { buffer.Append("the member is already serialized by Unity. "); } } else { buffer.Append("Odin serialization is not implemented. "); if (flags.HasAll(SerializationFlags.OdinSerializeAttribute)) { buffer.Append("The use of [OdinSerialize] attribute is invalid."); } } } } else // Why not? { // Property members with Odin implementation. if (flags.HasAll(SerializationFlags.Property) && serializationBackend.HasAll(SerializationBackendFlags.Odin)) { if (flags.HasAll(SerializationFlags.AutoProperty) == false) { buffer.Append("is skipped by Odin because non-auto properties are not serialized. "); if (flags.HasAll(SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute)) { buffer.Append("The use of [SerializeField] and [OdinSerialize] attributes is invalid. "); } else if (flags.HasAll(SerializationFlags.OdinSerializeAttribute)) { buffer.Append("The use of [OdinSerialize] attribute is invalid. "); } else if (flags.HasAll(SerializationFlags.SerializeFieldAttribute)) { buffer.Append("The use of [SerializeField] attribute is invalid. "); } else if (flags.HasAll(SerializationFlags.NonSerializedAttribute)) { buffer.Append("The use of [NonSerialized] attribute is unnecessary. "); } } else { buffer.Append("Auto property member is skipped by Odin because "); if (flags.HasNone(SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute)) { buffer.Append("neither [SerializeField] nor [OdinSerialize] attributes have been used."); } } } // Property members without Odin implementation. else if (flags.HasAll(SerializationFlags.Property)) { buffer.Append("is skipped by Unity because Unity does not serialize properties. "); if (flags.HasAll(SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute)) { buffer.Append("The use of [SerializeField] and [OdinSerialize] attributes is invalid. "); } else if (flags.HasAll(SerializationFlags.OdinSerializeAttribute)) { buffer.Append("The use of [OdinSerialize] attribute is invalid. "); } else if (flags.HasAny(SerializationFlags.SerializeFieldAttribute)) { buffer.Append("The use of [SerializeField] attribute is invalid. "); } if (flags.HasAny(SerializationFlags.NonSerializedAttribute)) { buffer.Append("The use of [NonSerialized] attribute is unnecessary."); } } // Field members. else { // Backend ? buffer.Append("is skipped by "); switch (serializationBackend) { case SerializationBackendFlags.Unity: buffer.Append("Unity "); break; case SerializationBackendFlags.Odin: buffer.Append("Odin "); break; case SerializationBackendFlags.UnityAndOdin: buffer.Append("both Unity and Odin "); break; } buffer.Append("because "); if (serializationBackend == SerializationBackendFlags.None) { buffer.Append("there is no serialization backend? "); } else if (flags.HasAll(SerializationFlags.NonSerializedAttribute)) { buffer.Append("the [NonSerialized] attribute is defined. "); } else if (flags.HasNone(SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute)) { buffer.Append("the field is neither public nor a [SerializeField] attribute. "); } else if (serializationBackend == SerializationBackendFlags.Unity && flags.HasAny(SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute)) { buffer.Append("Unity does not support the type " + member.GetReturnType().GetNiceName()); } // Empty the buffer. if (buffer.Length > 0) { notes.Add(buffer.ToString()); buffer.Length = 0; } // Invalid use of OdinSerialize. if ((serializationBackend & SerializationBackendFlags.Odin) == 0 && flags.HasAll(SerializationFlags.OdinSerializeAttribute)) { notes.Add("Odin serialization is not implemented. The use of [OdinSerialize] attribute is invalid."); // Just add this line directly to the notes list. } } // Using both [SerializeField] and [NonSerialized] attributes. if (flags.HasAll(SerializationFlags.SerializeFieldAttribute | SerializationFlags.NonSerializedAttribute) && flags.HasNone(SerializationFlags.OdinSerializeAttribute)) { notes.Add("Use of [SerializeField] along with [NonSerialized] attributes is weird. Remove either the [SerializeField] or [NonSerialized] attribute."); } } // Empty the buffer. if (buffer.Length > 0) { notes.Add(buffer.ToString()); buffer.Length = 0; } // Add notes on Unity serialization support. if (serializationBackend.HasAll(SerializationBackendFlags.UnityAndOdin)) { if (flags.HasAll(SerializationFlags.SerializedByOdin | SerializationFlags.TypeSupportedByUnity) && flags.HasNone(SerializationFlags.SerializedByUnity)) { buffer.Append("The type " + member.GetReturnType().GetNiceName() + " appears to be supported by Unity. Are you certain that you want to use Odin for serializing?"); } else if (flags.HasAll(SerializationFlags.SerializedByOdin) && flags.HasNone(SerializationFlags.TypeSupportedByUnity)) { buffer.Append("The type " + member.GetReturnType().GetNiceName() + " is not supported by Unity" + GuessWhyUnityDoesNotSupport(member.GetReturnType())); } } else if (serializationBackend.HasAll(SerializationBackendFlags.Unity) && flags.HasNone(SerializationFlags.TypeSupportedByUnity)) { buffer.Append("The type " + member.GetReturnType().GetNiceName() + " is not supported by Unity" + GuessWhyUnityDoesNotSupport(member.GetReturnType())); } // Empty the buffer. if (buffer.Length > 0) { notes.Add(buffer.ToString()); buffer.Length = 0; } // Implement Odin support. if (serializationBackend.HasAll(SerializationBackendFlags.Unity) && serializationBackend.HasNone(SerializationBackendFlags.Odin) && flags.HasNone(SerializationFlags.TypeSupportedByUnity) && flags.HasAny(SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute) && flags.HasAny(SerializationFlags.Field | SerializationFlags.AutoProperty)) { string inheritFrom = "You could implement Odin serializing by inheriting " + member.DeclaringType.GetNiceName() + " from "; if (typeof(MonoBehaviour).IsAssignableFrom(member.DeclaringType)) { buffer.Append(inheritFrom + typeof(SerializedMonoBehaviour).GetNiceName()); } else if (typeof(UnityEngine.Networking.NetworkBehaviour).IsAssignableFrom(member.DeclaringType)) { buffer.Append(inheritFrom + typeof(SerializedNetworkBehaviour).GetNiceName()); } else if (typeof(Behaviour).IsAssignableFrom(member.DeclaringType)) { buffer.Append(inheritFrom + typeof(SerializedBehaviour).GetNiceName()); } else if (typeof(ScriptableObject).IsAssignableFrom(member.DeclaringType)) { buffer.Append(inheritFrom + typeof(SerializedScriptableObject).GetNiceName()); } } // Empty the buffer. if (buffer.Length > 0) { notes.Add(buffer.ToString()); buffer.Length = 0; } // Recommend using fields instead of auto properties. if (serializationBackend.HasAll(SerializationBackendFlags.Odin) && flags.HasAll(SerializationFlags.AutoProperty | SerializationFlags.SerializedByOdin)) { buffer.Append("It's recommend to use backing fields for serializing instead of auto-properties."); } // Empty the buffer. if (buffer.Length > 0) { notes.Add(buffer.ToString()); buffer.Length = 0; } return(notes.ToArray()); }
protected override void OnAfterDeserialize() { UnitySerializationUtility.DeserializeUnityObject(this, ref serializationData); base.OnAfterDeserialize(); }
private MemberSerializationInfo(MemberInfo member, string[] notes, SerializationFlags flags, SerializationBackendFlags serializationBackend) { Assert.IsNotNull(member); Assert.IsFalse(flags == 0); this.MemberInfo = member; this.Notes = notes; this.Info = flags; this.Backend = serializationBackend; this.OdinMessageType = InfoMessageType.None; this.UnityMessageType = InfoMessageType.None; // Should the member be serialized, but isn't? if (flags.HasNone(SerializationFlags.SerializedByUnity | SerializationFlags.SerializedByOdin | SerializationFlags.NonSerializedAttribute) && flags.HasAny(SerializationFlags.Public | SerializationFlags.SerializeFieldAttribute) && (flags.HasAll(SerializationFlags.Field) || flags.HasAll(SerializationFlags.AutoProperty))) { if (serializationBackend.HasNone(SerializationBackendFlags.Odin)) { this.OdinMessageType = InfoMessageType.Info; } if (flags.HasNone(SerializationFlags.Property) && UnitySerializationUtility.GuessIfUnityWillSerialize(member.GetReturnType()) == false) { this.UnityMessageType = InfoMessageType.Info; } } // Is the member serialized by both Odin and Unity? if (this.Info.HasAny(SerializationFlags.SerializedByOdin) && this.Info.HasAny(SerializationFlags.SerializedByUnity)) { this.OdinMessageType = InfoMessageType.Warning; this.UnityMessageType = InfoMessageType.Warning; } // Does the member have both SerializeField and NonSerialized attributes? if (this.Info.HasAll(SerializationFlags.SerializeFieldAttribute | SerializationFlags.NonSerializedAttribute)) { this.UnityMessageType = InfoMessageType.Warning; } // Does the member have both SerializeField and OdinSerialize attributes? if (this.Info.HasAll(SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute)) { if (this.Info.HasAll(SerializationFlags.SerializedByOdin)) { this.OdinMessageType = InfoMessageType.Warning; } if (this.Info.HasAll(SerializationFlags.SerializedByUnity)) { this.UnityMessageType = InfoMessageType.Warning; } } if (serializationBackend.HasAll(SerializationBackendFlags.UnityAndOdin) && this.Info.HasAll(SerializationFlags.SerializedByOdin | SerializationFlags.TypeSupportedByUnity) && this.Info.HasNone(SerializationFlags.SerializedByUnity)) { this.OdinMessageType = InfoMessageType.Warning; } // Does the member have a OdinSerialize attribute, but no Odin backend is available? if (!serializationBackend.HasAll(SerializationBackendFlags.Odin) && flags.HasAny(SerializationFlags.OdinSerializeAttribute)) { this.OdinMessageType = InfoMessageType.Error; } // Does the member have OdinSerialize attribute, but is not serialized by Odin? if (this.Info.HasAny(SerializationFlags.OdinSerializeAttribute) && !this.Info.HasAny(SerializationFlags.SerializedByOdin)) { this.OdinMessageType = InfoMessageType.Error; } // Is the member marked for serialzation but not serialized? if (this.Info.HasAny(SerializationFlags.SerializeFieldAttribute | SerializationFlags.OdinSerializeAttribute) && !this.Info.HasAny(SerializationFlags.SerializedByUnity | SerializationFlags.SerializedByOdin | SerializationFlags.NonSerializedAttribute)) { if (serializationBackend.HasAll(SerializationBackendFlags.Odin)) { this.OdinMessageType = InfoMessageType.Error; } if (!this.Info.HasAny(SerializationFlags.Property) && UnitySerializationUtility.GuessIfUnityWillSerialize(member.GetReturnType())) { this.UnityMessageType = InfoMessageType.Error; } } // Is the member public, not marked with NonSerialized, but not serialized? if (this.Info.HasAll(SerializationFlags.Public | SerializationFlags.Field) && !this.Info.HasAny(SerializationFlags.NonSerializedAttribute) && !this.Info.HasAny(SerializationFlags.SerializedByUnity | SerializationFlags.SerializedByOdin)) { if (serializationBackend.HasAll(SerializationBackendFlags.Odin)) { this.OdinMessageType = InfoMessageType.Error; } if (!this.Info.HasAny(SerializationFlags.Property) && UnitySerializationUtility.GuessIfUnityWillSerialize(member.GetReturnType())) { this.UnityMessageType = InfoMessageType.Error; } } }
void ISerializationCallbackReceiver.OnBeforeSerialize() { this.OnBeforeSerialize(); UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData); }
private static string GuessWhyUnityDoesNotSupport(Type type) { if (type == typeof(Coroutine)) { return(" because Unity will never serialize Coroutines."); } if (typeof(Delegate).IsAssignableFrom(type)) { return(" because Unity does not support delegates."); } if (type.IsInterface) { return(" because the type is an interface."); } if (type.IsAbstract) { return(" because the type is abstract."); } if (type == typeof(System.Object)) { return(" because Unity does not support serializing System.Object."); } if (typeof(Enum).IsAssignableFrom(type)) { Type underlying = Enum.GetUnderlyingType(type); if (UnityVersion.IsVersionOrGreater(5, 6) && (underlying == typeof(long) || underlying == typeof(ulong))) { return(" because Unity does not support enums with underlying type of long or ulong."); } else if (UnityVersion.Major <= 5 && UnityVersion.Minor < 6 && underlying != typeof(int) && underlying != typeof(byte)) { return(" because prior to Version 5.6 Unity only supports enums with underlying type of int or byte."); } return(". Was unable to determine why Unity does not support enum with underlying type of: " + underlying.GetNiceName() + "."); } if (typeof(UnityEngine.Events.UnityEventBase).IsAssignableFrom(type) && type.IsGenericType) { return(" because the type is a generic implementation of UnityEventBase."); } if (type.IsArray) { if (type.GetArrayRank() > 1 || type.GetElementType().IsArray || type.GetElementType().ImplementsOpenGenericClass(typeof(List <>))) { return(" because Unity does not support multi-dimensional arrays."); } else if (UnitySerializationUtility.GuessIfUnityWillSerialize(type.GetElementType()) == false) { return(" because Unity does not support the type " + type.GetElementType().GetNiceName() + " as an array element."); } } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>)) { var elementType = type.GetArgumentsOfInheritedOpenGenericClass(typeof(List <>))[0]; if (elementType.IsArray) { return(" because Unity does not support Lists of arrays."); } else if (elementType.ImplementsOpenGenericClass(typeof(List <>))) { return(" because Unity does not support Lists of Lists."); } else if (UnitySerializationUtility.GuessIfUnityWillSerialize(elementType) == false) { return(" because Unity does not support the element type of " + elementType.GetNiceName() + "."); } } if (type.IsGenericType || type.GetGenericArguments().Length > 0) { return(" because Unity does not support generic types."); } if (type.Assembly == typeof(string).Assembly) { return(" because Unity does not serialize [Serializable] structs and classes if they are defined in mscorlib."); } if (type.IsDefined <SerializableAttribute>(false) == false) { return(" because the type is missing a [Serializable] attribute."); } // No reason found. return(". Was unable to determine reason, please report this to Sirenix."); }
public bool ScanScenes(string[] scenePaths, bool includeSceneDependencies, bool showProgressBar) { if (scenePaths.Length == 0) { return(true); } bool formerForceEditorModeSerialization = UnitySerializationUtility.ForceEditorModeSerialization; try { UnitySerializationUtility.ForceEditorModeSerialization = true; bool hasDirtyScenes = false; for (int i = 0; i < EditorSceneManager.sceneCount; i++) { if (EditorSceneManager.GetSceneAt(i).isDirty) { hasDirtyScenes = true; break; } } if (hasDirtyScenes && !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { return(false); } var oldSceneSetup = EditorSceneManager.GetSceneManagerSetup(); try { for (int i = 0; i < scenePaths.Length; i++) { var scenePath = scenePaths[i]; if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Scanning scenes for AOT support", "Scene " + (i + 1) + "/" + scenePaths.Length + " - " + scenePath, (float)i / scenePaths.Length)) { return(false); } if (!System.IO.File.Exists(scenePath)) { Debug.LogWarning("Skipped AOT scanning scene '" + scenePath + "' for a file not existing at the scene path."); continue; } Scene openScene = default(Scene); try { openScene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single); } catch { Debug.LogWarning("Skipped AOT scanning scene '" + scenePath + "' for throwing exceptions when trying to load it."); continue; } var sceneGOs = Resources.FindObjectsOfTypeAll <GameObject>(); foreach (var go in sceneGOs) { if (go.scene != openScene) { continue; } if ((go.hideFlags & HideFlags.DontSaveInBuild) == 0) { foreach (var component in go.GetComponents <ISerializationCallbackReceiver>()) { try { this.allowRegisteringScannedTypes = true; component.OnBeforeSerialize(); var prefabSupporter = component as ISupportsPrefabSerialization; if (prefabSupporter != null) { // Also force a serialization of the object's prefab modifications, in case there are unknown types in there List <UnityEngine.Object> objs = null; var mods = UnitySerializationUtility.DeserializePrefabModifications(prefabSupporter.SerializationData.PrefabModifications, prefabSupporter.SerializationData.PrefabModificationsReferencedUnityObjects); UnitySerializationUtility.SerializePrefabModifications(mods, ref objs); } } finally { this.allowRegisteringScannedTypes = false; } } } } } // Load a new empty scene that will be unloaded immediately, just to be sure we completely clear all changes made by the scan // Sometimes this fails for unknown reasons. In that case, swallow any exceptions, and just soldier on and hope for the best! // Additionally, also eat any debug logs that happen here, because logged errors can stop the build process, and we don't want // that to happen. UnityEngine.ILogger logger = null; if (Debug_Logger_Property != null) { logger = (UnityEngine.ILogger)Debug_Logger_Property.GetValue(null, null); } bool previous = true; try { if (logger != null) { previous = logger.logEnabled; logger.logEnabled = false; } EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); } catch { } finally { if (logger != null) { logger.logEnabled = previous; } } } finally { if (oldSceneSetup != null && oldSceneSetup.Length > 0) { if (showProgressBar) { EditorUtility.DisplayProgressBar("Restoring scene setup", "", 1.0f); } EditorSceneManager.RestoreSceneManagerSetup(oldSceneSetup); } } if (includeSceneDependencies) { for (int i = 0; i < scenePaths.Length; i++) { var scenePath = scenePaths[i]; if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Scanning scene dependencies for AOT support", "Scene " + (i + 1) + "/" + scenePaths.Length + " - " + scenePath, (float)i / scenePaths.Length)) { return(false); } string[] dependencies = AssetDatabase.GetDependencies(scenePath, recursive: true); foreach (var dependency in dependencies) { this.ScanAsset(dependency, includeAssetDependencies: false); // All dependencies of this asset were already included recursively by Unity } } } return(true); } finally { if (showProgressBar) { EditorUtility.ClearProgressBar(); } UnitySerializationUtility.ForceEditorModeSerialization = formerForceEditorModeSerialization; } }
void ISerializationCallbackReceiver.OnBeforeSerialize() { UnitySerializationUtility.SerializeUnityObject(this, ref serializationData); _backingUdonBehaviourDump = _udonSharpBackingUdonBehaviour; }