1.9.0: Added support for attributes for drawing handles in the scene

This commit is contained in:
Anders Ejlersen 2024-02-11 22:02:10 +01:00
parent 81906d49dd
commit 5ce34bde70
48 changed files with 1354 additions and 8 deletions

View file

@ -16,7 +16,16 @@ namespace Module.Inspector.Editor
bool prevEnabled = GUI.enabled;
GUI.enabled = prevEnabled && accessType == EAccessType.Enabled;
if (Event.current.type == EventType.Repaint)
{
for (var i = 0; i < result.handleDrawers.Count; i++)
{
EditorPropertyUtility.ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer> value = result.handleDrawers[i];
HandleDrawerEditor.Add(value.attribute, property, value.drawer);
}
}
label.tooltip = result.tooltip;
for (var i = 0; i < result.predrawerModifiers.Count; i++)

View file

@ -0,0 +1,83 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[InitializeOnLoad]
internal static class HandleDrawerEditor
{
private static readonly List<Element> ELEMENTS = new List<Element>();
static HandleDrawerEditor()
{
SceneView.beforeSceneGui -= SceneGUI;
SceneView.beforeSceneGui += SceneGUI;
Selection.selectionChanged -= OnSelectionChanged;
Selection.selectionChanged += OnSelectionChanged;
}
private static void SceneGUI(SceneView view)
{
for (int i = ELEMENTS.Count - 1; i >= 0; i--)
{
Element e = ELEMENTS[i];
bool valid = e.target != null;
if (e.target != null)
{
var serializedObject = new SerializedObject(e.target);
SerializedProperty serializedProperty = serializedObject.FindProperty(e.propertyPath);
valid = serializedProperty != null && e.drawer.IsValidFor(serializedProperty);
if (valid)
{
EditorGUI.BeginChangeCheck();
e.drawer.Draw(e.attribute, serializedProperty);
if (EditorGUI.EndChangeCheck())
serializedObject.ApplyModifiedProperties();
}
serializedObject.Dispose();
}
if (!valid)
ELEMENTS.RemoveAt(i);
}
}
private static void OnSelectionChanged()
{
ELEMENTS.Clear();
}
public static void Add(HandleDrawerPropertyAttribute attribute, SerializedProperty property, HandlePropertyDrawer drawer)
{
ELEMENTS.Add(new Element(attribute, property, drawer));
}
public static void Clear()
{
ELEMENTS.Clear();
}
private sealed class Element
{
public readonly HandleDrawerPropertyAttribute attribute;
public readonly HandlePropertyDrawer drawer;
public readonly Object target;
public readonly string propertyPath;
public Element(HandleDrawerPropertyAttribute attribute, SerializedProperty property, HandlePropertyDrawer drawer)
{
this.attribute = attribute;
this.drawer = drawer;
target = property.serializedObject.targetObject;
propertyPath = property.propertyPath;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3357a3447d20469487fd17f88d47ce6d
timeCreated: 1669410085

View file

@ -0,0 +1,10 @@
using UnityEditor;
namespace Module.Inspector.Editor
{
public abstract class HandlePropertyDrawer : AbstractPropertyDrawer
{
public abstract void Draw(HandleDrawerPropertyAttribute attribute, SerializedProperty serializedProperty);
public abstract bool IsValidFor(SerializedProperty serializedProperty);
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 315f22f458d84fdcb3049f579622c15a
timeCreated: 1669408966

3
Editor/Handles.meta Normal file
View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7347da106b234bc2b88466d8567e92d4
timeCreated: 1669408266

View file

@ -0,0 +1,103 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(BoxHandleAttribute))]
internal sealed class BoxHandleAttributeDrawer : HandlePropertyDrawer
{
public override void Draw(HandleDrawerPropertyAttribute attribute, SerializedProperty serializedProperty)
{
var att = (BoxHandleAttribute)attribute;
bool hasPositionField = EditorHandleUtility.TryGetWorldPosition(serializedProperty, att.fieldPosition, att.space, out Vector3 worldPosition);
bool hasRotationField = EditorHandleUtility.TryGetWorldRotation(serializedProperty, att.fieldRotation, att.space, out Quaternion worldRotation);
Vector3 size = GetValue(serializedProperty, out EAxis axii);
Color color = Handles.color;
if (hasPositionField)
worldPosition = EditorHandleUtility.PositionHandle(worldPosition, worldRotation);
if (hasRotationField)
worldRotation = EditorHandleUtility.RotationHandle(worldPosition, worldRotation);
size = EditorHandleUtility.BoxHandle(worldPosition, worldRotation, size, axii);
if (hasPositionField)
EditorHandleUtility.SetWorldPosition(serializedProperty, att.fieldPosition, worldPosition, att.space);
if (hasRotationField)
EditorHandleUtility.SetWorldRotation(serializedProperty, att.fieldRotation, worldRotation, att.space);
SetValue(serializedProperty, size);
Handles.color = color;
}
private Vector3 GetValue(SerializedProperty serializedProperty, out EAxis axii)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
axii = EAxis.X;
return new Vector3(serializedProperty.intValue, serializedProperty.intValue, serializedProperty.intValue);
case SerializedPropertyType.Float:
axii = EAxis.X;
return new Vector3(serializedProperty.floatValue, serializedProperty.floatValue, serializedProperty.floatValue);
case SerializedPropertyType.Vector2:
axii = EAxis.X | EAxis.Y;
return new Vector3(serializedProperty.vector2Value.x, serializedProperty.vector2Value.y, 0f);
case SerializedPropertyType.Vector3:
axii = EAxis.All;
return serializedProperty.vector3Value;
case SerializedPropertyType.Vector2Int:
axii = EAxis.X | EAxis.Y;
return new Vector3(serializedProperty.vector2IntValue.x, serializedProperty.vector2IntValue.y, 0f);
case SerializedPropertyType.Vector3Int:
axii = EAxis.All;
return serializedProperty.vector3IntValue;
default:
axii = EAxis.X;
return Vector3.one;
}
}
private void SetValue(SerializedProperty serializedProperty, Vector3 value)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
serializedProperty.intValue = Mathf.RoundToInt(value.x);
break;
case SerializedPropertyType.Float:
serializedProperty.floatValue = value.x;
break;
case SerializedPropertyType.Vector2:
serializedProperty.vector2Value = new Vector2(value.x, value.y);
break;
case SerializedPropertyType.Vector3:
serializedProperty.vector3Value = value;
break;
case SerializedPropertyType.Vector2Int:
serializedProperty.vector2IntValue = new Vector2Int(Mathf.RoundToInt(value.x), Mathf.RoundToInt(value.y));
break;
case SerializedPropertyType.Vector3Int:
serializedProperty.vector3IntValue = new Vector3Int(Mathf.RoundToInt(value.x), Mathf.RoundToInt(value.y), Mathf.RoundToInt(value.z));
break;
}
}
public override bool IsValidFor(SerializedProperty serializedProperty)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
case SerializedPropertyType.Float:
case SerializedPropertyType.Vector2:
case SerializedPropertyType.Vector3:
case SerializedPropertyType.Vector2Int:
case SerializedPropertyType.Vector3Int:
return true;
default:
return false;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3dfa4467da7444549585b2992516427e
timeCreated: 1669475655

