A game about forced loneliness, made by TACStudios
at master 271 lines 14 kB view raw
1using System; 2using UnityEngine; 3using UnityEngine.Rendering; 4 5namespace UnityEditor.Rendering 6{ 7 internal enum DirectionalLightUnit 8 { 9 Lux = LightUnit.Lux, 10 } 11 12 internal enum AreaLightUnit 13 { 14 Lumen = LightUnit.Lumen, 15 Nits = LightUnit.Nits, 16 Ev100 = LightUnit.Ev100, 17 } 18 19 internal enum PunctualLightUnit 20 { 21 Lumen = LightUnit.Lumen, 22 Candela = LightUnit.Candela, 23 Lux = LightUnit.Lux, 24 Ev100 = LightUnit.Ev100 25 } 26 27 /// <summary> 28 /// Contains a set of methods to help render the inspectors of Lights across SRP's 29 /// </summary> 30 public partial class LightUI 31 { 32 /// <summary> 33 /// Draws the color temperature for a serialized light 34 /// </summary> 35 /// <param name="serialized">The serizalized light</param> 36 /// <param name="owner">The editor</param> 37 public static void DrawColor(ISerializedLight serialized, Editor owner) 38 { 39 if (GraphicsSettings.lightsUseLinearIntensity && GraphicsSettings.lightsUseColorTemperature) 40 { 41 // Use the color temperature bool to create a popup dropdown to choose between the two modes. 42 43 var serializedUseColorTemperature = serialized.settings.useColorTemperature; 44 using (var check = new EditorGUI.ChangeCheckScope()) 45 using (new EditorGUI.MixedValueScope(serializedUseColorTemperature.hasMultipleDifferentValues)) 46 { 47 var colorTemperaturePopupValue = Convert.ToInt32(serializedUseColorTemperature.boolValue); 48 colorTemperaturePopupValue = EditorGUILayout.Popup(Styles.lightAppearance, colorTemperaturePopupValue, Styles.lightAppearanceOptions); 49 if(check.changed) 50 serializedUseColorTemperature.boolValue = Convert.ToBoolean(colorTemperaturePopupValue); 51 } 52 53 if (serialized.settings.useColorTemperature.boolValue) 54 { 55 EditorGUI.indentLevel += 1; 56 EditorGUILayout.PropertyField(serialized.settings.color, Styles.colorFilter); 57 58 // Light unit slider 59 const int k_ValueUnitSeparator = 2; 60 var lineRect = EditorGUILayout.GetControlRect(); 61 var labelRect = lineRect; 62 labelRect.width = EditorGUIUtility.labelWidth; 63 EditorGUI.LabelField(labelRect, Styles.colorTemperature); 64 65 var temperatureSliderRect = lineRect; 66 temperatureSliderRect.x += EditorGUIUtility.labelWidth + k_ValueUnitSeparator; 67 temperatureSliderRect.width -= EditorGUIUtility.labelWidth + k_ValueUnitSeparator; 68 TemperatureSliderUIDrawer.Draw(serialized.settings, serialized.serializedObject, serialized.settings.colorTemperature, temperatureSliderRect); 69 70 // Value and unit label 71 // Match const defined in EditorGUI.cs 72 const int k_IndentPerLevel = 15; 73 const int k_UnitWidth = 60 + k_IndentPerLevel; 74 int indent = k_IndentPerLevel * EditorGUI.indentLevel; 75 Rect valueRect = EditorGUILayout.GetControlRect(); 76 valueRect.width += indent - k_ValueUnitSeparator - k_UnitWidth; 77 Rect unitRect = valueRect; 78 unitRect.x += valueRect.width - indent + k_ValueUnitSeparator; 79 unitRect.width = k_UnitWidth + k_ValueUnitSeparator; 80 81 EditorGUI.PropertyField(valueRect, serialized.settings.colorTemperature, CoreEditorStyles.empty); 82 EditorGUI.LabelField(unitRect, Styles.lightAppearanceUnits[0]); 83 84 EditorGUI.indentLevel -= 1; 85 } 86 else 87 EditorGUILayout.PropertyField(serialized.settings.color, Styles.color); 88 } 89 else 90 EditorGUILayout.PropertyField(serialized.settings.color, Styles.color); 91 } 92 93 /// <summary> 94 /// Draws the intensity field and slider, including the light unit dropdown for a serialized light. 95 /// </summary> 96 /// <param name="serialized">The serialized light.</param> 97 /// <param name="owner">The editor.</param> 98 public static void DrawIntensity(ISerializedLight serialized, Editor owner) 99 { 100 // Match const defined in EditorGUI.cs 101 const int k_IndentPerLevel = 15; 102 const int k_ValueUnitSeparator = 2; 103 const int k_UnitWidth = 100; 104 105 float indent = k_IndentPerLevel * EditorGUI.indentLevel; 106 107 Rect lineRect = EditorGUILayout.GetControlRect(); 108 Rect labelRect = lineRect; 109 labelRect.width = EditorGUIUtility.labelWidth; 110 111 // Expand to reach both lines of the intensity field. 112 var interlineOffset = EditorGUIUtility.singleLineHeight + 2f; 113 labelRect.height += interlineOffset; 114 115 //handling of prefab overrides in a parent label 116 GUIContent parentLabel = Styles.lightIntensity; 117 parentLabel = EditorGUI.BeginProperty(labelRect, parentLabel, serialized.settings.lightUnit); 118 parentLabel = EditorGUI.BeginProperty(labelRect, parentLabel, serialized.settings.intensity); 119 { 120 // Restore the original rect for actually drawing the label. 121 labelRect.height -= interlineOffset; 122 123 EditorGUI.LabelField(labelRect, parentLabel); 124 } 125 EditorGUI.EndProperty(); 126 EditorGUI.EndProperty(); 127 128 Light light = serialized.settings.light; 129 LightType lightType = serialized.settings.lightType.GetEnumValue<LightType>(); 130 LightUnit nativeUnit = LightUnitUtils.GetNativeLightUnit(lightType); 131 LightUnit lightUnit = serialized.settings.lightUnit.GetEnumValue<LightUnit>(); 132 float nativeIntensity = serialized.settings.intensity.floatValue; 133 134 // Verify that ui light unit is in fact supported or revert to native. 135 lightUnit = LightUnitUtils.IsLightUnitSupported(lightType, lightUnit) ? lightUnit : nativeUnit; 136 137 // Draw the light unit slider + icon + tooltip 138 Rect lightUnitSliderRect = lineRect; // TODO: Move the value and unit rects to new line 139 lightUnitSliderRect.x += EditorGUIUtility.labelWidth + k_ValueUnitSeparator; 140 lightUnitSliderRect.width -= EditorGUIUtility.labelWidth + k_ValueUnitSeparator; 141 LightIntensitySlider.Draw(serialized, owner, lightUnitSliderRect); 142 143 // We use PropertyField to draw the value to keep the handle at left of the field 144 // This will apply the indent again thus we need to remove it time for alignment 145 Rect valueRect = EditorGUILayout.GetControlRect(); 146 labelRect.width = EditorGUIUtility.labelWidth; 147 valueRect.width += indent - k_ValueUnitSeparator - k_UnitWidth; 148 Rect unitRect = valueRect; 149 unitRect.x += valueRect.width - indent + k_ValueUnitSeparator; 150 unitRect.width = k_UnitWidth + .5f; 151 152 // Draw the intensity float field 153 EditorGUI.BeginChangeCheck(); 154 float curIntensity = LightUnitUtils.ConvertIntensity(light, nativeIntensity, nativeUnit, lightUnit); 155 EditorGUI.showMixedValue = serialized.settings.lightUnit.hasMultipleDifferentValues; 156 float newIntensity = EditorGUI.FloatField(valueRect, CoreEditorStyles.empty, curIntensity); 157 if (EditorGUI.EndChangeCheck()) 158 { 159 serialized.settings.intensity.floatValue = Mathf.Max( 160 0f, 161 LightUnitUtils.ConvertIntensity(light, newIntensity, lightUnit, nativeUnit) 162 ); 163 } 164 EditorGUI.showMixedValue = false; 165 166 // Draw the light unit dropdown 167 { 168 EditorGUI.BeginChangeCheck(); 169 170 EditorGUI.BeginProperty(unitRect, GUIContent.none, serialized.settings.lightUnit); 171 EditorGUI.showMixedValue = serialized.settings.lightUnit.hasMultipleDifferentValues; 172 173 LightUnit selectedLightUnit = DrawLightIntensityUnitPopup( 174 unitRect, 175 serialized.settings.lightUnit.GetEnumValue<LightUnit>(), 176 lightType 177 ); 178 179 EditorGUI.showMixedValue = false; 180 EditorGUI.EndProperty(); 181 182 if (EditorGUI.EndChangeCheck()) 183 { 184 serialized.settings.lightUnit.SetEnumValue(selectedLightUnit); 185 } 186 } 187 188 } 189 190 /// <summary> 191 /// Draws additional light intensity modifiers, depending on light type/unit for a serialized light. 192 /// </summary> 193 /// <param name="serialized">The serialized light.</param> 194 /// <param name="hideReflector">If true, the reflector checkbox will be hidden.</param> 195 public static void DrawIntensityModifiers(ISerializedLight serialized, bool hideReflector = false) 196 { 197 LightType lightType = serialized.settings.lightType.GetEnumValue<LightType>(); 198 LightUnit lightUnit = serialized.settings.lightUnit.GetEnumValue<LightUnit>(); 199 200 // Draw the "Lux At Distance" field 201 if (lightType != LightType.Directional && lightType != LightType.Box && lightUnit == LightUnit.Lux) 202 { 203 // Box and directional lights shouldn't display this widget, since their light source are considered to 204 // be at infinity, and the distance is always infinity. So we only display this widget for light types 205 // that support the Lux unit, and whose sources aren't positioned at infinity. 206 EditorGUI.indentLevel++; 207 EditorGUI.BeginChangeCheck(); 208 209 float oldLuxAtDistance = serialized.settings.luxAtDistance.floatValue; 210 EditorGUILayout.PropertyField(serialized.settings.luxAtDistance, Styles.luxAtDistance); 211 212 if (EditorGUI.EndChangeCheck()) 213 { 214 serialized.settings.luxAtDistance.floatValue = Mathf.Max(serialized.settings.luxAtDistance.floatValue, 0.01f); 215 // Derive the lux from intensity, which is in Candela, and the old distance value 216 float lux = LightUnitUtils.CandelaToLux(serialized.settings.intensity.floatValue, oldLuxAtDistance); 217 // Calculate the new intensity in Candela from the lux value, and the new distance 218 serialized.settings.intensity.floatValue = LightUnitUtils.LuxToCandela(lux, serialized.settings.luxAtDistance.floatValue); 219 } 220 EditorGUI.indentLevel--; 221 } 222 223 // Draw the "Reflector" checkbox 224 if ((lightType == LightType.Spot || lightType == LightType.Pyramid) && lightUnit == (int)LightUnit.Lumen && !hideReflector) 225 { 226 EditorGUI.indentLevel++; 227 EditorGUI.BeginChangeCheck(); 228 EditorGUILayout.PropertyField(serialized.settings.enableSpotReflector, Styles.enableSpotReflector); 229 if (EditorGUI.EndChangeCheck()) 230 { 231 // ^ The reflector bool has changed, and the light unit is set to Lumen. Update the intensity (in Candela). 232 float oldCandela = serialized.settings.intensity.floatValue; 233 float spotAngle = serialized.settings.spotAngle.floatValue; 234 float aspectRatio = serialized.settings.areaSizeX.floatValue; 235 bool enableSpotReflector = serialized.settings.enableSpotReflector.boolValue; 236 237 float oldSolidAngle = LightUnitUtils.GetSolidAngle(lightType, !enableSpotReflector, spotAngle, aspectRatio); 238 float oldLumen = LightUnitUtils.CandelaToLumen(oldCandela, oldSolidAngle); 239 float newSolidAngle = LightUnitUtils.GetSolidAngle(lightType, enableSpotReflector, spotAngle, aspectRatio); 240 serialized.settings.intensity.floatValue = LightUnitUtils.LumenToCandela(oldLumen, newSolidAngle); 241 } 242 EditorGUI.indentLevel--; 243 } 244 } 245 246 /// <summary> 247 /// Draws a light unit dropdown. 248 /// </summary> 249 /// <param name="position">Rectangle on the screen to use for the field.</param> 250 /// <param name="selected">The light unit the field shows.</param> 251 /// <param name="type">The type of the light. This determines which options are available.</param> 252 /// <returns>The light unit that has been selected by the user. </returns> 253 public static LightUnit DrawLightIntensityUnitPopup(Rect position, LightUnit selected, LightType type) 254 { 255 switch (type) 256 { 257 case LightType.Box: 258 case LightType.Directional: 259 return (LightUnit)EditorGUI.EnumPopup(position, (DirectionalLightUnit)selected); 260 261 case LightType.Point: 262 case LightType.Spot: 263 case LightType.Pyramid: 264 return (LightUnit)EditorGUI.EnumPopup(position, (PunctualLightUnit)selected); 265 266 default: 267 return (LightUnit)EditorGUI.EnumPopup(position, (AreaLightUnit)selected); 268 } 269 } 270 } 271}