- Home /
How does GUI.Toggle work?
I have a level editor with a test button that I want to change into a toggle button - I want it to turn on when pressed and stay on until pressed again. Currently I have a setup like this
//In variable declaration
private bool testButtonToggle = false; //Off by default
//In OnGUI()
if (GUI.Toggle(testButtonRect, testButtonToggle, "", testToggleStyle)) {
Debug.Log("Toggle code block ran: " + testCounter + " times!");
if (testButtonToggle)
{
testButtonToggle = false;
//Turn off test mode
}
else if (!testButtonToggle)
{
testButtonToggle = true;
//Turn on test mode
}
testCounter++;
}
With it coded that way, it stays toggled on when you first press it and while you hold down the mouse button, but as soon as the mouse goes up it toggles off instantly. That led me to think that when you give a Toggle a bool parameter it automatically toggles it when it is pressed, but that makes it function like a normal button and it will only run the 'else if (false)' block.
Answer by Bunny83 · Dec 07, 2012 at 09:38 PM
Just in addition to Eric's answer:
A Toggle just switches between two states. It doesn't have something like "onMouseDown" or "onMouseUp" events. It just turns the variable on when you click it once (and it stays on) and when you click again it turns off again (and stays off)
private bool testButtonToggle = false;
void OnGUI()
{
testButtonToggle = GUI.Toggle(testButtonRect, testButtonToggle, "", testToggleStyle);
if (testButtonToggle)
{
// Do something when it's toggled on, for example draw addtional GUI elements:
if (GUI.Button(...))
{
//...
}
}
}
I have to admit that the example on the Toggle page is terrible.
edit
Just read your comment above. Well The problem is OnGUI is ment for GUI element / event processing and might get called several times per frame. If you want to execute code every frame you should do it like this:
private bool testButtonToggle = false;
void OnGUI()
{
testButtonToggle = GUI.Toggle(testButtonRect, testButtonToggle, "", testToggleStyle);
}
void Update()
{
if (testButtonToggle)
{
// Do something when it's toggled on
}
else
{
// Do something else when it's toggled off.
}
}
edit2:
To detect a state change you just have to store value of your state variable from the last frame and compare it with the current. If it's different a change has occurred.
private bool testButtonToggle = false;
private bool oldTestButtonToggle = false;
void OnGUI()
{
// Responsible for the state change
testButtonToggle = GUI.Toggle(testButtonRect, testButtonToggle, "", testToggleStyle);
// When the two variables are uneven a change has occurred. Either has been turned
// on or off this frame
if (testButtonToggle != oldTestButtonToggle)
{
if (testButtonToggle)
{
// on event
}
else
{
// off event
}
}
}
With a toggle you can simplify it like this:
private bool testButtonToggle = false;
void OnGUI()
{
if (GUI.Toggle(testButtonRect, testButtonToggle, "", testToggleStyle) != testButtonToggle)
{
testButtonToggle = !testButtonToggle; // toggle manually
if (testButtonToggle)
{
// on event
}
else
{
// off event
}
}
}
Now the toggle works just like a normal button. The only difference is that you have an active state which changes it's visual appearence.
I know that it doesn't have mouse events, I described it that way because the way it is behaving the different ways I've tried it don't make sense.
And I don't want the code to run every frame, I placed it inside the if statement around the toggle call because I only want it to run when the state is changed, and all the buttons I've ever made worked that way just fine.
From my understanding the code inside the if block will only run when the GUI control inside the if statement is pressed, and from there it will run the true block or the false block alternatively. Like a light switch that is a push button ins$$anonymous$$d of a lever.
There's a huge difference between a Button and a toggle. A Button will execute an event when it's pressed. A Toggle changes a state. I will add another example how to detect a state change. This is actually irrelevant for GUI since it always works the same way.
I'll add another example specific for a GUI.Toggle.
Alright, so what I was trying was wrong. Thanks for your help gentlemen!
Answer by Eric5h5 · Dec 07, 2012 at 08:58 PM
Please see the example in the docs; you assign the result of GUI.Toggle to a variable.
How would I do that and still be able to place the GUI call in an if statement? Like so?
if (testButtonToggle = GUI.Toggle(testButtonRect, testButtonToggle, "", testToggleStyle))
Well I tried that and it runs the code inside the if block every tick. On top of that it seems wrong to me - to have an assignment in an if statement seems programatically illogical because it isn't a comparison.
After that I tried adding 'testButtonToggle = GUI.Toggle(identical parameters)' at the end of the if block, but it never assigns any value to the bool.
After that I tried adding it after the if block, but then it toggles to true and never toggles back to false even when pressed again.
Finally I tried adding "testButtonToggle = GUI.Toggle(...);" before the original code (if (testButtonToggle = GUI.Toggle(...)); and in that case it toggles to true from the first Toggle, runs the true block inside the if statement every tick, and never toggles back to false even when clicked.
Why so difficult >.>
All I want is a button that toggles on/off (I have different textures for each) with an if statement around it to run code only when it is clicked, one block for true, one block for false.
Like my snippet, except...you know. Functional.
Can I do that?
Just check to see if the variable changed. You can also potentially use GUI.changed, though that depends on the circumstances.
I am checking if it changed, the problem is that I apparently don't get how it is supposed to work because none of the ways I have tried behave in ways that make sense.