View file

@ -0,0 +1,72 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(CircleHandleAttribute))]
internal sealed class CircleHandleAttributeDrawer : HandlePropertyDrawer
{
public override void Draw(HandleDrawerPropertyAttribute attribute, SerializedProperty serializedProperty)
{
var att = (CircleHandleAttribute)attribute;
bool hasPositionField = EditorHandleUtility.TryGetWorldPosition(serializedProperty, att.fieldPosition, att.space, out Vector3 worldPosition);
bool hasRotationField = EditorHandleUtility.TryGetWorldRotation(serializedProperty, att.fieldRotation, att.space, out Quaternion worldRotation);
float size = GetValue(serializedProperty);
Color color = Handles.color;
if (hasPositionField)
worldPosition = EditorHandleUtility.PositionHandle(worldPosition, worldRotation);
if (hasRotationField)
worldRotation = EditorHandleUtility.RotationHandle(worldPosition, worldRotation);
size = EditorHandleUtility.CircleHandle(worldPosition, worldRotation, size);
if (hasPositionField)
EditorHandleUtility.SetWorldPosition(serializedProperty, att.fieldPosition, worldPosition, att.space);
if (hasRotationField)
EditorHandleUtility.SetWorldRotation(serializedProperty, att.fieldRotation, worldRotation, att.space);
SetValue(serializedProperty, size);
Handles.color = color;
}
private float GetValue(SerializedProperty serializedProperty)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
return serializedProperty.intValue;
case SerializedPropertyType.Float:
return serializedProperty.floatValue;
default:
return 1f;
}
}
private void SetValue(SerializedProperty serializedProperty, float value)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
serializedProperty.intValue = Mathf.RoundToInt(value);
break;
case SerializedPropertyType.Float:
serializedProperty.floatValue = value;
break;
}
}
public override bool IsValidFor(SerializedProperty serializedProperty)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
case SerializedPropertyType.Float:
return true;
default:
return false;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1ec82d143086477aa01a1ce9634b2689
timeCreated: 1669475467

View file

