Skip to content

Instantly share code, notes, and snippets.

@EmreDogann
Last active April 21, 2023 02:13
Show Gist options
  • Select an option

  • Save EmreDogann/d8c0d146a17321baa016d84baffef458 to your computer and use it in GitHub Desktop.

Select an option

Save EmreDogann/d8c0d146a17321baa016d84baffef458 to your computer and use it in GitHub Desktop.
A small Unity Property Attribute I made which aims to modify the rendering of a Vector3 field to only allow the input of an orthogonal unit direction vector.
// This file should go inside a normal directory (i.e. not /Editor) somewhere in your project.
using System;
using UnityEngine;
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
public class OrthogonalUnitVector3Attribute : PropertyAttribute {}
// This file should go inside a /Editor directory somewhere in your project.
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(OrthogonalUnitVector3Attribute))] [CanEditMultipleObjects]
public class OrthogonalUnitVector3Drawer : PropertyDrawer
{
private readonly string[] _enumNames = { "X", "Y", "Z" };
private int _axis;
private bool _invert;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// Get existing axis value.
if (property.vector3Value.x != 0)
{
_axis = 0;
_invert = !(property.vector3Value.x > 0);
}
else if (property.vector3Value.y != 0)
{
_axis = 1;
_invert = !(property.vector3Value.y > 0);
}
else
{
_axis = 2;
_invert = !(property.vector3Value.z > 0);
}
Rect initialRect = position;
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
// Wrap property drawer fields to new line if screen size is too small.
if (Screen.width < 332)
{
position.x = initialRect.xMin;
position.y += EditorGUIUtility.singleLineHeight;
position.width = initialRect.width;
position.height = EditorGUIUtility.singleLineHeight;
EditorGUI.indentLevel = 1;
position = EditorGUI.IndentedRect(position);
}
EditorGUI.indentLevel = 0;
Rect column = new Rect(position.x, position.y, position.width / 3, position.height);
Rect axisRect = new Rect(column.x, column.y, column.width / 4, column.height);
Rect invertRect = new Rect(column.xMax, column.y, column.width / 4 * 3, column.height);
Rect vector3Rect = new Rect(column.xMax + 2, column.y, position.width / 3 * 2 - 2, position.height);
EditorGUI.BeginChangeCheck();
int chosenAxis = EditorGUI.Popup(axisRect, _axis, _enumNames, EditorStyles.miniButton);
GUIContent toggleLabel = new GUIContent("Invert");
float labelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = EditorStyles.label.CalcSize(toggleLabel).x + 2;
invertRect.x -= EditorStyles.toggle.CalcSize(toggleLabel).x + EditorStyles.toggle.margin.right +
EditorStyles.toggle.margin.left;
bool chosenInvert = EditorGUI.Toggle(invertRect, toggleLabel, _invert, EditorStyles.toggle);
EditorGUIUtility.labelWidth = labelWidth;
if (EditorGUI.EndChangeCheck())
{
_axis = chosenAxis;
_invert = chosenInvert;
if (chosenInvert) SetVectorComponent(property, _enumNames[_axis], -1.0f);
else SetVectorComponent(property, _enumNames[_axis], 1.0f);
}
GUI.enabled = false;
EditorGUI.Vector3Field(vector3Rect, "", property.vector3Value);
GUI.enabled = true;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return Screen.width < 332 ? EditorGUIUtility.singleLineHeight * 2 : EditorGUIUtility.singleLineHeight;
}
private void SetVectorComponent(SerializedProperty property, string componentName, float invert)
{
if (componentName == "X") property.vector3Value = Vector3.right * invert;
else if (componentName == "Y") property.vector3Value = Vector3.up * invert;
else property.vector3Value = Vector3.forward * invert;
}
}
// You might also have to import the OrthogonalUnitVector3Attribute.cs file depending on where you put it...
using UnityEngine;
public class Example : MonoBehaviour
{
[OrthogonalUnitVector3] public Vector3 axis = Vector3.forward;
}
@EmreDogann
Copy link
Author

EmreDogann commented Apr 21, 2023

Screenshot of UsageExample.cs in Inspector:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment