Unity Editor: Enum Flags as Toggle Buttons

Note: We’ve since cleaned up this code, added view options and released it as a cheap plugin on the Unity Asset Store.

Working on the content tools for our current project I needed enum flags, unfortunately the Unity Editor doesn’t natively support those. Looking around I found a few implementations of enum flags as dropdowns similar to the layer mask dropdown in Unity itself. While that’s pretty neat it has the disadvantage that you don’t have a quick overview over which flags are on and which are off. To that end I’ve built a new custom PropertyDrawer that displays EnumFlags as a neat row of toggle buttons:

Toggle Buttons in Action

Toggle Buttons in Action

All you need is two scripts and an attribute. Also note that your enum needs to start with 1, not 0 and that each value needs to be a power of two (1, 2, 4, 8 etc.)

And here’s the code:

EnumFlagAttribute.cs

This file needs to go in a regular scripts folder (not Editor!). It creates the [EnumFlags] attribute.

using UnityEngine;

public class EnumFlagAttribute : PropertyAttribute
{
	public EnumFlagAttribute() {}
}

EnumFlagDrawer.cs

This one goes into an Editor folder. It manages the display of fields that have the [EnumFlags] attribute.

using System;
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
public class EnumFlagsAttributeDrawer : PropertyDrawer
{

	public override void OnGUI(Rect _position, SerializedProperty _property, GUIContent _label)
	{
		int buttonsIntValue = 0;
		int enumLength = _property.enumNames.Length;
		bool[] buttonPressed = new bool[enumLength];
		float buttonWidth = (_position.width - EditorGUIUtility.labelWidth) / enumLength;

		EditorGUI.LabelField(new Rect(_position.x, _position.y, EditorGUIUtility.labelWidth, _position.height), _label);

		EditorGUI.BeginChangeCheck ();

		for (int i = 0; i < enumLength; i++) {

			// Check if the button is/was pressed 
			if ( ( _property.intValue & (1 << i) ) == 1 << i ) {
				buttonPressed[i] = true;
			}

			Rect buttonPos = new Rect (_position.x + EditorGUIUtility.labelWidth + buttonWidth * i, _position.y, buttonWidth, _position.height);

			buttonPressed[i] = GUI.Toggle(buttonPos, buttonPressed[i], _property.enumNames[i],  "Button");

			if (buttonPressed[i])
				buttonsIntValue += 1 << i;
		}

		if (EditorGUI.EndChangeCheck()) {
			_property.intValue = buttonsIntValue;
		}
	}
}

I hope you enjoy it. And if you’ve got comments or ideas, let me know!

– Martin

Update: Note about the Unity Asset Store release of an updated version of this code added.


Tooltips with the new Unity UI (uGUI)

Since I needed tooltips to test something really quick I went to see if there was an implementation in the new uGUI system. Unfortunately there were none but a few custom made solutions from other devs. None of those suited me though, so I quickly built my own, very rough version. It consists of two scripts and a view that is the tooltip.

Tooltip Demo

Tooltip Demo

TooltipTrigger

This script is put on all the objects you want to trigger the tooltip. It contains the text that should be shown as a public variable. Everything else is handled by the TooltipView.

using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;

namespace Sharkbomb.View {
	public class TooltipTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler {

		public string text;

		public void OnPointerEnter(PointerEventData eventData)
		{
			StartHover(new Vector3(eventData.position.x, eventData.position.y - 18f, 0f));
		}	
		public void OnSelect(BaseEventData eventData)
		{
			StartHover(transform.position);
		}
		public void OnPointerExit(PointerEventData eventData)
		{
			StopHover();
		}
		public void OnDeselect(BaseEventData eventData)
		{
			StopHover();
		}

		void StartHover(Vector3 position) {
			TooltipView.Instance.ShowTooltip(text, position);
		}
		void StopHover() {
			TooltipView.Instance.HideTooltip();
		}

	}
}

TooltipView

This script is put on a separate uGUI object that is the actual visible tooltip. It’s a singleton so the many TooltipTriggers can access it quickly and easily.

using UnityEngine;
using System.Collections;

namespace Sharkbomb.View {
	public class TooltipView : MonoBehaviour {
		
		public bool IsActive {
			get {
				return gameObject.activeSelf;
			}
		}
		//public CanvasGroup tooltip;
		public UnityEngine.UI.Text tooltipText;

		void Awake() {
			instance = this;
			HideTooltip();
		}

		public void ShowTooltip(string text, Vector3 pos) {
			if (tooltipText.text != text)
				tooltipText.text = text;

			transform.position = pos;

			gameObject.SetActive(true);
		}
		
		public void HideTooltip() {
			gameObject.SetActive(false);
		}
		
		// Standard Singleton Access 
		private static TooltipView instance;
		public static TooltipView Instance
		{
			get
			{
				if (instance == null)
					instance = GameObject.FindObjectOfType<TooltipView>();
				return instance;
			}
		}
	}
}

As said, it’s a very simple script. There’s a bunch of things it doesn’t do and a few things to be aware of:

– It doesn’t wait a second before showing the tooltip.
– It currently places the tooltip over the object when selecting it via keyboard
– The tooltip can leave the boundaries of the screen and become (partially) invisible
– The tooltip doesn’t move with the cursor – that means it can block raytraces and cause flickering as it blocks the ray to the hovered object, disappearing and reappearing in a new pos


Fast ScriptableObject Creation in Unity

ScriptableObjects can be a very useful feature of Unity but they’re a hassle to create. Here’s a way to do this quickly:

Scriptable Object Context Menu

Scriptable Object Context Menu

In the stock interface there is no way to create ScriptableObjects. Most solutions I found solve this by adding a MenuItem to the top bar. This item then creates a ScriptableObject .asset file of a specific class. This is works but it requires you to adjust the script for each project so it points to a class of that pr oject. It also requires you to create a specific script for each of your classes, even if that might otherwise not be neccessary.

Our ScriptableObjectContextEditor script avoids these problems. Instead of the clumsy menu, it allows you to create .asset files directy from the project pane, where you’d expect it. Not only that, it also has an implementation that allows you to select a script file from which to create an asset, so you don’t need to adjust the script for each project. However if you want to do that you can make use of a generic function provided to create additional pulldown options for specific classes of your own.