You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
10 KiB
248 lines
10 KiB
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; |
|
} |
|
} |
|
}
|
|
|