Skip to content

Migrate Physical Camera to Core. #7146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
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