2021-09-09 20:42:29 -04:00

263 lines
9.1 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VFX;
using System.Linq;
using System.Reflection;
using Type = System.Type;
using Delegate = System.Delegate;
namespace UnityEditor.VFX
{
class VFXGizmoAttribute : System.Attribute
{
public VFXGizmoAttribute(Type type)
{
this.type = type;
}
public readonly Type type;
}
abstract class VFXGizmo
{
public interface IProperty<T>
{
bool isEditable { get; }
void SetValue(T value);
}
public interface IContext
{
IProperty<T> RegisterProperty<T>(string memberPath);
}
public abstract void RegisterEditableMembers(IContext context);
public abstract void CallDrawGizmo(object value);
public abstract Bounds CallGetGizmoBounds(object obj);
protected const float handleSize = 0.1f;
protected const float arcHandleSizeMultiplier = 1.25f;
public VFXCoordinateSpace currentSpace { get; set; }
public bool spaceLocalByDefault { get; set; }
public VisualEffect component {get; set; }
public bool PositionGizmo(ref Vector3 position, bool always)
{
if (always || Tools.current == Tool.Move || Tools.current == Tool.Transform || Tools.current == Tool.None)
{
EditorGUI.BeginChangeCheck();
position = Handles.PositionHandle(position, Tools.pivotRotation == PivotRotation.Local ? Quaternion.identity : Handles.matrix.inverse.rotation);
return EditorGUI.EndChangeCheck();
}
return false;
}
public bool ScaleGizmo(Vector3 position, ref Vector3 scale, Quaternion rotation, bool always)
{
if (always || Tools.current == Tool.Scale || Tools.current == Tool.Transform || Tools.current == Tool.None)
{
EditorGUI.BeginChangeCheck();
scale = Handles.ScaleHandle(scale, position , rotation, Tools.current == Tool.Transform || Tools.current == Tool.None ? HandleUtility.GetHandleSize(position) * 0.75f : HandleUtility.GetHandleSize(position));
return EditorGUI.EndChangeCheck();
}
return false;
}
public bool ScaleGizmo(Vector3 position, Vector3 scale, Quaternion rotation, IProperty<Vector3> scaleProperty, bool always)
{
if (scaleProperty.isEditable && ScaleGizmo(position, ref scale, rotation, always))
{
scaleProperty.SetValue(scale);
return true;
}
return false;
}
public bool PositionGizmo(Vector3 position, IProperty<Vector3> positionProperty, bool always)
{
if (positionProperty.isEditable && PositionGizmo(ref position, always))
{
positionProperty.SetValue(position);
return true;
}
return false;
}
public bool RotationGizmo(Vector3 position, Vector3 rotation, IProperty<Vector3> anglesProperty, bool always)
{
if (anglesProperty.isEditable && RotationGizmo(position, ref rotation, always))
{
anglesProperty.SetValue(rotation);
return true;
}
return false;
}
public bool RotationGizmo(Vector3 position, ref Vector3 rotation, bool always)
{
Quaternion quaternion = Quaternion.Euler(rotation);
bool result = RotationGizmo(position, ref quaternion, always);
if (result)
{
rotation = quaternion.eulerAngles;
return true;
}
return false;
}
public bool RotationGizmo(Vector3 position, ref Quaternion rotation, bool always)
{
if (always || Tools.current == Tool.Rotate || Tools.current == Tool.Transform || Tools.current == Tool.None)
{
EditorGUI.BeginChangeCheck();
rotation = Handles.RotationHandle(rotation, position);
return EditorGUI.EndChangeCheck();
}
return false;
}
public bool ArcGizmo(Vector3 center, float radius, float degArc, IProperty<float> arcProperty, Quaternion rotation, bool always)
{
// Arc handle control
if (arcProperty.isEditable && (always || Tools.current == Tool.Rotate || Tools.current == Tool.Transform))
{
using (new Handles.DrawingScope(Handles.matrix * Matrix4x4.Translate(center) * Matrix4x4.Rotate(rotation)))
{
EditorGUI.BeginChangeCheck();
Vector3 arcHandlePosition = Quaternion.AngleAxis(degArc, Vector3.up) * Vector3.forward * radius;
arcHandlePosition = Handles.Slider2D(
arcHandlePosition,
Vector3.up,
Vector3.forward,
Vector3.right,
handleSize * arcHandleSizeMultiplier * HandleUtility.GetHandleSize(arcHandlePosition),
DefaultAngleHandleDrawFunction,
0
);
if (EditorGUI.EndChangeCheck())
{
float newArc = Vector3.Angle(Vector3.forward, arcHandlePosition) * Mathf.Sign(Vector3.Dot(Vector3.right, arcHandlePosition));
degArc += Mathf.DeltaAngle(degArc, newArc);
degArc = Mathf.Repeat(degArc, 360.0f);
arcProperty.SetValue(degArc * Mathf.Deg2Rad);
return true;
}
}
}
return false;
}
static Vector3 m_InitialNormal;
public bool NormalGizmo(Vector3 position, ref Vector3 normal , bool always)
{
if (Event.current.type == EventType.MouseDown)
{
m_InitialNormal = normal;
}
EditorGUI.BeginChangeCheck();
Quaternion delta = Quaternion.identity;
RotationGizmo(position, ref delta, always);
if (EditorGUI.EndChangeCheck())
{
normal = delta * m_InitialNormal;
return true;
}
return false;
}
public static void DefaultAngleHandleDrawFunction(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)
{
Handles.DrawLine(Vector3.zero, position);
// draw a cylindrical "hammer head" to indicate the direction the handle will move
Vector3 worldPosition = Handles.matrix.MultiplyPoint3x4(position);
Vector3 normal = worldPosition - Handles.matrix.MultiplyPoint3x4(Vector3.zero);
Vector3 tangent = Handles.matrix.MultiplyVector(Quaternion.AngleAxis(90f, Vector3.up) * position);
rotation = Quaternion.LookRotation(tangent, normal);
Matrix4x4 matrix = Matrix4x4.TRS(worldPosition, rotation, (Vector3.one + Vector3.forward * arcHandleSizeMultiplier));
using (new Handles.DrawingScope(matrix))
Handles.CylinderHandleCap(controlID, Vector3.zero, Quaternion.identity, size, eventType);
}
public virtual bool needsComponent { get { return false; } }
}
abstract class VFXGizmo<T> : VFXGizmo
{
public override void CallDrawGizmo(object value)
{
if (value is T)
OnDrawGizmo((T)value);
}
public override Bounds CallGetGizmoBounds(object value)
{
if (value is T)
{
return OnGetGizmoBounds((T)value);
}
return new Bounds();
}
public abstract void OnDrawGizmo(T value);
public abstract Bounds OnGetGizmoBounds(T value);
}
abstract class VFXSpaceableGizmo<T> : VFXGizmo<T>
{
public override void OnDrawGizmo(T value)
{
Matrix4x4 oldMatrix = Handles.matrix;
if (currentSpace == VFXCoordinateSpace.Local)
{
if (component == null) return;
Handles.matrix = component.transform.localToWorldMatrix;
}
else
{
Handles.matrix = Matrix4x4.identity;
}
OnDrawSpacedGizmo(value);
Handles.matrix = oldMatrix;
}
public override Bounds OnGetGizmoBounds(T value)
{
Bounds bounds = OnGetSpacedGizmoBounds(value);
if (currentSpace == VFXCoordinateSpace.Local)
{
if (component == null)
return new Bounds();
return UnityEditorInternal.InternalEditorUtility.TransformBounds(bounds, component.transform);
}
return bounds;
}
public override bool needsComponent
{
get { return (currentSpace == VFXCoordinateSpace.Local) != spaceLocalByDefault; }
}
public abstract void OnDrawSpacedGizmo(T value);
public abstract Bounds OnGetSpacedGizmoBounds(T value);
}
}