using System.Linq;
using UnityEngine;
namespace UnityEditor.Rendering
{
/// Camera UI Shared Properties among SRP
public static partial class CameraUI
{
/// Camera Projection type
public enum ProjectionType
{
/// Perspective
Perspective,
/// Orthographic
Orthographic
}
/// Camera Projection matrix mode
public enum ProjectionMatrixMode
{
/// Explicit
Explicit,
/// Implicit
Implicit,
/// PhysicalPropertiesBased
PhysicalPropertiesBased,
}
static bool s_FovChanged;
static float s_FovLastValue;
static ProjectionType DrawerProjectionType(ISerializedCamera p, Editor owner)
{
var cam = p.baseCameraSettings;
ProjectionType projectionType;
Rect perspectiveRect = EditorGUILayout.GetControlRect();
EditorGUI.BeginProperty(perspectiveRect, Styles.projectionContent, cam.orthographic);
{
projectionType = cam.orthographic.boolValue ? ProjectionType.Orthographic : ProjectionType.Perspective;
EditorGUI.BeginChangeCheck();
projectionType = (ProjectionType)EditorGUI.EnumPopup(perspectiveRect, Styles.projectionContent, projectionType);
if (EditorGUI.EndChangeCheck())
cam.orthographic.boolValue = (projectionType == ProjectionType.Orthographic);
}
EditorGUI.EndProperty();
return projectionType;
}
static void DrawerOrthographicType(ISerializedCamera p, Editor owner)
{
EditorGUILayout.PropertyField(p.baseCameraSettings.orthographicSize, Styles.sizeContent);
Drawer_FieldClippingPlanes(p, owner);
}
static void DrawerPerspectiveType(ISerializedCamera p, Editor owner)
{
var cam = p.baseCameraSettings;
var targets = p.serializedObject.targetObjects;
var camera0 = targets[0] as Camera;
float fovCurrentValue;
bool multipleDifferentFovValues = false;
bool isPhysicalCamera = p.projectionMatrixMode.intValue == (int)ProjectionMatrixMode.PhysicalPropertiesBased;
var rect = EditorGUILayout.GetControlRect();
var guiContent = EditorGUI.BeginProperty(rect, Styles.FOVAxisModeContent, cam.fovAxisMode);
EditorGUI.showMixedValue = cam.fovAxisMode.hasMultipleDifferentValues;
CoreEditorUtils.DrawEnumPopup(rect, guiContent, cam.fovAxisMode);
bool fovAxisVertical = cam.fovAxisMode.intValue == 0;
if (!fovAxisVertical && !cam.fovAxisMode.hasMultipleDifferentValues)
{
float aspectRatio = isPhysicalCamera ? cam.sensorSize.vector2Value.x / cam.sensorSize.vector2Value.y : camera0.aspect;
// camera.aspect is not serialized so we have to check all targets.
fovCurrentValue = Camera.VerticalToHorizontalFieldOfView(camera0.fieldOfView, aspectRatio);
if (targets.Cast().Any(camera => camera.fieldOfView != fovCurrentValue))
multipleDifferentFovValues = true;
}
else
{
fovCurrentValue = cam.verticalFOV.floatValue;
multipleDifferentFovValues = cam.fovAxisMode.hasMultipleDifferentValues;
}
EditorGUI.showMixedValue = multipleDifferentFovValues;
var content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), Styles.fieldOfViewContent, cam.verticalFOV);
EditorGUI.BeginDisabledGroup(p.projectionMatrixMode.hasMultipleDifferentValues || isPhysicalCamera && (cam.sensorSize.hasMultipleDifferentValues || cam.fovAxisMode.hasMultipleDifferentValues));
EditorGUI.BeginChangeCheck();
s_FovLastValue = EditorGUILayout.Slider(content, fovCurrentValue, 0.00001f, 179f);
s_FovChanged = EditorGUI.EndChangeCheck();
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndHorizontal();
EditorGUI.EndProperty();
EditorGUI.showMixedValue = false;
Drawer_FieldClippingPlanes(p, owner);
content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), Styles.physicalCameraContent, p.projectionMatrixMode);
EditorGUI.showMixedValue = p.projectionMatrixMode.hasMultipleDifferentValues;
EditorGUI.BeginChangeCheck();
isPhysicalCamera = EditorGUILayout.Toggle(content, isPhysicalCamera);
if (EditorGUI.EndChangeCheck())
{
p.projectionMatrixMode.intValue = isPhysicalCamera ? (int)ProjectionMatrixMode.PhysicalPropertiesBased : (int)ProjectionMatrixMode.Implicit;
s_FovChanged = true;
}
EditorGUILayout.EndHorizontal();
EditorGUI.EndProperty();
EditorGUI.showMixedValue = false;
if (s_FovChanged)
{
if (!isPhysicalCamera || p.projectionMatrixMode.hasMultipleDifferentValues)
{
cam.verticalFOV.floatValue = fovAxisVertical
? s_FovLastValue
: Camera.HorizontalToVerticalFieldOfView(s_FovLastValue, camera0.aspect);
}
else if (!p.projectionMatrixMode.hasMultipleDifferentValues)
{
cam.verticalFOV.floatValue = fovAxisVertical
? s_FovLastValue
: Camera.HorizontalToVerticalFieldOfView(s_FovLastValue, camera0.aspect);
}
}
}
/// Draws projection related fields on the inspector
/// The serialized camera
/// The editor owner calling this drawer
public static void Drawer_Projection(ISerializedCamera p, Editor owner)
{
// Most of this is replicated from CameraEditor.DrawProjection as we don't want to draw
// it the same way it's done in non-SRP cameras. Unfortunately, because a lot of the
// code is internal, we have to copy/paste some stuff from the editor code :(
var projectionType = DrawerProjectionType(p, owner);
if (p.baseCameraSettings.orthographic.hasMultipleDifferentValues)
return;
using (new EditorGUI.IndentLevelScope())
{
if (projectionType == ProjectionType.Orthographic)
{
DrawerOrthographicType(p, owner);
}
else
{
DrawerPerspectiveType(p, owner);
}
}
}
static void Drawer_FieldClippingPlanes(ISerializedCamera p, Editor owner)
{
CoreEditorUtils.DrawMultipleFields(
Styles.clippingPlaneMultiFieldTitle,
new[] { p.baseCameraSettings.nearClippingPlane, p.baseCameraSettings.farClippingPlane },
new[] { Styles.nearPlaneContent, Styles.farPlaneContent });
}
}
}