I want to create a tool similar to Unity's Terrain tool, which has some nice toggle buttons in the inspector:

Toggle buttons in the inspector Toggled button

How can I achieve similar design to this? I know how to create normal buttons and other UI components in the inspector, but I can not find enough information to make the buttons toggle.

So far I have used normal toggles that produce a checkbox:

var tmp = EditorGUILayout.Toggle( SetAmountFieldContent, _setValue );

if ( tmp != _setValue )
{
  _setValue = tmp;
  if ( _setValue )
    _smoothValue = false;
}

tmp = EditorGUILayout.Toggle( SmoothValueFieldContent, _smoothValue );

if ( tmp != _smoothValue )
{
  _smoothValue = tmp;
  if ( _smoothValue )
    _setValue = false;
}

Setting the toggle GUIStyle to "Button" does not produce the wanted result. The text or image content goes on left of the button instead of inside.

var tmp = EditorGUILayout.Toggle( SetAmountFieldContent, _setValue, "Button" );

Unwanted behaviour on toggle

Also none of the options found in GUISkin does not seem to help.

up vote 7 down vote accepted

I solved this problem by using buttons instead of toggles.

First define two button styles before any functions:

private static GUIStyle ToggleButtonStyleNormal = null;
private static GUIStyle ToggleButtonStyleToggled = null;

Then in OnInspectorGui() make sure they are generated if null:

if ( ToggleButtonStyleNormal == null )
{
  ToggleButtonStyleNormal = "Button";
  ToggleButtonStyleToggled = new GUIStyle(ToggleButtonStyleNormal);
  ToggleButtonStyleToggled.normal.background = ToggleButtonStyleToggled.active.background;
}

And then use the idea proposed by @jzx to toggle the styles:

GUILayout.BeginHorizontal(  );

if ( GUILayout.Button( SetAmountFieldContent, _setValue ? ToggleButtonStyleToggled : ToggleButtonStyleNormal ) )
{
  _setValue = true;
  _smoothValue = false;
}

if ( GUILayout.Button( SmoothValueFieldContent, _smoothValue ? ToggleButtonStyleToggled : ToggleButtonStyleNormal ) )
{
  _smoothValue = true;
  _setValue = false;
}

GUILayout.EndHorizontal();

This produces what I wanted:

First toggled button Second toggled button

  • 1
    Great job! I was looking for days to find the answer for toggle buttons in the Unity3D Editor. Just one question - why don't you just use _smoothValue = !GUILayout.Button( SetAmountFieldContent, _smoothValue ? ToggleButtonStyleToggled : ToggleButtonStyleNormal), instead of having two booleans? That works well for me and the code looks close to using stadnard unity button/toggles – Ivaylo Slavov Oct 16 '17 at 19:31
  • 1
    @IvayloSlavov I used that as an example for clarity – Lasse Oct 18 '17 at 14:20

Toggle returns the current state of the button - either the same state passed in value or the new value as changed by the user. So a better pattern would be...

// TODO: Initialize these with GUIContent
private GUIContent _toggleButtonDepressedLabel;
private GUIContent _toggleButtonDefaultLabel;

// Current toggle state
bool _toggleButtonState;

void DisplayToggle()
{
    var image = _toggleButtonValue
                ? _toggleButtonDepressedLabel
                : _toggleButtonDefaultLabel;
    var newState = EditorGUILayout.Toggle(image, _toggleButtonState);
    if (newState != _toggleButtonState)
    {
        _toggleButtonState = newState;
        OnToggleButtonChanged();
    }
}

void OnGUI ()
{
    DisplayToggle();
}

void OnToggleButtonChanged()
{
    // Do stuff.
}

You can use the same state-dependent swapping pattern for GUIStyles.

private GUIStyle _toggleButtonDepressedStyle;
private GUIStyle _toggleButtonDefaultStyle;
// ...
    var image = _toggleButtonValue
                ? _toggleButtonDepressedLabel
                : _toggleButtonDefaultLabel;
    var style = _toggleButtonValue
                ? _toggleButtonDepressedStyle
                : _toggleButtonDefaultStyle;
    var newState = EditorGUILayout.Toggle(image, _toggleButtonState, style);

Here is a basic, but simple way to do it:

 pressed = GUILayout.Toggle(pressed, "Toggle me !", "Button");

taken from here

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.