Alex
Alex

Reputation: 1420

UNITY Draw rectangle on mouse drag

What's the proper way of drawing rect outline based on mouse hover. Effect you get in strategy games when selecting units. Running Unity 2018.3.0f. Perhaps my code can be slightly changed. I was unable to find something done. As second option I could use LineRenderer and create a rect based on that line. Adding lines that would make the rect.

This is an example: enter image description here

This is what I came up with but for some reason this has wrong Y coords.

using UnityEngine;
using System.Collections;
using System;

public class MouseDragSelect : MonoBehaviour
{

    private Rect position = new Rect(193, 148, 249-193, 148-104);
    public Color color = Color.green;
    private Vector3[] mousePositions = new Vector3[2];
    private bool draggingMouse = false;
    private bool drawRect = false;
    public float timer = 1.2f;

    void OnGUI()
    {
        if (drawRect)
        {
            DrawRectangle(position, 1, color);
        }
    }

    void DrawRectangle(Rect area, int frameWidth, Color color)
    {
        //Create a one pixel texture with the right color
        var texture = new Texture2D(1, 1);
        texture.SetPixel(0, 0, color);
        texture.Apply();

        Rect lineArea = area;
        lineArea.height = frameWidth; //Top line
        GUI.DrawTexture(lineArea, texture);
        lineArea.y = area.yMax - frameWidth; //Bottom
        GUI.DrawTexture(lineArea, texture);
        lineArea = area;
        lineArea.width = frameWidth; //Left
        GUI.DrawTexture(lineArea, texture);
        lineArea.x = area.xMax - frameWidth;//Right
        GUI.DrawTexture(lineArea, texture);
    }

    void reset() {
        drawRect = false;
        mousePositions[0] = new Vector3();
        mousePositions[1] = new Vector3();
        timer = 1.2f;
        draggingMouse = false;
    }
    private void Update()
    {
        if (drawRect)
        {
            if (timer > 0.1)
            {
                timer -= 1 * Time.deltaTime;
            } else {
               reset();
            }
        }
        if(Input.GetMouseButtonDown(0)) {
            if(!draggingMouse){
                mousePositions[0] = Input.mousePosition;
                print("x start:" + mousePositions[0].x);
                print("y start:" + mousePositions[0].y);
            }
            draggingMouse = true;
        }
        if(Input.GetMouseButtonUp(0)) {
            if(draggingMouse) {
                mousePositions[1] = Input.mousePosition;
                float width = Math.Abs(mousePositions[1].x - mousePositions[0].x);
                float height = Math.Abs(mousePositions[1].y - mousePositions[0].y);
                float x = mousePositions[0].x;
                float y = mousePositions[0].y;
               // print("width:" + width);
               // print("height:" + height);
                print("x end:" + mousePositions[1].x);
                print("y end:" + mousePositions[1].y);
                position = new Rect(x, y, width, height);
               // print("Got last mouse position!");
                drawRect = true;
            }
        }
    }
}

Tried selecting area around the character.. Getting weird Y coords.. enter image description here

Following solutions does not work either :( as I am getting weird Y coords

            float x = Math.Min(mousePositions[0].x, mousePositions[1].x);
            float y = Math.Min(mousePositions[0].y, mousePositions[1].y);
            float width = Math.Max(mousePositions[0].x, mousePositions[1].x) - x;
            float height = Math.Max(mousePositions[0].y, mousePositions[1].y) - y;

Upvotes: 1

Views: 3143

Answers (3)

Recessive
Recessive

Reputation: 1939

The key issue was Screen.height-mousePosition.y as suggested by Technivorous, however this problem can be solved much more succinctly:

public class DrawSelect : MonoBehaviour
{
    Texture2D selectTexture;

    Vector3 boxOrigin;
    Vector3 boxEnd;

    bool drawing;

    private void Start() {
        selectTexture = new Texture2D(1, 1);
        selectTexture.SetPixel(0, 0, UnityEngine.Color.white);
        selectTexture.Apply();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0)) {
            boxOrigin = Input.mousePosition;
            drawing = true;
        }

        if (drawing) {
            boxEnd = Input.mousePosition;
        }

        if(Input.GetKeyUp(KeyCode.Mouse0)) {
            drawing = false;
        }
    }

    void OnGUI() {
        if (drawing) {
            Rect area = new Rect(boxOrigin.x, Screen.height - boxOrigin.y, boxEnd.x - boxOrigin.x, boxOrigin.y - boxEnd.y);
            
            Rect lineArea = area;
            lineArea.height = 1; //Top line
            GUI.DrawTexture(lineArea, selectTexture);
            lineArea.y = area.yMax - 1; //Bottom
            GUI.DrawTexture(lineArea, selectTexture);
            lineArea = area;
            lineArea.width = 1; //Left
            GUI.DrawTexture(lineArea, selectTexture);
            lineArea.x = area.xMax - 1;//Right
            GUI.DrawTexture(lineArea, selectTexture);
        }
    }

}

