A game about forced loneliness, made by TACStudios
at master 286 lines 16 kB view raw
1using System; 2using System.Runtime.CompilerServices; 3using UnityEngine; 4 5namespace UnityEditor.Rendering 6{ 7 public static partial class CameraUI 8 { 9 /// <summary> 10 /// Physical camera related drawers 11 /// </summary> 12 public static partial class PhysicalCamera 13 { 14 // Saves the value of the sensor size when the user switches from "custom" size to a preset per camera. 15 // We use a ConditionalWeakTable instead of a Dictionary to avoid keeping alive (with strong references) deleted cameras 16 static ConditionalWeakTable<Camera, object> s_PerCameraSensorSizeHistory = new ConditionalWeakTable<Camera, object>(); 17 18 /// <summary>Draws Body Sensor related fields on the inspector</summary> 19 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 20 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 21 public static void Drawer_PhysicalCamera_CameraBody_Sensor(ISerializedCamera p, Editor owner) 22 { 23 var cam = p.baseCameraSettings; 24 EditorGUI.BeginChangeCheck(); 25 26 int oldFilmGateIndex = Array.IndexOf(Styles.apertureFormatValues, new Vector2((float)Math.Round(cam.sensorSize.vector2Value.x, 3), (float)Math.Round(cam.sensorSize.vector2Value.y, 3))); 27 28 // If it is not one of the preset sizes, set it to custom 29 oldFilmGateIndex = (oldFilmGateIndex == -1) ? Styles.customPresetIndex : oldFilmGateIndex; 30 31 // Get the new user selection 32 int newFilmGateIndex = EditorGUILayout.Popup(Styles.sensorType, oldFilmGateIndex, Styles.apertureFormatNames); 33 34 if (EditorGUI.EndChangeCheck()) 35 { 36 // Retrieve the previous custom size value, if one exists for this camera 37 object previousCustomValue; 38 s_PerCameraSensorSizeHistory.TryGetValue((Camera)p.serializedObject.targetObject, out previousCustomValue); 39 40 // When switching from custom to a preset, update the last custom value (to display again, in case the user switches back to custom) 41 if (oldFilmGateIndex == Styles.customPresetIndex) 42 { 43 if (previousCustomValue == null) 44 { 45 s_PerCameraSensorSizeHistory.Add((Camera)p.serializedObject.targetObject, cam.sensorSize.vector2Value); 46 } 47 else 48 { 49 previousCustomValue = cam.sensorSize.vector2Value; 50 } 51 } 52 53 if (newFilmGateIndex < Styles.customPresetIndex) 54 { 55 cam.sensorSize.vector2Value = Styles.apertureFormatValues[newFilmGateIndex]; 56 } 57 else 58 { 59 // The user switched back to custom, so display by deafulr the previous custom value 60 if (previousCustomValue != null) 61 { 62 cam.sensorSize.vector2Value = (Vector2)previousCustomValue; 63 } 64 else 65 { 66 cam.sensorSize.vector2Value = new Vector2(36.0f, 24.0f); // this is the value new cameras are created with 67 } 68 } 69 } 70 71 EditorGUILayout.PropertyField(cam.sensorSize, Styles.sensorSize); 72 } 73 74 /// <summary>Draws Gate fit related fields on the inspector</summary> 75 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 76 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 77 public static void Drawer_PhysicalCamera_CameraBody_GateFit(ISerializedCamera p, Editor owner) 78 { 79 var cam = p.baseCameraSettings; 80 81 using (var horizontal = new EditorGUILayout.HorizontalScope()) 82 using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, Styles.gateFit, cam.gateFit)) 83 using (var checkScope = new EditorGUI.ChangeCheckScope()) 84 { 85 int gateValue = (int)(Camera.GateFitMode)EditorGUILayout.EnumPopup(propertyScope.content, (Camera.GateFitMode)cam.gateFit.intValue); 86 if (checkScope.changed) 87 cam.gateFit.intValue = gateValue; 88 } 89 } 90 91 /// <summary>Draws Focal Length related fields on the inspector</summary> 92 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 93 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 94 public static void Drawer_PhysicalCamera_Lens_FocalLength(ISerializedCamera p, Editor owner) 95 { 96 var cam = p.baseCameraSettings; 97 98 using (var horizontal = new EditorGUILayout.HorizontalScope()) 99 using (new EditorGUI.PropertyScope(horizontal.rect, Styles.focalLength, cam.focalLength)) 100 using (var checkScope = new EditorGUI.ChangeCheckScope()) 101 { 102 bool isPhysical = p.projectionMatrixMode.intValue == (int)CameraUI.ProjectionMatrixMode.PhysicalPropertiesBased; 103 // We need to update the focal length if the camera is physical and the FoV has changed. 104 bool focalLengthIsDirty = (s_FovChanged && isPhysical); 105 106 float sensorLength = cam.fovAxisMode.intValue == 0 ? cam.sensorSize.vector2Value.y : cam.sensorSize.vector2Value.x; 107 float focalLengthVal = focalLengthIsDirty ? Camera.FieldOfViewToFocalLength(s_FovLastValue, sensorLength) : cam.focalLength.floatValue; 108 focalLengthVal = EditorGUILayout.FloatField(Styles.focalLength, focalLengthVal); 109 if (checkScope.changed || focalLengthIsDirty) 110 cam.focalLength.floatValue = focalLengthVal; 111 } 112 } 113 114 /// <summary>Draws Lens Shift related fields on the inspector</summary> 115 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 116 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 117 public static void Drawer_PhysicalCamera_Lens_Shift(ISerializedCamera p, Editor owner) 118 { 119 EditorGUILayout.PropertyField(p.baseCameraSettings.lensShift, Styles.shift); 120 } 121 122 123 /// <summary>Draws Focus Distance related fields on the inspector</summary> 124 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 125 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 126 public static void Drawer_PhysicalCamera_FocusDistance(ISerializedCamera p, Editor owner) 127 { 128 var cam = p.baseCameraSettings; 129 EditorGUILayout.PropertyField(cam.focusDistance, Styles.focusDistance); 130 } 131 132 /// <summary>Draws ISO related fields on the inspector</summary> 133 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 134 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 135 public static void Drawer_PhysicalCamera_CameraBody_ISO(ISerializedCamera p, Editor owner) 136 { 137 var cam = p.baseCameraSettings; 138 EditorGUILayout.PropertyField(cam.iso, Styles.ISO); 139 } 140 141 static EditorPrefBoolFlags<ShutterSpeedUnit> m_ShutterSpeedState = new EditorPrefBoolFlags<ShutterSpeedUnit>($"HDRP:{nameof(CameraUI)}:ShutterSpeedState"); 142 143 enum ShutterSpeedUnit 144 { 145 [InspectorName("Second")] 146 Second, 147 [InspectorName("1 \u2215 Second")] // Don't use a slash here else Unity will auto-create a submenu... 148 OneOverSecond 149 } 150 151 /// <summary>Draws Shutter Speed related fields on the inspector</summary> 152 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 153 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 154 public static void Drawer_PhysicalCamera_CameraBody_ShutterSpeed(ISerializedCamera p, Editor owner) 155 { 156 var cam = p.baseCameraSettings; 157 158 // Custom layout for shutter speed 159 const int k_UnitMenuWidth = 90; 160 const int k_OffsetPerIndent = 15; 161 const int k_LabelFieldSeparator = 2; 162 const int k_Offset = 1; 163 int oldIndentLevel = EditorGUI.indentLevel; 164 165 // Don't take into account the indentLevel when rendering the units field 166 EditorGUI.indentLevel = 0; 167 168 var lineRect = EditorGUILayout.GetControlRect(); 169 var fieldRect = new Rect(k_OffsetPerIndent + k_LabelFieldSeparator + k_Offset, lineRect.y, lineRect.width - k_UnitMenuWidth, lineRect.height); 170 var unitMenu = new Rect(fieldRect.xMax + k_LabelFieldSeparator, lineRect.y, k_UnitMenuWidth - k_LabelFieldSeparator, lineRect.height); 171 172 // We cannot had the shutterSpeedState as this is not a serialized property but a global edition mode. 173 // This imply that it will never go bold nor can be reverted in prefab overrides 174 175 m_ShutterSpeedState.value = (ShutterSpeedUnit)EditorGUI.EnumPopup(unitMenu, m_ShutterSpeedState.value); 176 // Reset the indent level 177 EditorGUI.indentLevel = oldIndentLevel; 178 179 EditorGUI.BeginProperty(fieldRect, Styles.shutterSpeed, cam.shutterSpeed); 180 { 181 // if we we use (1 / second) units, then change the value for the display and then revert it back 182 if (m_ShutterSpeedState.value == ShutterSpeedUnit.OneOverSecond && cam.shutterSpeed.floatValue > 0) 183 cam.shutterSpeed.floatValue = 1.0f / cam.shutterSpeed.floatValue; 184 EditorGUI.PropertyField(fieldRect, cam.shutterSpeed, Styles.shutterSpeed); 185 if (m_ShutterSpeedState.value == ShutterSpeedUnit.OneOverSecond && cam.shutterSpeed.floatValue > 0) 186 cam.shutterSpeed.floatValue = 1.0f / cam.shutterSpeed.floatValue; 187 } 188 EditorGUI.EndProperty(); 189 } 190 191 /// <summary>Draws Lens Aperture related fields on the inspector</summary> 192 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 193 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 194 public static void Drawer_PhysicalCamera_Lens_Aperture(ISerializedCamera p, Editor owner) 195 { 196 var cam = p.baseCameraSettings; 197 198 // Custom layout for aperture 199 var rect = EditorGUILayout.BeginHorizontal(); 200 { 201 // Magic values/offsets to get the UI look consistent 202 const float textRectSize = 80; 203 const float textRectPaddingRight = 62; 204 const float unitRectPaddingRight = 97; 205 const float sliderPaddingLeft = 2; 206 const float sliderPaddingRight = 77; 207 208 var labelRect = rect; 209 labelRect.width = EditorGUIUtility.labelWidth; 210 labelRect.height = EditorGUIUtility.singleLineHeight; 211 EditorGUI.LabelField(labelRect, Styles.aperture); 212 213 GUI.SetNextControlName("ApertureSlider"); 214 var sliderRect = rect; 215 sliderRect.x += labelRect.width + sliderPaddingLeft; 216 sliderRect.width = rect.width - labelRect.width - sliderPaddingRight; 217 float newVal = GUI.HorizontalSlider(sliderRect, cam.aperture.floatValue, Camera.kMinAperture, Camera.kMaxAperture); 218 219 // keep only 2 digits of precision, like the otehr editor fields 220 newVal = Mathf.Floor(100 * newVal) / 100.0f; 221 222 if (cam.aperture.floatValue != newVal) 223 { 224 cam.aperture.floatValue = newVal; 225 // Note: We need to move the focus when the slider changes, otherwise the textField will not update 226 GUI.FocusControl("ApertureSlider"); 227 } 228 229 var unitRect = rect; 230 unitRect.x += rect.width - unitRectPaddingRight; 231 unitRect.width = textRectSize; 232 unitRect.height = EditorGUIUtility.singleLineHeight; 233 EditorGUI.LabelField(unitRect, "f /", EditorStyles.label); 234 235 var textRect = rect; 236 textRect.x = rect.width - textRectPaddingRight; 237 textRect.width = textRectSize; 238 textRect.height = EditorGUIUtility.singleLineHeight; 239 string newAperture = EditorGUI.TextField(textRect, cam.aperture.floatValue.ToString()); 240 if (float.TryParse(newAperture, out float parsedValue)) 241 cam.aperture.floatValue = Mathf.Clamp(parsedValue, Camera.kMinAperture, Camera.kMaxAperture); 242 } 243 244 EditorGUILayout.EndHorizontal(); 245 EditorGUILayout.Space(EditorGUIUtility.singleLineHeight); 246 } 247 248 /// <summary>Draws Aperture Shape related fields on the inspector</summary> 249 /// <param name="p"><see cref="ISerializedCamera"/> The serialized camera</param> 250 /// <param name="owner"><see cref="Editor"/> The editor owner calling this drawer</param> 251 public static void Drawer_PhysicalCamera_ApertureShape(ISerializedCamera p, Editor owner) 252 { 253 var cam = p.baseCameraSettings; 254 255 EditorGUILayout.PropertyField(cam.bladeCount, Styles.bladeCount); 256 257 using (var horizontal = new EditorGUILayout.HorizontalScope()) 258 using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, Styles.curvature, cam.curvature)) 259 { 260 var v = cam.curvature.vector2Value; 261 262 // The layout system breaks alignment when mixing inspector fields with custom layout'd 263 // fields as soon as a scrollbar is needed in the inspector, so we'll do the layout 264 // manually instead 265 const int kFloatFieldWidth = 50; 266 const int kSeparatorWidth = 5; 267 float indentOffset = EditorGUI.indentLevel * 15f; 268 var lineRect = EditorGUILayout.GetControlRect(); 269 var labelRect = new Rect(lineRect.x, lineRect.y, EditorGUIUtility.labelWidth - indentOffset, lineRect.height); 270 var floatFieldLeft = new Rect(labelRect.xMax, lineRect.y, kFloatFieldWidth + indentOffset, lineRect.height); 271 var sliderRect = new Rect(floatFieldLeft.xMax + kSeparatorWidth - indentOffset, lineRect.y, lineRect.width - labelRect.width - kFloatFieldWidth * 2 - kSeparatorWidth * 2, lineRect.height); 272 var floatFieldRight = new Rect(sliderRect.xMax + kSeparatorWidth - indentOffset, lineRect.y, kFloatFieldWidth + indentOffset, lineRect.height); 273 274 EditorGUI.PrefixLabel(labelRect, propertyScope.content); 275 v.x = EditorGUI.FloatField(floatFieldLeft, v.x); 276 EditorGUI.MinMaxSlider(sliderRect, ref v.x, ref v.y, Camera.kMinAperture, Camera.kMaxAperture); 277 v.y = EditorGUI.FloatField(floatFieldRight, v.y); 278 cam.curvature.vector2Value = v; 279 } 280 281 EditorGUILayout.PropertyField(cam.barrelClipping, Styles.barrelClipping); 282 EditorGUILayout.PropertyField(cam.anamorphism, Styles.anamorphism); 283 } 284 } 285 } 286}