A game about forced loneliness, made by TACStudios
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}