UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/Editor/Decal/ProjectedTransform.cs
2024-10-27 10:53:47 +03:00

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;
}
}
}