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;
            }
        }