/// <summary> /// BaseEditor.cs is calling this method when the editor receives /// an OnDestroy call and the application isn't playing. This /// behavior is assumed to be a "select -> delete". /// </summary> /// <param name="gameObject"></param> public static void OnEditorDestroy() { if (!HasInstance) { return; } List <GameObject> gameObjectsToDestroy = new List <GameObject>(); foreach (Transform childTransform in Instance.gameObject.transform) { GameObject child = childTransform.gameObject; OnSelectionProxy selectionProxy = child.GetComponent <OnSelectionProxy>(); if (selectionProxy != null) { gameObjectsToDestroy.Add(selectionProxy.gameObject); } } while (gameObjectsToDestroy.Count > 0) { DestroyImmediate(gameObjectsToDestroy[gameObjectsToDestroy.Count - 1]); gameObjectsToDestroy.RemoveAt(gameObjectsToDestroy.Count - 1); } }
protected void Update() { UpdateIsActiveForSynchronize(); // When the application is playing we rely on callbacks // from the objects when they've synchronized their // transforms. if (Application.isPlaying) { return; } // Shapes with inactive game objects will be updated below when we're // traversing all children. FindObjectsOfType <Collide.Shape>().ToList().ForEach( shape => SynchronizeShape(shape) ); FindObjectsOfType <Constraint>().ToList().ForEach( constraint => constraint.AttachmentPair.Synchronize() ); List <GameObject> gameObjectsToDestroy = new List <GameObject>(); foreach (var node in Children) { OnSelectionProxy proxy = node.GetComponent <OnSelectionProxy>(); if (proxy == null) { continue; } if (proxy.Target == null) { gameObjectsToDestroy.Add(node); } // FindObjectsOfType will not include the Shape if its game object is inactive. // We're handling that shape here instead. else if (!proxy.Target.activeInHierarchy && proxy.Component is Collide.Shape) { SynchronizeShape(proxy.Component as Collide.Shape); } } while (gameObjectsToDestroy.Count > 0) { DestroyImmediate(gameObjectsToDestroy.Last()); gameObjectsToDestroy.RemoveAt(gameObjectsToDestroy.Count - 1); } }
/// <summary> /// Routes given object to the game object of an AGXUnity.Collide.Shape if /// the connection is given using OnSelectionProxy. /// </summary> /// <returns>Shape game object if found - otherwise null.</returns> public static GameObject RouteToShape(UnityEngine.Object obj) { GameObject gameObject = obj as GameObject; OnSelectionProxy selectionProxy = null; if (gameObject == null || (selectionProxy = gameObject.GetComponent <OnSelectionProxy>()) == null) { return(null); } if (selectionProxy.Target != null && selectionProxy.Target.GetComponent <AGXUnity.Collide.Shape>() != null) { return(selectionProxy.Target); } return(null); }
/// <summary> /// Routes current object to the desired object when e.g., selected. /// This method uses OnSelectionProxy to find the desired object. /// </summary> /// <returns>Input object if the object doesn't contains an OnSelectionProxy route.</returns> public static UnityEngine.Object RouteObject(UnityEngine.Object obj) { GameObject gameObject = obj as GameObject; OnSelectionProxy proxy = null; if (gameObject != null) { proxy = gameObject.GetComponents <OnSelectionProxy>().FirstOrDefault(); } // If proxy target is null we're ignoring it. var result = proxy != null && !GetSelectedInHierarchyData(proxy).Bool&& proxy.Target != null ? proxy.Target : obj; return(result); }
/// <summary> /// BaseEditor.cs is calling this method when the editor receives /// an OnDestroy call and the application isn't playing. This /// behavior is assumed to be a "select -> delete". /// </summary> /// <param name="gameObject"></param> public static void OnEditorDestroy() { if (!HasInstance) { return; } List <GameObject> gameObjectsToDestroy = new List <GameObject>(); foreach (var node in Instance.Children) { OnSelectionProxy selectionProxy = node.GetComponent <OnSelectionProxy>(); if (selectionProxy != null) { gameObjectsToDestroy.Add(selectionProxy.gameObject); } } while (gameObjectsToDestroy.Count > 0) { DestroyImmediate(gameObjectsToDestroy[gameObjectsToDestroy.Count - 1]); gameObjectsToDestroy.RemoveAt(gameObjectsToDestroy.Count - 1); } }
/// <summary> /// * Verifies version of OnSelectionProxy and patches it if Target == null. /// * Verifies so that our shapes doesn't have multiple debug rendering components. /// </summary> private static void VerifyOnSelectionTarget(Scene scene) { var shapes = Object.FindObjectsOfType <AGXUnity.Collide.Shape>(); foreach (var shape in shapes) { OnSelectionProxy selectionProxy = shape.GetComponent <OnSelectionProxy>(); if (selectionProxy != null && selectionProxy.Target == null) { selectionProxy.Component = shape; } var data = shape.GetComponents <AGXUnity.Rendering.ShapeDebugRenderData>(); if (data.Length > 1) { Debug.Log("Shape has several ShapeDebugRenderData. Removing/resetting.", shape); foreach (var instance in data) { Component.DestroyImmediate(instance); } data = null; } } }
/// <summary> /// Editor data entry for "SelectedInHierarchy" property. /// </summary> /// <param name="proxy">OnSelectionProxy instance. Invalid if null.</param> /// <returns>EditorDataEntry for given <paramref name="proxy"/>.</returns> private static EditorDataEntry GetSelectedInHierarchyData(OnSelectionProxy proxy) { return(EditorData.Instance.GetData(proxy, "SelectedInHierarchy")); }
private static void OnHierarchyWindowChanged() { var scene = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene(); if (scene != null && scene.name != m_currentSceneName) { EditorData.Instance.GC(); m_currentSceneName = scene.name; // - Verifies so that our shapes doesn't have multiple debug rendering components. // - Verifies version of OnSelectionProxy and patches it if Target == null. AgXUnity.Collide.Shape[] shapes = UnityEngine.Object.FindObjectsOfType <AgXUnity.Collide.Shape>(); foreach (var shape in shapes) { OnSelectionProxy selectionProxy = shape.GetComponent <OnSelectionProxy>(); if (selectionProxy != null && selectionProxy.Target == null) { selectionProxy.Component = shape; } AgXUnity.Rendering.ShapeDebugRenderData[] data = shape.GetComponents <AgXUnity.Rendering.ShapeDebugRenderData>(); if (data.Length > 1) { Debug.Log("Shape has several ShapeDebugRenderData. Removing/resetting.", shape); foreach (var instance in data) { Component.DestroyImmediate(instance); } data = null; } } // We're back to ScriptComponent version of MassProperties. AgXUnity.RigidBody[] bodies = UnityEngine.Object.FindObjectsOfType <AgXUnity.RigidBody>(); foreach (var rb in bodies) { if (!rb.PatchMassPropertiesAsComponent()) { continue; } Debug.Log("Updated RigidBody: " + rb.name + " to new MassProperties version.", rb); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } // Patching constraints where we removed ElementaryConstraint as component. // Now we're back and I hope the components will still show up as null now // that AgXUnity.ElementaryConstraint is a component again. { AgXUnity.Constraint[] constraints = UnityEngine.Object.FindObjectsOfType <AgXUnity.Constraint>(); foreach (var constraint in constraints) { bool isOldVersion = (from component in constraint.GetComponents <Component>() where component == null select component).ToArray().Length > 0 && constraint.ElementaryConstraints.Length == 0; if (!isOldVersion) { continue; } if (EditorUtility.DisplayDialog("Update \"" + constraint.name + "\" (type: " + constraint.Type + ") to the new version?", "The game object will be deleted and a new will be created with the same Reference/Connected setup. All data such as compliance, damping, motor speed etc. will be lost.", "Update", "Ignore")) { AgXUnity.Constraint newConstraint = AgXUnity.Constraint.Create(constraint.Type); newConstraint.AttachmentPair.ReferenceObject = constraint.AttachmentPair.ReferenceObject; newConstraint.AttachmentPair.ReferenceFrame.LocalPosition = constraint.AttachmentPair.ReferenceFrame.LocalPosition; newConstraint.AttachmentPair.ReferenceFrame.LocalRotation = constraint.AttachmentPair.ReferenceFrame.LocalRotation; newConstraint.AttachmentPair.Synchronized = constraint.AttachmentPair.Synchronized; newConstraint.AttachmentPair.ConnectedObject = constraint.AttachmentPair.ConnectedObject; newConstraint.AttachmentPair.ConnectedFrame.LocalPosition = constraint.AttachmentPair.ConnectedFrame.LocalPosition; newConstraint.AttachmentPair.ConnectedFrame.LocalRotation = constraint.AttachmentPair.ConnectedFrame.LocalRotation; newConstraint.name = constraint.name; GameObject.DestroyImmediate(constraint.gameObject); Debug.Log("Constraint: " + newConstraint.name + " updated.", newConstraint); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } } } // Patching constraints where ElementaryConstraint is a ScriptAsset. { AgXUnity.Constraint[] constraints = UnityEngine.Object.FindObjectsOfType <AgXUnity.Constraint>(); foreach (var constraint in constraints) { bool isOldVersion = constraint.ElementaryConstraints.Length > 0 && constraint.GetComponents <AgXUnity.ElementaryConstraint>().Length == 0; if (!isOldVersion) { continue; } // Updating to new attachment pair. var attachmentPair = constraint.AttachmentPair; // Updating to where ElementaryConstraints are components. constraint.TransformToComponentVersion(); Debug.Log("Constraint: " + constraint.name + " updated to new version.", constraint); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } } // Patching old constraints to new versions. { AgXUnity.Constraint[] constraints = UnityEngine.Object.FindObjectsOfType <AgXUnity.Constraint>(); foreach (var constraint in constraints) { if (!constraint.VerifyImplementation()) { continue; } Debug.Log("Constraint: " + constraint.name + " successfully updated to new version.", constraint); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } } // Patching OnSelectionProxy (Target == null) in the wire rendering SegmentSpawner. { AgXUnity.Wire[] wires = UnityEngine.Object.FindObjectsOfType <AgXUnity.Wire>(); foreach (var wire in wires) { AgXUnity.Rendering.SegmentSpawner ss = wire.GetComponent <AgXUnity.Rendering.WireRenderer>().SegmentSpawner; if (ss == null) { continue; } var segments = ss.Segments; foreach (var segment in segments) { OnSelectionProxy selectionProxy = segment.GetComponent <OnSelectionProxy>(); if (selectionProxy != null && selectionProxy.Target == null) { selectionProxy.Component = wire; } } } } // Patching Wire to use Route as component and RouteNode as Frame. { AgXUnity.Wire[] wires = UnityEngine.Object.FindObjectsOfType <AgXUnity.Wire>(); foreach (var wire in wires) { if (wire.GetComponent <AgXUnity.WireRoute>() != null) { continue; } var routeData = wire.GetComponent <AgXUnity.Legacy.WireRouteData>(); var route = wire.gameObject.AddComponent <AgXUnity.WireRoute>(); if (routeData != null && routeData.Restore()) { Debug.Log("Successfully restored " + route.NumNodes + " from local data.", wire); AgXUnity.ScriptComponent.DestroyImmediate(routeData); } else { Debug.LogWarning("Wire: " + wire.name + " is not possible to load and has to be re-routed.", wire); } UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } } // Patching Cable to use Route as component and RouteNode as Frame. { AgXUnity.Cable[] cables = UnityEngine.Object.FindObjectsOfType <AgXUnity.Cable>(); foreach (var cable in cables) { if (cable.GetComponent <AgXUnity.CableRoute>() != null) { continue; } var routeData = cable.GetComponent <AgXUnity.Legacy.CableRouteData>(); var route = cable.gameObject.AddComponent <AgXUnity.CableRoute>(); if (routeData != null && routeData.Restore()) { Debug.Log("Successfully restored " + route.NumNodes + " from local data.", cable); AgXUnity.ScriptComponent.DestroyImmediate(routeData); } else { Debug.LogWarning("Cable: " + cable.name + " is not possible to load and has to be re-routed.", cable); } UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } } // Verifying shape visuals material. { AgXUnity.Rendering.ShapeVisual[] shapeVisuals = UnityEngine.Object.FindObjectsOfType <AgXUnity.Rendering.ShapeVisual>(); foreach (var shapeVisual in shapeVisuals) { var renderers = shapeVisual.GetComponentsInChildren <MeshRenderer>(); foreach (var renderer in renderers) { if (renderer.sharedMaterial == null) { renderer.sharedMaterial = GetOrCreateShapeVisualDefaultMaterial(); Debug.Log("Shape visual with null material. Assigning default.", shapeVisual); if (!EditorApplication.isPlaying) { UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } } } } } // Patching Collide.Mesh single source object to source object list. { AgXUnity.Collide.Mesh[] meshes = UnityEngine.Object.FindObjectsOfType <AgXUnity.Collide.Mesh>(); foreach (var mesh in meshes) { if (!mesh.PatchSingleSourceToSourceList()) { continue; } Debug.Log("Patch: Moved mesh source to source list.", mesh); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } } } else if (Selection.activeGameObject != null && Selection.activeGameObject.GetComponent <AgXUnity.IO.RestoredAGXFile>() != null) { AssetPostprocessorHandler.OnPrefabAddedToScene(Selection.activeGameObject); } }
protected void Update() { gameObject.transform.position = Vector3.zero; gameObject.transform.rotation = Quaternion.identity; // Change parent before scale is set - otherwise scale will be preserved. // E.g., move "this" to a parent with scale x, scale will be set, // parent = null will remove the parent but the scale will be preserved. // Fix - set scale after set parent. gameObject.transform.parent = null; gameObject.transform.localScale = Vector3.one; UpdateIsActiveForSynchronize(); // When the application is playing we rely on callbacks // from the objects when they've synchronized their // transforms. if (Application.isPlaying) { return; } // Shapes with inactive game objects will be updated below when we're // traversing all children. FindObjectsOfType <Collide.Shape>().ToList().ForEach( shape => SynchronizeShape(shape) ); FindObjectsOfType <Constraint>().ToList().ForEach( constraint => constraint.AttachmentPair.Update() ); List <GameObject> gameObjectsToDestroy = new List <GameObject>(); foreach (Transform child in gameObject.transform) { GameObject node = child.gameObject; OnSelectionProxy proxy = node.GetComponent <OnSelectionProxy>(); if (proxy == null) { continue; } if (proxy.Target == null) { gameObjectsToDestroy.Add(node); } // FindObjectsOfType will not include the Shape if its game object is inactive. // We're handling that shape here instead. else if (!proxy.Target.activeInHierarchy && proxy.Component is Collide.Shape) { SynchronizeShape(proxy.Component as Collide.Shape); } } while (gameObjectsToDestroy.Count > 0) { DestroyImmediate(gameObjectsToDestroy.Last()); gameObjectsToDestroy.RemoveAt(gameObjectsToDestroy.Count - 1); } }
private static void OnHierarchyWindowChanged() { var scene = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene(); if (scene.name != m_currentSceneName) { EditorData.Instance.GC(); m_currentSceneName = scene.name; // - Verifies so that our shapes doesn't have multiple debug rendering components. // - Verifies version of OnSelectionProxy and patches it if Target == null. AGXUnity.Collide.Shape[] shapes = UnityEngine.Object.FindObjectsOfType <AGXUnity.Collide.Shape>(); foreach (var shape in shapes) { OnSelectionProxy selectionProxy = shape.GetComponent <OnSelectionProxy>(); if (selectionProxy != null && selectionProxy.Target == null) { selectionProxy.Component = shape; } AGXUnity.Rendering.ShapeDebugRenderData[] data = shape.GetComponents <AGXUnity.Rendering.ShapeDebugRenderData>(); if (data.Length > 1) { Debug.Log("Shape has several ShapeDebugRenderData. Removing/resetting.", shape); foreach (var instance in data) { Component.DestroyImmediate(instance); } data = null; } } // Verifying shape visuals material. { AGXUnity.Rendering.ShapeVisual[] shapeVisuals = UnityEngine.Object.FindObjectsOfType <AGXUnity.Rendering.ShapeVisual>(); foreach (var shapeVisual in shapeVisuals) { var renderers = shapeVisual.GetComponentsInChildren <MeshRenderer>(); foreach (var renderer in renderers) { if (renderer.sharedMaterial == null) { renderer.sharedMaterial = GetOrCreateShapeVisualDefaultMaterial(); Debug.Log("Shape visual with null material. Assigning default.", shapeVisual); if (!EditorApplication.isPlaying) { UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); } } } } } } else if (Selection.activeGameObject != null) { if (Selection.activeGameObject.GetComponent <AGXUnity.IO.RestoredAGXFile>() != null) { AssetPostprocessorHandler.OnPrefabAddedToScene(Selection.activeGameObject); } var savedPrefabData = Selection.activeGameObject.GetComponent <AGXUnity.IO.SavedPrefabLocalData>(); if (savedPrefabData != null && savedPrefabData.DisabledGroups.Length > 0) { Undo.SetCurrentGroupName("Adding prefab data for " + Selection.activeGameObject.name + " to scene."); var grouId = Undo.GetCurrentGroup(); foreach (var disabledGroup in savedPrefabData.DisabledGroups) { TopMenu.GetOrCreateUniqueGameObject <AGXUnity.CollisionGroupsManager>().SetEnablePair(disabledGroup.First, disabledGroup.Second, false); } Undo.CollapseUndoOperations(grouId); } } }