using UnityEditor;
using UnityEditor.Actions;
using UnityEngine;
// Add a menu item to the Scene View context menu that creates a cube where-ever the mouse clicks.
public class CreateCube : EditorAction
{
    GameObject m_GameObject;
    int m_UndoStart;
    // Prefixing the menu item path with "CONTEXT" indicates that this is a context menu item. Context menu items are
    // not added to the application menu bar. The second section of the menu path is the name of the type that this
    // menu item is applicable to. The context menu in the Scene View for example will look for context menu items for
    // each of the following types:
    //    1. The active EditorToolContext type.
    //    2. The active EditorTool type.
    //    3. All component types in the selection. Ex, Transform, MeshRenderer, BoxCollider, etc...
    // As an example, to create a context menu item that is shown when context clicking in the Scene View with a
    // GameObject selected that has a MeshFilter component, use "CONTEXT/MeshFilter/My Menu Item".
    [MenuItem("CONTEXT/GameObjectToolContext/Create Cube")]
    static void Init()
    {
        EditorAction.Start<CreateCube>();
    }
    public CreateCube()
    {
        // Show a preview cube at the cursor.
        m_GameObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
        // If the action is cancelled, we'll clean up the unused resource by calling Undo.PerformUndo().
        Undo.RegisterCreatedObjectUndo(m_GameObject, "Create Cube");
        // To avoid an unsightly "jump" when the cursor first moves, disable the preview until we have a valid
        // intersection point to place the object.
        m_GameObject.SetActive(false);
        m_UndoStart = Undo.GetCurrentGroup();
    }
    public override void OnSceneGUI(SceneView view)
    {
        var evt = Event.current;
        var id = GUIUtility.GetControlID(FocusType.Passive);
        if (evt.type == EventType.MouseMove)
        {
            HandleUtility.AddControl(id, 0);
            // Disable preview object so that we don't intersect with object placement ray.
            m_GameObject.SetActive(false);
            var intersected = HandleUtility.PlaceObject(evt.mousePosition, out var position, out var normal);
            m_GameObject.SetActive(true);
            if (intersected)
            {
                Undo.RecordObject(m_GameObject, "Create Cube");
                m_GameObject.transform.position = position;
                m_GameObject.transform.rotation = Quaternion.LookRotation(normal);
            }
        }
        // By checking that no mouse modifiers are active, we can allow for camera movement without breaking the
        // action.
        if (evt.type == EventType.MouseDown && evt.modifiers == EventModifiers.None)
        {
            GUIUtility.hotControl = id;
            evt.Use();
        }
        if (GUIUtility.hotControl == id && evt.type == EventType.MouseUp)
        {
            evt.Use();
            GUIUtility.hotControl = 0;
            Finish(EditorActionResult.Success);
        }
    }
    // Since the object we want to instantiate is already in the scene, there is nothing more to do in the OnFinish
    // function if the action exits successfully. If the action is cancelled however, we'll remove the instantiated
    // object from the scene by calling undo.
    protected override void OnFinish(EditorActionResult result)
    {
        if (result == EditorActionResult.Canceled)
        {
            Undo.PerformUndo();
            return;
        }
        Selection.activeObject = m_GameObject;
        // Merge the selection change and GameObject creation/placement to a single undo entry.
        Undo.CollapseUndoOperations(m_UndoStart);
    }
}