249 lines
10 KiB
C#
249 lines
10 KiB
C#
using System;
|
|
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
|
|
namespace UnityEngine.Rendering.Universal
|
|
{
|
|
// Copy of UnityEditor.Rendering.HighDefinition.DisplacableRectHandles
|
|
class ProjectedTransform
|
|
{
|
|
struct PositionHandleIds
|
|
{
|
|
static int s_xAxisMoveHandleHash = "xAxisDecalPivot".GetHashCode();
|
|
static int s_yAxisMoveHandleHash = "yAxisDecalPivot".GetHashCode();
|
|
static int s_zAxisMoveHandleHash = "zAxisDecalPivot".GetHashCode();
|
|
static int s_xyAxisMoveHandleHash = "xyAxisDecalPivot".GetHashCode();
|
|
|
|
public static PositionHandleIds @default
|
|
{
|
|
get
|
|
{
|
|
return new PositionHandleIds(
|
|
GUIUtility.GetControlID(s_xAxisMoveHandleHash, FocusType.Passive),
|
|
GUIUtility.GetControlID(s_yAxisMoveHandleHash, FocusType.Passive),
|
|
GUIUtility.GetControlID(s_zAxisMoveHandleHash, FocusType.Passive),
|
|
GUIUtility.GetControlID(s_xyAxisMoveHandleHash, FocusType.Passive)
|
|
);
|
|
}
|
|
}
|
|
|
|
public readonly int x, y, z, xy;
|
|
|
|
public int this[int index]
|
|
{
|
|
get
|
|
{
|
|
switch (index)
|
|
{
|
|
case 0: return x;
|
|
case 1: return y;
|
|
case 2: return z;
|
|
case 3: return xy;
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public bool Has(int id)
|
|
{
|
|
return x == id
|
|
|| y == id
|
|
|| z == id
|
|
|| xy == id;
|
|
}
|
|
|
|
public PositionHandleIds(int x, int y, int z, int xy)
|
|
{
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.xy = xy;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return x ^ y ^ z ^ xy;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (!(obj is PositionHandleIds o))
|
|
return false;
|
|
|
|
return o.x == x && o.y == y && o.z == z && o.xy == xy;
|
|
}
|
|
}
|
|
|
|
struct PositionHandleParam
|
|
{
|
|
public static PositionHandleParam defaultHandleXY = new PositionHandleParam(
|
|
Handle.X | Handle.Y | Handle.XY,
|
|
Vector3.zero, Vector3.one, Vector3.zero, Vector3.one * .25f,
|
|
Orientation.Signed, Orientation.Camera);
|
|
|
|
public static PositionHandleParam defaultHandleZ = new PositionHandleParam(
|
|
Handle.Z,
|
|
Vector3.zero, Vector3.one, Vector3.zero, Vector3.one * .25f,
|
|
Orientation.Signed, Orientation.Camera);
|
|
|
|
[Flags]
|
|
public enum Handle
|
|
{
|
|
None = 0,
|
|
X = 1 << 0,
|
|
Y = 1 << 1,
|
|
Z = 1 << 2,
|
|
XY = 1 << 3,
|
|
All = ~None
|
|
}
|
|
|
|
public enum Orientation
|
|
{
|
|
Signed,
|
|
Camera
|
|
}
|
|
|
|
public readonly Vector3 axisOffset;
|
|
public readonly Vector3 axisSize;
|
|
public readonly Vector3 planeOffset;
|
|
public readonly Vector3 planeSize;
|
|
public readonly Handle handles;
|
|
public readonly Orientation axesOrientation;
|
|
public readonly Orientation planeOrientation;
|
|
|
|
public bool ShouldShow(int axis)
|
|
{
|
|
return (handles & (Handle)(1 << axis)) != 0;
|
|
}
|
|
|
|
public bool ShouldShow(Handle handle)
|
|
{
|
|
return (handles & handle) != 0;
|
|
}
|
|
|
|
public PositionHandleParam(
|
|
Handle handles,
|
|
Vector3 axisOffset,
|
|
Vector3 axisSize,
|
|
Vector3 planeOffset,
|
|
Vector3 planeSize,
|
|
Orientation axesOrientation,
|
|
Orientation planeOrientation)
|
|
{
|
|
this.axisOffset = axisOffset;
|
|
this.axisSize = axisSize;
|
|
this.planeOffset = planeOffset;
|
|
this.planeSize = planeSize;
|
|
this.handles = handles;
|
|
this.axesOrientation = axesOrientation;
|
|
this.planeOrientation = planeOrientation;
|
|
}
|
|
}
|
|
|
|
static PositionHandleParam paramXY = PositionHandleParam.defaultHandleXY;
|
|
static PositionHandleParam paramZ = PositionHandleParam.defaultHandleZ;
|
|
static PositionHandleIds ids = PositionHandleIds.@default;
|
|
|
|
static int[] s_DoPositionHandle_Internal_NextIndex = { 1, 2, 0 };
|
|
static int[] s_DoPositionHandle_Internal_PrevIndex = { 2, 0, 1 };
|
|
static Vector3[] verts = { Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero };
|
|
|
|
static Func<bool> s_IsGridSnappingActive;
|
|
|
|
|
|
static ProjectedTransform()
|
|
{
|
|
//We need to know if grid snaping is active or not in Editor. Sadly this is internal so we must grab it by reflection.
|
|
Type gridSnappingType = typeof(Handles).Assembly.GetType("UnityEditor.GridSnapping");
|
|
PropertyInfo activePropertyInfo = gridSnappingType.GetProperty("active", BindingFlags.Public | BindingFlags.Static);
|
|
MethodCallExpression activePropertyGetCall = Expression.Call(null, activePropertyInfo.GetGetMethod());
|
|
var activeGetLambda = Expression.Lambda<Func<bool>>(activePropertyGetCall);
|
|
s_IsGridSnappingActive = activeGetLambda.Compile();
|
|
}
|
|
|
|
static bool IsHovering(int controlID, Event evt)
|
|
{
|
|
return controlID == HandleUtility.nearestControl && GUIUtility.hotControl == 0 && !Tools.viewToolActive;
|
|
}
|
|
|
|
public static Vector3 DrawHandles(Vector3 position, float zProjectionDistance, Quaternion rotation)
|
|
{
|
|
var isHot = ids.Has(GUIUtility.hotControl);
|
|
var planeSize = isHot ? paramXY.planeSize + paramXY.planeOffset : paramXY.planeSize;
|
|
var planarSize = Mathf.Max(planeSize[0], planeSize[s_DoPositionHandle_Internal_NextIndex[0]]);
|
|
Vector3 sliderRotatedWorldPos = Quaternion.Inverse(rotation) * position;
|
|
var size1D = HandleUtility.GetHandleSize(sliderRotatedWorldPos);
|
|
var size2D = HandleUtility.GetHandleSize(sliderRotatedWorldPos - new Vector3(0, 0, zProjectionDistance)) * planarSize * .5f;
|
|
Vector3 depthSlider = sliderRotatedWorldPos;
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
{
|
|
// dot offset = transform position seen as a sphere
|
|
EditorGUI.BeginChangeCheck();
|
|
depthSlider = Handles.Slider(depthSlider, Vector3.forward, size1D * .1f, Handles.SphereHandleCap, -1);
|
|
if (EditorGUI.EndChangeCheck())
|
|
sliderRotatedWorldPos.z = depthSlider.z;
|
|
|
|
// 2D slider: square xy-axis
|
|
Vector3 sliderFaceProjected = sliderRotatedWorldPos - new Vector3(0, 0, zProjectionDistance);
|
|
sliderFaceProjected.x += size2D;
|
|
sliderFaceProjected.y += size2D;
|
|
using (new Handles.DrawingScope(Handles.zAxisColor))
|
|
{
|
|
verts[0] = sliderFaceProjected + (Vector3.right + Vector3.up) * size2D;
|
|
verts[1] = sliderFaceProjected + (-Vector3.right + Vector3.up) * size2D;
|
|
verts[2] = sliderFaceProjected + (-Vector3.right - Vector3.up) * size2D;
|
|
verts[3] = sliderFaceProjected + (Vector3.right - Vector3.up) * size2D;
|
|
int id = GUIUtility.GetControlID(ids.xy, FocusType.Passive);
|
|
float faceOpacity = 0.8f;
|
|
if (GUIUtility.hotControl == id)
|
|
Handles.color = Handles.selectedColor;
|
|
else if (IsHovering(id, Event.current))
|
|
faceOpacity = 0.4f;
|
|
else
|
|
faceOpacity = 0.1f;
|
|
Color faceColor = new Color(Handles.zAxisColor.r, Handles.zAxisColor.g, Handles.zAxisColor.b, Handles.zAxisColor.a * faceOpacity);
|
|
Handles.DrawSolidRectangleWithOutline(verts, faceColor, Color.clear);
|
|
EditorGUI.BeginChangeCheck();
|
|
sliderFaceProjected = Handles.Slider2D(id, sliderFaceProjected, Vector3.forward, Vector3.right, Vector3.up, size2D, Handles.RectangleHandleCap, s_IsGridSnappingActive() ? Vector2.zero : new Vector2(EditorSnapSettings.move[0], EditorSnapSettings.move[1]), false);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
sliderRotatedWorldPos.x = sliderFaceProjected.x;
|
|
sliderRotatedWorldPos.y = sliderFaceProjected.y;
|
|
}
|
|
}
|
|
sliderFaceProjected.x -= size2D;
|
|
sliderFaceProjected.y -= size2D;
|
|
|
|
// 2D slider: x-axis
|
|
EditorGUI.BeginChangeCheck();
|
|
using (new Handles.DrawingScope(Handles.xAxisColor))
|
|
sliderFaceProjected = Handles.Slider(sliderFaceProjected, Vector3.right);
|
|
if (EditorGUI.EndChangeCheck())
|
|
sliderRotatedWorldPos.x = sliderFaceProjected.x;
|
|
|
|
// 2D slider: y-axis
|
|
EditorGUI.BeginChangeCheck();
|
|
using (new Handles.DrawingScope(Handles.yAxisColor))
|
|
sliderFaceProjected = Handles.Slider(sliderFaceProjected, Vector3.up);
|
|
if (EditorGUI.EndChangeCheck())
|
|
sliderRotatedWorldPos.y = sliderFaceProjected.y;
|
|
|
|
// depth: z-axis
|
|
EditorGUI.BeginChangeCheck();
|
|
using (new Handles.DrawingScope(Handles.zAxisColor))
|
|
depthSlider = Handles.Slider(depthSlider, Vector3.forward);
|
|
if (EditorGUI.EndChangeCheck())
|
|
sliderRotatedWorldPos.z = depthSlider.z;
|
|
}
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
position = rotation * sliderRotatedWorldPos;
|
|
}
|
|
|
|
return position;
|
|
}
|
|
}
|
|
}
|