Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Editor: Drag Box Select

Discussion in 'Scripting' started by skeptika, Jan 24, 2018.

  1. skeptika

    skeptika

    Joined:
    Dec 31, 2011
    Posts:
    108
    I'm trying to implement a typical Box Select (drag a box selection) in a custom Editor Window.

    I felt like this should be simple, but nothing draws, even though Debug.Log is telling me I'm drawing a Rect properly (so I'm sure its firing, and is drawing a Rect correctly starting at the click with width/height values that make sense).

    Code (csharp):
    1.  
    2.     bool dragBox = false;
    3.     Vector2 startPos;
    4.  
    5.     void OnGUI()
    6.     {    
    7.         Event e = Event.current;
    8.      
    9.         if (e.isMouse && e.type == EventType.MouseDrag)
    10.         {        
    11.             if (!dragBox)
    12.             {
    13.                 dragBox = true;
    14.                 startPos = e.mousePosition;
    15.             }
    16.  
    17.             if (dragBox)
    18.             {
    19.                 Rect boxRect = new Rect(startPos.x, startPos.y, e.mousePosition.x - startPos.x, e.mousePosition.y - startPos.y);
    20.                 GUI.Box(boxRect, "test");
    21.                 Debug.Log(boxRect);
    22.             }
    23.         }
    24.  
    25.         Repaint ();
    26.     }
    I must be missing something stupid simple, what am I missing? I played with adding in GUIStyles to GUI.Box, but still nothing. No Box whatsoever is drawn.
     
    Last edited: Jan 24, 2018
  2. skeptika

    skeptika

    Joined:
    Dec 31, 2011
    Posts:
    108
    To answer my own question, it's because EventType.MouseDrag does not work like I expected it to. I thought it would be the equivalent of Input.GetKey and continuously return true.

    It actually only fires ONCE, it will not keep on firing as long as the mouse is held down. However it DOES refire once your mouse position changes (so if you're moving your mouse it SEEMS to be returning continuously which is what tricked me via the Debug Log, it looks like its continuously firing). It's just a different way to think about things that how the Input class works.

    Rather the way to use it is to just set my dragBox to true per the above when MouseDrag first fires, then just use that boolean itself to define when to draw the box like so.

    Code (csharp):
    1.  
    2.         //Box Select
    3.         if (e.type == EventType.MouseDrag)
    4.         {        
    5.             if (!dragBox)
    6.             {
    7.                 dragBox = true;
    8.                 startPos = e.mousePosition;
    9.             }
    10.  
    11.         }
    12.         if (e.type == EventType.MouseUp)
    13.         {
    14.             dragBox = false;
    15.         }
    16.  
    17.         if (dragBox)
    18.         {
    19.             Rect boxRect = new Rect(startPos.x, startPos.y, e.mousePosition.x - startPos.x, e.mousePosition.y - startPos.y);
    20.             GUI.Box(boxRect, "");
    21.         }
     
    Last edited: Jan 24, 2018
    ThermalFusion and flashframe like this.
  3. blu3drag0n

    blu3drag0n

    Joined:
    Nov 9, 2018
    Posts:
    94
    This is an old post, but when I was looking for a solution to get a selection rectangle drawing in game mode, also in a build version, then there were not really satisfying answers. Most tried via some assets packages or either Line Renderer or Shaders, which I found to be overloaded for what I was trying to achieve.

    I finally managed to build it myself with very few code and want to share for everyone else googling in the future, enjoy:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. /// <summary>
    4. /// Draws a selection rectangle on the left mouse button down & dragging
    5. ///
    6. /// You only need an InputReceiverManager that basically tracks
    7. /// - if the left mouse button is currently down and saves it in "LeftMouseButtonDown"
    8. /// - saves the initial click position when mouse button was clicked  and saves it in "InitialMousePositionOnLeftClick"
    9. /// - updates the current mouse position and saves it in "CurrentMousePosition"
    10. ///
    11. /// </summary>
    12. public class SelectionRectangleDrawer : MonoBehaviour
    13. {
    14.     //set color via inspector for the selection rectangles filler color
    15.     public Color SelectionRectangleFillerColor;
    16.     //set color via inspector for the selection rectangles border color
    17.     public Color SelectionRectangleBorderColor;
    18.     //set selection rectangles  border thickness
    19.     public int SelectionRectangleBorderThickness = 2;
    20.     private Texture2D _selectionRectangleFiller;
    21.     private Texture2D _selectionRectangleBorder;
    22.     private bool _drawSelectionRectangle;
    23.     private float _x1, _x2, _y1, _y2;
    24.     private Vector2 pos1, pos2;
    25.     void Start()
    26.     {
    27.         _selectionRectangleFiller = new Texture2D(1, 1);
    28.         _selectionRectangleFiller.SetPixel(0, 0, SelectionRectangleFillerColor);
    29.         _selectionRectangleFiller.Apply();
    30.         _selectionRectangleFiller.wrapMode = TextureWrapMode.Clamp;
    31.         _selectionRectangleFiller.filterMode = FilterMode.Point;
    32.         _selectionRectangleBorder = new Texture2D(1, 1);
    33.         _selectionRectangleBorder.SetPixel(0, 0, SelectionRectangleBorderColor);
    34.         _selectionRectangleBorder.Apply();
    35.         _selectionRectangleBorder.wrapMode = TextureWrapMode.Clamp;
    36.         _selectionRectangleBorder.filterMode = FilterMode.Point;
    37.     }
    38.     void Update()
    39.     {
    40.         if (InputReceiverManager.Instance.LeftMouseButtonDown && !Mathf.Approximately(Vector2.Distance(InputReceiverManager.Instance.CurrentMousePosition,
    41.                                                                                                        InputReceiverManager.Instance.InitialMousePositionOnLeftClick), 0f))
    42.             _drawSelectionRectangle = true;
    43.         else if (!InputReceiverManager.Instance.LeftMouseButtonDown && _drawSelectionRectangle)
    44.             _drawSelectionRectangle = false;
    45.     }
    46.     private void OnGUI()
    47.     {
    48.         if (_drawSelectionRectangle)
    49.             drawSelectionRectangle();
    50.     }
    51.     private void drawSelectionRectangle()
    52.     {
    53.         pos1 = InputReceiverManager.Instance.InitialMousePositionOnLeftClick;
    54.         pos2 = InputReceiverManager.Instance.CurrentMousePosition;
    55.         //check initial mouse position on X axis versus dragging mouse position
    56.         if (pos1.x < pos2.x)
    57.         {
    58.             _x1 = pos1.x;
    59.             _x2 = pos2.x;
    60.         }
    61.         else
    62.         {
    63.             _x1 = pos2.x;
    64.             _x2 = pos1.x;
    65.         }
    66.         //check initial mouse position on Y axis versus dragging mouse position
    67.         if (pos1.y < pos2.y)
    68.         {
    69.             _y1 = pos1.y;
    70.             _y2 = pos2.y;
    71.         }
    72.         else
    73.         {
    74.             _y1 = pos2.y;
    75.             _y2 = pos1.y;
    76.         }
    77.         //filler
    78.         GUI.DrawTexture(new Rect(_x1, Screen.height - _y1, _x2 - _x1, _y1 - _y2), _selectionRectangleFiller, ScaleMode.StretchToFill);
    79.         //top line
    80.         GUI.DrawTexture(new Rect(_x1, Screen.height - _y1, _x2 - _x1, -SelectionRectangleBorderThickness), _selectionRectangleBorder, ScaleMode.StretchToFill);
    81.         //bottom line
    82.         GUI.DrawTexture(new Rect(_x1, Screen.height - _y2, _x2 - _x1, SelectionRectangleBorderThickness), _selectionRectangleBorder, ScaleMode.StretchToFill);
    83.         //left line
    84.         GUI.DrawTexture(new Rect(_x1, Screen.height - _y1, SelectionRectangleBorderThickness, _y1 - _y2), _selectionRectangleBorder, ScaleMode.StretchToFill);
    85.         //right line
    86.         GUI.DrawTexture(new Rect(_x2, Screen.height - _y1, -SelectionRectangleBorderThickness, _y1 - _y2), _selectionRectangleBorder, ScaleMode.StretchToFill);
    87.     }
    88. }
    89.  
    90.  
    91.  
     
    SeerSucker69 likes this.