浏览代码

Merge pull request #1902 from Unity-Technologies/HDRP/decalprojector-gizmo-improvements-rebase-master

Improvements to decal projector editor gizmo.
/main
GitHub 6 年前
当前提交
45793fd6
共有 4 个文件被更改,包括 238 次插入13 次删除
  1. 60
      com.unity.render-pipelines.high-definition/HDRP/Editor/Material/Decal/DecalProjectorComponentEditor.cs
  2. 7
      com.unity.render-pipelines.high-definition/HDRP/Material/Decal/DecalProjectorComponent.cs
  3. 173
      com.unity.render-pipelines.high-definition/HDRP/Editor/Material/Decal/DecalProjectorComponentHandle.cs
  4. 11
      com.unity.render-pipelines.high-definition/HDRP/Editor/Material/Decal/DecalProjectorComponentHandle.cs.meta

60
com.unity.render-pipelines.high-definition/HDRP/Editor/Material/Decal/DecalProjectorComponentEditor.cs


private SerializedProperty m_UVScaleProperty;
private SerializedProperty m_UVBiasProperty;
private SerializedProperty m_AffectsTransparencyProperty;
private SerializedProperty m_Center;
private BoxBoundsHandle m_Handle = new BoxBoundsHandle();
private SerializedProperty m_IsCropModeEnabledProperty;
private DecalProjectorComponentHandle m_Handle = new DecalProjectorComponentHandle();
private void OnEnable()
{

m_UVScaleProperty = serializedObject.FindProperty("m_UVScale");
m_UVBiasProperty = serializedObject.FindProperty("m_UVBias");
m_AffectsTransparencyProperty = serializedObject.FindProperty("m_AffectsTransparency");
m_Center = serializedObject.FindProperty("m_Offset");
m_IsCropModeEnabledProperty = serializedObject.FindProperty("m_IsCropModeEnabled");
}
private void OnDisable()

}
void OnSceneGUI()
{
{
Handles.matrix = m_DecalProjectorComponent.transform.localToWorldMatrix;
Handles.matrix = m_DecalProjectorComponent.transform.localToWorldMatrix;
Vector3 boundsSizePreviousOS = m_Handle.size;
Vector3 boundsMinPreviousOS = m_Handle.size * -0.5f + m_Handle.center;
// adjust decal transform if handle changed
// Adjust decal transform if handle changed.
Undo.RecordObject(m_DecalProjectorComponent, "Decal Projector Change");
m_DecalProjectorComponent.m_Size = m_Handle.size;
m_DecalProjectorComponent.m_Size = m_Handle.size;
EditorUtility.SetDirty(m_DecalProjectorComponent);
Vector3 boundsSizeCurrentOS = m_Handle.size;
Vector3 boundsMinCurrentOS = m_Handle.size * -0.5f + m_Handle.center;
if (m_DecalProjectorComponent.m_IsCropModeEnabled)
{
// Treat decal projector bounds as a crop tool, rather than a scale tool.
// Compute a new uv scale and bias terms to pin decal projection pixels in world space, irrespective of projector bounds.
m_DecalProjectorComponent.m_UVScale.x *= Mathf.Max(1e-5f, boundsSizeCurrentOS.x) / Mathf.Max(1e-5f, boundsSizePreviousOS.x);
m_DecalProjectorComponent.m_UVScale.y *= Mathf.Max(1e-5f, boundsSizeCurrentOS.z) / Mathf.Max(1e-5f, boundsSizePreviousOS.z);
m_DecalProjectorComponent.m_UVBias.x += (boundsMinCurrentOS.x - boundsMinPreviousOS.x) / Mathf.Max(1e-5f, boundsSizeCurrentOS.x) * m_DecalProjectorComponent.m_UVScale.x;
m_DecalProjectorComponent.m_UVBias.y += (boundsMinCurrentOS.z - boundsMinPreviousOS.z) / Mathf.Max(1e-5f, boundsSizeCurrentOS.z) * m_DecalProjectorComponent.m_UVScale.y;
}
// Automatically recenter our transform component if necessary.
// In order to correctly handle world-space snapping, we only perform this recentering when the user is no longer interacting with the gizmo.
if ((GUIUtility.hotControl == 0) && (m_DecalProjectorComponent.m_Offset != Vector3.zero))
{
// Both the DecalProjectorComponent, and the transform will be modified.
// The undo system will automatically group all RecordObject() calls here into a single action.
Undo.RecordObject(m_DecalProjectorComponent.transform, "Decal Projector Change");
// Re-center the transform to the center of the decal projector bounds,
// while maintaining the world-space coordinates of the decal projector boundings vertices.
m_DecalProjectorComponent.transform.Translate(
Vector3.Scale(m_DecalProjectorComponent.m_Offset, m_DecalProjectorComponent.transform.localScale),
Space.Self
);
m_DecalProjectorComponent.m_Offset = Vector3.zero;
}
Handles.matrix = mat;
Handles.color = col;
}

EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_Center);
EditorGUILayout.PropertyField(m_IsCropModeEnabledProperty, new GUIContent("Crop Decal with Gizmo"));
EditorGUILayout.PropertyField(m_Size);
EditorGUILayout.PropertyField(m_MaterialProperty);
EditorGUILayout.PropertyField(m_DrawDistanceProperty);

