public void DrawPropertyTree() { if (this.ScriptableObj == null) { return; } if (this.window.isScanning && Event.current.type == EventType.Repaint) { OdinInspectorValidationChecker.BeginValidationCheck(); } GUILayout.BeginVertical(new GUIStyle() { padding = new RectOffset(10, 10, 6, 10) }); { if (this.propertyTree != null) { if (this.window.isScanning) { InspectorUtilities.BeginDrawPropertyTree(this.propertyTree, true); foreach (var property in this.propertyTree.EnumerateTree(true)) { try { property.Draw(); } catch (System.Exception ex) { if (ex is ExitGUIException || ex.InnerException is ExitGUIException) { throw ex; } Debug.Log("The following exception was thrown when drawing property " + property.Path + "."); Debug.LogException(ex); } } InspectorUtilities.EndDrawPropertyTree(this.propertyTree); } else { this.propertyTree.Draw(); } } else { SirenixEditorGUI.ErrorMessageBox("Missing Reference."); } } GUILayout.EndVertical(); if (this.window.isScanning && Event.current.type == EventType.Repaint) { // We can't count the correct the correct number of warnings and errors for each behavior // until we have a proper way of drawing a property tree with the guarantee that every property will be drawn. this.WarningCount = OdinInspectorValidationChecker.WarningMessages.Count(); this.ErrorCount = OdinInspectorValidationChecker.ErrorMessages.Count(); OdinInspectorValidationChecker.EndValidationCheck(); } }
private void DrawTree() { if (this.targetType == null) { this.tree = null; return; } if (Event.current.type == EventType.Layout) { this.currMemberTypes = this.memberTypes; this.currAccessModifiers = this.accessModifiers; } if (this.tree == null || this.tree.TargetType != this.targetType) { if (this.targetType.IsGenericType && !this.targetType.IsFullyConstructedGenericType()) { SirenixEditorGUI.ErrorMessageBox("Cannot statically inspect generic type definitions"); return; } this.tree = PropertyTree.CreateStatic(this.targetType); } var allowObsoleteMembers = (this.currMemberTypes & MemberTypeFlags.Obsolete) == MemberTypeFlags.Obsolete; var allowObsoleteMembersContext = this.tree.SecretRootProperty.Context.GetGlobal("ALLOW_OBSOLETE_STATIC_MEMBERS", false); if (allowObsoleteMembersContext.Value != allowObsoleteMembers) { allowObsoleteMembersContext.Value = allowObsoleteMembers; this.tree.SecretRootProperty.RefreshSetup(); } InspectorUtilities.BeginDrawPropertyTree(tree, false); foreach (var prop in tree.EnumerateTree(false)) { if (this.DrawProperty(prop)) { if (prop.Info.PropertyType != PropertyType.Group && prop.Info.GetMemberInfo() != null && prop.Info.GetMemberInfo().DeclaringType != this.targetType) { prop.Draw(new GUIContent(prop.Info.GetMemberInfo().DeclaringType.GetNiceName() + " -> " + prop.NiceName)); } else { prop.Draw(); } } else { prop.Update(); } } InspectorUtilities.EndDrawPropertyTree(tree); }
/// <summary> /// Draws all properties in a given property tree; must be wrapped by a <see cref="BeginDrawPropertyTree(PropertyTree, bool)"/> and <see cref="EndDrawPropertyTree(PropertyTree)"/>. /// </summary> /// <param name="tree">The tree to be drawn.</param> public static void DrawPropertiesInTree(PropertyTree tree) { foreach (var property in tree.EnumerateTree(false)) { try { InspectorUtilities.DrawProperty(property); } catch (Exception ex) { if (ex is ExitGUIException || ex.InnerException is ExitGUIException) { throw ex; } else { Debug.Log("The following exception was thrown when drawing property " + property.Path + "."); Debug.LogException(ex); } } } }
/// <summary> /// Draws this property in the inspector with a given label. This is a shorthand for <see cref="InspectorUtilities.DrawProperty(InspectorProperty, GUIContent)"/>. /// </summary> public void Draw(GUIContent label) { InspectorUtilities.DrawProperty(this, label); }
/// <summary> /// Draws this property in the inspector. This is a shorthand for <see cref="InspectorUtilities.DrawProperty(InspectorProperty)"/>. /// </summary> public void Draw() { InspectorUtilities.DrawProperty(this); }
public static void UpdatePrefabInstancePropertyModifications(UnityEngine.Object prefabInstance, bool withUndo) { if (prefabInstance == null) { throw new ArgumentNullException("prefabInstance"); } if (!(prefabInstance is ISupportsPrefabSerialization)) { throw new ArgumentException("Type must implement ISupportsPrefabSerialization"); } if (!(prefabInstance is ISerializationCallbackReceiver)) { throw new ArgumentException("Type must implement ISerializationCallbackReceiver"); } if (!OdinPrefabSerializationEditorUtility.ObjectIsPrefabInstance(prefabInstance)) { throw new ArgumentException("Value must be a prefab instance"); } Action action = null; EditorApplication.HierarchyWindowItemCallback hierarchyCallback = (arg1, arg2) => action(); EditorApplication.ProjectWindowItemCallback projectCallback = (arg1, arg2) => action(); SceneView.OnSceneFunc sceneCallback = (arg) => action(); EditorApplication.hierarchyWindowItemOnGUI += hierarchyCallback; EditorApplication.projectWindowItemOnGUI += projectCallback; SceneView.onSceneGUIDelegate += sceneCallback; action = () => { EditorApplication.hierarchyWindowItemOnGUI -= hierarchyCallback; EditorApplication.projectWindowItemOnGUI -= projectCallback; SceneView.onSceneGUIDelegate -= sceneCallback; // Clear out pre-existing modifications, as they can actually mess this up { ISupportsPrefabSerialization supporter = (ISupportsPrefabSerialization)prefabInstance; if (supporter.SerializationData.PrefabModifications != null) { supporter.SerializationData.PrefabModifications.Clear(); } if (supporter.SerializationData.PrefabModificationsReferencedUnityObjects != null) { supporter.SerializationData.PrefabModificationsReferencedUnityObjects.Clear(); } UnitySerializationUtility.PrefabModificationCache.CachePrefabModifications(prefabInstance, new List <PrefabModification>()); } try { if (prefabInstance == null) { // Ignore - the object has been destroyed since the method was invoked. return; } if (Event.current == null) { throw new InvalidOperationException("Delayed property modification delegate can only be called during the GUI event loop; Event.current must be accessible."); } try { PrefabUtility.RecordPrefabInstancePropertyModifications(prefabInstance); } catch (Exception ex) { Debug.LogError("Exception occurred while calling Unity's PrefabUtility.RecordPrefabInstancePropertyModifications:"); Debug.LogException(ex); } var tree = PropertyTree.Create(prefabInstance); tree.DrawMonoScriptObjectField = false; bool isRepaint = Event.current.type == EventType.Repaint; if (!isRepaint) { GUIHelper.PushEventType(EventType.Repaint); } InspectorUtilities.BeginDrawPropertyTree(tree, withUndo); foreach (var property in tree.EnumerateTree(true)) { if (property.ValueEntry == null) { continue; } if (!property.SupportsPrefabModifications) { continue; } property.Update(true); if (!(property.ChildResolver is IKeyValueMapResolver)) { continue; } if (property.ValueEntry.DictionaryChangedFromPrefab) { tree.PrefabModificationHandler.RegisterPrefabDictionaryDeltaModification(property, 0); } else { var prefabProperty = tree.PrefabModificationHandler.PrefabPropertyTree.GetPropertyAtPath(property.Path); if (prefabProperty == null) { continue; } if (prefabProperty.ValueEntry == null) { continue; } if (!property.SupportsPrefabModifications) { continue; } if (!(property.ChildResolver is IKeyValueMapResolver)) { continue; } tree.PrefabModificationHandler.RegisterPrefabDictionaryDeltaModification(property, 0); } } InspectorUtilities.EndDrawPropertyTree(tree); if (!isRepaint) { GUIHelper.PopEventType(); } ISerializationCallbackReceiver receiver = (ISerializationCallbackReceiver)prefabInstance; receiver.OnBeforeSerialize(); receiver.OnAfterDeserialize(); } catch (Exception ex) { Debug.LogException(ex); } }; foreach (SceneView scene in SceneView.sceneViews) { scene.Repaint(); } }
public static void UpdatePrefabInstancePropertyModifications(UnityEngine.Object prefabInstance, bool withUndo) { var prefabType = PrefabUtility.GetPrefabType(prefabInstance); //Assert.IsTrue(prefabInstance != null, "Argument is null"); //Assert.IsTrue(prefabInstance is ISupportsPrefabSerialization, "Type must implement ISupportsPrefabSerialization"); //Assert.IsTrue(prefabInstance is ISerializationCallbackReceiver, "Type must implement ISerializationCallbackReceiver"); //Assert.IsTrue(prefabType == PrefabType.PrefabInstance || prefabType == PrefabType.ModelPrefabInstance, "Value must be a prefab instance"); if (prefabInstance == null) { throw new ArgumentNullException("prefabInstance"); } if (!(prefabInstance is ISupportsPrefabSerialization)) { throw new ArgumentException("Type must implement ISupportsPrefabSerialization"); } if (!(prefabInstance is ISerializationCallbackReceiver)) { throw new ArgumentException("Type must implement ISerializationCallbackReceiver"); } if (!(prefabType == PrefabType.PrefabInstance || prefabType == PrefabType.ModelPrefabInstance)) { throw new ArgumentException("Value must be a prefab instance"); } Action action = null; EditorApplication.HierarchyWindowItemCallback hierarchyCallback = (arg1, arg2) => action(); EditorApplication.ProjectWindowItemCallback projectCallback = (arg1, arg2) => action(); SceneView.OnSceneFunc sceneCallback = (arg) => action(); EditorApplication.hierarchyWindowItemOnGUI += hierarchyCallback; EditorApplication.projectWindowItemOnGUI += projectCallback; SceneView.onSceneGUIDelegate += sceneCallback; action = () => { EditorApplication.hierarchyWindowItemOnGUI -= hierarchyCallback; EditorApplication.projectWindowItemOnGUI -= projectCallback; SceneView.onSceneGUIDelegate -= sceneCallback; try { //Assert.IsTrue(prefabInstance != null, "Invalid Argument: The prefab instance to update modifications for has been destroyed before updating could start."); //Assert.IsNotNull(Event.current, "Can only be called during the GUI event loop; Event.current must be accessible."); //if (prefabInstance == null) throw new InvalidOperationException("The prefab instance to update modifications for has been destroyed before updating could start."); if (prefabInstance == null) { // Ignore - the object has been destroyed since the method was invoked. return; } if (Event.current == null) { throw new InvalidOperationException("Delayed property modification delegate can only be called during the GUI event loop; Event.current must be accessible."); } try { PrefabUtility.RecordPrefabInstancePropertyModifications(prefabInstance); } catch (Exception ex) { Debug.LogError("Exception occurred while calling Unity's PrefabUtility.RecordPrefabInstancePropertyModifications:"); Debug.LogException(ex); } var tree = PropertyTree.Create(prefabInstance); //if (tree == null) Debug.LogError("Tree is null"); tree.DrawMonoScriptObjectField = false; bool isRepaint = Event.current.type == EventType.Repaint; if (!isRepaint) { GUIHelper.PushEventType(EventType.Repaint); } InspectorUtilities.BeginDrawPropertyTree(tree, withUndo); foreach (var property in tree.EnumerateTree(true)) { //if (property == null) Debug.LogError("Property is null"); if (property.ValueEntry == null) { continue; } if (property.ValueEntry.GetDictionaryHandler() == null) { continue; } if (property.ValueEntry.DictionaryChangedFromPrefab) { tree.RegisterPrefabDictionaryDeltaModification(property, 0); } else { var prefabProperty = tree.PrefabPropertyTree.GetPropertyAtPath(property.Path); if (prefabProperty == null) { continue; } if (prefabProperty.ValueEntry == null) { continue; } if (prefabProperty.ValueEntry.GetDictionaryHandler() == null) { continue; } //if (property.Children == null) Debug.LogError("Property children is null"); //if (prefabProperty.Children == null) Debug.LogError("Prefab property children is null"); if (property.Children.Count != prefabProperty.Children.Count) { tree.RegisterPrefabDictionaryDeltaModification(property, 0); } } } InspectorUtilities.EndDrawPropertyTree(tree); if (!isRepaint) { GUIHelper.PopEventType(); } ISerializationCallbackReceiver receiver = (prefabInstance as ISerializationCallbackReceiver); if (receiver == null) { Debug.LogError("Receiver is null"); } receiver.OnBeforeSerialize(); } catch (Exception ex) { Debug.LogException(ex); } }; foreach (SceneView scene in SceneView.sceneViews) { scene.Repaint(); } }