Rasagar/Library/PackageCache/com.unity.render-pipelines.high-definition/Editor/Compositor/CompositionLayerUI.Drawers.cs
2024-08-26 23:07:20 +03:00

326 lines
19 KiB
C#

using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering.HighDefinition.Compositor;
using UnityEngine.Experimental.Rendering;
using UnityEditorInternal;
namespace UnityEditor.Rendering.HighDefinition.Compositor
{
internal class CompositionLayerUI
{
static partial class Styles
{
// main layer
static public readonly GUIContent k_Resolution = EditorGUIUtility.TrTextContent("Resolution", "Specifies the resolution of this layer's render target. Lower resolution increases the performance at the expense of visual quality.");
static public readonly GUIContent k_BufferFormat = EditorGUIUtility.TrTextContent("Format", "Specifies the color buffer format of this layer. ");
static public readonly GUIContent k_OutputRenderer = EditorGUIUtility.TrTextContent("Output Renderer", "Redirects the output of this layer to the surface which is drawn by the selected mesh renderer. ");
static public readonly GUIContent k_AOVs = EditorGUIUtility.TrTextContent("AOVs", "Specifies the Arbitrary Output Variable (AOV) that will be drawn on this layer. This option affects all cameras that are stacked on this layer.");
// Sub layer
static public readonly GUIContent k_NameContent = EditorGUIUtility.TrTextContent("Layer Name", "Specifies the name of this layer.");
static public readonly GUIContent k_Camera = EditorGUIUtility.TrTextContent("Source Camera", "Specifies the camera of the scene that will provide the content for this sublayer.");
static public readonly GUIContent k_Image = EditorGUIUtility.TrTextContent("Source Image", "Specifies the image that will provide the content for this sublayer.");
static public readonly GUIContent k_Video = EditorGUIUtility.TrTextContent("Source Video", "Specifies the video that will provide the content for this sublayer.");
static public readonly GUIContent k_ClearDepth = EditorGUIUtility.TrTextContent("Clear Depth", "If enabled, the depth buffer will be cleared before rendering this layer. Not clearing the depth can be useful when stacking sublayers. The first sublayer of a stack always clears the depth.");
static public readonly GUIContent k_ClearAlpha = EditorGUIUtility.TrTextContent("Clear Alpha", "If enabled, the alpha channel will be cleared before rendering this layer. If enabled, post processing will affect only the objects of this layer");
static public readonly GUIContent k_ClearMode = EditorGUIUtility.TrTextContent("Clear Color", "To override the clear mode of this layer, activate the option by clicking on the check-box and then select the desired value. This can be changed only on the first sub layer of a stack (stacked sublayers do not clear the color).");
static public readonly GUIContent k_AAMode = EditorGUIUtility.TrTextContent("Post Anti-aliasing", "To override the postprocess Anti-aliasing mode, activate the option by clicking on the check-box and then select the desired value.");
static public readonly GUIContent k_CullingMask = EditorGUIUtility.TrTextContent("Culling Mask", "To override the culling mask, activate the option by clicking on the check-box and then select the desired value.");
static public readonly GUIContent k_VolumeMask = EditorGUIUtility.TrTextContent("Volume Mask", "To override the volume mask, activate the option by clicking on the check-box and then select the desired value.");
static public readonly GUIContent k_AlphaRange = EditorGUIUtility.TrTextContent("Alpha Range", "The range of alpha values used when transitioning from post-processed to plain image regions. A smaller range will result in a steeper transition.");
static public readonly string k_AlphaInfoPost = "The use of AOVs properties in a player requires to enable the Runtime AOV API support in the HDRP quality settings.";
static public readonly string k_ShaderCompilationWarning = "The Unity Editor is compiling the AOV shaders for the first time. The output might not be correct until the compilation is over.";
static public float infoBoxIconWidth = 100;
}
static bool s_AsyncCompileState = false;
static bool s_HasStartedCompiling = false;
public static void DrawItemInList(Rect rect, SerializedCompositionLayer serialized, RenderTexture thumbnail, float aspectRatio, bool isAlphaEnbaled)
{
bool isCameraStack = serialized.outTarget.intValue == (int)CompositorLayer.OutputTarget.CameraStack;
// Compute the desired indentation
{
const float listBorder = 2.0f;
rect.x = isCameraStack ? rect.x + CompositorStyle.k_ListItemStackPading + listBorder : rect.x + listBorder;
rect.width = isCameraStack ? rect.width - CompositorStyle.k_ListItemStackPading - listBorder : rect.width - listBorder;
rect.y += CompositorStyle.k_ListItemPading;
rect.height = EditorGUIUtility.singleLineHeight;
}
if (thumbnail)
{
Rect newRect = rect;
newRect.width = EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(newRect, serialized.show, GUIContent.none);
rect.x += CompositorStyle.k_CheckboxSpacing;
Rect previewRect = rect;
previewRect.width = CompositorStyle.k_ThumbnailSize * aspectRatio;
previewRect.height = CompositorStyle.k_ThumbnailSize;
EditorGUI.DrawPreviewTexture(previewRect, thumbnail);
previewRect.x += previewRect.width + CompositorStyle.k_ThumbnailDivider;
rect.x += previewRect.width + CompositorStyle.k_ThumbnailSpacing;
rect.width -= previewRect.width + CompositorStyle.k_ThumbnailSpacing;
if (isAlphaEnbaled
&& (thumbnail.graphicsFormat == GraphicsFormat.R16G16B16A16_SFloat
|| thumbnail.graphicsFormat == GraphicsFormat.R32G32B32A32_SFloat
|| thumbnail.graphicsFormat == GraphicsFormat.R16G16B16A16_UNorm))
{
EditorGUI.DrawTextureAlpha(previewRect, thumbnail);
rect.x += previewRect.width + CompositorStyle.k_ThumbnailSpacing;
rect.width -= previewRect.width + CompositorStyle.k_ThumbnailSpacing;
}
rect.y += CompositorStyle.k_LabelVerticalOffset;
EditorGUI.LabelField(rect, serialized.layerName.stringValue);
}
else
{
Rect newRect = rect;
newRect.width = EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(newRect, serialized.show, GUIContent.none);
newRect.x += CompositorStyle.k_CheckboxSpacing;
if (isCameraStack)
{
Rect iconRect = newRect;
iconRect.width = CompositorStyle.k_IconSize;
iconRect.height = CompositorStyle.k_IconSize;
iconRect.y -= CompositorStyle.k_IconVerticalOffset;
switch (serialized.inputLayerType.enumValueIndex)
{
case (int)CompositorLayer.LayerType.Camera:
GUI.DrawTexture(iconRect, EditorGUIUtility.ObjectContent(null, typeof(Camera)).image);
break;
case (int)CompositorLayer.LayerType.Video:
GUI.DrawTexture(iconRect, EditorGUIUtility.ObjectContent(null, typeof(UnityEngine.Video.VideoClip)).image);
break;
case (int)CompositorLayer.LayerType.Image:
GUI.DrawTexture(iconRect, EditorGUIUtility.ObjectContent(null, typeof(Texture)).image);
break;
default:
// This will happen if someone adds a new layer type and does not update this switch statement
Debug.Log("Unknown layer type: Please add code here to draw this type of layer.");
break;
}
newRect.x += CompositorStyle.k_IconSize + CompositorStyle.k_IconSpacing;
}
newRect.width = rect.width - newRect.x;
EditorGUI.LabelField(newRect, serialized.layerName.stringValue);
}
}
public static void DrawOutputLayerProperties(Rect rect, SerializedCompositionLayer serializedProperties, System.Action resetRenderTargetCallback)
{
rect.y += CompositorStyle.k_ListItemPading;
rect.height = CompositorStyle.k_SingleLineHeight;
EditorGUI.PropertyField(rect, serializedProperties.colorFormat, Styles.k_BufferFormat);
rect.y += CompositorStyle.k_Spacing;
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField(rect, serializedProperties.resolutionScale, Styles.k_Resolution);
if (EditorGUI.EndChangeCheck())
{
// if the resolution changes, reset the RTs
resetRenderTargetCallback();
}
rect.y += CompositorStyle.k_Spacing;
EditorGUI.PropertyField(rect, serializedProperties.outputRenderer, Styles.k_OutputRenderer);
rect.y += CompositorStyle.k_Spacing;
EditorGUI.PropertyField(rect, serializedProperties.aovBitmask, Styles.k_AOVs);
rect.y += CompositorStyle.k_Spacing;
if (serializedProperties.aovBitmask.intValue != 0)
{
// [case 1288744] Enable async compile for the debug shaders to avoid editor freeze when the user selects AOVs
s_AsyncCompileState = ShaderUtil.allowAsyncCompilation;
ShaderUtil.allowAsyncCompilation = true;
// Note: We cannot check immediately if "anythingCompiling", this has to be delayed for the next frame
if (s_HasStartedCompiling && ShaderUtil.anythingCompiling)
{
// Display a message while we are compiling the shaders
Rect infoRect = rect;
// Compute the height of the infobox based on the width of the window and the amount of text
GUIStyle.none.CalcMinMaxWidth(new GUIContent(Styles.k_ShaderCompilationWarning), out float minWidth, out float maxWidth);
float lines = Mathf.Max(2, Mathf.CeilToInt(maxWidth / (rect.width - Styles.infoBoxIconWidth)));
infoRect.height = lines * CompositorStyle.k_Spacing;
EditorGUI.HelpBox(infoRect, Styles.k_ShaderCompilationWarning, MessageType.Warning);
rect.y += infoRect.height + EditorGUIUtility.standardVerticalSpacing;
}
else
{
// If the shaders have finished compiling, set the async compilation to the previous state
if (s_HasStartedCompiling)
{
ShaderUtil.allowAsyncCompilation = s_AsyncCompileState;
s_HasStartedCompiling = false;
}
else
{
s_HasStartedCompiling = true;
}
}
}
else
{
// Check if the user switched off the AOV before the shaders were compiled
if (s_HasStartedCompiling)
{
ShaderUtil.allowAsyncCompilation = s_AsyncCompileState;
s_HasStartedCompiling = false;
}
}
HDRenderPipelineAsset hdrp = HDRenderPipeline.currentAsset;
if (serializedProperties.aovBitmask.intValue != 0 && hdrp && !hdrp.currentPlatformRenderPipelineSettings.supportRuntimeAOVAPI)
{
Rect infoRect = rect;
// Compute the height of the infobox based on the width of the window and the amount of text
GUIStyle.none.CalcMinMaxWidth(new GUIContent(Styles.k_AlphaInfoPost), out float minWidth, out float maxWidth);
float lines = Mathf.Max(2, Mathf.CeilToInt(maxWidth / (rect.width - Styles.infoBoxIconWidth)));
infoRect.height = lines * CompositorStyle.k_Spacing;
EditorGUI.HelpBox(infoRect, Styles.k_AlphaInfoPost, MessageType.Info);
rect.y += infoRect.height + EditorGUIUtility.standardVerticalSpacing;
}
}
public static void DrawStackedLayerProperties(Rect rect, SerializedCompositionLayer serializedProperties, ReorderableList filterList)
{
rect.y += CompositorStyle.k_ListItemPading;
rect.height = CompositorStyle.k_SingleLineHeight;
EditorGUI.PropertyField(rect, serializedProperties.layerName, Styles.k_NameContent);
rect.y += CompositorStyle.k_Spacing;
switch (serializedProperties.inputLayerType.enumValueIndex)
{
case (int)CompositorLayer.LayerType.Camera:
EditorGUI.PropertyField(rect, serializedProperties.inputCamera, Styles.k_Camera);
break;
case (int)CompositorLayer.LayerType.Video:
EditorGUI.PropertyField(rect, serializedProperties.inputVideo, Styles.k_Video);
break;
case (int)CompositorLayer.LayerType.Image:
EditorGUI.PropertyField(rect, serializedProperties.inputTexture, Styles.k_Image);
rect.y += CompositorStyle.k_Spacing;
EditorGUI.PropertyField(rect, serializedProperties.fitType);
break;
default:
// This will happen if someone adds a new layer type and does not update this switch statement
Debug.Log("Unknown layer type: Please add code here to handle this type of layer.");
break;
}
rect.y += 1.5f * CompositorStyle.k_Spacing;
using (new EditorGUI.DisabledScope(serializedProperties.positionInStack.intValue == 0))
{
EditorGUI.PropertyField(rect, serializedProperties.clearDepth, Styles.k_ClearDepth);
rect.y += CompositorStyle.k_Spacing;
}
EditorGUI.PropertyField(rect, serializedProperties.clearAlpha, Styles.k_ClearAlpha);
rect.y += 1.0f * CompositorStyle.k_Spacing;
// Draw a min/max slider for tha alpha range
{
const float spacing = 5;
var labelRect = new Rect(rect.x, rect.y, EditorGUIUtility.labelWidth, rect.height);
EditorGUI.PrefixLabel(labelRect, Styles.k_AlphaRange);
var minLabelRect = rect;
minLabelRect.x += EditorGUIUtility.labelWidth;
minLabelRect.width = EditorGUIUtility.fieldWidth / 2;
serializedProperties.alphaMin.floatValue = EditorGUI.FloatField(minLabelRect, serializedProperties.alphaMin.floatValue);
GUI.SetNextControlName("AlphaMinMaxSlider");
var sliderRect = rect;
sliderRect.x += EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth / 2 + spacing;
sliderRect.width -= (EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth + 2 * spacing);
float minVal = serializedProperties.alphaMin.floatValue;
float maxVal = serializedProperties.alphaMax.floatValue;
EditorGUI.MinMaxSlider(sliderRect, ref minVal, ref maxVal, 0, 1);
if (serializedProperties.alphaMin.floatValue != minVal || serializedProperties.alphaMax.floatValue != maxVal)
{
// Note: We need to move the focus when the slider changes, otherwise the textField will not update
GUI.FocusControl("AlphaMinMaxSlider");
serializedProperties.alphaMin.floatValue = minVal;
serializedProperties.alphaMax.floatValue = maxVal;
}
var maxLabelRect = rect;
maxLabelRect.x = sliderRect.x + sliderRect.width + spacing;
maxLabelRect.width = EditorGUIUtility.fieldWidth / 2;
serializedProperties.alphaMax.floatValue = EditorGUI.FloatField(maxLabelRect, serializedProperties.alphaMax.floatValue);
// sanity checks
if (serializedProperties.alphaMax.floatValue < serializedProperties.alphaMin.floatValue)
{
serializedProperties.alphaMax.floatValue = serializedProperties.alphaMin.floatValue;
}
if (serializedProperties.alphaMax.floatValue > 1)
{
serializedProperties.alphaMax.floatValue = 1;
}
if (serializedProperties.alphaMin.floatValue > serializedProperties.alphaMax.floatValue)
{
serializedProperties.alphaMin.floatValue = serializedProperties.alphaMax.floatValue;
}
if (serializedProperties.alphaMin.floatValue < 0)
{
serializedProperties.alphaMin.floatValue = 0;
}
}
rect.y += 1.5f * CompositorStyle.k_Spacing;
// The clear mode should be visible / configurable only for the first layer in the stack. For the other layers we set a camera-stacking specific clear-mode .
using (new EditorGUI.DisabledScope(serializedProperties.positionInStack.intValue != 0))
{
DrawPropertyHelper(rect, Styles.k_ClearMode, serializedProperties.overrideClearMode, serializedProperties.clearMode);
rect.y += CompositorStyle.k_Spacing;
}
DrawPropertyHelper(rect, Styles.k_AAMode, serializedProperties.overrideAA, serializedProperties.aaMode);
rect.y += CompositorStyle.k_Spacing;
DrawPropertyHelper(rect, Styles.k_CullingMask, serializedProperties.overrideCulling, serializedProperties.cullingMaskProperty);
rect.y += CompositorStyle.k_Spacing;
DrawPropertyHelper(rect, Styles.k_VolumeMask, serializedProperties.overrideVolume, serializedProperties.volumeMask);
rect.y += CompositorStyle.k_Spacing;
Rect filterRect = rect;
filterRect.y += 0.5f * CompositorStyle.k_Spacing;
filterList.DoList(filterRect);
}
static void DrawPropertyHelper(Rect rect, GUIContent label, SerializedProperty checkBox, SerializedProperty serializedProperty)
{
Rect rectCopy = rect;
EditorGUI.PropertyField(rectCopy, checkBox, GUIContent.none);
rectCopy.x += EditorGUIUtility.singleLineHeight;
rectCopy.width = EditorGUIUtility.labelWidth - EditorGUIUtility.singleLineHeight;
EditorGUI.LabelField(rectCopy, label);
using (new EditorGUI.DisabledScope(!checkBox.boolValue))
{
float pad = EditorGUIUtility.labelWidth;
rect.x += pad;
rect.width -= rect.x;
EditorGUI.PropertyField(rect, serializedProperty, GUIContent.none);
}
}
}
}