static DragAndDropVisualMode PrefabModeDraggingHandler(GameObjectTreeViewItem parentItem, GameObjectTreeViewItem targetItem, TreeViewDragging.DropPosition dropPos, bool perform) { var stage = StageNavigationManager.instance.currentItem; if (!stage.isPrefabStage) { throw new InvalidOperationException("PrefabModeDraggingHandler should only be called in Prefab Mode"); } // Disallow dropping as sibling to the prefab instance root (In Prefab Mode we only want to show one root). if (parentItem != null && parentItem.parent == null && dropPos != TreeViewDragging.DropPosition.Upon) { return(DragAndDropVisualMode.Rejected); } // Check for cyclic nesting (only on perform since it is an expensive operation) if (perform) { var prefabAssetThatIsAddedTo = AssetDatabase.LoadMainAssetAtPath(stage.prefabAssetPath); foreach (var dragged in DragAndDrop.objectReferences) { if (dragged is GameObject && EditorUtility.IsPersistent(dragged)) { var prefabAssetThatWillBeAdded = dragged; if (PrefabUtility.CheckIfAddingPrefabWouldResultInCyclicNesting(prefabAssetThatIsAddedTo, prefabAssetThatWillBeAdded)) { PrefabUtility.ShowCyclicNestingWarningDialog(); return(DragAndDropVisualMode.Rejected); } } } } return(DragAndDropVisualMode.None); }
internal static bool DragPerform(SceneView sceneView, GameObject draggedObject, GameObject go) { var stage = StageNavigationManager.instance.currentStage; if (stage is PrefabStage) { var prefabAssetThatIsAddedTo = AssetDatabase.LoadMainAssetAtPath(stage.assetPath); if (PrefabUtility.CheckIfAddingPrefabWouldResultInCyclicNesting(prefabAssetThatIsAddedTo, go)) { PrefabUtility.ShowCyclicNestingWarningDialog(); return(false); } } var defaultParentObject = SceneView.GetDefaultParentObjectIfSet(); var parent = defaultParentObject != null ? defaultParentObject : sceneView.customParentForDraggedObjects; string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent, draggedObject.name); if (parent != null) { draggedObject.transform.parent = parent; } draggedObject.hideFlags = 0; Undo.RegisterCreatedObjectUndo(draggedObject, "Place " + draggedObject.name); EditorUtility.SetDirty(draggedObject); DragAndDrop.AcceptDrag(); Selection.activeObject = draggedObject; HandleUtility.ignoreRaySnapObjects = null; if (SceneView.mouseOverWindow != null) { SceneView.mouseOverWindow.Focus(); } if (!Application.IsPlaying(draggedObject)) { draggedObject.name = uniqueName; } return(true); }
public void OnSceneDrag(SceneView sceneView) { GameObject go = target as GameObject; if (!PrefabUtility.IsPartOfPrefabAsset(go)) { return; } var prefabAssetRoot = go.transform.root.gameObject; Event evt = Event.current; switch (evt.type) { case EventType.DragUpdated: Scene destinationScene = sceneView.customScene.IsValid() ? sceneView.customScene : SceneManager.GetActiveScene(); if (dragObject == null) { dragObject = (GameObject)PrefabUtility.InstantiatePrefab(prefabAssetRoot, destinationScene); dragObject.hideFlags = HideFlags.HideInHierarchy; dragObject.name = go.name; } if (HandleUtility.ignoreRaySnapObjects == null) { HandleUtility.ignoreRaySnapObjects = dragObject.GetComponentsInChildren <Transform>(); } DragAndDrop.visualMode = DragAndDropVisualMode.Copy; object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition)); if (hit != null) { RaycastHit rh = (RaycastHit)hit; float offset = 0; if (Tools.pivotMode == PivotMode.Center) { float geomOffset = HandleUtility.CalcRayPlaceOffset(HandleUtility.ignoreRaySnapObjects, rh.normal); if (geomOffset != Mathf.Infinity) { offset = Vector3.Dot(dragObject.transform.position, rh.normal) - geomOffset; } } dragObject.transform.position = Matrix4x4.identity.MultiplyPoint(rh.point + (rh.normal * offset)); } else { dragObject.transform.position = HandleUtility.GUIPointToWorldRay(evt.mousePosition).GetPoint(10); } // Use prefabs original z position when in 2D mode if (sceneView.in2DMode) { Vector3 dragPosition = dragObject.transform.position; dragPosition.z = prefabAssetRoot.transform.position.z; dragObject.transform.position = dragPosition; } evt.Use(); break; case EventType.DragPerform: var stage = StageNavigationManager.instance.currentItem; if (stage.isPrefabStage) { var prefabAssetThatIsAddedTo = AssetDatabase.LoadMainAssetAtPath(stage.prefabAssetPath); if (PrefabUtility.CheckIfAddingPrefabWouldResultInCyclicNesting(prefabAssetThatIsAddedTo, go)) { PrefabUtility.ShowCyclicNestingWarningDialog(); return; } } Transform parent = sceneView.customParentForDraggedObjects; string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent, dragObject.name); if (parent != null) { dragObject.transform.parent = parent; } dragObject.hideFlags = 0; Undo.RegisterCreatedObjectUndo(dragObject, "Place " + dragObject.name); EditorUtility.SetDirty(dragObject); DragAndDrop.AcceptDrag(); Selection.activeObject = dragObject; HandleUtility.ignoreRaySnapObjects = null; if (SceneView.mouseOverWindow != null) { SceneView.mouseOverWindow.Focus(); } dragObject.name = uniqueName; dragObject = null; evt.Use(); break; case EventType.DragExited: if (dragObject) { UnityObject.DestroyImmediate(dragObject, false); HandleUtility.ignoreRaySnapObjects = null; dragObject = null; evt.Use(); } break; } }
internal void OnSceneDragInternal(SceneView sceneView, int index, EventType type, Vector2 mousePosition, bool alt) { GameObject go = target as GameObject; if (!PrefabUtility.IsPartOfPrefabAsset(go)) { return; } var prefabAssetRoot = go.transform.root.gameObject; switch (type) { case EventType.DragUpdated: Scene destinationScene = sceneView.customScene.IsValid() ? sceneView.customScene : SceneManager.GetActiveScene(); if (m_DragObject == null) { // While dragging the instantiated prefab we do not want to record undo for this object // this will cause a remerge of the instance since changes are undone while dragging. // The DrivenRectTransformTracker by default records Undo when used when driving // UI components. This breaks our hideflag setup below due to a remerge of the dragged instance. // StartRecordingUndo() is called on DragExited. Fixes case 1223793. DrivenRectTransformTracker.StopRecordingUndo(); if (!EditorApplication.isPlaying || EditorSceneManager.IsPreviewScene(destinationScene)) { m_DragObject = (GameObject)PrefabUtility.InstantiatePrefab(prefabAssetRoot, destinationScene); m_DragObject.name = go.name; } else { // Instatiate as regular GameObject in Play Mode so runtime logic // won't run into restrictions on restructuring Prefab instances. m_DragObject = Instantiate(prefabAssetRoot); SceneManager.MoveGameObjectToScene(m_DragObject, destinationScene); } m_DragObject.hideFlags = HideFlags.HideInHierarchy; if (HandleUtility.ignoreRaySnapObjects == null) { HandleUtility.ignoreRaySnapObjects = m_DragObject.GetComponentsInChildren <Transform>(); } else { HandleUtility.ignoreRaySnapObjects = HandleUtility.ignoreRaySnapObjects.Union(m_DragObject.GetComponentsInChildren <Transform>()).ToArray(); } PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { GameObject prefab = AssetDatabase.LoadMainAssetAtPath(prefabStage.assetPath) as GameObject; if (prefab != null) { if (PrefabUtility.CheckIfAddingPrefabWouldResultInCyclicNesting(prefab, target)) { s_CyclicNestingDetected = true; } } } } DragAndDrop.visualMode = DragAndDropVisualMode.Copy; Vector3 point, normal; float offset = 0; if (index == 0) { s_PlaceObject = HandleUtility.PlaceObject(mousePosition, out s_PlaceObjectPoint, out s_PlaceObjectNormal); } point = s_PlaceObjectPoint; normal = s_PlaceObjectNormal; if (s_PlaceObject) { if (Tools.pivotMode == PivotMode.Center) { float geomOffset = HandleUtility.CalcRayPlaceOffset(m_DragObject.GetComponentsInChildren <Transform>(), normal); if (geomOffset != Mathf.Infinity) { offset = Vector3.Dot(m_DragObject.transform.position, normal) - geomOffset; } } m_DragObject.transform.position = Matrix4x4.identity.MultiplyPoint(point + (normal * offset)); } else { m_DragObject.transform.position = HandleUtility.GUIPointToWorldRay(mousePosition).GetPoint(10); } if (alt) { if (offset != 0) { m_DragObject.transform.position = point; } m_DragObject.transform.position += prefabAssetRoot.transform.localPosition; } // Use prefabs original z position when in 2D mode if (sceneView.in2DMode) { Vector3 dragPosition = m_DragObject.transform.position; dragPosition.z = prefabAssetRoot.transform.position.z; m_DragObject.transform.position = dragPosition; } // Schedule selection clearing for when we start performing the actual drag action s_ShouldClearSelection = true; break; case EventType.DragPerform: DragPerform(sceneView, m_DragObject, go); m_DragObject = null; break; case EventType.DragExited: // DragExited is always fired after DragPerform so we do no need to call StartRecordingUndo // in DragPerform DrivenRectTransformTracker.StartRecordingUndo(); if (m_DragObject) { DestroyImmediate(m_DragObject, false); HandleUtility.ignoreRaySnapObjects = null; m_DragObject = null; } s_ShouldClearSelection = false; s_CyclicNestingDetected = false; break; } }