您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
563 行
26 KiB
563 行
26 KiB
using System;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEditor.Experimental.Rendering;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace UnityEngine.Experimental.Rendering.HDPipeline
|
|
{
|
|
// TODO: Simplify this editor once we can target 2018.1
|
|
[CanEditMultipleObjects]
|
|
[CustomEditorForRenderPipeline(typeof(Light), typeof(HDRenderPipelineAsset))]
|
|
sealed partial class HDLightEditor : LightEditor
|
|
{
|
|
sealed class SerializedBaseData
|
|
{
|
|
public SerializedProperty type;
|
|
public SerializedProperty range;
|
|
public SerializedProperty spotAngle;
|
|
public SerializedProperty cookie;
|
|
public SerializedProperty cookieSize;
|
|
public SerializedProperty color;
|
|
public SerializedProperty intensity;
|
|
public SerializedProperty bounceIntensity;
|
|
public SerializedProperty colorTemperature;
|
|
public SerializedProperty useColorTemperature;
|
|
public SerializedProperty shadowsType;
|
|
public SerializedProperty shadowsBias;
|
|
public SerializedProperty shadowsNormalBias;
|
|
public SerializedProperty shadowsNearPlane;
|
|
public SerializedProperty lightmapping;
|
|
public SerializedProperty areaSizeX;
|
|
public SerializedProperty areaSizeY;
|
|
public SerializedProperty bakedShadowRadius;
|
|
public SerializedProperty bakedShadowAngle;
|
|
}
|
|
|
|
sealed class SerializedLightData
|
|
{
|
|
public SerializedProperty spotInnerPercent;
|
|
public SerializedProperty lightDimmer;
|
|
public SerializedProperty fadeDistance;
|
|
public SerializedProperty affectDiffuse;
|
|
public SerializedProperty affectSpecular;
|
|
public SerializedProperty lightTypeExtent;
|
|
public SerializedProperty spotLightShape;
|
|
public SerializedProperty shapeLength;
|
|
public SerializedProperty shapeWidth;
|
|
public SerializedProperty shapeRadius;
|
|
public SerializedProperty maxSmoothness;
|
|
public SerializedProperty applyRangeAttenuation;
|
|
|
|
// Editor stuff
|
|
public SerializedProperty useOldInspector;
|
|
public SerializedProperty showFeatures;
|
|
public SerializedProperty showAdditionalSettings;
|
|
}
|
|
|
|
sealed class SerializedShadowData
|
|
{
|
|
public SerializedProperty dimmer;
|
|
public SerializedProperty fadeDistance;
|
|
public SerializedProperty cascadeCount;
|
|
public SerializedProperty cascadeRatios;
|
|
public SerializedProperty cascadeBorders;
|
|
public SerializedProperty resolution;
|
|
}
|
|
|
|
SerializedObject m_SerializedAdditionalLightData;
|
|
SerializedObject m_SerializedAdditionalShadowData;
|
|
|
|
SerializedBaseData m_BaseData;
|
|
SerializedLightData m_AdditionalLightData;
|
|
SerializedShadowData m_AdditionalShadowData;
|
|
|
|
// Copied over from teh original LightEditor class. Will go away once we can target 2018.1
|
|
bool m_TypeIsSame { get { return !m_BaseData.type.hasMultipleDifferentValues; } }
|
|
bool m_LightmappingTypeIsSame { get { return !m_BaseData.lightmapping.hasMultipleDifferentValues; } }
|
|
bool m_IsCompletelyBaked { get { return m_BaseData.lightmapping.intValue == 2; } }
|
|
bool m_IsRealtime { get { return m_BaseData.lightmapping.intValue == 4; } }
|
|
Light light { get { return serializedObject.targetObject as Light; } }
|
|
Texture m_Cookie { get { return m_BaseData.cookie.objectReferenceValue as Texture; } }
|
|
bool m_BakingWarningValue { get { return !Lightmapping.bakedGI && m_LightmappingTypeIsSame && !m_IsRealtime; } }
|
|
bool m_BounceWarningValue
|
|
{
|
|
get
|
|
{
|
|
return m_TypeIsSame && (light.type == LightType.Point || light.type == LightType.Spot) &&
|
|
m_LightmappingTypeIsSame && m_IsRealtime && !m_BaseData.bounceIntensity.hasMultipleDifferentValues
|
|
&& m_BaseData.bounceIntensity.floatValue > 0.0f;
|
|
}
|
|
}
|
|
public bool cookieWarningValue
|
|
{
|
|
get
|
|
{
|
|
return m_TypeIsSame && light.type == LightType.Spot &&
|
|
!m_BaseData.cookie.hasMultipleDifferentValues && m_Cookie && m_Cookie.wrapMode != TextureWrapMode.Clamp;
|
|
}
|
|
}
|
|
|
|
// LightType + LightTypeExtent combined
|
|
enum LightShape
|
|
{
|
|
Spot,
|
|
Directional,
|
|
Point,
|
|
//Area, <= offline base type not displayed in our case but used for GI of our area light
|
|
Rectangle,
|
|
Line,
|
|
//Sphere,
|
|
//Disc,
|
|
}
|
|
|
|
// Used for UI only; the processing code must use LightTypeExtent and LightType
|
|
LightShape m_LightShape;
|
|
|
|
void OnEnable()
|
|
{
|
|
// Get & automatically add additional HD data if not present
|
|
var lightData = GetAdditionalData<HDAdditionalLightData>();
|
|
var shadowData = GetAdditionalData<AdditionalShadowData>();
|
|
m_SerializedAdditionalLightData = new SerializedObject(lightData);
|
|
m_SerializedAdditionalShadowData = new SerializedObject(shadowData);
|
|
|
|
// Grab all the serialized data we need
|
|
m_BaseData = new SerializedBaseData
|
|
{
|
|
type = serializedObject.FindProperty("m_Type"),
|
|
range = serializedObject.FindProperty("m_Range"),
|
|
spotAngle = serializedObject.FindProperty("m_SpotAngle"),
|
|
cookie = serializedObject.FindProperty("m_Cookie"),
|
|
cookieSize = serializedObject.FindProperty("m_CookieSize"),
|
|
color = serializedObject.FindProperty("m_Color"),
|
|
intensity = serializedObject.FindProperty("m_Intensity"),
|
|
bounceIntensity = serializedObject.FindProperty("m_BounceIntensity"),
|
|
colorTemperature = serializedObject.FindProperty("m_ColorTemperature"),
|
|
useColorTemperature = serializedObject.FindProperty("m_UseColorTemperature"),
|
|
shadowsType = serializedObject.FindProperty("m_Shadows.m_Type"),
|
|
shadowsBias = serializedObject.FindProperty("m_Shadows.m_Bias"),
|
|
shadowsNormalBias = serializedObject.FindProperty("m_Shadows.m_NormalBias"),
|
|
shadowsNearPlane = serializedObject.FindProperty("m_Shadows.m_NearPlane"),
|
|
lightmapping = serializedObject.FindProperty("m_Lightmapping"),
|
|
areaSizeX = serializedObject.FindProperty("m_AreaSize.x"),
|
|
areaSizeY = serializedObject.FindProperty("m_AreaSize.y"),
|
|
bakedShadowRadius = serializedObject.FindProperty("m_ShadowRadius"),
|
|
bakedShadowAngle = serializedObject.FindProperty("m_ShadowAngle")
|
|
};
|
|
|
|
using (var o = new PropertyFetcher<HDAdditionalLightData>(m_SerializedAdditionalLightData))
|
|
m_AdditionalLightData = new SerializedLightData
|
|
{
|
|
spotInnerPercent = o.FindProperty(x => x.m_InnerSpotPercent),
|
|
lightDimmer = o.FindProperty(x => x.lightDimmer),
|
|
fadeDistance = o.FindProperty(x => x.fadeDistance),
|
|
affectDiffuse = o.FindProperty(x => x.affectDiffuse),
|
|
affectSpecular = o.FindProperty(x => x.affectSpecular),
|
|
lightTypeExtent = o.FindProperty(x => x.lightTypeExtent),
|
|
spotLightShape = o.FindProperty(x => x.spotLightShape),
|
|
shapeLength = o.FindProperty(x => x.shapeLength),
|
|
shapeWidth = o.FindProperty(x => x.shapeWidth),
|
|
shapeRadius = o.FindProperty(x => x.shapeRadius),
|
|
maxSmoothness = o.FindProperty(x => x.maxSmoothness),
|
|
applyRangeAttenuation = o.FindProperty(x => x.applyRangeAttenuation),
|
|
|
|
// Editor stuff
|
|
useOldInspector = o.FindProperty(x => x.useOldInspector),
|
|
showFeatures = o.FindProperty(x => x.featuresFoldout),
|
|
showAdditionalSettings = o.FindProperty(x => x.showAdditionalSettings)
|
|
};
|
|
|
|
// TODO: Review this once AdditionalShadowData is refactored
|
|
using (var o = new PropertyFetcher<AdditionalShadowData>(m_SerializedAdditionalShadowData))
|
|
m_AdditionalShadowData = new SerializedShadowData
|
|
{
|
|
dimmer = o.FindProperty(x => x.shadowDimmer),
|
|
fadeDistance = o.FindProperty(x => x.shadowFadeDistance),
|
|
cascadeCount = o.FindProperty("shadowCascadeCount"),
|
|
cascadeRatios = o.FindProperty("shadowCascadeRatios"),
|
|
cascadeBorders = o.FindProperty("shadowCascadeBorders"),
|
|
resolution = o.FindProperty(x => x.shadowResolution)
|
|
};
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
m_SerializedAdditionalLightData.Update();
|
|
m_SerializedAdditionalShadowData.Update();
|
|
|
|
// Temporary toggle to go back to the old editor & separated additional datas
|
|
bool useOldInspector = m_AdditionalLightData.useOldInspector.boolValue;
|
|
|
|
if (GUILayout.Button("Toggle default light editor"))
|
|
useOldInspector = !useOldInspector;
|
|
|
|
m_AdditionalLightData.useOldInspector.boolValue = useOldInspector;
|
|
|
|
if (useOldInspector)
|
|
{
|
|
DrawDefaultInspector();
|
|
ApplyAdditionalComponentsVisibility(false);
|
|
m_SerializedAdditionalShadowData.ApplyModifiedProperties();
|
|
m_SerializedAdditionalLightData.ApplyModifiedProperties();
|
|
return;
|
|
}
|
|
|
|
// New editor
|
|
ApplyAdditionalComponentsVisibility(true);
|
|
CheckStyles();
|
|
|
|
serializedObject.Update();
|
|
|
|
ResolveLightShape();
|
|
|
|
DrawFoldout(m_AdditionalLightData.showFeatures, "Features", DrawFeatures);
|
|
DrawFoldout(m_BaseData.type, "Shape", DrawShape);
|
|
DrawFoldout(m_BaseData.intensity, "Light", DrawLightSettings);
|
|
|
|
if (m_BaseData.shadowsType.enumValueIndex != (int)LightShadows.None)
|
|
DrawFoldout(m_BaseData.shadowsType, "Shadows", DrawShadows);
|
|
|
|
EditorLightUtilities.DrawSplitter();
|
|
EditorGUILayout.Space();
|
|
|
|
m_SerializedAdditionalShadowData.ApplyModifiedProperties();
|
|
m_SerializedAdditionalLightData.ApplyModifiedProperties();
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
void DrawFoldout(SerializedProperty foldoutProperty, string title, Action func)
|
|
{
|
|
EditorLightUtilities.DrawSplitter();
|
|
|
|
bool state = foldoutProperty.isExpanded;
|
|
state = EditorLightUtilities.DrawHeaderFoldout(title, state);
|
|
|
|
if (state)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
func();
|
|
EditorGUI.indentLevel--;
|
|
GUILayout.Space(2f);
|
|
}
|
|
|
|
foldoutProperty.isExpanded = state;
|
|
}
|
|
|
|
void DrawFeatures()
|
|
{
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.showAdditionalSettings);
|
|
|
|
bool disabledScope = m_IsCompletelyBaked
|
|
|| m_LightShape == LightShape.Line
|
|
|| m_LightShape == LightShape.Rectangle;
|
|
|
|
using (new EditorGUI.DisabledScope(disabledScope))
|
|
{
|
|
bool shadowsEnabled = EditorGUILayout.Toggle(new GUIContent("Enable Shadows"), m_BaseData.shadowsType.enumValueIndex != 0);
|
|
m_BaseData.shadowsType.enumValueIndex = shadowsEnabled ? (int)LightShadows.Hard : (int)LightShadows.None;
|
|
}
|
|
}
|
|
|
|
void DrawShape()
|
|
{
|
|
m_LightShape = (LightShape)EditorGUILayout.Popup(s_Styles.shape, (int)m_LightShape, s_Styles.shapeNames);
|
|
|
|
// LightShape is HD specific, it need to drive LightType from the original LightType
|
|
// when it make sense, so the GI is still in sync with the light shape
|
|
switch (m_LightShape)
|
|
{
|
|
case LightShape.Directional:
|
|
m_BaseData.type.enumValueIndex = (int)LightType.Directional;
|
|
m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual;
|
|
break;
|
|
|
|
case LightShape.Point:
|
|
m_BaseData.type.enumValueIndex = (int)LightType.Point;
|
|
m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual;
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.maxSmoothness, s_Styles.maxSmoothness);
|
|
break;
|
|
|
|
case LightShape.Spot:
|
|
m_BaseData.type.enumValueIndex = (int)LightType.Spot;
|
|
m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual;
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.spotLightShape, s_Styles.spotLightShape);
|
|
var spotLightShape = (SpotLightShape)m_AdditionalLightData.spotLightShape.enumValueIndex;
|
|
// Cone Spot
|
|
if (spotLightShape == SpotLightShape.Cone)
|
|
{
|
|
EditorGUILayout.Slider(m_BaseData.spotAngle, 0f, 179.9f, s_Styles.spotAngle);
|
|
EditorGUILayout.Slider(m_AdditionalLightData.spotInnerPercent, 0f, 100f, s_Styles.spotInnerPercent);
|
|
}
|
|
// TODO : replace with angle and ratio
|
|
else if (spotLightShape == SpotLightShape.Pyramid)
|
|
{
|
|
EditorGUILayout.Slider(m_AdditionalLightData.shapeLength, 0.01f, 10f, s_Styles.shapeLengthPyramid);
|
|
EditorGUILayout.Slider(m_AdditionalLightData.shapeWidth, 0.01f, 10f, s_Styles.shapeWidthPyramid);
|
|
}
|
|
else if (spotLightShape == SpotLightShape.Box)
|
|
{
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.shapeLength, s_Styles.shapeLengthBox);
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.shapeWidth, s_Styles.shapeWidthBox);
|
|
}
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.maxSmoothness, s_Styles.maxSmoothness);
|
|
break;
|
|
|
|
case LightShape.Rectangle:
|
|
// TODO: Currently if we use Area type as it is offline light in legacy, the light will not exist at runtime
|
|
//m_BaseData.type.enumValueIndex = (int)LightType.Area;
|
|
m_BaseData.type.enumValueIndex = (int)LightType.Point;
|
|
m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Rectangle;
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.shapeLength, s_Styles.shapeLengthRect);
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.shapeWidth, s_Styles.shapeWidthRect);
|
|
m_BaseData.areaSizeX.floatValue = m_AdditionalLightData.shapeLength.floatValue;
|
|
m_BaseData.areaSizeY.floatValue = m_AdditionalLightData.shapeWidth.floatValue;
|
|
m_BaseData.shadowsType.enumValueIndex = (int)LightShadows.None;
|
|
break;
|
|
|
|
case LightShape.Line:
|
|
// TODO: Currently if we use Area type as it is offline light in legacy, the light will not exist at runtime
|
|
//m_BaseData.type.enumValueIndex = (int)LightType.Area;
|
|
m_BaseData.type.enumValueIndex = (int)LightType.Point;
|
|
m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Line;
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.shapeLength, s_Styles.shapeLengthLine);
|
|
// Fake line with a small rectangle in vanilla unity for GI
|
|
m_BaseData.areaSizeX.floatValue = m_AdditionalLightData.shapeLength.floatValue;
|
|
m_BaseData.areaSizeY.floatValue = 0.01f;
|
|
m_BaseData.shadowsType.enumValueIndex = (int)LightShadows.None;
|
|
break;
|
|
|
|
case (LightShape)(-1):
|
|
// don't do anything, this is just to handle multi selection
|
|
break;
|
|
|
|
default:
|
|
Debug.Assert(false, "Not implemented light type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DrawLightSettings()
|
|
{
|
|
if (GraphicsSettings.lightsUseLinearIntensity && GraphicsSettings.lightsUseColorTemperature)
|
|
{
|
|
EditorGUILayout.PropertyField(m_BaseData.useColorTemperature, s_Styles.useColorTemperature);
|
|
if (m_BaseData.useColorTemperature.boolValue)
|
|
{
|
|
const float kMinKelvin = 1000f;
|
|
const float kMaxKelvin = 20000f;
|
|
|
|
EditorGUILayout.LabelField(s_Styles.color);
|
|
EditorGUI.indentLevel += 1;
|
|
EditorGUILayout.PropertyField(m_BaseData.color, s_Styles.colorFilter);
|
|
EditorGUILayout.Slider(m_BaseData.colorTemperature, kMinKelvin, kMaxKelvin, s_Styles.colorTemperature);
|
|
EditorGUI.indentLevel -= 1;
|
|
}
|
|
else EditorGUILayout.PropertyField(m_BaseData.color, s_Styles.color);
|
|
}
|
|
else EditorGUILayout.PropertyField(m_BaseData.color, s_Styles.color);
|
|
|
|
EditorGUILayout.PropertyField(m_BaseData.intensity, s_Styles.intensity);
|
|
EditorGUILayout.PropertyField(m_BaseData.bounceIntensity, s_Styles.lightBounceIntensity);
|
|
|
|
// Indirect shadows warning (Should be removed when we support realtime indirect shadows)
|
|
if (m_BounceWarningValue)
|
|
EditorGUILayout.HelpBox(s_Styles.indirectBounceShadowWarning.text, MessageType.Info);
|
|
|
|
EditorGUILayout.PropertyField(m_BaseData.range, s_Styles.range);
|
|
EditorGUILayout.PropertyField(m_BaseData.lightmapping, s_Styles.lightmappingMode);
|
|
|
|
// Warning if GI Baking disabled and m_Lightmapping isn't realtime
|
|
if (m_BakingWarningValue)
|
|
EditorGUILayout.HelpBox(s_Styles.bakingWarning.text, MessageType.Info);
|
|
|
|
// No cookie with area light (maybe in future textured area light ?)
|
|
if (m_LightShape != LightShape.Rectangle && m_LightShape != LightShape.Line)
|
|
{
|
|
EditorGUILayout.PropertyField(m_BaseData.cookie, s_Styles.cookie);
|
|
|
|
// Warn on spotlights if the cookie is set to repeat
|
|
if (cookieWarningValue)
|
|
EditorGUILayout.HelpBox(s_Styles.cookieWarning.text, MessageType.Warning);
|
|
|
|
// When directional light use a cookie, it can control the size
|
|
if (m_Cookie != null && m_LightShape == LightShape.Directional)
|
|
{
|
|
EditorGUILayout.Slider(m_AdditionalLightData.shapeLength, 0.01f, 10f, s_Styles.cookieSizeX);
|
|
EditorGUILayout.Slider(m_AdditionalLightData.shapeWidth, 0.01f, 10f, s_Styles.cookieSizeY);
|
|
}
|
|
}
|
|
|
|
if (m_AdditionalLightData.showAdditionalSettings.boolValue)
|
|
{
|
|
EditorGUILayout.LabelField("Additional Settings", EditorStyles.boldLabel);
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.affectDiffuse, s_Styles.affectDiffuse);
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.affectSpecular, s_Styles.affectSpecular);
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.fadeDistance, s_Styles.fadeDistance);
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.lightDimmer, s_Styles.lightDimmer);
|
|
EditorGUILayout.PropertyField(m_AdditionalLightData.applyRangeAttenuation, s_Styles.applyRangeAttenuation);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
void DrawShadows()
|
|
{
|
|
if (m_IsCompletelyBaked)
|
|
{
|
|
switch ((LightType)m_BaseData.type.enumValueIndex)
|
|
{
|
|
case LightType.Directional:
|
|
EditorGUILayout.Slider(m_BaseData.bakedShadowAngle, 0f, 90f, s_Styles.bakedShadowAngle);
|
|
break;
|
|
case LightType.Spot:
|
|
case LightType.Point:
|
|
EditorGUILayout.PropertyField(m_BaseData.bakedShadowRadius, s_Styles.bakedShadowRadius);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
EditorGUILayout.PropertyField(m_AdditionalShadowData.resolution, s_Styles.shadowResolution);
|
|
EditorGUILayout.Slider(m_BaseData.shadowsBias, 0.001f, 1f, s_Styles.shadowBias);
|
|
EditorGUILayout.Slider(m_BaseData.shadowsNormalBias, 0.001f, 1f, s_Styles.shadowNormalBias);
|
|
EditorGUILayout.Slider(m_BaseData.shadowsNearPlane, 0.01f, 10f, s_Styles.shadowNearPlane);
|
|
|
|
if (m_BaseData.type.enumValueIndex != (int)LightType.Directional)
|
|
return;
|
|
|
|
using (var scope = new EditorGUI.ChangeCheckScope())
|
|
{
|
|
EditorGUILayout.IntSlider(m_AdditionalShadowData.cascadeCount, 1, 4, s_Styles.shadowCascadeCount);
|
|
|
|
if (scope.changed)
|
|
{
|
|
int len = m_AdditionalShadowData.cascadeCount.intValue;
|
|
m_AdditionalShadowData.cascadeRatios.arraySize = len - 1;
|
|
m_AdditionalShadowData.cascadeBorders.arraySize = len;
|
|
}
|
|
}
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
using (var scope = new EditorGUI.ChangeCheckScope())
|
|
{
|
|
// Draw each field first...
|
|
int arraySize = m_AdditionalShadowData.cascadeRatios.arraySize;
|
|
for (int i = 0; i < arraySize; i++)
|
|
EditorGUILayout.Slider(m_AdditionalShadowData.cascadeRatios.GetArrayElementAtIndex(i), 0f, 1f, s_Styles.shadowCascadeRatios[i]);
|
|
|
|
if (scope.changed)
|
|
{
|
|
// ...then clamp values to avoid out of bounds cascade ratios
|
|
for (int i = 0; i < arraySize; i++)
|
|
{
|
|
var ratios = m_AdditionalShadowData.cascadeRatios;
|
|
var ratioProp = ratios.GetArrayElementAtIndex(i);
|
|
float val = ratioProp.floatValue;
|
|
|
|
if (i > 0)
|
|
{
|
|
var prevRatioProp = ratios.GetArrayElementAtIndex(i - 1);
|
|
float prevVal = prevRatioProp.floatValue;
|
|
val = Mathf.Max(val, prevVal);
|
|
}
|
|
|
|
if (i < arraySize - 1)
|
|
{
|
|
var nextRatioProp = ratios.GetArrayElementAtIndex(i + 1);
|
|
float nextVal = nextRatioProp.floatValue;
|
|
val = Mathf.Min(val, nextVal);
|
|
}
|
|
|
|
ratioProp.floatValue = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
|
|
if (m_AdditionalLightData.showAdditionalSettings.boolValue)
|
|
{
|
|
EditorGUILayout.LabelField("Additional Settings", EditorStyles.boldLabel);
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.PropertyField(m_AdditionalShadowData.fadeDistance, s_Styles.shadowFadeDistance);
|
|
EditorGUILayout.PropertyField(m_AdditionalShadowData.dimmer, s_Styles.shadowDimmer);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
// Internal utilities
|
|
void ApplyAdditionalComponentsVisibility(bool hide)
|
|
{
|
|
var flags = hide ? HideFlags.HideInInspector : HideFlags.None;
|
|
|
|
foreach (var t in m_SerializedAdditionalLightData.targetObjects)
|
|
((HDAdditionalLightData)t).hideFlags = flags;
|
|
|
|
foreach (var t in m_SerializedAdditionalShadowData.targetObjects)
|
|
((AdditionalShadowData)t).hideFlags = flags;
|
|
}
|
|
|
|
void ResolveLightShape()
|
|
{
|
|
var type = m_BaseData.type;
|
|
|
|
// Special case for multi-selection: don't resolve light shape or it'll corrupt lights
|
|
if (type.hasMultipleDifferentValues)
|
|
{
|
|
m_LightShape = (LightShape)(-1);
|
|
return;
|
|
}
|
|
|
|
var lightTypeExtent = (LightTypeExtent)m_AdditionalLightData.lightTypeExtent.enumValueIndex;
|
|
|
|
if (lightTypeExtent == LightTypeExtent.Punctual)
|
|
{
|
|
switch ((LightType)type.enumValueIndex)
|
|
{
|
|
case LightType.Directional:
|
|
m_LightShape = LightShape.Directional;
|
|
break;
|
|
case LightType.Point:
|
|
m_LightShape = LightShape.Point;
|
|
break;
|
|
case LightType.Spot:
|
|
m_LightShape = LightShape.Spot;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (lightTypeExtent)
|
|
{
|
|
case LightTypeExtent.Rectangle:
|
|
m_LightShape = LightShape.Rectangle;
|
|
break;
|
|
case LightTypeExtent.Line:
|
|
m_LightShape = LightShape.Line;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: Move this to a generic EditorUtilities class
|
|
T[] GetAdditionalData<T>()
|
|
where T : Component
|
|
{
|
|
// Handles multi-selection
|
|
var data = targets.Cast<Component>()
|
|
.Select(t => t.GetComponent<T>())
|
|
.ToArray();
|
|
|
|
for (int i = 0; i < data.Length; i++)
|
|
{
|
|
if (data[i] == null)
|
|
data[i] = Undo.AddComponent<T>(((Component)targets[i]).gameObject);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
}
|
|
}
|