Declaring a GUI Btn as a class var

Hi there,
I had a OnGUI function like this…

function OnGUI()
{
var leftBtn = GUI.RepeatButton (Rect (10, 790, 200, 400), leftBtnImage, guiStyle);
if(Screen.orientation == ScreenOrientation.Portrait)
{
leftBtn = GUI.RepeatButton (Rect (10, 790, 100, 400), leftBtnImage, guiStyle);
print(“P”);
return;
}
if(Screen.orientation == ScreenOrientation.LandscapeLeft)
{
leftBtn = GUI.RepeatButton (Rect (10, 790, 200, 500), leftBtnImage, guiStyle);
print(“LSL”);
return;
}
}

My aim was to change the btns postion depending on the screen orientation. However, it was causing a gdb crash in xcode. My thinking was somehow my continous call for leftBtn in the 2 if statements caused this becuase if they are removed, it runs fine.

So I wanted to declare leftBtn as a class var however to no avail…
I did so like this…

	var leftBtn : GUI.Button;

also like this…

	var leftBtn : GUI.Button = GUI.RepeatButton (Rect (10, 790, 200, 400), leftBtnImage, guiStyle);

Anyone have any ideas as to how I can best declare a GUI.Button var and have it change position depending on screen orientation?

You can’t. But you can certainly declare a Rect at the class level and use that to re-position your button accordingly.

Well, you could do something as simple as this:

var portraitRect:Rect;
var LandscapeRect:Rect;
var leftBtn;

function OnGUI()
{
	if(Screen.orientation == ScreenOrientation.Portrait)
	{
		leftBtn = GUI.RepeatButton (PortraitRect, leftBtnImage, guiStyle);
		print("P");	
		return;	
	}
	if(Screen.orientation == ScreenOrientation.LandscapeLeft)
	{
		leftBtn = GUI.RepeatButton (LandscapeRect, leftBtnImage, guiStyle);
		print("LSL");	
		return;	
	}	
}

Then when you look in the editor, you can just set the rectangles that way. This way you can also hit the play button, and drag the numbers to what you want, take note of them, stop the game and insert the new numbers, to get exactly where you want it, visually. Also, shouldn’t cause any problems when compiling.

Ok thank you.
But I have run into one problem…

I declared my various rects as class vars.

Then in my OnGUI() looks like this…

	var leftBtn = GUI.RepeatButton (Rect (0, 0, 0, 0), leftBtnImage, guiStyle);		
	
	if(Screen.orientation == ScreenOrientation.Portrait)
	{
		leftBtn = GUI.RepeatButton (Rect (leftBtnRectP), leftBtnImage, guiStyle);
		print("P");	
		return;		
	}
	if(Screen.orientation == ScreenOrientation.LandscapeLeft)
	{
		leftBtn = GUI.RepeatButton (Rect (leftBtnRectPUD), leftBtnImage, guiStyle);
		print("LSL");	
		return;		
	}

My problem is… is there a way I can declare the var leftBtn, and only have it exist in the correct if statement? Meaning, that currently, tho I can not see it, as its dimensions are 0, 0, and I can move it off screen by giving it outlandish coordinates, is there a way I can insure that it does not exist out side the if statement.

Currently it does. I know this because if I make it have visible dimensions, it can be seen along side the btn in the if statement.

You don’t need the first line of code, just replace it with

var leftBtn = false;

(I would move this line outside of OnGUI)

The RepeatButton method returns boolean, not Rect. In your case leftBtn should cause errors in your code, since you declare it above as Rect but then treat it as boolean to store the return of RepeatButton. [EDIT] I just noticed you don’t declare its type, so it won’t return errors, but still you’re using it wrong.

As such, you cannot store a button in a variable. This is deliberate from Unity. The current GUI system is not supposed to be object based, it is supposed to be state based. Buttons are not instances in your scene and get destroyed (and then re-drawn) when the frame ends.

And therefore, you cannot treat them as instances. As for your specific issue, make your Rect values resolution independent. Unity sorts all GUI elements automatically when orientation switches, and as long as your dimensions are resolution independent they are going to keep their proper place. If however you wish to place them in a different way when the orientation changes, do what was suggested to you above and only change the Rect coordinates.

Because I love me some Dictionaries I would do it this way. (Off the top of my head so untested)

private Dictionary<ScreenOrientation, Rect> btnCoords = new Dictionary<ScreenOrientation, Rect>();
private bool leftBtn;
void Awake()
{
    btnCoords.Add(ScreenOrientation.Portrait, new Rect(0, 0, 10, 10));
    btnCoords.Add(ScreenOrientation.Landscape, new Rect(10, 10, 10, 10));
}

void OnGUI()
{
    leftBtn = GUI.RepeatButton(btnCoords[Screen.orientation], leftBtnImage, guiStyle);
}

Thats interesting.
So is by setting var leftBtn = false, just creating a var that could be anything?

No, you’re creating a boolean variable (unity casts it to boolean due to its initial value (false) typed by you).

As Diviner said above, GUI.Button returns only a boolean value. It represents the state of your button, whether it is pressed or not.

Hmm.
I am confused.
While I get it, I dont.

How can a boolean be a GUI.Button?

For instance could I
var leftBtn = false;

function Start()
{
leftBtn = 32;
}

Technically speaking, yes, you could. If you don’t define a type, it’s set to a type of object. An Object is able to hold multiple types of variables without being cast to a specific type. It makes it easier to use if you don’t know what the type is, but uses a lot more ram. It’s best to cast types so that you keep ram consumption low.

ok, so by doing this, Unity in essence, holds onto it, waiting to see what it is declared as?

And in that sense, is there a way to declare it a GUI.Button, outside OnGUI so RAM is not eaten?

GUI.Button is not an object, it is a static method that both draws the button and returns a boolean denoting whether or not the button has been pushed in that frame.

If you want to treat a button as an object, take a look at my custom button class in this thread. (It is in C#)

I like handling buttons this way, but it is not necessary.

Thanks.
It seems a bit much to do it that way (@avidesk). I am fine just declaring it as false, then using it as long as not too much RAM is being eaten. I set it to a Bool type but that crashes it (XCode). Just a test.