@ -0,0 +1,46 @@
using System.Text;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(LabelHandleAttribute))]
internal sealed class LabelHandleAttributeDrawer : HandlePropertyDrawer
{
private readonly StringBuilder builder = new StringBuilder();
private GUIStyle style;
public override void Draw(HandleDrawerPropertyAttribute attribute, SerializedProperty serializedProperty)
{
var att = (LabelHandleAttribute)attribute;
Vector3 wp = EditorHandleUtility.GetWorldPosition(serializedProperty, att.fieldPosition, att.space);
if (style == null)
{
style = new GUIStyle(GUI.skin.label);
style.alignment = TextAnchor.MiddleCenter;
}
builder.Clear();
if ((att.type & ELabelType.Field) != 0)
builder.Append(serializedProperty.displayName);
if ((att.type & ELabelType.Value) != 0)
{
if ((att.type & ELabelType.Field) != 0)
builder.Append('\n');
builder.Append(serializedProperty.GetValueAsString());
}
Handles.Label(wp, builder.ToString(), style);
}
public override bool IsValidFor(SerializedProperty serializedProperty)
{
return true;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9a9cc06839c34083a5e8793dab6ac651
timeCreated: 1669475780

View file

@ -0,0 +1,40 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(PositionHandleAttribute))]
internal sealed class PositionHandleAttributeDrawer : HandlePropertyDrawer
{
public override void Draw(HandleDrawerPropertyAttribute attribute, SerializedProperty serializedProperty)
{
var att = (PositionHandleAttribute)attribute;
Vector3 worldPosition = EditorHandleUtility.GetWorldPosition(serializedProperty, att.space);
Quaternion worldRotation = EditorHandleUtility.GetWorldRotation(serializedProperty, att.space);
Color color = Handles.color;
worldPosition = EditorHandleUtility.PositionHandle(worldPosition, worldRotation, att.axiis);
EditorHandleUtility.SetWorldPosition(serializedProperty, worldPosition, att.space);
Handles.color = color;
}
public override bool IsValidFor(SerializedProperty serializedProperty)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
case SerializedPropertyType.Float:
case SerializedPropertyType.Vector2:
case SerializedPropertyType.Vector3:
case SerializedPropertyType.Vector2Int:
case SerializedPropertyType.Vector3Int:
return true;
case SerializedPropertyType.ObjectReference:
return serializedProperty.objectReferenceValue != null && serializedProperty.objectReferenceValue is Transform;
default:
return false;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 517a50351ebe49549d55dfe6c037941c
timeCreated: 1669408276

View file

@ -0,0 +1,103 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(RectangleHandleAttribute))]
internal sealed class RectangleHandleAttributeDrawer : HandlePropertyDrawer
{
public override void Draw(HandleDrawerPropertyAttribute attribute, SerializedProperty serializedProperty)
{
var att = (RectangleHandleAttribute)attribute;
bool hasPositionField = EditorHandleUtility.TryGetWorldPosition(serializedProperty, att.fieldPosition, att.space, out Vector3 worldPosition);
bool hasRotationField = EditorHandleUtility.TryGetWorldRotation(serializedProperty, att.fieldRotation, att.space, out Quaternion worldRotation);
Vector2 size = GetValue(serializedProperty, out EAxis axii);
Color color = Handles.color;
if (hasPositionField)
worldPosition = EditorHandleUtility.PositionHandle(worldPosition, worldRotation);
if (hasRotationField)
worldRotation = EditorHandleUtility.RotationHandle(worldPosition, worldRotation);
size = EditorHandleUtility.RectHandle(worldPosition, worldRotation, size, axii);
if (hasPositionField)
EditorHandleUtility.SetWorldPosition(serializedProperty, att.fieldPosition, worldPosition, att.space);
if (hasRotationField)
EditorHandleUtility.SetWorldRotation(serializedProperty, att.fieldRotation, worldRotation, att.space);
SetValue(serializedProperty, size);
Handles.color = color;
}
private Vector2 GetValue(SerializedProperty serializedProperty, out EAxis axii)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
axii = EAxis.X;
return new Vector2(serializedProperty.intValue, serializedProperty.intValue);
case SerializedPropertyType.Float:
axii = EAxis.X;
return new Vector2(serializedProperty.floatValue, serializedProperty.floatValue);
case SerializedPropertyType.Vector2:
axii = EAxis.All;
return serializedProperty.vector2Value;
case SerializedPropertyType.Vector3:
axii = EAxis.All;
return serializedProperty.vector3Value;
case SerializedPropertyType.Vector2Int:
axii = EAxis.All;
return serializedProperty.vector2IntValue;
case SerializedPropertyType.Vector3Int:
axii = EAxis.All;
return new Vector2(serializedProperty.vector3IntValue.x, serializedProperty.vector3IntValue.y);
default:
axii = EAxis.None;
return Vector2.one;
}
}
private void SetValue(SerializedProperty serializedProperty, Vector2 value)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
serializedProperty.intValue = Mathf.RoundToInt(value.x);
break;
case SerializedPropertyType.Float:
serializedProperty.floatValue = value.x;
break;
case SerializedPropertyType.Vector2:
serializedProperty.vector2Value = value;
break;
case SerializedPropertyType.Vector3:
serializedProperty.vector3Value = value;
break;
case SerializedPropertyType.Vector2Int:
serializedProperty.vector2IntValue = new Vector2Int(Mathf.RoundToInt(value.x), Mathf.RoundToInt(value.y));
break;
case SerializedPropertyType.Vector3Int:
serializedProperty.vector3IntValue = new Vector3Int(Mathf.RoundToInt(value.x), Mathf.RoundToInt(value.y), 0);
break;
}
}
public override bool IsValidFor(SerializedProperty serializedProperty)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
case SerializedPropertyType.Float:
case SerializedPropertyType.Vector2:
case SerializedPropertyType.Vector3:
case SerializedPropertyType.Vector2Int:
case SerializedPropertyType.Vector3Int:
return true;
default:
return false;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: add3ba2b5b1c46088aaf8604ce8929f8
timeCreated: 1669475681

View file

