浏览代码

Merge pull request #1054 from Unity-Technologies/LW-UI

Added Cascade Split UI
/main
GitHub 7 年前
当前提交
0adb2b7b
共有 2 个文件被更改,包括 266 次插入26 次删除
  1. 259
      ScriptableRenderPipeline/Core/CoreRP/Editor/CoreEditorUtils.cs
  2. 33
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/LightweightAssetEditor.cs

259
ScriptableRenderPipeline/Core/CoreRP/Editor/CoreEditorUtils.cs


return value;
}
public static void DrawPopup(GUIContent label, SerializedProperty property, string[] options)
{
var mode = property.intValue;
EditorGUI.BeginChangeCheck();
if (mode >= options.Length)
Debug.LogError(string.Format("Invalid option while trying to set {0}", label.text));
mode = EditorGUILayout.Popup(label, mode, options);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(property.objectReferenceValue, property.name);
property.intValue = mode;
}
}
public static void DrawCascadeSplitGUI<T>(ref SerializedProperty shadowCascadeSplit)
{
float[] cascadePartitionSizes = null;
System.Type type = typeof(T);
if (type == typeof(float))
{
cascadePartitionSizes = new float[] { shadowCascadeSplit.floatValue };
}
else if (type == typeof(Vector3))
{
Vector3 splits = shadowCascadeSplit.vector3Value;
cascadePartitionSizes = new float[]
{
Mathf.Clamp(splits[0], 0.0f, 1.0f),
Mathf.Clamp(splits[1] - splits[0], 0.0f, 1.0f),
Mathf.Clamp(splits[2] - splits[1], 0.0f, 1.0f)
};
}
if (cascadePartitionSizes != null)
{
EditorGUI.BeginChangeCheck();
ShadowCascadeSplitGUI.HandleCascadeSliderGUI(ref cascadePartitionSizes);
if (EditorGUI.EndChangeCheck())
{
if (type == typeof(float))
shadowCascadeSplit.floatValue = cascadePartitionSizes[0];
else
{
Vector3 updatedValue = new Vector3();
updatedValue[0] = cascadePartitionSizes[0];
updatedValue[1] = updatedValue[0] + cascadePartitionSizes[1];
updatedValue[2] = updatedValue[1] + cascadePartitionSizes[2];
shadowCascadeSplit.vector3Value = updatedValue;
}
}
}
}
public static void RemoveMaterialKeywords(Material material)
{
material.shaderKeywords = null;

}
return data;
}
}
static class ShadowCascadeSplitGUI
{
private const int kSliderbarTopMargin = 2;
private const int kSliderbarHeight = 24;
private const int kSliderbarBottomMargin = 2;
private const int kPartitionHandleWidth = 2;
private const int kPartitionHandleExtraHitAreaWidth = 2;
private static readonly Color[] kCascadeColors =
{
new Color(0.5f, 0.5f, 0.6f, 1.0f),
new Color(0.5f, 0.6f, 0.5f, 1.0f),
new Color(0.6f, 0.6f, 0.5f, 1.0f),
new Color(0.6f, 0.5f, 0.5f, 1.0f),
};
// using a LODGroup skin
private static readonly GUIStyle s_CascadeSliderBG = "LODSliderRange";
private static readonly GUIStyle s_TextCenteredStyle = new GUIStyle(EditorStyles.whiteMiniLabel)
{
alignment = TextAnchor.MiddleCenter
};
// Internal struct to bundle drag information
private class DragCache
{
public int m_ActivePartition; // the cascade partition that we are currently dragging/resizing
public float m_NormalizedPartitionSize; // the normalized size of the partition (0.0f < size < 1.0f)
public Vector2 m_LastCachedMousePosition; // mouse position the last time we registered a drag or mouse down.
public DragCache(int activePartition, float normalizedPartitionSize, Vector2 currentMousePos)
{
m_ActivePartition = activePartition;
m_NormalizedPartitionSize = normalizedPartitionSize;
m_LastCachedMousePosition = currentMousePos;
}
};
private static DragCache s_DragCache;
private static readonly int s_CascadeSliderId = "s_CascadeSliderId".GetHashCode();
private static SceneView s_RestoreSceneView;
private static SceneView.CameraMode s_OldSceneDrawMode;
private static bool s_OldSceneLightingMode;
/**
* Static function to handle the GUI and User input related to the cascade slider.
*
* @param normalizedCascadePartition The array of partition sizes in the range 0.0f - 1.0f; expects ONE entry if cascades = 2, and THREE if cascades=4
* The last entry will be automatically determined by summing up the array, and doing 1.0f - sum
*/
public static void HandleCascadeSliderGUI(ref float[] normalizedCascadePartitions)
{
EditorGUILayout.LabelField("Cascade splits");
// get the inspector width since we need it while drawing the partition rects.
// Only way currently is to reserve the block in the layout using GetRect(), and then immediately drawing the empty box
// to match the call to GetRect.
// From this point on, we move to non-layout based code.
var sliderRect = GUILayoutUtility.GetRect(GUIContent.none
, s_CascadeSliderBG
, GUILayout.Height(kSliderbarTopMargin + kSliderbarHeight + kSliderbarBottomMargin)
, GUILayout.ExpandWidth(true));
GUI.Box(sliderRect, GUIContent.none);
float currentX = sliderRect.x;
float cascadeBoxStartY = sliderRect.y + kSliderbarTopMargin;
float cascadeSliderWidth = sliderRect.width - (normalizedCascadePartitions.Length * kPartitionHandleWidth);
Color origTextColor = GUI.color;
Color origBackgroundColor = GUI.backgroundColor;
int colorIndex = -1;
// setup the array locally with the last partition
float[] adjustedCascadePartitions = new float[normalizedCascadePartitions.Length + 1];
System.Array.Copy(normalizedCascadePartitions, adjustedCascadePartitions, normalizedCascadePartitions.Length);
adjustedCascadePartitions[adjustedCascadePartitions.Length - 1] = 1.0f - normalizedCascadePartitions.Sum();
// check for user input on any of the partition handles
// this mechanism gets the current event in the queue... make sure that the mouse is over our control before consuming the event
int sliderControlId = GUIUtility.GetControlID(s_CascadeSliderId, FocusType.Passive);
Event currentEvent = Event.current;
int hotPartitionHandleIndex = -1; // the index of any partition handle that we are hovering over or dragging
// draw each cascade partition
for (int i = 0; i < adjustedCascadePartitions.Length; ++i)
{
float currentPartition = adjustedCascadePartitions[i];
colorIndex = (colorIndex + 1) % kCascadeColors.Length;
GUI.backgroundColor = kCascadeColors[colorIndex];
float boxLength = (cascadeSliderWidth * currentPartition);
// main cascade box
Rect partitionRect = new Rect(currentX, cascadeBoxStartY, boxLength, kSliderbarHeight);
GUI.Box(partitionRect, GUIContent.none, s_CascadeSliderBG);
currentX += boxLength;
// cascade box percentage text
GUI.color = Color.white;
Rect textRect = partitionRect;
var cascadeText = string.Format("{0}\n{1:F1}%", i, currentPartition * 100.0f);
GUI.Label(textRect, cascadeText, s_TextCenteredStyle);
// no need to draw the partition handle for last box
if (i == adjustedCascadePartitions.Length - 1)
break;
// partition handle
GUI.backgroundColor = Color.black;
Rect handleRect = partitionRect;
handleRect.x = currentX;
handleRect.width = kPartitionHandleWidth;
GUI.Box(handleRect, GUIContent.none, s_CascadeSliderBG);
// we want a thin handle visually (since wide black bar looks bad), but a slightly larger
// hit area for easier manipulation
Rect handleHitRect = handleRect;
handleHitRect.xMin -= kPartitionHandleExtraHitAreaWidth;
handleHitRect.xMax += kPartitionHandleExtraHitAreaWidth;
if (handleHitRect.Contains(currentEvent.mousePosition))
hotPartitionHandleIndex = i;
// add regions to slider where the cursor changes to Resize-Horizontal
if (s_DragCache == null)
{
EditorGUIUtility.AddCursorRect(handleHitRect, MouseCursor.ResizeHorizontal, sliderControlId);
}
currentX += kPartitionHandleWidth;
}
GUI.color = origTextColor;
GUI.backgroundColor = origBackgroundColor;
EventType eventType = currentEvent.GetTypeForControl(sliderControlId);
switch (eventType)
{
case EventType.MouseDown:
if (hotPartitionHandleIndex >= 0)
{
s_DragCache = new DragCache(hotPartitionHandleIndex, normalizedCascadePartitions[hotPartitionHandleIndex], currentEvent.mousePosition);
if (GUIUtility.hotControl == 0)
GUIUtility.hotControl = sliderControlId;
currentEvent.Use();
// Switch active scene view into shadow cascades visualization mode, once we start
// tweaking cascade splits.
if (s_RestoreSceneView == null)
{
s_RestoreSceneView = SceneView.lastActiveSceneView;
if (s_RestoreSceneView != null)
{
s_OldSceneDrawMode = s_RestoreSceneView.cameraMode;
s_OldSceneLightingMode = s_RestoreSceneView.m_SceneLighting;
s_RestoreSceneView.cameraMode = SceneView.GetBuiltinCameraMode(DrawCameraMode.ShadowCascades);
}
}
}
break;
case EventType.MouseUp:
// mouseUp event anywhere should release the hotcontrol (if it belongs to us), drags (if any)
if (GUIUtility.hotControl == sliderControlId)
{
GUIUtility.hotControl = 0;
currentEvent.Use();
}
s_DragCache = null;
// Restore previous scene view drawing mode once we stop tweaking cascade splits.
if (s_RestoreSceneView != null)
{
s_RestoreSceneView.cameraMode = s_OldSceneDrawMode;
s_RestoreSceneView.m_SceneLighting = s_OldSceneLightingMode;
s_RestoreSceneView = null;
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl != sliderControlId)
break;
// convert the mouse movement to normalized cascade width. Make sure that we are safe to apply the delta before using it.
float delta = (currentEvent.mousePosition - s_DragCache.m_LastCachedMousePosition).x / cascadeSliderWidth;
bool isLeftPartitionHappy = ((adjustedCascadePartitions[s_DragCache.m_ActivePartition] + delta) > 0.0f);
bool isRightPartitionHappy = ((adjustedCascadePartitions[s_DragCache.m_ActivePartition + 1] - delta) > 0.0f);
if (isLeftPartitionHappy && isRightPartitionHappy)
{
s_DragCache.m_NormalizedPartitionSize += delta;
normalizedCascadePartitions[s_DragCache.m_ActivePartition] = s_DragCache.m_NormalizedPartitionSize;
if (s_DragCache.m_ActivePartition < normalizedCascadePartitions.Length - 1)
normalizedCascadePartitions[s_DragCache.m_ActivePartition + 1] -= delta;
GUI.changed = true;
}
s_DragCache.m_LastCachedMousePosition = currentEvent.mousePosition;
currentEvent.Use();
break;
}
}
}
}

