- Home /
[wonderfully illustrated] Dragging a GUI-box-handle
Greetings, I am creating a simple text based game. The left and middle part of the screen is filled with text and the right part is for controlls.
I have the problem with controls, more specifically with GUI.What I want to get is the following: On RMB down I want the cursor to dissapear, instead a person will see 4 boxes-buttons and a handle. If the mouse goes up - the handle should do the same, if down - down, left - left, right - right. It shouldn't go out of boundaries, however.
I can't create a handle which will be able to satisfy this conditions. Problem #1 make movement of handle = movement of cursor Problem #2 prevent handle from going out of the box border (marked green in the picture)
Here is what I was able to achieve:
var GUIEnabled : boolean = false;
function Update () {
if (Input.GetMouseButton(1)){GUIEnabled = true;}
else {GUIEnabled=false;}
Debug.Log("GUIEnabled");
}
function OnGUI(){
if(GUIEnabled){
GUI.Button (Rect (960,320,100,40), GUIContent ("BT1", "Button 1"));
GUI.Button (Rect (960,480,100,40), GUIContent ("BT2", "Button 2"));
GUI.Button (Rect (760,400,100,40), GUIContent ("BT3", "Button 3"));
GUI.Button (Rect (1160,400,100,40), GUIContent ("BT4", "Button 4"));
}
}
For your better understanding I drew 2 pictures, please find attachments or use the imagehosting links: http://postimg.org/image/kmohty3lb/ and another one http://postimg.org/image/jglcsrfyj/
Any help is welcome and very appreciated!
Answer by robertbu · Apr 23, 2014 at 10:23 AM
Since Unity Answers are to have a single, specific question, I'm going to assume that you want a solution to your handle problem. I was curious to see what it would take to make a drag and drop with GUI, so I played a bit. It took a surprising amount of code to make it work right:
#pragma strict
public var tex : Texture;
private var bgRect : Rect = Rect(300,300,500,500);
private var handleRect : Rect;
private var minX : float;
private var minY : float;
private var maxX : float;
private var maxY : float;
private var offset : Vector2;
private var dragging = false;
function Start() {
handleRect = Rect(0,0,tex.width, tex.height);
handleRect.center = bgRect.center;
minX = bgRect.x + tex.width / 2.0;
minY = bgRect.y + tex.height / 2.0;
maxX = bgRect.x + bgRect.width - tex.width / 2.0;
maxY = bgRect.y + bgRect.height - tex.height / 2.0;
}
function OnGUI() {
var e : Event = Event.current;
if (e.type == EventType.MouseDown && handleRect.Contains(e.mousePosition)) {
offset = handleRect.center - e.mousePosition;
dragging = true;
}
if (e.type == EventType.MouseDrag && dragging) {
handleRect.center = e.mousePosition + offset;
handleRect.center.x = Mathf.Clamp(handleRect.center.x, minX, maxX);
handleRect.center.y = Mathf.Clamp(handleRect.center.y, minY, maxY);
offset = handleRect.center - e.mousePosition;
}
if (e.type == EventType.MouseUp) {
dragging = false;
}
GUI.Box(bgRect, "");
GUI.DrawTexture(handleRect, tex);
}
Note this is not any any way integrated with the rest of your code or concept. It is just some demonstration code on how to have your handle displayed and be able to drag the handle around, but at the same time constraining the handle to an area. Add this script to an empty game object. Drag and drop the handle texture on the 'tex' variable. You may also want to adjust the 'bgRect'. This rect is the background rect the handle is confined to.
Robertbu, thank you very very much!!! It works! I changed the script a little bit (to return the handle to initial position, remove cursor and placed the buttons inside the box) and the script is almost ready.
Guys, I have stucked with the last problem, though. - How to press a button (execute the code, behind this button), over which the handle is floating (without clicking it)? I googled, but the only useful thing I found was how to detect if the $$anonymous$$OUSE is hovering over smth. Since in our case, a mouse pointer may be anywhere in the screen (it's hidden) and we only control the handle, I assume some other soultion is needed.
Below is the script (Robertbu + some my changes).
Does anyone know and does anyone have any idea if it is possible to press a button over which the handle is floating?
#pragma strict
public var tex : Texture;
private var bgRect : Rect = Rect(900,200,300,300);
private var handleRect : Rect;
private var $$anonymous$$X : float;
private var $$anonymous$$Y : float;
private var maxX : float;
private var maxY : float;
private var offset : Vector2;
private var dragging = false;
var GUIEnab: boolean = false;
handleRect = Rect(0,0,tex.width, tex.height);
handleRect.center = bgRect.center;
$$anonymous$$X = bgRect.x + tex.width / 2.0;
$$anonymous$$Y = bgRect.y + tex.height / 2.0;
maxX = bgRect.x + bgRect.width - tex.width / 2.0;
maxY = bgRect.y + bgRect.height - tex.height / 2.0;
function Update() {
Screen.showCursor = false;
}
function OnGUI() {
GUI.Button (Rect (1010,210,70,70), GUIContent ("BT1", "Button 1"));
GUI.Button (Rect (1010,420,70,70), GUIContent ("BT2", "Button 2"));
GUI.Button (Rect (910,320,70,70), GUIContent ("BT3", "Button 3"));
GUI.Button (Rect (1120,320,70,70), GUIContent ("BT4", "Button 4"));
var e : Event = Event.current;
if (e.type == EventType.$$anonymous$$ouseDown) {
offset = handleRect.center - e.mousePosition;
dragging = true;
}
if (e.type == EventType.$$anonymous$$ouseDrag && dragging) {
handleRect.center = e.mousePosition + offset;
handleRect.center.x = $$anonymous$$athf.Clamp(handleRect.center.x, $$anonymous$$X, maxX);
handleRect.center.y = $$anonymous$$athf.Clamp(handleRect.center.y, $$anonymous$$Y, maxY);
offset = handleRect.center - e.mousePosition;
}
if (e.type == EventType.$$anonymous$$ouseUp) {
dragging = false;
handleRect.center = bgRect.center;
}
GUI.Box(bgRect, "");
GUI.DrawTexture(handleRect, tex);
}
Any suggestions?)
Don't use buttons. Use textures to emulate a button. Then you can just check to see if the position is within the rect of each pseudo-button and execute the appropriate code if it is.
Thanks! No buttons!
I tried textures, but found no way to check if an Object is inside, not a mouse. Here's an example:
var BoxRect = new Rect(1010,210,70,70);
GUI.Box(BoxRect,"$$anonymous$$y GUI Box");
if (BoxRect.Contains(Event.current.mousePosition))
{
print("$$anonymous$$ouse inside");
}
But I would like to change ins$$anonymous$$d of mousePosition - the position of a handle and when I substitute "Event.current.mousePosition" for "handleRect.center" it says it's not a member of Unity.Event
I need to see the code that is generating the error to be sure of the probelm, but I believe you want:
if (BoxRect.Contains(handleRect.center))
$$anonymous$$y guess is that you did this:
if (BoxRect.Contains(Event.current.handleRect.center))
You are right it was the case. Thank you again, Robertbu!