Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

namespace UnityEditor.Rendering
{

using CED = CoreEditorDrawer<ISerializedCamera>;

/// <summary> Camera UI Shared Properties among SRP</summary>
public static partial class CameraUI
{
Expand Down Expand Up @@ -119,6 +122,169 @@ public static void Drawer_PhysicalCamera_Lens_Shift(ISerializedCamera p, Editor
{
EditorGUILayout.PropertyField(p.baseCameraSettings.lensShift, Styles.shift);
}


/// <summary>Draws Focus Distance related fields on the inspector</summary>
/// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param>
/// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param>
public static void Drawer_PhysicalCamera_FocusDistance(ISerializedCamera p, Editor owner)
{
var cam = p.baseCameraSettings;
EditorGUILayout.PropertyField(cam.focusDistance, Styles.focusDistance);
}

/// <summary>Draws ISO related fields on the inspector</summary>
/// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param>
/// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param>
public static void Drawer_PhysicalCamera_CameraBody_ISO(ISerializedCamera p, Editor owner)
{
var cam = p.baseCameraSettings;
EditorGUILayout.PropertyField(cam.iso, Styles.ISO);
}

static EditorPrefBoolFlags<ShutterSpeedUnit> m_ShutterSpeedState = new EditorPrefBoolFlags<ShutterSpeedUnit>($"HDRP:{nameof(CameraUI)}:ShutterSpeedState");

enum ShutterSpeedUnit
{
[InspectorName("Second")]
Second,
[InspectorName("1 \u2215 Second")] // Don't use a slash here else Unity will auto-create a submenu...
OneOverSecond
}

/// <summary>Draws Shutter Speed related fields on the inspector</summary>
/// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param>
/// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param>
public static void Drawer_PhysicalCamera_CameraBody_ShutterSpeed(ISerializedCamera p, Editor owner)
{
var cam = p.baseCameraSettings;

// Custom layout for shutter speed
const int k_UnitMenuWidth = 90;
const int k_OffsetPerIndent = 15;
const int k_LabelFieldSeparator = 2;
const int k_Offset = 1;
int oldIndentLevel = EditorGUI.indentLevel;

// Don't take into account the indentLevel when rendering the units field
EditorGUI.indentLevel = 0;

var lineRect = EditorGUILayout.GetControlRect();
var fieldRect = new Rect(k_OffsetPerIndent + k_LabelFieldSeparator + k_Offset, lineRect.y, lineRect.width - k_UnitMenuWidth, lineRect.height);
var unitMenu = new Rect(fieldRect.xMax + k_LabelFieldSeparator, lineRect.y, k_UnitMenuWidth - k_LabelFieldSeparator, lineRect.height);

// We cannot had the shutterSpeedState as this is not a serialized property but a global edition mode.
// This imply that it will never go bold nor can be reverted in prefab overrides

m_ShutterSpeedState.value = (ShutterSpeedUnit)EditorGUI.EnumPopup(unitMenu, m_ShutterSpeedState.value);
// Reset the indent level
EditorGUI.indentLevel = oldIndentLevel;

EditorGUI.BeginProperty(fieldRect, Styles.shutterSpeed, cam.shutterSpeed);
{
// if we we use (1 / second) units, then change the value for the display and then revert it back
if (m_ShutterSpeedState.value == ShutterSpeedUnit.OneOverSecond && cam.shutterSpeed.floatValue > 0)
cam.shutterSpeed.floatValue = 1.0f / cam.shutterSpeed.floatValue;
EditorGUI.PropertyField(fieldRect, cam.shutterSpeed, Styles.shutterSpeed);
if (m_ShutterSpeedState.value == ShutterSpeedUnit.OneOverSecond && cam.shutterSpeed.floatValue > 0)
cam.shutterSpeed.floatValue = 1.0f / cam.shutterSpeed.floatValue;
}
EditorGUI.EndProperty();
}

/// <summary>Draws Lens Aperture related fields on the inspector</summary>
/// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param>
/// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param>
public static void Drawer_PhysicalCamera_Lens_Aperture(ISerializedCamera p, Editor owner)
{
var cam = p.baseCameraSettings;

// Custom layout for aperture
var rect = EditorGUILayout.BeginHorizontal();
{
// Magic values/offsets to get the UI look consistent
const float textRectSize = 80;
const float textRectPaddingRight = 62;
const float unitRectPaddingRight = 97;
const float sliderPaddingLeft = 2;
const float sliderPaddingRight = 77;

var labelRect = rect;
labelRect.width = EditorGUIUtility.labelWidth;
labelRect.height = EditorGUIUtility.singleLineHeight;
EditorGUI.LabelField(labelRect, Styles.aperture);

GUI.SetNextControlName("ApertureSlider");
var sliderRect = rect;
sliderRect.x += labelRect.width + sliderPaddingLeft;
sliderRect.width = rect.width - labelRect.width - sliderPaddingRight;
float newVal = GUI.HorizontalSlider(sliderRect, cam.aperture.floatValue, Camera.kMinAperture, Camera.kMaxAperture);

// keep only 2 digits of precision, like the otehr editor fields
newVal = Mathf.Floor(100 * newVal) / 100.0f;

if (cam.aperture.floatValue != newVal)
{
cam.aperture.floatValue = newVal;
// Note: We need to move the focus when the slider changes, otherwise the textField will not update
GUI.FocusControl("ApertureSlider");
}

var unitRect = rect;
unitRect.x += rect.width - unitRectPaddingRight;
unitRect.width = textRectSize;
unitRect.height = EditorGUIUtility.singleLineHeight;
EditorGUI.LabelField(unitRect, "f /", EditorStyles.label);

var textRect = rect;
textRect.x = rect.width - textRectPaddingRight;
textRect.width = textRectSize;
textRect.height = EditorGUIUtility.singleLineHeight;
string newAperture = EditorGUI.TextField(textRect, cam.aperture.floatValue.ToString());
if (float.TryParse(newAperture, out float parsedValue))
cam.aperture.floatValue = Mathf.Clamp(parsedValue, Camera.kMinAperture, Camera.kMaxAperture);
}

EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(EditorGUIUtility.singleLineHeight);
}

/// <summary>Draws Aperture Shape related fields on the inspector</summary>
/// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param>
/// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param>
public static void Drawer_PhysicalCamera_ApertureShape(ISerializedCamera p, Editor owner)
{
var cam = p.baseCameraSettings;

EditorGUILayout.PropertyField(cam.bladeCount, Styles.bladeCount);

using (var horizontal = new EditorGUILayout.HorizontalScope())
using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, Styles.curvature, cam.curvature))
{
var v = cam.curvature.vector2Value;

// The layout system breaks alignment when mixing inspector fields with custom layout'd
// fields as soon as a scrollbar is needed in the inspector, so we'll do the layout
// manually instead
const int kFloatFieldWidth = 50;
const int kSeparatorWidth = 5;
float indentOffset = EditorGUI.indentLevel * 15f;
var lineRect = EditorGUILayout.GetControlRect();
var labelRect = new Rect(lineRect.x, lineRect.y, EditorGUIUtility.labelWidth - indentOffset, lineRect.height);
var floatFieldLeft = new Rect(labelRect.xMax, lineRect.y, kFloatFieldWidth + indentOffset, lineRect.height);
var sliderRect = new Rect(floatFieldLeft.xMax + kSeparatorWidth - indentOffset, lineRect.y, lineRect.width - labelRect.width - kFloatFieldWidth * 2 - kSeparatorWidth * 2, lineRect.height);
var floatFieldRight = new Rect(sliderRect.xMax + kSeparatorWidth - indentOffset, lineRect.y, kFloatFieldWidth + indentOffset, lineRect.height);

EditorGUI.PrefixLabel(labelRect, propertyScope.content);
v.x = EditorGUI.FloatField(floatFieldLeft, v.x);
EditorGUI.MinMaxSlider(sliderRect, ref v.x, ref v.y, Camera.kMinAperture, Camera.kMaxAperture);
v.y = EditorGUI.FloatField(floatFieldRight, v.y);
cam.curvature.vector2Value = v;
}

EditorGUILayout.PropertyField(cam.barrelClipping, Styles.barrelClipping);
EditorGUILayout.PropertyField(cam.anamorphism, Styles.anamorphism);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,61 @@ public static class Styles
public static readonly GUIContent lens = EditorGUIUtility.TrTextContent("Lens");

/// <summary>
/// Focal Length Content
/// Focal Length content
/// </summary>
public static readonly GUIContent focalLength = EditorGUIUtility.TrTextContent("Focal Length", "The simulated distance between the lens and the sensor of the physical camera. Larger values give a narrower field of view.");

/// <summary>
/// Shift content
/// </summary>
public static readonly GUIContent shift = EditorGUIUtility.TrTextContent("Shift", "Offset from the camera sensor. Use these properties to simulate a shift lens. Measured as a multiple of the sensor size.");

/// <summary>
/// ISO content
/// </summary>
public static readonly GUIContent ISO = EditorGUIUtility.TrTextContent("ISO", "Sets the light sensitivity of the Camera sensor. This property affects Exposure if you set its Mode to Use Physical Camera.");

/// <summary>
/// Shutter Speed content
/// </summary>
public static readonly GUIContent shutterSpeed = EditorGUIUtility.TrTextContent("Shutter Speed", "The amount of time the Camera sensor is capturing light.");

/// <summary>
/// Aperture content
/// </summary>
public static readonly GUIContent aperture = EditorGUIUtility.TrTextContent("Aperture", "The f-stop (f-number) of the lens. Lower values give a wider lens aperture.");

/// <summary>
/// Focus Distance content
/// </summary>
public static readonly GUIContent focusDistance = EditorGUIUtility.TrTextContent("Focus Distance", "The distance from the camera where objects appear sharp when Depth Of Field is enabled.");

// Aperture Shape

/// <summary>
/// Aperture Shape content
/// </summary>
public static readonly GUIContent apertureShape = EditorGUIUtility.TrTextContent("Aperture Shape", "Common sensor sizes. Choose an item to set Sensor Size, or edit Sensor Size for your custom settings.");

/// <summary>
/// Blade Count content
/// </summary>
public static readonly GUIContent bladeCount = EditorGUIUtility.TrTextContent("Blade Count", "The number of blades in the lens aperture. Higher values give a rounder aperture shape.");

/// <summary>
/// Curvature content
/// </summary>
public static readonly GUIContent curvature = EditorGUIUtility.TrTextContent("Curvature", "Controls the curvature of the lens aperture blades. The minimum value results in fully-curved, perfectly-circular bokeh, and the maximum value results in visible aperture blades.");

/// <summary>
/// Barrel Clipping content
/// </summary>
public static readonly GUIContent barrelClipping = EditorGUIUtility.TrTextContent("Barrel Clipping", "Controls the self-occlusion of the lens, creating a cat's eye effect.");

/// <summary>
/// Anamorphism content
/// </summary>
public static readonly GUIContent anamorphism = EditorGUIUtility.TrTextContent("Anamorphism", "Use the slider to stretch the sensor to simulate an anamorphic look.");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;

Expand Down
Loading