33
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/LightweightAssetEditor.cs


using System.Linq;
using UnityEditor.Experimental.Rendering;
namespace UnityEngine.Experimental.Rendering.LightweightPipeline
{

EditorGUILayout.PropertyField(prop, content);
}
protected void DoPopup(GUIContent label, SerializedProperty property, string[] options)
{
var mode = property.intValue;
EditorGUI.BeginChangeCheck();
if (mode >= options.Length)
Debug.LogError(string.Format("Invalid option while trying to set {0}", label.text));
mode = EditorGUILayout.Popup(label, mode, options);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(property.objectReferenceValue, property.name);
property.intValue = mode;
}
}
public override void OnInspectorGUI()
{
serializedObject.Update();

EditorGUILayout.LabelField(Styles.shadowLabel, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
DoPopup(Styles.shadowType, m_ShadowTypeProp, Styles.shadowTypeOptions);
CoreEditorUtils.DrawPopup(Styles.shadowType, m_ShadowTypeProp, Styles.shadowTypeOptions);
EditorGUILayout.PropertyField(m_ShadowDistanceProp, Styles.shadowDistante);
DoPopup(Styles.shadowCascades, m_ShadowCascadesProp, Styles.shadowCascadeOptions);
m_ShadowDistanceProp.floatValue = Mathf.Max(0.0f, EditorGUILayout.FloatField(Styles.shadowDistante, m_ShadowDistanceProp.floatValue));
CoreEditorUtils.DrawPopup(Styles.shadowCascades, m_ShadowCascadesProp, Styles.shadowCascadeOptions);
{
EditorGUILayout.PropertyField(m_ShadowCascade4SplitProp, Styles.shadowCascadeSplit);
}
CoreEditorUtils.DrawCascadeSplitGUI<Vector3>(ref m_ShadowCascade4SplitProp);
{
EditorGUILayout.PropertyField(m_ShadowCascade2SplitProp, Styles.shadowCascadeSplit);
}
CoreEditorUtils.DrawCascadeSplitGUI<float>(ref m_ShadowCascade2SplitProp);
EditorGUI.indentLevel--;

正在加载...
取消
保存