EditorGUILayout.PropertyField(m_AffectsTransparencyProperty);
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();

7
com.unity.render-pipelines.high-definition/HDRP/Material/Decal/DecalProjectorComponent.cs


public Vector3 m_Size = new Vector3(1, 1, 1);
private Material m_OldMaterial = null;
private DecalSystem.DecalHandle m_Handle = null;
public bool m_IsCropModeEnabled = false;
public DecalSystem.DecalHandle Handle
{

}
if (m_Handle != null)
{
{
DecalSystem.instance.RemoveDecal(m_Handle);
m_Handle = null;
}

public void OnDisable()
{
if (m_Handle != null)
{
{
DecalSystem.instance.RemoveDecal(m_Handle);
m_Handle = null;
}

public event OnMaterialChangeDelegate OnMaterialChange;
public void OnValidate()
{
{
if (m_Handle != null) // don't do anything if OnEnable hasn't been called yet when scene is loading.
{
Vector4 uvScaleBias = new Vector4(m_UVScale.x, m_UVScale.y, m_UVBias.x, m_UVBias.y);

173
com.unity.render-pipelines.high-definition/HDRP/Editor/Material/Decal/DecalProjectorComponentHandle.cs


using System;
using UnityEngine;
namespace UnityEditor.IMGUI.Controls
{
public class DecalProjectorComponentHandle : PrimitiveBoundsHandle
{
public DecalProjectorComponentHandle() : base()
{
midpointHandleDrawFunction = DrawHandleMidpoint;
}
public UnityEngine.Vector3 size { get { return GetSize(); } set { SetSize(value); } }
protected override void DrawWireframe()
{
Handles.DrawWireCube(center, size);
DrawArrowDownProjectionDirection();
}
protected void DrawArrowDownProjectionDirection()
{
int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);
Quaternion arrowRotation = Quaternion.LookRotation(Vector3.down, Vector3.right);
float arrowSize = size.y * 0.25f;
Handles.ArrowHandleCap(controlID, center, arrowRotation, arrowSize, EventType.Repaint);
}
// Could use a static readonly LUT, but this would require syncing with order with enum HandleDirection.
protected static Color ColorFromHandleDirection(HandleDirection handleDirection)
{
switch (handleDirection)
{
case HandleDirection.PositiveX:
case HandleDirection.NegativeX:
return Handles.xAxisColor;
case HandleDirection.PositiveY:
case HandleDirection.NegativeY:
return Handles.yAxisColor;
case HandleDirection.PositiveZ:
case HandleDirection.NegativeZ:
return Handles.zAxisColor;
default:
throw new ArgumentOutOfRangeException("handleDirection", "Must be PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, or NegativeZ");
}
}
protected static void PlaneVerticesFromHandleDirection(ref Vector3[] outVertices, HandleDirection handleDirection, Vector3 boundsSize, Vector3 boundsCenter)
{
Vector3 boundsMin = boundsSize * -0.5f + boundsCenter;
Vector3 boundsMax = boundsSize * 0.5f + boundsCenter;
switch (handleDirection)
{
case HandleDirection.PositiveX:
outVertices[0] = new Vector3(boundsMax.x, boundsMin.y, boundsMin.z);
outVertices[1] = new Vector3(boundsMax.x, boundsMax.y, boundsMin.z);
outVertices[2] = new Vector3(boundsMax.x, boundsMax.y, boundsMax.z);
outVertices[3] = new Vector3(boundsMax.x, boundsMin.y, boundsMax.z);
break;
case HandleDirection.NegativeX:
outVertices[0] = new Vector3(boundsMin.x, boundsMin.y, boundsMin.z);
outVertices[1] = new Vector3(boundsMin.x, boundsMax.y, boundsMin.z);
outVertices[2] = new Vector3(boundsMin.x, boundsMax.y, boundsMax.z);
outVertices[3] = new Vector3(boundsMin.x, boundsMin.y, boundsMax.z);
break;
case HandleDirection.PositiveY:
outVertices[0] = new Vector3(boundsMin.x, boundsMax.y, boundsMin.z);
outVertices[1] = new Vector3(boundsMax.x, boundsMax.y, boundsMin.z);
outVertices[2] = new Vector3(boundsMax.x, boundsMax.y, boundsMax.z);
outVertices[3] = new Vector3(boundsMin.x, boundsMax.y, boundsMax.z);
break;
case HandleDirection.NegativeY:
outVertices[0] = new Vector3(boundsMin.x, boundsMin.y, boundsMin.z);
outVertices[1] = new Vector3(boundsMax.x, boundsMin.y, boundsMin.z);
outVertices[2] = new Vector3(boundsMax.x, boundsMin.y, boundsMax.z);
outVertices[3] = new Vector3(boundsMin.x, boundsMin.y, boundsMax.z);
break;
case HandleDirection.PositiveZ:
outVertices[0] = new Vector3(boundsMin.x, boundsMin.y, boundsMax.z);
outVertices[1] = new Vector3(boundsMax.x, boundsMin.y, boundsMax.z);
outVertices[2] = new Vector3(boundsMax.x, boundsMax.y, boundsMax.z);
outVertices[3] = new Vector3(boundsMin.x, boundsMax.y, boundsMax.z);
break;
case HandleDirection.NegativeZ:
outVertices[0] = new Vector3(boundsMin.x, boundsMin.y, boundsMin.z);
outVertices[1] = new Vector3(boundsMax.x, boundsMin.y, boundsMin.z);
outVertices[2] = new Vector3(boundsMax.x, boundsMax.y, boundsMin.z);
outVertices[3] = new Vector3(boundsMin.x, boundsMax.y, boundsMin.z);
break;
default:
throw new ArgumentOutOfRangeException("handleDirection", "Must be PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, or NegativeZ");
}
}
// As DrawHandleDirectionPlane() is called every frame during gizmo rendering, we pre-allocate a scratch array for passing along to DrawSolidRectangleWithOutline()
// rather than putting pressure on the garbage collector every frame. Since DrawHandleDirectionPlane() is responsible for drawing handles, we will only ever call
// it from the main thread, so there is no realistic risk of a race condition occuring due to this static allocation.
private static Vector3[] s_PlaneVertices = new Vector3[4];
protected static void DrawHandleDirectionPlane(HandleDirection handleDirection, Vector3 size, Vector3 center)
{
// Set global Handles.color to white to avoid global state from interfering with the desired colors set at DrawSolidRectangleWithOutline().
Color handlesColorPrevious = Handles.color;
Handles.color = Color.white;
Color planeColorOutline = ColorFromHandleDirection(handleDirection);
const float planeColorFillAlpha = 0.25f;
Color planeColorFill = planeColorOutline * planeColorFillAlpha;
PlaneVerticesFromHandleDirection(ref s_PlaneVertices, handleDirection, size, center);
Handles.DrawSolidRectangleWithOutline(s_PlaneVertices, planeColorFill, planeColorOutline);
Handles.color = handlesColorPrevious;
}
// Utility function for determining the handle direction (which face) we are currently rendering within DrawHandleMidpoint().
// Ideally, the base class PrimitiveBoundsHandle would expose the reverse lookup: HandleDirectionFromControlID().
// In lieu of an explicit way to handle this look up, we derive the handle direction from the handle rotation.
protected static HandleDirection HandleDirectionFromRotation(Quaternion rotation)
{
if (rotation.x == 0.0f && rotation.y == 0.7071068f && rotation.z == 0.0f && rotation.w == 0.7071068f)
{
return HandleDirection.PositiveX;
}
else if (rotation.x == 0.0f && rotation.y == -0.7071068f && rotation.z == 0.0f && rotation.w == 0.7071068f)
{
return HandleDirection.NegativeX;
}
else if (rotation.x == -0.7071068f && rotation.y == 0.0f && rotation.z == 0.0f && rotation.w == 0.7071068f)
{
return HandleDirection.PositiveY;
}
else if (rotation.x == 0.7071068f && rotation.y == 0.0f && rotation.z == 0.0f && rotation.w == 0.7071068f)
{
return HandleDirection.NegativeY;
}
else if (rotation.x == 0.0f && rotation.y == 0.0f && rotation.z == 0.0f && rotation.w == 1.0f)
{
return HandleDirection.PositiveZ;
}
else if (rotation.x == 0.0f && rotation.y == 1.0f && rotation.z == 0.0f && rotation.w == 0.0f)
{
return HandleDirection.NegativeZ;
}
else
{
throw new ArgumentOutOfRangeException("rotation", "Must point down PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, or NegativeZ");
}
}
protected void DrawHandleMidpoint(int handleControlID, Vector3 handlePosition, Quaternion handleRotation, float handleSize, EventType eventType)
{
// Highlight the plane we are currently interacting with.
if (handleControlID == GUIUtility.hotControl)
{
HandleDirection handleDirection = HandleDirectionFromRotation(handleRotation);
DrawHandleDirectionPlane(handleDirection, size, center);
}
// Draw standard PrimitiveBoundsHandle mindpoint handle.
Handles.DotHandleCap(handleControlID, handlePosition, handleRotation, handleSize, eventType);
}
}
}

11
com.unity.render-pipelines.high-definition/HDRP/Editor/Material/Decal/DecalProjectorComponentHandle.cs.meta


fileFormatVersion: 2
guid: b29d5aac6308c3a4088143d90a1f1925
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存