A game about forced loneliness, made by TACStudios
1using System.Linq;
2using UnityEngine;
3
4namespace UnityEditor.Rendering
5{
6 /// <summary> Camera UI Shared Properties among SRP</summary>
7 public static partial class CameraUI
8 {
9 /// <summary>Camera Projection type</summary>
10 public enum ProjectionType
11 {
12 /// <summary> Perspective</summary>
13 Perspective,
14 /// <summary> Orthographic</summary>
15 Orthographic
16 }
17
18 /// <summary>Camera Projection matrix mode</summary>
19 public enum ProjectionMatrixMode
20 {
21 /// <summary> Explicit</summary>
22 Explicit,
23 /// <summary> Implicit</summary>
24 Implicit,
25 /// <summary> PhysicalPropertiesBased</summary>
26 PhysicalPropertiesBased,
27 }
28
29 static bool s_FovChanged;
30 static float s_FovLastValue;
31
32 static ProjectionType DrawerProjectionType(ISerializedCamera p, Editor owner)
33 {
34 var cam = p.baseCameraSettings;
35
36 ProjectionType projectionType;
37
38 Rect perspectiveRect = EditorGUILayout.GetControlRect();
39 EditorGUI.BeginProperty(perspectiveRect, Styles.projectionContent, cam.orthographic);
40 {
41 projectionType = cam.orthographic.boolValue ? ProjectionType.Orthographic : ProjectionType.Perspective;
42
43 EditorGUI.BeginChangeCheck();
44 projectionType = (ProjectionType)EditorGUI.EnumPopup(perspectiveRect, Styles.projectionContent, projectionType);
45 if (EditorGUI.EndChangeCheck())
46 cam.orthographic.boolValue = (projectionType == ProjectionType.Orthographic);
47 }
48 EditorGUI.EndProperty();
49
50 return projectionType;
51 }
52
53 static void DrawerOrthographicType(ISerializedCamera p, Editor owner)
54 {
55 EditorGUILayout.PropertyField(p.baseCameraSettings.orthographicSize, Styles.sizeContent);
56 Drawer_FieldClippingPlanes(p, owner);
57 }
58
59 static void DrawerPerspectiveType(ISerializedCamera p, Editor owner)
60 {
61 var cam = p.baseCameraSettings;
62
63 var targets = p.serializedObject.targetObjects;
64 var camera0 = targets[0] as Camera;
65
66 float fovCurrentValue;
67 bool multipleDifferentFovValues = false;
68 bool isPhysicalCamera = p.projectionMatrixMode.intValue == (int)ProjectionMatrixMode.PhysicalPropertiesBased;
69
70 var rect = EditorGUILayout.GetControlRect();
71
72 var guiContent = EditorGUI.BeginProperty(rect, Styles.FOVAxisModeContent, cam.fovAxisMode);
73 EditorGUI.showMixedValue = cam.fovAxisMode.hasMultipleDifferentValues;
74
75 CoreEditorUtils.DrawEnumPopup<Camera.FieldOfViewAxis>(rect, guiContent, cam.fovAxisMode);
76
77 bool fovAxisVertical = cam.fovAxisMode.intValue == 0;
78
79 if (!fovAxisVertical && !cam.fovAxisMode.hasMultipleDifferentValues)
80 {
81 float aspectRatio = isPhysicalCamera ? cam.sensorSize.vector2Value.x / cam.sensorSize.vector2Value.y : camera0.aspect;
82 // camera.aspect is not serialized so we have to check all targets.
83 fovCurrentValue = Camera.VerticalToHorizontalFieldOfView(camera0.fieldOfView, aspectRatio);
84 if (targets.Cast<Camera>().Any(camera => camera.fieldOfView != fovCurrentValue))
85 multipleDifferentFovValues = true;
86 }
87 else
88 {
89 fovCurrentValue = cam.verticalFOV.floatValue;
90 multipleDifferentFovValues = cam.fovAxisMode.hasMultipleDifferentValues;
91 }
92
93 EditorGUI.showMixedValue = multipleDifferentFovValues;
94 var content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), Styles.fieldOfViewContent, cam.verticalFOV);
95 EditorGUI.BeginDisabledGroup(p.projectionMatrixMode.hasMultipleDifferentValues || isPhysicalCamera && (cam.sensorSize.hasMultipleDifferentValues || cam.fovAxisMode.hasMultipleDifferentValues));
96 EditorGUI.BeginChangeCheck();
97 s_FovLastValue = EditorGUILayout.Slider(content, fovCurrentValue, 0.00001f, 179f);
98 s_FovChanged = EditorGUI.EndChangeCheck();
99 EditorGUI.EndDisabledGroup();
100 EditorGUILayout.EndHorizontal();
101 EditorGUI.EndProperty();
102 EditorGUI.showMixedValue = false;
103
104 Drawer_FieldClippingPlanes(p, owner);
105
106 content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), Styles.physicalCameraContent, p.projectionMatrixMode);
107 EditorGUI.showMixedValue = p.projectionMatrixMode.hasMultipleDifferentValues;
108
109 EditorGUI.BeginChangeCheck();
110 isPhysicalCamera = EditorGUILayout.Toggle(content, isPhysicalCamera);
111 if (EditorGUI.EndChangeCheck())
112 {
113 p.projectionMatrixMode.intValue = isPhysicalCamera ? (int)ProjectionMatrixMode.PhysicalPropertiesBased : (int)ProjectionMatrixMode.Implicit;
114 s_FovChanged = true;
115 }
116 EditorGUILayout.EndHorizontal();
117 EditorGUI.EndProperty();
118
119 EditorGUI.showMixedValue = false;
120 if (s_FovChanged)
121 {
122 if (!isPhysicalCamera || p.projectionMatrixMode.hasMultipleDifferentValues)
123 {
124 cam.verticalFOV.floatValue = fovAxisVertical
125 ? s_FovLastValue
126 : Camera.HorizontalToVerticalFieldOfView(s_FovLastValue, camera0.aspect);
127 }
128 else if (!p.projectionMatrixMode.hasMultipleDifferentValues)
129 {
130 cam.verticalFOV.floatValue = fovAxisVertical
131 ? s_FovLastValue
132 : Camera.HorizontalToVerticalFieldOfView(s_FovLastValue, camera0.aspect);
133 }
134 }
135 }
136
137 /// <summary>Draws projection related fields on the inspector</summary>
138 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param>
139 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param>
140 public static void Drawer_Projection(ISerializedCamera p, Editor owner)
141 {
142 // Most of this is replicated from CameraEditor.DrawProjection as we don't want to draw
143 // it the same way it's done in non-SRP cameras. Unfortunately, because a lot of the
144 // code is internal, we have to copy/paste some stuff from the editor code :(
145 var projectionType = DrawerProjectionType(p, owner);
146
147 if (p.baseCameraSettings.orthographic.hasMultipleDifferentValues)
148 return;
149
150 using (new EditorGUI.IndentLevelScope())
151 {
152 if (projectionType == ProjectionType.Orthographic)
153 {
154 DrawerOrthographicType(p, owner);
155 }
156 else
157 {
158 DrawerPerspectiveType(p, owner);
159 }
160 }
161 }
162
163 static void Drawer_FieldClippingPlanes(ISerializedCamera p, Editor owner)
164 {
165 CoreEditorUtils.DrawMultipleFields(
166 Styles.clippingPlaneMultiFieldTitle,
167 new[] { p.baseCameraSettings.nearClippingPlane, p.baseCameraSettings.farClippingPlane },
168 new[] { Styles.nearPlaneContent, Styles.farPlaneContent });
169 }
170 }
171}