Upvotes: 0

evilkissyou
evilkissyou

Reputation: 11

Just in case anyone was struggling with it as I was, here is the solution, which seems to be working correctly. The solution uses initial code by @Alex and adjustment by @Technivorous.

using UnityEngine;
using System.Collections;
using System;

public class MouseDragSelection : MonoBehaviour
{

    private Rect position = new Rect(193, 148, 249 - 193, 148 - 104);
    public Color color = Color.green;
    private Vector3[] mousePositions = new Vector3[2];
    private bool draggingMouse = false;
    private bool drawRect = false;
    public float timer = 1.2f;

    void OnGUI()
    {
        if (drawRect)
        {
            DrawRectangle(position, 1, color);
        }
    }

    void DrawRectangle(Rect area, int frameWidth, Color color)
    {
        //Create a one pixel texture with the right color
        var texture = new Texture2D(1, 1);
        texture.SetPixel(0, 0, color);
        texture.Apply();

        Rect lineArea = area;
        lineArea.height = frameWidth; //Top line
        GUI.DrawTexture(lineArea, texture);
        lineArea.y = area.yMax - frameWidth; //Bottom
        GUI.DrawTexture(lineArea, texture);
        lineArea = area;
        lineArea.width = frameWidth; //Left
        GUI.DrawTexture(lineArea, texture);
        lineArea.x = area.xMax - frameWidth;//Right
        GUI.DrawTexture(lineArea, texture);
    }

    void reset()
    {
        drawRect = false;
        mousePositions[0] = new Vector3();
        mousePositions[1] = new Vector3();
        timer = 1.2f;
        draggingMouse = false;
    }
    private void Update()
    {
        if (drawRect)
        {
            if (timer > 0.1)
            {
                timer -= 1 * Time.deltaTime;
            }
            else
            {
                reset();
            }
        }
        if (Input.GetMouseButtonDown(0))
        {
            if (!draggingMouse)
            {
                mousePositions[0] = Input.mousePosition;
                print("x start:" + mousePositions[0].x);
                print("y start:" + mousePositions[0].y);
            }
            draggingMouse = true;
        }
        if (Input.GetMouseButtonUp(0))
        {
            if (draggingMouse)
            {
                mousePositions[1] = Input.mousePosition;
                float width = Math.Abs(mousePositions[1].x - mousePositions[0].x);
                float height = Math.Abs(mousePositions[1].y - mousePositions[0].y);
                float x = mousePositions[0].x;
                float y = Screen.height - mousePositions[0].y;
                // print("width:" + width);
                // print("height:" + height);
                print("x end:" + mousePositions[1].x);
                print("y end:" + mousePositions[1].y);
                if (mousePositions[0].x < mousePositions[1].x && mousePositions[0].y < mousePositions[1].y)
                {
                    print("x1 < x2, y1 < y2");
                    position = new Rect(x, y, width, -height);
                }
                else if (mousePositions[0].x > mousePositions[1].x && mousePositions[0].y < mousePositions[1].y)
                {
                    print("x1 > x2, y1 < y2");
                    position = new Rect(x, y, -width, -height);
                }
                else if (mousePositions[0].x < mousePositions[1].x && mousePositions[0].y > mousePositions[1].y)
                {
                    print("x1 < x2, y1 > y2");
                    position = new Rect(x, y, width, height);
                } else
                {
                    print("x1 > x2, y1 > y2");
                    position = new Rect(x, y, -width, height);
                }
                // print("Got last mouse position!");
                drawRect = true;
            }
        }
    }
}

Upvotes: 1

Technivorous
Technivorous

Reputation: 1712

so for your y coord, screen space and world space are different frommouse to screen. change your y to Screen.height-mousePosition.y. this will fix it for you

Upvotes: 3

Related Questions