UGUI Align Icons in the Inspector - how to recreate them?

I’m looking for a way to create exactly the same alignment buttons as shown in the Screenshot:100334-screenshot-6.jpg

They are the buttons from Unity UI Text component.
I’m already using miniButton layout.

I have already tried :

  • to load an image and add padding - quality gets degraded :
    100335-screenshot-7.jpg

The rightmost button is the icon button. As you can see, it’s quite bad.

The icon that I’m using is 16x16. It uses custom miniButton editor style with added padding of 4.
If I remove padding it looks super bad.

Is there any way to get a good looking align icon like in the first screenshot?

Sure, here it goes. :slight_smile:

Code

using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class MyComponent : MonoBehaviour
{
	// Nothing to do here.
}

#if UNITY_EDITOR
[CustomEditor(typeof(MyComponent))]
public class MyComponentEditor : Editor
{
	public static GUIStyle alignmentButtonLeft;
	public static GUIStyle alignmentButtonMid;
	public static GUIStyle alignmentButtonRight;

	public static GUIContent m_LeftAlignText;
	public static GUIContent m_CenterAlignText;
	public static GUIContent m_RightAlignText;
	public static GUIContent m_TopAlignText;
	public static GUIContent m_MiddleAlignText;
	public static GUIContent m_BottomAlignText;

	public static GUIContent m_LeftAlignTextActive;
	public static GUIContent m_CenterAlignTextActive;
	public static GUIContent m_RightAlignTextActive;
	public static GUIContent m_TopAlignTextActive;
	public static GUIContent m_MiddleAlignTextActive;
	public static GUIContent m_BottomAlignTextActive;

	private void OnEnable() // Warning: OnEnable is used for this demo, but should be replaced by different pattern, see below.
	{
		alignmentButtonLeft = new GUIStyle(EditorStyles.miniButtonLeft);
		alignmentButtonMid = new GUIStyle(EditorStyles.miniButtonMid);
		alignmentButtonRight = new GUIStyle(EditorStyles.miniButtonRight);

		m_LeftAlignText = EditorGUIUtility.IconContent(@"GUISystem/align_horizontally_left", "Left Align");
		m_CenterAlignText = EditorGUIUtility.IconContent(@"GUISystem/align_horizontally_center", "Center Align");
		m_RightAlignText = EditorGUIUtility.IconContent(@"GUISystem/align_horizontally_right", "Right Align");
		m_LeftAlignTextActive = EditorGUIUtility.IconContent(@"GUISystem/align_horizontally_left_active", "Left Align");
		m_CenterAlignTextActive = EditorGUIUtility.IconContent(@"GUISystem/align_horizontally_center_active", "Center Align");
		m_RightAlignTextActive = EditorGUIUtility.IconContent(@"GUISystem/align_horizontally_right_active", "Right Align");

		m_TopAlignText = EditorGUIUtility.IconContent(@"GUISystem/align_vertically_top", "Top Align");
		m_MiddleAlignText = EditorGUIUtility.IconContent(@"GUISystem/align_vertically_center", "Middle Align");
		m_BottomAlignText = EditorGUIUtility.IconContent(@"GUISystem/align_vertically_bottom", "Bottom Align");
		m_TopAlignTextActive = EditorGUIUtility.IconContent(@"GUISystem/align_vertically_top_active", "Top Align");
		m_MiddleAlignTextActive = EditorGUIUtility.IconContent(@"GUISystem/align_vertically_center_active", "Middle Align");
		m_BottomAlignTextActive = EditorGUIUtility.IconContent(@"GUISystem/align_vertically_bottom_active", "Bottom Align");

		FixAlignmentButtonStyles(alignmentButtonLeft, alignmentButtonMid, alignmentButtonRight);
	}

	static void FixAlignmentButtonStyles(params GUIStyle[] styles)
	{
		foreach (GUIStyle style in styles)
		{
			style.padding.left = 2;
			style.padding.right = 2;
		}
	}

	bool toggleLeft, toggleMid, toggleRight;
	bool toggleTop, toggleCenter, toggleBottom;