@ -0,0 +1,40 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(RotationHandleAttribute))]
internal sealed class RotationHandleAttributeDrawer : HandlePropertyDrawer
{
public override void Draw(HandleDrawerPropertyAttribute attribute, SerializedProperty serializedProperty)
{
var att = (RotationHandleAttribute)attribute;
bool hasPositionField = EditorHandleUtility.TryGetWorldPosition(serializedProperty, att.fieldPosition, att.space, out Vector3 worldPosition);
Quaternion worldRotation = EditorHandleUtility.GetWorldRotation(serializedProperty, att.space);
Color color = Handles.color;
if (hasPositionField)
worldPosition = EditorHandleUtility.PositionHandle(worldPosition, worldRotation);
worldRotation = EditorHandleUtility.RotationHandle(worldPosition, worldRotation);
if (hasPositionField)
EditorHandleUtility.SetWorldPosition(serializedProperty, att.fieldPosition, worldPosition, att.space);
EditorHandleUtility.SetWorldRotation(serializedProperty, worldRotation, att.space);
Handles.color = color;
}
public override bool IsValidFor(SerializedProperty serializedProperty)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Quaternion:
return true;
default:
return false;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9193d6531ba843749d9fd78bc6b166d7
timeCreated: 1669475582

View file

@ -0,0 +1,72 @@
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
namespace Module.Inspector.Editor
{
[CustomPropertyDrawer(typeof(SphereHandleAttribute))]
internal sealed class SphereHandleAttributeDrawer : HandlePropertyDrawer
{
public override void Draw(HandleDrawerPropertyAttribute attribute, SerializedProperty serializedProperty)
{
var att = (SphereHandleAttribute)attribute;
bool hasPositionField = EditorHandleUtility.TryGetWorldPosition(serializedProperty, att.fieldPosition, att.space, out Vector3 worldPosition);
bool hasRotationField = EditorHandleUtility.TryGetWorldRotation(serializedProperty, att.fieldRotation, att.space, out Quaternion worldRotation);
float size = GetValue(serializedProperty);
Color color = Handles.color;
if (hasPositionField)
worldPosition = EditorHandleUtility.PositionHandle(worldPosition, worldRotation);
if (hasRotationField)
worldRotation = EditorHandleUtility.RotationHandle(worldPosition, worldRotation);
size = EditorHandleUtility.SphereHandle(worldPosition, worldRotation, size);
if (hasPositionField)
EditorHandleUtility.SetWorldPosition(serializedProperty, att.fieldPosition, worldPosition, att.space);
if (hasRotationField)
EditorHandleUtility.SetWorldRotation(serializedProperty, att.fieldRotation, worldRotation, att.space);
SetValue(serializedProperty, size);
Handles.color = color;
}
private float GetValue(SerializedProperty serializedProperty)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
return serializedProperty.intValue;
case SerializedPropertyType.Float:
return serializedProperty.floatValue;
default:
return 1f;
}
}
private void SetValue(SerializedProperty serializedProperty, float value)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
serializedProperty.intValue = Mathf.RoundToInt(value);
break;
case SerializedPropertyType.Float:
serializedProperty.floatValue = value;
break;
}
}
public override bool IsValidFor(SerializedProperty serializedProperty)
{
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
case SerializedPropertyType.Float:
return true;
default:
return false;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 199eb743ed1846d498b6bbba499cf9f6
timeCreated: 1669475521

View file

@ -10,11 +10,14 @@ namespace Module.Inspector.Editor
{
public override void OnInspectorGUI()
{
if (Event.current.type == EventType.Repaint)
HandleDrawerEditor.Clear();
DrawDefaultInspector();
DrawHiddenInspector();
DrawMethodInspector();
}
private void DrawHiddenInspector()
{
if (!IsValidTarget())

View file

@ -0,0 +1,470 @@
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Module.Inspector.Editor.Utilities
{
public static class EditorHandleUtility
{
private static readonly Color DEFAULT_AXIS_COLOR = new Color(0.7f, 0.7f, 0.7f, 0.93f);
private static readonly Color X_AXIS_COLOR = new Color(0.85882354f, 0.24313726f, 0.11372549f, 0.93f);
private static readonly Color Y_AXIS_COLOR = new Color(0.6039216f, 0.9529412f, 0.28235295f, 0.93f);
private static readonly Color Z_AXIS_COLOR = new Color(0.22745098f, 0.47843137f, 0.972549f, 0.93f);
private static readonly Color EDGE_COLOR = new Color(0.6039216f, 0.9529412f, 0.28235295f, 0.93f);
private static readonly Color EDGE_COLOR2 = new Color(0.6039216f, 0.9529412f, 0.28235295f, 0.4f);
private static readonly Quaternion CIRCLE_CAP_ROTATION = Quaternion.Euler(90f, 0f, 0f);
private static readonly Quaternion CIRCLE_CAP_ROTATION2 = Quaternion.Euler(0f, 90f, 0f);
private static readonly Quaternion RECTANGLE_CAP_ROTATION = Quaternion.Euler(90f, 0f, 0f);
public static Vector2 RectHandle(Vector3 worldPosition, Quaternion worldRotation, Vector2 rectSize, EAxis axii)
{
float size = HandleUtility.GetHandleSize(worldPosition);
float dotSize = size * 0.125f;
Handles.matrix = Matrix4x4.TRS(worldPosition, worldRotation * RECTANGLE_CAP_ROTATION, Vector3.one);
Color color = Handles.color;
Handles.color = EDGE_COLOR;
Handles.DrawWireCube(Vector3.zero, rectSize);
if ((axii & EAxis.X) != 0)
{
var point = new Vector3(rectSize.x * 0.5f, 0f, 0f);
Handles.color = DEFAULT_AXIS_COLOR;
point = Handles.Slider(point, Vector3.right, dotSize, Handles.CubeHandleCap, 0.01f);
rectSize.x = Mathf.Max(point.x, 0f) * 2f;
}
if ((axii & EAxis.Y) != 0)
{
var point = new Vector3(0f, rectSize.y * 0.5f, 0f);
Handles.color = DEFAULT_AXIS_COLOR;
point = Handles.Slider(point, Vector3.up, dotSize, Handles.CubeHandleCap, 0.01f);
rectSize.y = Mathf.Max(point.y, 0f) * 2f;
}
Handles.color = color;
Handles.matrix = Matrix4x4.identity;
return rectSize;
}
public static float CircleHandle(Vector3 worldPosition, Quaternion worldRotation, float circleSize)
{
float size = HandleUtility.GetHandleSize(worldPosition);
float dotSize = size * 0.125f;
Handles.matrix = Matrix4x4.TRS(worldPosition, worldRotation, Vector3.one);
Color color = Handles.color;
Handles.color = EDGE_COLOR;
Handles.CircleHandleCap(-1, Vector3.zero, CIRCLE_CAP_ROTATION, circleSize, EventType.Repaint);
var point = new Vector3(circleSize, 0f, 0f);
Handles.color = DEFAULT_AXIS_COLOR;
point = Handles.Slider(point, Vector3.right, dotSize, Handles.CubeHandleCap, 0.01f);
circleSize = Mathf.Max(point.x, 0f);
Handles.color = color;
Handles.matrix = Matrix4x4.identity;
return circleSize;
}
public static float SphereHandle(Vector3 worldPosition, Quaternion worldRotation, float sphereSize)
{
float size = HandleUtility.GetHandleSize(worldPosition);
float dotSize = size * 0.125f;
Handles.matrix = Matrix4x4.TRS(worldPosition, worldRotation, Vector3.one);
Color color = Handles.color;
Handles.color = EDGE_COLOR;
Handles.CircleHandleCap(-1, Vector3.zero, CIRCLE_CAP_ROTATION, sphereSize, EventType.Repaint);
Handles.color = EDGE_COLOR2;
Handles.CircleHandleCap(-1, Vector3.zero, Quaternion.identity, sphereSize, EventType.Repaint);
Handles.CircleHandleCap(-1, Vector3.zero, CIRCLE_CAP_ROTATION2, sphereSize, EventType.Repaint);
var point = new Vector3(sphereSize, 0f, 0f);
Handles.color = DEFAULT_AXIS_COLOR;
point = Handles.Slider(point, Vector3.right, dotSize, Handles.CubeHandleCap, 0.01f);
sphereSize = Mathf.Max(point.x, 0f);
Handles.color = color;
Handles.matrix = Matrix4x4.identity;
return sphereSize;
}
public static Vector3 BoxHandle(Vector3 worldPosition, Quaternion worldRotation, Vector3 boxSize, EAxis axii = EAxis.All)
{
float size = HandleUtility.GetHandleSize(worldPosition);
float dotSize = size * 0.125f;
Handles.matrix = Matrix4x4.TRS(worldPosition, worldRotation, Vector3.one);
Color color = Handles.color;
Handles.color = EDGE_COLOR;
Handles.DrawWireCube(Vector3.zero, boxSize);
if ((axii & EAxis.X) != 0)
{
var point = new Vector3(boxSize.x * 0.5f, 0f, 0f);
Handles.color = DEFAULT_AXIS_COLOR;
point = Handles.Slider(point, Vector3.right, dotSize, Handles.CubeHandleCap, 0.01f);
boxSize.x = Mathf.Max(point.x, 0f) * 2f;
}
if ((axii & EAxis.Y) != 0)
{
var point = new Vector3(0f, boxSize.y * 0.5f, 0f);
Handles.color = DEFAULT_AXIS_COLOR;
point = Handles.Slider(point, Vector3.up, dotSize, Handles.CubeHandleCap, 0.01f);
boxSize.y = Mathf.Max(point.y, 0f) * 2f;
}
if ((axii & EAxis.Z) != 0)
{
var point = new Vector3(0f, 0f, boxSize.z * 0.5f);
Handles.color = DEFAULT_AXIS_COLOR;
point = Handles.Slider(point, Vector3.forward, dotSize, Handles.CubeHandleCap, 0.01f);
boxSize.z = Mathf.Max(point.z, 0f) * 2f;
}
Handles.color = color;
Handles.matrix = Matrix4x4.identity;
return boxSize;
}
public static Vector3 PositionHandle(Vector3 worldPosition, Quaternion worldRotation, EAxis axii = EAxis.All)
{
float size = HandleUtility.GetHandleSize(worldPosition);
float twoAxisSize = size * 0.1f;
Color color = Handles.color;
if ((axii & (EAxis.X | EAxis.Y)) == (EAxis.X | EAxis.Y))
{
Handles.color = Z_AXIS_COLOR;
Vector3 offset = worldRotation * new Vector3(twoAxisSize, twoAxisSize, 0f);
worldPosition = Handles.Slider2D(worldPosition + offset,
worldRotation * Vector3.forward,
worldRotation * Vector3.right,
worldRotation * Vector3.up, twoAxisSize,
Handles.RectangleHandleCap, 0.01f) - offset;
}
if ((axii & (EAxis.X | EAxis.Z)) == (EAxis.X | EAxis.Z))
{
Handles.color = Y_AXIS_COLOR;
Vector3 offset = worldRotation * new Vector3(twoAxisSize, 0f, twoAxisSize);
worldPosition = Handles.Slider2D(worldPosition + offset,
worldRotation * Vector3.up,
worldRotation * Vector3.right,
worldRotation * Vector3.forward, twoAxisSize,
Handles.RectangleHandleCap, 0.01f) - offset;
}
if ((axii & (EAxis.Y | EAxis.Z)) == (EAxis.Y | EAxis.Z))
{
Handles.color = X_AXIS_COLOR;
Vector3 offset = worldRotation * new Vector3(0f, twoAxisSize, twoAxisSize);
worldPosition = Handles.Slider2D(worldPosition + offset,
worldRotation * Vector3.right,
worldRotation * Vector3.up,
worldRotation * Vector3.forward, twoAxisSize,
Handles.RectangleHandleCap, 0.01f) - offset;
}
if ((axii & EAxis.X) != 0)
{
Handles.color = X_AXIS_COLOR;
worldPosition = Handles.Slider(worldPosition, worldRotation * Vector3.right, size, Handles.ArrowHandleCap, 0.01f);
}
if ((axii & EAxis.Y) != 0)
{
Handles.color = Y_AXIS_COLOR;
worldPosition = Handles.Slider(worldPosition, worldRotation * Vector3.up, size, Handles.ArrowHandleCap, 0.01f);
}
if ((axii & EAxis.Z) != 0)
{
Handles.color = Z_AXIS_COLOR;
worldPosition = Handles.Slider(worldPosition, worldRotation * Vector3.forward, size, Handles.ArrowHandleCap, 0.01f);
}
Handles.color = color;
return worldPosition;
}
public static Quaternion RotationHandle(Vector3 worldPosition, Quaternion worldRotation)
{
Color color = Handles.color;
worldRotation = Handles.RotationHandle(worldRotation, worldPosition);
Handles.color = color;
return worldRotation;
}
public static bool TryGetWorldPosition(SerializedProperty serializedProperty, string fieldPosition, Space space, out Vector3 worldPosition)
{
SerializedProperty spPosition = serializedProperty.GetSibling(fieldPosition);
if (spPosition != null)
{
worldPosition = GetWorldPosition(spPosition, space);
}
else
{
Transform transform = GetTransform(serializedProperty);
worldPosition = transform != null ? transform.position : Vector3.zero;
}
return spPosition != null;
}
public static Vector3 GetWorldPosition(SerializedProperty serializedProperty, string fieldPosition, Space space)
{
Vector3 worldPosition = Vector3.zero;
SerializedProperty spPosition = serializedProperty.GetSibling(fieldPosition);
if (spPosition != null)
{
worldPosition = GetWorldPosition(spPosition, space);
}
else
{
Transform transform = GetTransform(serializedProperty);
if (transform != null)
worldPosition = transform.position;
}
return worldPosition;
}
private static Transform GetTransform(SerializedProperty serializedProperty)
{
Object target = serializedProperty.serializedObject.targetObject;
if (target is Component component)
return component.transform;
return null;
}
public static Vector3 GetWorldPosition(SerializedProperty serializedProperty, Space space)
{
Vector3 worldPosition = Vector3.zero;
var requireObjectTransform = true;
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
worldPosition = new Vector3(serializedProperty.intValue, serializedProperty.intValue, serializedProperty.intValue);
break;
case SerializedPropertyType.Float:
worldPosition = new Vector3(serializedProperty.floatValue, serializedProperty.floatValue, serializedProperty.floatValue);
break;
case SerializedPropertyType.ObjectReference:
if (serializedProperty.objectReferenceValue != null && serializedProperty.objectReferenceValue is Transform transform)
{
worldPosition = transform.position;
requireObjectTransform = false;
}
break;
case SerializedPropertyType.Vector2:
worldPosition = serializedProperty.vector2Value;
break;
case SerializedPropertyType.Vector3:
worldPosition = serializedProperty.vector3Value;
break;
case SerializedPropertyType.Vector2Int:
worldPosition = new Vector3(serializedProperty.vector2IntValue.x, serializedProperty.vector2IntValue.y, 0.0f);
break;
case SerializedPropertyType.Vector3Int:
worldPosition = new Vector3(serializedProperty.vector3IntValue.x, serializedProperty.vector3IntValue.y, serializedProperty.vector3IntValue.z);
break;
}
if (requireObjectTransform && space == Space.Self)
{
Transform objectTransform = GetTransform(serializedProperty);
if (objectTransform != null)
worldPosition = objectTransform.TransformPoint(worldPosition);
}
return worldPosition;
}
public static void SetWorldPosition(SerializedProperty serializedProperty, string fieldPosition, Vector3 worldPosition, Space space)
{
SerializedProperty spPosition = serializedProperty.GetSibling(fieldPosition);
if (spPosition != null)
{
SetWorldPosition(spPosition, worldPosition, space);
}
else
{
Transform transform = GetTransform(serializedProperty);
if (transform != null)
transform.position = worldPosition;
}
}
public static void SetWorldPosition(SerializedProperty serializedProperty, Vector3 worldPosition, Space space)
{
bool requireObjectTransform = !(serializedProperty.propertyType == SerializedPropertyType.ObjectReference && serializedProperty.objectReferenceValue != null && serializedProperty.objectReferenceValue is Transform);
if (requireObjectTransform && space == Space.Self)
{
Transform objectTransform = GetTransform(serializedProperty);
if (objectTransform != null)
worldPosition = objectTransform.InverseTransformPoint(worldPosition);
}
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.Integer:
serializedProperty.intValue = Mathf.RoundToInt(worldPosition.x);
break;
case SerializedPropertyType.Float:
serializedProperty.floatValue = worldPosition.x;
break;
case SerializedPropertyType.ObjectReference:
if (serializedProperty.objectReferenceValue != null && serializedProperty.objectReferenceValue is Transform transform)
transform.position = worldPosition;
break;
case SerializedPropertyType.Vector2:
serializedProperty.vector2Value = worldPosition;
break;
case SerializedPropertyType.Vector3:
serializedProperty.vector3Value = worldPosition;
break;
case SerializedPropertyType.Vector2Int:
serializedProperty.vector2IntValue = new Vector2Int(Mathf.RoundToInt(worldPosition.x), Mathf.RoundToInt(worldPosition.y));
break;
case SerializedPropertyType.Vector3Int:
serializedProperty.vector3IntValue = new Vector3Int(Mathf.RoundToInt(worldPosition.x), Mathf.RoundToInt(worldPosition.y), Mathf.RoundToInt(worldPosition.z));
break;
}
}
public static bool TryGetWorldRotation(SerializedProperty serializedProperty, string fieldRotation, Space space, out Quaternion worldRotation)
{
SerializedProperty spRotation = serializedProperty.GetSibling(fieldRotation);
if (spRotation != null)
{
worldRotation = GetWorldRotation(spRotation, space);
}
else
{
Transform transform = GetTransform(serializedProperty);
worldRotation = transform != null ? transform.rotation : Quaternion.identity;
}
return spRotation != null;
}
public static Quaternion GetWorldRotation(SerializedProperty serializedProperty, string fieldRotation, Space space)
{
Quaternion worldRotation = Quaternion.identity;
SerializedProperty spRotation = serializedProperty.GetSibling(fieldRotation);
if (spRotation != null)
{
worldRotation = GetWorldRotation(spRotation, space);
}
else
{
Transform transform = GetTransform(serializedProperty);
if (transform != null)
worldRotation = transform.rotation;
}
return worldRotation;
}
public static Quaternion GetWorldRotation(SerializedProperty serializedProperty, Space space)
{
Quaternion worldRotation = Quaternion.identity;
var requireObjectTransform = true;
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.ObjectReference:
if (serializedProperty.objectReferenceValue is Transform transform)
{
worldRotation = transform.rotation;
requireObjectTransform = false;
}
break;
case SerializedPropertyType.Quaternion:
worldRotation = serializedProperty.quaternionValue;
if (Mathf.Approximately(worldRotation.x, 0.0f) && Mathf.Approximately(worldRotation.y, 0.0f) && Mathf.Approximately(worldRotation.z, 0.0f) && Mathf.Approximately(worldRotation.w, 0.0f))
worldRotation = Quaternion.identity;
break;
}
if (requireObjectTransform && space == Space.Self)
{
Transform objectTransform = GetTransform(serializedProperty);
if (objectTransform != null)
worldRotation = objectTransform.rotation * worldRotation;
}
return worldRotation;
}
public static void SetWorldRotation(SerializedProperty serializedProperty, string fieldRotation, Quaternion worldRotation, Space space)
{
SerializedProperty spRotation = serializedProperty.GetSibling(fieldRotation);
if (spRotation != null)
{
SetWorldRotation(spRotation, worldRotation, space);
}
else
{
Transform transform = GetTransform(serializedProperty);
if (transform != null)
transform.rotation = worldRotation;
}
}
public static void SetWorldRotation(SerializedProperty serializedProperty, Quaternion worldRotation, Space space)
{
bool requireObjectTransform = !(serializedProperty.propertyType == SerializedPropertyType.ObjectReference && serializedProperty.objectReferenceValue != null && serializedProperty.objectReferenceValue is Transform);
if (requireObjectTransform && space == Space.Self)
{
Transform objectTransform = GetTransform(serializedProperty);
if (objectTransform != null)
worldRotation = Quaternion.Inverse(objectTransform.rotation) * worldRotation;
}
switch (serializedProperty.propertyType)
{
case SerializedPropertyType.ObjectReference:
if (serializedProperty.objectReferenceValue is Transform transform)
transform.rotation = worldRotation;
break;
case SerializedPropertyType.Quaternion:
serializedProperty.quaternionValue = worldRotation;
break;
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 45835ab2c4434b40a10616e608e4ce1b
timeCreated: 1669476070

View file

@ -76,6 +76,7 @@ namespace Module.Inspector.Editor.Utilities
var valueModifiers = new List<ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>>(2);
var accessModifiers = new List<ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer>>(2);
var validators = new List<ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer>>(2);
var handleDrawers = new List<ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer>>(2);
object[] attributes = fieldInfo.GetCustomAttributes(false);
string tooltip = null;
var isObsolete = false;
@ -123,6 +124,13 @@ namespace Module.Inspector.Editor.Utilities
if (prop != null)
validators.Add(new ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer>(validator, prop));
}
else if (att is HandleDrawerPropertyAttribute handleDrawer)
{
var prop = InternalCreateInstanceOf<HandlePropertyDrawer>(handleDrawer);
if (prop != null)
handleDrawers.Add(new ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer>(handleDrawer, prop));
}
else if (att is TooltipAttribute attTooltip)
{
tooltip = attTooltip.tooltip;
@ -139,9 +147,9 @@ namespace Module.Inspector.Editor.Utilities
if (string.IsNullOrEmpty(obsoleteText))
{
if (tooltip != null)
tooltip += $"\n[Obsolete]";
tooltip += "\n[Obsolete]";
else
tooltip = $"[Obsolete]";
tooltip = "[Obsolete]";
}
else
{
@ -152,9 +160,9 @@ namespace Module.Inspector.Editor.Utilities
}
}
return new Result(drawer, predrawerModifiers, valueModifiers, accessModifiers, validators, tooltip, isObsolete);
return new Result(drawer, predrawerModifiers, valueModifiers, accessModifiers, validators, handleDrawers, tooltip, isObsolete);
}
private static T InternalCreateInstanceOf<T>(AbstractPropertyAttribute att) where T : AbstractPropertyDrawer
{
if (CACHED_ATT_TO_DRAWER.TryGetValue(att.GetType(), out Type drawerType))
@ -181,6 +189,7 @@ namespace Module.Inspector.Editor.Utilities
public readonly List<ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>> valueModifiers;
public readonly List<ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer>> accessModifiers;
public readonly List<ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer>> validators;
public readonly List<ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer>> handleDrawers;
public readonly string tooltip;
public readonly bool isObsolete;
@ -189,6 +198,7 @@ namespace Module.Inspector.Editor.Utilities
List<ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>> valueModifiers,
List<ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer>> accessModifiers,
List<ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer>> validators,
List<ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer>> handleDrawers,
string tooltip,
bool isObsolete)
{
@ -197,6 +207,7 @@ namespace Module.Inspector.Editor.Utilities
this.valueModifiers = valueModifiers;
this.accessModifiers = accessModifiers;
this.validators = validators;
this.handleDrawers = handleDrawers;
this.tooltip = tooltip;
this.isObsolete = isObsolete;
}
@ -244,6 +255,17 @@ namespace Module.Inspector.Editor.Utilities
return null;
}
public T GetHandleDrawer<T>() where T : HandleDrawerPropertyAttribute
{
for (var i = 0; i < handleDrawers.Count; i++)
{
if (handleDrawers[i].attribute is T att)
return att;
}
return null;
}
}
/// <summary>

