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.


Coming Soon: Unity3d basics video

If you want to get to know Unity3d, this might be your chance.

My buddy Anjin Anhut (who made the Touch of Death graphics) and I have been wanting to do a little skill share. I will give Anjin an introduction to Unity3d while he will share his knowledge on Art Direction with me.

Now we’ve finally found time to get started with this. And since both of us are very open people we decided to go public with this. Our sessions will be streamed and recorded, for your convenience.

SkillShare

Introduction to Unity

We’ll be starting with my part first: An introduction to Unity3d. We’ll be on Google Hangouts on Air on February 1st 2014, at 2:00 PM, German time. We’re planning to run for about 4 hours, probably with some short breaks in between. Follow us on twitter (@mnerurkar or @anjinanhut) or check out the Sharkbomb Studios Google+ or YouTube page to join.

The whole session will be mostly covering the basics. I’ll try to help you get familiar with the engine. Anything from the interface to library management and export processes. We will probably also talk about some basic gameplay functionality like collisions, movement, which will provide an inroad into scripting. Since the session will be unscripted I can’t really give you a specific rundown yet. I still hope to see you there!

– Martin