	public override void OnInspectorGUI()
	{
		base.OnInspectorGUI();

		EditorGUIUtility.SetIconSize(new Vector2(15, 15));

		GUILayout.BeginHorizontal();

		toggleLeft = GUILayout.Toggle(toggleLeft, toggleLeft ? m_LeftAlignTextActive : m_LeftAlignText, alignmentButtonLeft,
			GUILayout.Width(20), GUILayout.Height(EditorGUIUtility.singleLineHeight));

		toggleCenter = GUILayout.Toggle(toggleCenter, toggleCenter ? m_CenterAlignTextActive : m_CenterAlignText, alignmentButtonMid,
			GUILayout.Width(20), GUILayout.Height(EditorGUIUtility.singleLineHeight));

		toggleRight = GUILayout.Toggle(toggleRight, toggleRight ? m_RightAlignTextActive : m_RightAlignText, alignmentButtonRight,
			GUILayout.Width(20), GUILayout.Height(EditorGUIUtility.singleLineHeight));

		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();

		toggleTop = GUILayout.Toggle(toggleTop, toggleTop ? m_TopAlignTextActive : m_TopAlignText, alignmentButtonLeft,
			GUILayout.Width(20), GUILayout.Height(EditorGUIUtility.singleLineHeight));

		toggleMid = GUILayout.Toggle(toggleMid, toggleMid ? m_MiddleAlignTextActive : m_MiddleAlignText, alignmentButtonMid,
			GUILayout.Width(20), GUILayout.Height(EditorGUIUtility.singleLineHeight));

		toggleBottom = GUILayout.Toggle(toggleBottom, toggleBottom ? m_BottomAlignTextActive : m_BottomAlignText, alignmentButtonRight,
			GUILayout.Width(20), GUILayout.Height(EditorGUIUtility.singleLineHeight));

		GUILayout.EndHorizontal();
	}
}
#endif

Result

100352-alignmentbuttons.png

How To

  1. Identify desired control in Unity (in this case Unity UI Text component)
  2. Enter Inspector Debug mode to dig deeper. Notice the alignment is part of the Font Data property within the component.
  3. Either search Unity C# source code via your favorite decompiler (like ILSpy) - unofficial and unsupported of course.
  4. But better for UI and the open source tech: Unity Technologies UI
  5. Find FontDataDrawer in the source code and copy paste, modify to your content.

The example code is not as bad as it looks. You probably want to refactor it a bit and use regular GUI controls instead of GUILayout and move some thing into their own methods or a helper class.

The important parts to notice are:

  • Get builtin icons via EditorGUIUtility.IconContent, but you have to find out their exact names from the source or via some tool that displays all loaded resources (potentially something like Show_Builtin_Resources - UnifyCommunity
  • Adjust the padding left and right to 2 (padding may change your icon size, sometimes you have to experiment)
  • Use EditorGUIUtility.SetIconSize to set icon size to 15 (in this case)
  • If the icon still looks blurry or distorted, you might need to adjust padding or size (usually there is only one specific size at which an icon looks good, the builtin ones can be a guideline when making custom ones, but there are many different types, so it depends)
  • The rest is just drawing controls with different styles, but probably you want to enforce width and height via regular Rect

Additional info regarding styles

I’ve created the GUIStyle and GUIContent objects in OnEnable because this is straightforward for this demo. However, for ‘real’ code one should follow the Unity-typical pattern of creating styles in the first GUI frame, in which they are needed. This is because it is possible that Unity throws an exception when calling things like EditorStyles.miniButtonLeft from any place outside of a GUI function. In this example, it will throw, when calling into EditorStyles from OnEnable after a recompile. Fix this with the following pattern:

// Within your editor class

private Styles m_Styles;

private class Styles
{
    public GUIStyle someStyle;

    public Styles()
    {
        someStyle = new GUIStyle(EditorStyles.miniButtonLeft);
    }
}

public overrive void OnInspectorGUI() // or any other GUI function
{
    if(m_Styles == null)
        m_Styles = new Styles();

    // now safe to use
}