View file

@ -176,4 +176,31 @@ To allow fields hidden from inspector either by `NonSerialized` or `HideInInspec
* `EnableShowHiddenFields`
* Enables an additional search to find any "hidden" fields and draw them below `DefaultInspector`
* `ShowHiddenField`
* Optional attribute for fields, if `EnableShowHiddenFields` has parameter `true`
* Optional attribute for fields, if `EnableShowHiddenFields` has parameter `true`
## Handles
List of all handle attributes:
* `BoxHandle`
* Resize a box shaped value, like Vector3
* Optional: Provide a `fieldPosition` and/or `fieldRotation` for handles to position and rotate
* `CircleHandle`
* Resize a circle shaped value, like float
* Optional: Provide a `fieldPosition` for handle to position
* `LabelHandle`
* Write text or field values
* Optional: Provide a `fieldPosition` and/or `fieldRotation` for handles to position and rotate
* `PositionHandle`
* Position handle with option to set number of axis visible (X, Y, Z)
* `RectangleHandle`
* Resize a rectangle shaped value, like Vector2
* Optional: Provide a `fieldPosition` and/or `fieldRotation` for handles to position and rotate
* `RotationHandle`
* Rotation handle for world or self-spaced rotation
* Optional: Provide a `fieldPosition` for handle to position
* `SphereHandle`
* Resize a sphere shaped value, like float
* Optional: Provide a `fieldPosition` and/or `fieldRotation` for handles to position and rotate

14
Runtime/Enums/EAxis.cs Normal file
View file

@ -0,0 +1,14 @@
using System;
namespace Module.Inspector
{
[Flags]
public enum EAxis
{
None = 0,
X = 1,
Y = 2,
Z = 4,
All = X | Y | Z
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6cea1a74f79c4b4e98b10fe9b98a0cfe
timeCreated: 1669408493

View file

@ -0,0 +1,12 @@
using System;
namespace Module.Inspector
{
[Flags]
public enum ELabelType
{
None = 0,
Field = 1,
Value = 2
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 00491187b70e400eb9bd403b49428b09
timeCreated: 1669499298

View file

@ -6,6 +6,7 @@
Drawer,
ValueModifier,
AccessModifier,
HandleDrawer,
Validate
}
}

View file

@ -0,0 +1,7 @@
namespace Module.Inspector
{
public abstract class HandleDrawerPropertyAttribute : AbstractPropertyAttribute
{
public override EPropertyType Type => EPropertyType.HandleDrawer;
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f9cdb8b0deb04fde8fa9b56e03a6f8c8
timeCreated: 1669408378

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6f0c558105634558964c91d5d8e3c979
timeCreated: 1669408405

View file

@ -0,0 +1,22 @@
using System;
using UnityEngine;
namespace Module.Inspector
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class BoxHandleAttribute : HandleDrawerPropertyAttribute
{
public readonly string fieldPosition;
public readonly string fieldRotation;
public readonly Space space;
public BoxHandleAttribute(string fieldPosition = null,
string fieldRotation = null,
Space space = Space.World)
{
this.fieldPosition = fieldPosition;
this.fieldRotation = fieldRotation;
this.space = space;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b2966619dc0e480480c69602eb4d25f4
timeCreated: 1669475646

View file

@ -0,0 +1,22 @@
using System;
using UnityEngine;
namespace Module.Inspector
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class CircleHandleAttribute : HandleDrawerPropertyAttribute
{
public readonly string fieldPosition;
public readonly string fieldRotation;
public readonly Space space;
public CircleHandleAttribute(string fieldPosition = null,
string fieldRotation = null,
Space space = Space.World)
{
this.fieldPosition = fieldPosition;
this.fieldRotation = fieldRotation;
this.space = space;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ec1137ba9e1344398415c1874809f64b
timeCreated: 1669475438

View file

@ -0,0 +1,22 @@
using System;
using UnityEngine;
namespace Module.Inspector
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class LabelHandleAttribute : HandleDrawerPropertyAttribute
{
public readonly ELabelType type;
public readonly string fieldPosition;
public readonly Space space;
public LabelHandleAttribute(ELabelType type = ELabelType.Value,
string fieldPosition = null,
Space space = Space.World)
{
this.type = type;
this.fieldPosition = fieldPosition;
this.space = space;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b04dcda9e8db4bfcab1d02ca1a7904f4
timeCreated: 1669475765

View file

@ -0,0 +1,18 @@
using System;
using UnityEngine;
namespace Module.Inspector
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class PositionHandleAttribute : HandleDrawerPropertyAttribute
{
public readonly Space space;
public readonly EAxis axiis;
public PositionHandleAttribute(Space space, EAxis axiis)
{
this.space = space;
this.axiis = axiis;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6ee82f8e6bfe42cd96c84a910b716d7a
timeCreated: 1669408436

View file

@ -0,0 +1,22 @@
using System;
using UnityEngine;
namespace Module.Inspector
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class RectangleHandleAttribute : HandleDrawerPropertyAttribute
{
public readonly string fieldPosition;
public readonly string fieldRotation;
public readonly Space space;
public RectangleHandleAttribute(string fieldPosition = null,
string fieldRotation = null,
Space space = Space.World)
{
this.fieldPosition = fieldPosition;
this.fieldRotation = fieldRotation;
this.space = space;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c0b65d01ae7944ababe1c42a9497192c
timeCreated: 1669475700

View file

@ -0,0 +1,18 @@
using System;
using UnityEngine;
namespace Module.Inspector
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class RotationHandleAttribute : HandleDrawerPropertyAttribute
{
public readonly string fieldPosition;
public readonly Space space;
public RotationHandleAttribute(string fieldPosition = null, Space space = Space.World)
{
this.fieldPosition = fieldPosition;
this.space = space;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0a51649ba7d643b59166944db5f2dc95
timeCreated: 1669475570

View file

@ -0,0 +1,22 @@
using System;
using UnityEngine;
namespace Module.Inspector
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class SphereHandleAttribute : HandleDrawerPropertyAttribute
{
public readonly string fieldPosition;
public readonly string fieldRotation;
public readonly Space space;
public SphereHandleAttribute(string fieldPosition = null,
string fieldRotation = null,
Space space = Space.World)
{
this.fieldPosition = fieldPosition;
this.fieldRotation = fieldRotation;
this.space = space;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4ec43235833844159723030f304ac03b
timeCreated: 1669475530

View file

@ -1,6 +1,6 @@
{
"name": "com.module.inspector",
"version": "1.8.4",
"version": "1.9.0",
"displayName": "Module.Inspector",
"description": "Custom inspector with various useful property drawers",
"unity": "2019.2",