浏览代码

LightEditor refactor for 2017.3

Awaiting 2018.1 features to simplify & improve it
/stochastic_alpha_test
Thomas 7 年前
当前提交
c6639f12
共有 7 个文件被更改,包括 581 次插入483 次删除
  1. 11
      ScriptableRenderPipeline/HDRenderPipeline/AdditionalData/HDAdditionalLightData.cs
  2. 881
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Editor/HDLightEditor.cs
  3. 5
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/EditorLightUtilities.cs
  4. 62
      ScriptableRenderPipeline/Core/Editor/PropertyFetcher.cs
  5. 13
      ScriptableRenderPipeline/Core/Editor/PropertyFetcher.cs.meta
  6. 79
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Editor/HDLightEditor.Styles.cs
  7. 13
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Editor/HDLightEditor.Styles.cs.meta

11
ScriptableRenderPipeline/HDRenderPipeline/AdditionalData/HDAdditionalLightData.cs


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
// This enum extent the original LightType enum with new light type from HD
public enum LightTypeExtent
{
public enum LightTypeExtent
{
// Sphere,
// Sphere,
// Disc,
};

return Mathf.Clamp(m_InnerSpotPercent, 0.0f, 100.0f) / 100.0f;
}
[Range(0.0f, 1.0f)]
[Range(0.0f, 1.0f)]
public float lightDimmer = 1.0f;
// Not used for directional lights.

[FormerlySerializedAs("lightWidth")]
public float shapeWidth = 0.5f;
// Only for Sphere/Disc
// Only for Sphere/Disc
public float shapeRadius = 0.0f;
// Only for Spot/Point - use to cheaply fake specular spherical area light

// This is specific for the LightEditor GUI and not use at runtime
public bool useOldInspector = false;
public bool featuresFoldout = true;
public bool showAdditionalSettings = true; // TODO: Maybe we can remove if if we decide to always show additional settings
#if UNITY_EDITOR

881
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Editor/HDLightEditor.cs


using System;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEditor.Experimental.Rendering;
using System.Linq;
[CustomEditorForRenderPipeline(typeof(Light), typeof(HDRenderPipelineAsset))]
// TODO: Simplify this editor once we can target 2018.1
public class HDLightEditor : Editor
[CustomEditorForRenderPipeline(typeof(Light), typeof(HDRenderPipelineAsset))]
sealed partial class HDLightEditor : LightEditor
// Original light editor
SerializedProperty m_Type;
SerializedProperty m_Range;
SerializedProperty m_SpotAngle;
SerializedProperty m_CookieSize;
SerializedProperty m_Color;
SerializedProperty m_Intensity;
SerializedProperty m_BounceIntensity;
SerializedProperty m_ColorTemperature;
SerializedProperty m_UseColorTemperature;
SerializedProperty m_Cookie;
SerializedProperty m_ShadowsType;
SerializedProperty m_ShadowsStrength;
SerializedProperty m_ShadowsResolution;
SerializedProperty m_ShadowsBias;
SerializedProperty m_ShadowsNormalBias;
SerializedProperty m_ShadowsNearPlane;
SerializedProperty m_Flare;
SerializedProperty m_RenderMode;
SerializedProperty m_CullingMask;
SerializedProperty m_Lightmapping;
SerializedProperty m_AreaSizeX;
SerializedProperty m_AreaSizeY;
SerializedProperty m_BakedShadowRadius;
SerializedProperty m_BakedShadowAngle;
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;
}
// HD Light editor part
SerializedObject additionalDataSerializedObject;
SerializedObject shadowDataSerializedObject;
sealed class SerializedShadowData
{
public SerializedProperty dimmer;
public SerializedProperty fadeDistance;
public SerializedProperty cascadeCount;
public SerializedProperty cascadeRatios;
public SerializedProperty cascadeBorders;
public SerializedProperty resolution;
}
SerializedProperty m_SpotInnerPercent;
SerializedProperty m_LightDimmer;
SerializedProperty m_FadeDistance;
SerializedProperty m_AffectDiffuse;
SerializedProperty m_AffectSpecular;
SerializedProperty m_LightTypeExtent;
SerializedProperty m_SpotLightShape;
SerializedProperty m_ShapeLength;
SerializedProperty m_ShapeWidth;
SerializedProperty m_ShapeRadius;
SerializedProperty m_MaxSmoothness;
SerializedProperty m_ApplyRangeAttenuation;
SerializedObject m_SerializedAdditionalLightData;
SerializedObject m_SerializedAdditionalShadowData;
// Extra data for GUI only
SerializedProperty m_UseOldInspector;
SerializedProperty m_ShowAdditionalSettings;
SerializedBaseData m_BaseData;
SerializedLightData m_AdditionalLightData;
SerializedShadowData m_AdditionalShadowData;
SerializedProperty m_ShadowDimmer;
SerializedProperty m_ShadowFadeDistance;
SerializedProperty m_ShadowCascadeCount;
SerializedProperty m_ShadowCascadeRatios;
SerializedProperty m_ShadowCascadeBorders;
SerializedProperty m_ShadowResolution;
// 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;
}
}
// This enum below is LightType enum + LightTypeExtent enum
public enum LightShape
// LightType + LightTypeExtent combined
enum LightShape
//Area, <= offline type of Unity not dispay in our case but reuse for GI of our area light
//Area, <= offline base type not displayed in our case but used for GI of our area light
// Sphere,
// Disc,
//Sphere,
//Disc,
// LightShape is use for displaying UI only. The processing code must use LightTypeExtent and LightType
// Used for UI only; the processing code must use LightTypeExtent and LightType
private Light light { get { return target as Light; } }
// Note: There is no Lightmapping enum, the code C# side must use int
// Light.h file: int m_Lightmapping; ///< enum { Dynamic=4, Stationary=1, Static=2 }
// Lighting.h file:
// enum LightmapBakeType (not accessible in C#)
//{
// kLightRealtime = 1 << 2, // Light is realtime
// kLightBaked = 1 << 1, // light will always be fully baked
// kLightMixed = 1 << 0, // depends on selected LightmapMixedBakeMode
//};
// This mean that m_Lightmapping.enumValueIndex is enum { Mixed=0, Baked=1, Realtime=2 }
enum LightMappingType
void OnEnable()
Mixed,
Baked,
Realtime
}
// 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);
protected class Styles
{
public static GUIContent CookieSizeX = new GUIContent("CookieSizeX", "");
public static GUIContent CookieSizeY = new GUIContent("CookieSizeY", "");
// 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")
};
public static GUIContent ShapeLengthLine = new GUIContent("Length", "Length of the line light");
public static GUIContent ShapeLengthRect = new GUIContent("SizeX", "SizeX of the rectangle light");
public static GUIContent ShapeWidthRect = new GUIContent("SizeY", "SizeY of the rectangle light");
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),
public static GUIContent ShapeLengthPyramid = new GUIContent("SizeX", "");
public static GUIContent ShapeWidthPyramid = new GUIContent("SizeY", "");
public static GUIContent ShapeLengthBox = new GUIContent("SizeX", "");
public static GUIContent ShapeWidthBox = new GUIContent("SizeY", "");
public static GUIContent MaxSmoothness = new GUIContent("MaxSmoothness", "Very low cost way of faking spherical area lighting. This will modify the roughness of the material lit. This is useful when the specular highlight is too small or too sharp.");
public static GUIContent SpotLightShape = new GUIContent("SpotLightShape", "The shape use for the spotlight. Has an impact on the cookie transformation and light angular attenuation.");
// Editor stuff
useOldInspector = o.FindProperty(x => x.useOldInspector),
showFeatures = o.FindProperty(x => x.featuresFoldout),
showAdditionalSettings = o.FindProperty(x => x.showAdditionalSettings)
};
public static GUIContent SpotAngle = new GUIContent("Spot Angle", "Controls the angle in degrees at the base of a Spot light's cone.");
public static GUIContent SpotInnerPercent = new GUIContent("Spot Inner Percent", "Controls size of the angular attenuation in percent of the base angle of the Spot light's cone.");
// 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 static GUIContent Color = new GUIContent("Color", "Controls the color being emitted by the light.");
public static GUIContent Intensity = new GUIContent("Intensity", "Controls the brightness of the light. Light color is multiplied by this value.");
public static GUIContent Range = new GUIContent("Range", "Controls how far the light is emitted from the center of the object.");
public static GUIContent LightmappingMode = new GUIContent("Mode", "Specifies the light mode used to determine if and how a light will be baked. Possible modes are Baked, Mixed, and Realtime.");
public static GUIContent BounceIntensity = new GUIContent("Indirect Multiplier", "Controls the intensity of indirect light being contributed to the scene. A value of 0 will cause Realtime lights to be removed from realtime global illumination and Baked and Mixed lights to no longer emit indirect lighting. Has no effect when both Realtime and Baked Global Illumination are disabled.");
public static GUIContent Cookie = new GUIContent("Cookie", "Specifies the Texture projected by the light. Spotlights require 2D texture and pointlights require texture cube.");
public static GUIContent BakedShadowRadius = new GUIContent("Baked Shadow Radius", "Controls the amount of artificial softening applied to the edges of shadows cast by the Point or Spot light.");
public static GUIContent BakedShadowAngle = new GUIContent("Baked Shadow Angle", "Controls the amount of artificial softening applied to the edges of shadows cast by directional lights.");
public static GUIContent ShadowResolution = new GUIContent("Resolution", "Controls the rendered resolution of the shadow maps. A higher resolution will increase the fidelity of shadows at the cost of GPU performance and memory usage.");
public static GUIContent ShadowBias = new GUIContent("Bias", "Controls the distance at which the shadows will be pushed away from the light. Useful for avoiding false self-shadowing artifacts.");
public static GUIContent ShadowNormalBias = new GUIContent("Normal Bias", "Controls distance at which the shadow casting surfaces will be shrunk along the surface normal. Useful for avoiding false self-shadowing artifacts.");
public static GUIContent ShadowNearPlane = new GUIContent("Near Plane", "Controls the value for the near clip plane when rendering shadows. Currently clamped to 0.1 units or 1% of the lights range property, whichever is lower.");
public static GUIContent ShadowCascadeCount = new GUIContent("ShadowCascadeCount", "");
public static GUIContent[] ShadowCascadeRatios = new GUIContent[6] { new GUIContent("Cascade 1"), new GUIContent("Cascade 2"), new GUIContent("Cascade 3"), new GUIContent("Cascade 4"), new GUIContent("Cascade 5"), new GUIContent("Cascade 6") };
public static GUIContent AffectDiffuse = new GUIContent("AffectDiffuse", "This will disable diffuse lighting for this light. Doesn't save performance, diffuse lighting is still computed.");
public static GUIContent AffectSpecular = new GUIContent("AffectSpecular", "This will disable specular lighting for this light. Doesn't save performance, specular lighting is still computed.");
public static GUIContent FadeDistance = new GUIContent("FadeDistance", "The distance at which the light will smoothly fade before being culled to minimize popping.");
public static GUIContent LightDimmer = new GUIContent("LightDimmer", "Aim to be used with script, timeline or animation. It allows dimming one or multiple lights of heterogeneous intensity easily (without needing to know the intensity of each light).");
public static GUIContent ApplyRangeAttenuation = new GUIContent("ApplyRangeAttenuation", "Allows disabling range attenuation. This is useful indoor (like a room) to avoid having to setup a large range for a light to get correct inverse square attenuation that may leak out of the indoor");
public static GUIContent ShadowFadeDistance = new GUIContent("ShadowFadeDistance", "The shadow will fade at distance ShadowFadeDistance before being culled to minimize popping.");
public static GUIContent ShadowDimmer = new GUIContent("ShadowDimmer", "Aim to be use with script, timeline or animation. It allows dimming one or multiple shadows. This can also be used as an optimization to fit in shadow budget manually and minimize popping.");
public override void OnInspectorGUI()
{
m_SerializedAdditionalLightData.Update();
m_SerializedAdditionalShadowData.Update();
public static GUIContent DisabledLightWarning = new GUIContent("Lighting has been disabled in at least one Scene view. Any changes applied to lights in the Scene will not be updated in these views until Lighting has been enabled again.");
public static GUIContent CookieWarning = new GUIContent("Cookie textures for spot lights must be set to clamp. Repeat is not supported.");
public static GUIContent IndirectBounceShadowWarning = new GUIContent("Realtime indirect bounce shadowing is not supported for Spot and Point lights.");
public static GUIContent BakingWarning = new GUIContent("Light mode is currently overridden to Realtime mode. Enable Baked Global Illumination to use Mixed or Baked light modes.");
// Temporary toggle to go back to the old editor & separated additional datas
bool useOldInspector = m_AdditionalLightData.useOldInspector.boolValue;
public static string lightShapeText = "LightShape";
public static readonly string[] lightShapeNames = Enum.GetNames(typeof(LightShape));
if (GUILayout.Button("Toggle default light editor"))
useOldInspector = !useOldInspector;
public static string lightmappingModeText = "Mode";
public static readonly string[] lightmappingModeNames = Enum.GetNames(typeof(LightMappingType));
}
m_AdditionalLightData.useOldInspector.boolValue = useOldInspector;
static Styles s_Styles;
if (useOldInspector)
{
DrawDefaultInspector();
ApplyAdditionalComponentsVisibility(false);
m_SerializedAdditionalShadowData.ApplyModifiedProperties();
m_SerializedAdditionalLightData.ApplyModifiedProperties();
return;
}
// Should match same colors in GizmoDrawers.cpp!
static Color kGizmoLight = new Color(254 / 255f, 253 / 255f, 136 / 255f, 128 / 255f);
static Color kGizmoDisabledLight = new Color(135 / 255f, 116 / 255f, 50 / 255f, 128 / 255f);
// New editor
ApplyAdditionalComponentsVisibility(true);
CheckStyles();
private bool typeIsSame { get { return !m_Type.hasMultipleDifferentValues; } }
private Texture cookie { get { return m_Cookie.objectReferenceValue as Texture; } }
serializedObject.Update();
private bool lightmappingTypeIsSame { get { return !m_Lightmapping.hasMultipleDifferentValues; } }
ResolveLightShape();
private bool isRealtime { get { return m_Lightmapping.enumValueIndex == (int)LightMappingType.Realtime; } }
DrawFoldout(m_AdditionalLightData.showFeatures, "Features", DrawFeatures);
DrawFoldout(m_BaseData.type, "Shape", DrawShape);
DrawFoldout(m_BaseData.intensity, "Light", DrawLightSettings);
private bool isBakedOrMixed { get { return !isRealtime; } }
if (m_BaseData.shadowsType.enumValueIndex != (int)LightShadows.None)
DrawFoldout(m_BaseData.shadowsType, "Shadows", DrawShadows);
private bool bakingWarningValue { get { return !Lightmapping.bakedGI && lightmappingTypeIsSame && isBakedOrMixed; } }
EditorLightUtilities.DrawSplitter();
EditorGUILayout.Space();
private bool cookieWarningValue
{
get
{
return typeIsSame && light.type == LightType.Spot &&
!m_Cookie.hasMultipleDifferentValues && cookie && cookie.wrapMode != TextureWrapMode.Clamp;
}
}
private bool bounceWarningValue
{
get
{
return typeIsSame && (light.type == LightType.Point || light.type == LightType.Spot) &&
lightmappingTypeIsSame && isRealtime && !m_BounceIntensity.hasMultipleDifferentValues && m_BounceIntensity.floatValue > 0.0f && m_ShadowsType.enumValueIndex != (int)LightShadows.None;
}
m_SerializedAdditionalShadowData.ApplyModifiedProperties();
m_SerializedAdditionalLightData.ApplyModifiedProperties();
serializedObject.ApplyModifiedProperties();
private void OnEnable()
void DrawFoldout(SerializedProperty foldoutProperty, string title, Action func)
m_Type = serializedObject.FindProperty("m_Type");
m_Range = serializedObject.FindProperty("m_Range");
m_SpotAngle = serializedObject.FindProperty("m_SpotAngle");
m_CookieSize = serializedObject.FindProperty("m_CookieSize");
m_Color = serializedObject.FindProperty("m_Color");
m_Intensity = serializedObject.FindProperty("m_Intensity");
m_BounceIntensity = serializedObject.FindProperty("m_BounceIntensity");
m_ColorTemperature = serializedObject.FindProperty("m_ColorTemperature");
m_UseColorTemperature = serializedObject.FindProperty("m_UseColorTemperature");
m_Cookie = serializedObject.FindProperty("m_Cookie");
m_ShadowsType = serializedObject.FindProperty("m_Shadows.m_Type");
m_ShadowsStrength = serializedObject.FindProperty("m_Shadows.m_Strength");
m_ShadowsResolution = serializedObject.FindProperty("m_Shadows.m_Resolution");
m_ShadowsBias = serializedObject.FindProperty("m_Shadows.m_Bias");
m_ShadowsNormalBias = serializedObject.FindProperty("m_Shadows.m_NormalBias");
m_ShadowsNearPlane = serializedObject.FindProperty("m_Shadows.m_NearPlane");
m_Flare = serializedObject.FindProperty("m_Flare");
m_RenderMode = serializedObject.FindProperty("m_RenderMode");
m_CullingMask = serializedObject.FindProperty("m_CullingMask");
m_Lightmapping = serializedObject.FindProperty("m_Lightmapping");
m_AreaSizeX = serializedObject.FindProperty("m_AreaSize.x");
m_AreaSizeY = serializedObject.FindProperty("m_AreaSize.y");
m_BakedShadowRadius = serializedObject.FindProperty("m_ShadowRadius");
m_BakedShadowAngle = serializedObject.FindProperty("m_ShadowAngle");
EditorLightUtilities.DrawSplitter();
// Automatically add HD data if not present
// We need to handle multiSelection. To do this we need to get the array of selection and assign it to additionalDataSerializedObject
// additionalDataSerializedObject must be see as an array of selection in all following operation (this is transparent)
bool state = foldoutProperty.isExpanded;
state = EditorLightUtilities.DrawHeaderFoldout(title, state);
var additionalDatas = this.targets.Select(t => (t as Component).GetComponent<HDAdditionalLightData>()).ToArray();
var shadowDatas = this.targets.Select(t => (t as Component).GetComponent<AdditionalShadowData>()).ToArray();
for (int i = 0; i < additionalDatas.Length; ++i)
{
if (additionalDatas[i] == null)
{
additionalDatas[i] = Undo.AddComponent<HDAdditionalLightData>((targets[i] as Component).gameObject);
}
}
for (int i = 0; i < shadowDatas.Length; ++i)
if (state)
if (shadowDatas[i] == null)
{
shadowDatas[i] = Undo.AddComponent<AdditionalShadowData>((targets[i] as Component).gameObject);
}
EditorGUI.indentLevel++;
func();
EditorGUI.indentLevel--;
GUILayout.Space(2f);
additionalDataSerializedObject = new SerializedObject(additionalDatas);
shadowDataSerializedObject = new SerializedObject(shadowDatas);
// Additional data
m_SpotInnerPercent = additionalDataSerializedObject.FindProperty("m_InnerSpotPercent");
m_LightDimmer = additionalDataSerializedObject.FindProperty("lightDimmer");
m_FadeDistance = additionalDataSerializedObject.FindProperty("fadeDistance");
m_AffectDiffuse = additionalDataSerializedObject.FindProperty("affectDiffuse");
m_AffectSpecular = additionalDataSerializedObject.FindProperty("affectSpecular");
m_LightTypeExtent = additionalDataSerializedObject.FindProperty("lightTypeExtent");
m_SpotLightShape = additionalDataSerializedObject.FindProperty("spotLightShape");
m_ShapeLength = additionalDataSerializedObject.FindProperty("shapeLength");
m_ShapeWidth = additionalDataSerializedObject.FindProperty("shapeWidth");
m_ShapeRadius = additionalDataSerializedObject.FindProperty("shapeRadius");
m_MaxSmoothness = additionalDataSerializedObject.FindProperty("maxSmoothness");
m_ApplyRangeAttenuation = additionalDataSerializedObject.FindProperty("applyRangeAttenuation");
// Editor only
m_UseOldInspector = additionalDataSerializedObject.FindProperty("useOldInspector");
m_ShowAdditionalSettings = additionalDataSerializedObject.FindProperty("showAdditionalSettings");
// Shadow data
m_ShadowDimmer = shadowDataSerializedObject.FindProperty("shadowDimmer");
m_ShadowFadeDistance = shadowDataSerializedObject.FindProperty("shadowFadeDistance");
m_ShadowCascadeCount = shadowDataSerializedObject.FindProperty("shadowCascadeCount");
m_ShadowCascadeRatios = shadowDataSerializedObject.FindProperty("shadowCascadeRatios");
m_ShadowCascadeBorders = shadowDataSerializedObject.FindProperty("shadowCascadeBorders");
m_ShadowResolution = shadowDataSerializedObject.FindProperty("shadowResolution");
foldoutProperty.isExpanded = state;
void ResolveLightShape()
void DrawFeatures()
// When we do multiple selection we must not avoid to chose a type, else it may corrupt light
if (m_Type.hasMultipleDifferentValues)
{
m_LightShape = (LightShape)(-1);
EditorGUILayout.PropertyField(m_AdditionalLightData.showAdditionalSettings);
return;
}
bool disabledScope = m_IsCompletelyBaked
|| m_LightShape == LightShape.Line
|| m_LightShape == LightShape.Rectangle;
if (m_LightTypeExtent.enumValueIndex == (int)LightTypeExtent.Punctual)
using (new EditorGUI.DisabledScope(disabledScope))
switch ((LightType)m_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)m_LightTypeExtent.enumValueIndex)
{
case LightTypeExtent.Rectangle:
m_LightShape = LightShape.Rectangle;
break;
case LightTypeExtent.Line:
m_LightShape = LightShape.Line;
break;
}
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 LigthShapeGUI()
void DrawShape()
m_LightShape = (LightShape)EditorGUILayout.Popup(Styles.lightShapeText, (int)m_LightShape, Styles.lightShapeNames);
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
// 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
m_Type.enumValueIndex = (int)LightType.Directional;
m_LightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual;
m_BaseData.type.enumValueIndex = (int)LightType.Directional;
m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual;
m_Type.enumValueIndex = (int)LightType.Point;
m_LightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual;
EditorGUILayout.PropertyField(m_MaxSmoothness, Styles.MaxSmoothness);
m_BaseData.type.enumValueIndex = (int)LightType.Point;
m_AdditionalLightData.lightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual;
EditorGUILayout.PropertyField(m_AdditionalLightData.maxSmoothness, s_Styles.maxSmoothness);
m_Type.enumValueIndex = (int)LightType.Spot;
m_LightTypeExtent.enumValueIndex = (int)LightTypeExtent.Punctual;
EditorGUILayout.PropertyField(m_SpotLightShape, Styles.SpotLightShape);
//Cone Spot
if (m_SpotLightShape.enumValueIndex == (int)SpotLightShape.Cone)
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_SpotAngle, 1f, 179f, Styles.SpotAngle);
EditorGUILayout.Slider(m_SpotInnerPercent, 0f, 100f, Styles.SpotInnerPercent);
EditorGUILayout.Slider(m_BaseData.spotAngle, 0f, 179.9f, s_Styles.spotAngle);
EditorGUILayout.Slider(m_AdditionalLightData.spotInnerPercent, 0f, 100f, s_Styles.spotInnerPercent);
if (m_SpotLightShape.enumValueIndex == (int)SpotLightShape.Pyramid)
else if (spotLightShape == SpotLightShape.Pyramid)
EditorGUILayout.Slider(m_ShapeLength, 0.01f, 10, Styles.ShapeLengthPyramid);
EditorGUILayout.Slider(m_ShapeWidth, 0.01f, 10, Styles.ShapeWidthPyramid);
EditorGUILayout.Slider(m_AdditionalLightData.shapeLength, 0.01f, 10f, s_Styles.shapeLengthPyramid);
EditorGUILayout.Slider(m_AdditionalLightData.shapeWidth, 0.01f, 10f, s_Styles.shapeWidthPyramid);
if (m_SpotLightShape.enumValueIndex == (int)SpotLightShape.Box)
else if (spotLightShape == SpotLightShape.Box)
EditorGUILayout.PropertyField(m_ShapeLength, Styles.ShapeLengthBox);
EditorGUILayout.PropertyField(m_ShapeWidth, Styles.ShapeWidthBox);
EditorGUILayout.PropertyField(m_AdditionalLightData.shapeLength, s_Styles.shapeLengthBox);
EditorGUILayout.PropertyField(m_AdditionalLightData.shapeWidth, s_Styles.shapeWidthBox);
EditorGUILayout.PropertyField(m_MaxSmoothness, Styles.MaxSmoothness);
EditorGUILayout.PropertyField(m_AdditionalLightData.maxSmoothness, s_Styles.maxSmoothness);
//m_Type.enumValueIndex = (int)LightType.Area;
m_Type.enumValueIndex = (int)LightType.Point;
m_LightTypeExtent.enumValueIndex = (int)LightTypeExtent.Rectangle;
EditorGUILayout.PropertyField(m_ShapeLength, Styles.ShapeLengthRect);
EditorGUILayout.PropertyField(m_ShapeWidth, Styles.ShapeWidthRect);
m_AreaSizeX.floatValue = m_ShapeLength.floatValue;
m_AreaSizeY.floatValue = m_ShapeWidth.floatValue;
m_ShadowsType.enumValueIndex = (int)LightShadows.None;
//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;
//m_Type.enumValueIndex = (int)LightType.Area;
m_Type.enumValueIndex = (int)LightType.Point;
m_LightTypeExtent.enumValueIndex = (int)LightTypeExtent.Line;
EditorGUILayout.PropertyField(m_ShapeLength, Styles.ShapeLengthLine);
//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);
m_AreaSizeX.floatValue = m_ShapeLength.floatValue;
m_AreaSizeY.floatValue = 0.01f;
m_ShadowsType.enumValueIndex = (int)LightShadows.None;
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):

}
}
void LightGUI()
void DrawLightSettings()
EditorGUILayout.PropertyField(m_Color, Styles.Color);
EditorGUILayout.PropertyField(m_Intensity, Styles.Intensity);
EditorGUILayout.PropertyField(m_BounceIntensity, Styles.BounceIntensity);
// Indirect shadows warning (Should be removed when we support realtime indirect shadows)
if (bounceWarningValue)
if (GraphicsSettings.lightsUseLinearIntensity && GraphicsSettings.lightsUseColorTemperature)
EditorGUILayout.HelpBox(Styles.IndirectBounceShadowWarning.text, MessageType.Info);
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);
EditorGUILayout.PropertyField(m_Range, Styles.Range);
else EditorGUILayout.PropertyField(m_BaseData.color, s_Styles.color);
// We need to overwrite the name of the default enum that doesn't make any sense
// EditorGUILayout.PropertyField(m_Lightmapping, Styles.LightmappingMode);
m_Lightmapping.enumValueIndex = EditorGUILayout.Popup(Styles.lightmappingModeText, (int)m_Lightmapping.enumValueIndex, Styles.lightmappingModeNames);
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);
if (bakingWarningValue)
{
EditorGUILayout.HelpBox(Styles.BakingWarning.text, MessageType.Info);
}
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))
// No cookie with area light (maybe in future textured area light ?)
if (m_LightShape != LightShape.Rectangle && m_LightShape != LightShape.Line)
EditorGUILayout.PropertyField(m_Cookie, Styles.Cookie);
EditorGUILayout.PropertyField(m_BaseData.cookie, s_Styles.cookie);
// When directional light use a cookie, it can control the size
if (m_LightShape == LightShape.Directional)
{
EditorGUILayout.Slider(m_ShapeLength, 0.01f, 10, Styles.CookieSizeX);
EditorGUILayout.Slider(m_ShapeWidth, 0.01f, 10, Styles.CookieSizeY);
}
// Warn on spotlights if the cookie is set to repeat
{
// warn on spotlights if the cookie is set to repeat
EditorGUILayout.HelpBox(Styles.CookieWarning.text, MessageType.Warning);
}
}
}
EditorGUILayout.HelpBox(s_Styles.cookieWarning.text, MessageType.Warning);
void ShadowsGUI()
{
if (m_ShadowsType.enumValueIndex != (int)LightShadows.None)
{
if (m_Lightmapping.enumValueIndex == (int)LightMappingType.Baked)
{
switch ((LightType)m_Type.enumValueIndex)
{
case LightType.Directional:
EditorGUILayout.PropertyField(m_BakedShadowAngle, Styles.BakedShadowAngle);
break;
case LightType.Spot:
case LightType.Point:
EditorGUILayout.PropertyField(m_BakedShadowRadius, Styles.BakedShadowRadius);
break;
}
}
else
// When directional light use a cookie, it can control the size
if (m_Cookie != null && m_LightShape == LightShape.Directional)
EditorGUILayout.PropertyField(m_ShadowResolution, Styles.ShadowResolution);
EditorGUILayout.Slider(m_ShadowsBias, 0.001f, 1, Styles.ShadowBias);
EditorGUILayout.Slider(m_ShadowsNormalBias, 0.001f, 1, Styles.ShadowNormalBias);
EditorGUILayout.Slider(m_ShadowsNearPlane, 0.01f, 10, Styles.ShadowNearPlane);
EditorGUILayout.Slider(m_AdditionalLightData.shapeLength, 0.01f, 10f, s_Styles.cookieSizeX);
EditorGUILayout.Slider(m_AdditionalLightData.shapeWidth, 0.01f, 10f, s_Styles.cookieSizeY);
}
void ShadowsCascadeGUI()
{
UnityEditor.EditorGUI.BeginChangeCheck();
EditorGUILayout.IntSlider(m_ShadowCascadeCount, 1, 4, Styles.ShadowCascadeCount);
if (UnityEditor.EditorGUI.EndChangeCheck())
if (m_AdditionalLightData.showAdditionalSettings.boolValue)
m_ShadowCascadeRatios.arraySize = m_ShadowCascadeCount.intValue - 1;
m_ShadowCascadeBorders.arraySize = m_ShadowCascadeCount.intValue;
}
for (int i = 0; i < m_ShadowCascadeRatios.arraySize; i++)
{
UnityEditor.EditorGUILayout.Slider(m_ShadowCascadeRatios.GetArrayElementAtIndex(i), 0.0f, 1.0f, Styles.ShadowCascadeRatios[i]);
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 AdditionalSettingsGUI()
void DrawShadows()
// Currently culling mask is not working with HD
// EditorGUILayout.LabelField(new GUIContent("General"), EditorStyles.boldLabel);
// EditorGUILayout.PropertyField(m_CullingMask);
EditorGUILayout.LabelField(new GUIContent("Light"), EditorStyles.boldLabel);
EditorGUILayout.PropertyField(m_AffectDiffuse, Styles.AffectDiffuse);
EditorGUILayout.PropertyField(m_AffectSpecular, Styles.AffectSpecular);
EditorGUILayout.PropertyField(m_FadeDistance, Styles.FadeDistance);
EditorGUILayout.PropertyField(m_LightDimmer, Styles.LightDimmer);
EditorGUILayout.PropertyField(m_ApplyRangeAttenuation, Styles.ApplyRangeAttenuation);
if (m_ShadowsType.enumValueIndex != (int)LightShadows.None && m_Lightmapping.enumValueIndex != (int)LightMappingType.Baked)
if (m_IsCompletelyBaked)
EditorGUILayout.LabelField(new GUIContent("Shadows"), EditorStyles.boldLabel);
EditorGUILayout.PropertyField(m_ShadowFadeDistance, Styles.ShadowFadeDistance);
EditorGUILayout.PropertyField(m_ShadowDimmer, Styles.ShadowDimmer);
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;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
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);
// Sanity check
if (additionalDataSerializedObject == null || shadowDataSerializedObject == null)
if (m_BaseData.type.enumValueIndex != (int)LightType.Directional)
additionalDataSerializedObject.Update();
shadowDataSerializedObject.Update();
ResolveLightShape();
if (GUILayout.Button("Toggle light editor"))
using (var scope = new EditorGUI.ChangeCheckScope())
m_UseOldInspector.boolValue = !m_UseOldInspector.boolValue;
}
EditorGUILayout.IntSlider(m_AdditionalShadowData.cascadeCount, 1, 4, s_Styles.shadowCascadeCount);
EditorGUILayout.Space();
if (m_UseOldInspector.boolValue)
{
base.DrawDefaultInspector();
ApplyAdditionalComponentsVisibility(false);
serializedObject.ApplyModifiedProperties();
// It is required to save m_UseOldInspector value
additionalDataSerializedObject.ApplyModifiedProperties();
shadowDataSerializedObject.ApplyModifiedProperties(); // Should not be needed but if we do some change, could be, so let it here.
return;
if (scope.changed)
{
int len = m_AdditionalShadowData.cascadeCount.intValue;
m_AdditionalShadowData.cascadeRatios.arraySize = len - 1;
m_AdditionalShadowData.cascadeBorders.arraySize = len;
}
ApplyAdditionalComponentsVisibility(true);
// Light features
EditorGUILayout.LabelField(new GUIContent("Light features"), EditorStyles.boldLabel);
// Do not display option for shadow if we are fully bake
if (m_Lightmapping.enumValueIndex != (int)LightMappingType.Baked)
using (var scope = new EditorGUI.ChangeCheckScope())
if (EditorGUILayout.Toggle(new GUIContent("Enable Shadow"), m_ShadowsType.enumValueIndex != 0))
m_ShadowsType.enumValueIndex = (int)LightShadows.Hard;
else
m_ShadowsType.enumValueIndex = (int)LightShadows.None;
}
// 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]);
EditorGUI.indentLevel--;
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;
// Allow to display the arrow for reduce/expand correctly
EditorGUI.indentLevel = 1;
if (i > 0)
{
var prevRatioProp = ratios.GetArrayElementAtIndex(i - 1);
float prevVal = prevRatioProp.floatValue;
val = Mathf.Max(val, prevVal);
}
// LightShape
EditorGUI.indentLevel--;
EditorLightUtilities.DrawSplitter();
m_Type.isExpanded = EditorLightUtilities.DrawHeaderFoldout("Shape", m_Type.isExpanded);
EditorGUI.indentLevel++;
if (i < arraySize - 1)
{
var nextRatioProp = ratios.GetArrayElementAtIndex(i + 1);
float nextVal = nextRatioProp.floatValue;
val = Mathf.Min(val, nextVal);
}
if (m_Type.isExpanded)
{
LigthShapeGUI();
ratioProp.floatValue = val;
}
}
// Light
EditorLightUtilities.DrawSplitter();
m_Intensity.isExpanded = EditorLightUtilities.DrawHeaderFoldout("Light", m_Intensity.isExpanded);
EditorGUI.indentLevel++;
if (m_Intensity.isExpanded)
if (m_AdditionalLightData.showAdditionalSettings.boolValue)
LightGUI();
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--;
}
// Shadows
if (m_ShadowsType.enumValueIndex != (int)LightShadows.None)
{
EditorGUI.indentLevel--;
EditorLightUtilities.DrawSplitter();
m_ShadowsType.isExpanded = EditorLightUtilities.DrawHeaderFoldout("Shadow", m_ShadowsType.isExpanded);
EditorGUI.indentLevel++;
// Internal utilities
void ApplyAdditionalComponentsVisibility(bool hide)
{
var flags = hide ? HideFlags.HideInInspector : HideFlags.None;
if (m_ShadowsType.isExpanded)
{
ShadowsGUI();
}
foreach (var t in m_SerializedAdditionalLightData.targetObjects)
((HDAdditionalLightData)t).hideFlags = flags;
// shadow cascade
if (m_Type.enumValueIndex == (int)LightType.Directional && m_Lightmapping.enumValueIndex != (int)LightMappingType.Baked)
{
EditorGUI.indentLevel--;
EditorLightUtilities.DrawSplitter();
m_ShadowCascadeCount.isExpanded = EditorLightUtilities.DrawHeaderFoldout("ShadowCascades", m_ShadowCascadeCount.isExpanded);
EditorGUI.indentLevel++;
foreach (var t in m_SerializedAdditionalShadowData.targetObjects)
((AdditionalShadowData)t).hideFlags = flags;
}
if (m_ShadowCascadeCount.isExpanded)
{
ShadowsCascadeGUI();
}
}
}
void ResolveLightShape()
{
var type = m_BaseData.type;
// AdditionalSettings
EditorGUI.indentLevel--;
EditorLightUtilities.DrawSplitter();
m_ShowAdditionalSettings.boolValue = EditorLightUtilities.DrawHeaderFoldout("Additional Settings", m_ShowAdditionalSettings.boolValue);
EditorGUI.indentLevel++;
if (m_ShowAdditionalSettings.boolValue)
// Special case for multi-selection: don't resolve light shape or it'll corrupt lights
if (type.hasMultipleDifferentValues)
AdditionalSettingsGUI();
m_LightShape = (LightShape)(-1);
return;
EditorGUI.indentLevel = 0; // Reset the value that we have init to 1
var lightTypeExtent = (LightTypeExtent)m_AdditionalLightData.lightTypeExtent.enumValueIndex;
if (SceneView.lastActiveSceneView != null && SceneView.lastActiveSceneView.m_SceneLighting == false)
if (lightTypeExtent == LightTypeExtent.Punctual)
EditorGUILayout.HelpBox(Styles.DisabledLightWarning.text, MessageType.Warning);
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;
}
serializedObject.ApplyModifiedProperties();
additionalDataSerializedObject.ApplyModifiedProperties();
shadowDataSerializedObject.ApplyModifiedProperties();
void ApplyAdditionalComponentsVisibility(bool hide)
// TODO: Move this to a generic EditorUtilities class
T[] GetAdditionalData<T>()
where T : Component
var additionalData = light.GetComponent<HDAdditionalLightData>();
var shadowData = light.GetComponent<AdditionalShadowData>();
// 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);
}
additionalData.hideFlags = hide ? HideFlags.HideInInspector : HideFlags.None;
shadowData.hideFlags = hide ? HideFlags.HideInInspector : HideFlags.None;
return data;
}
}
}

5
ScriptableRenderPipeline/HDRenderPipeline/Lighting/EditorLightUtilities.cs


var nearDiscDistance = Mathf.Cos(Mathf.Deg2Rad * spotlight.spotAngle / 2) * spotlight.shadowNearPlane;
var nearDiscRadius = spotlight.shadowNearPlane * Mathf.Sin(spotlight.spotAngle * Mathf.Deg2Rad * 0.5f);
//Draw Range disc
Handles.Disc(spotlight.gameObject.transform.rotation, spotlight.gameObject.transform.position + spotlight.gameObject.transform.forward * rangeDiscDistance, spotlight.gameObject.transform.forward, rangeDiscRadius, false, 1);
//Draw Lines

public static void DrawArealightGizmo(Light arealight)
{
var RectangleSize = new Vector3(arealight.areaSize.x, arealight.areaSize.y, 0);
Gizmos.matrix = arealight.transform.localToWorldMatrix;
Gizmos.DrawWireCube(Vector3.zero, RectangleSize);

public static void DrawSplitter()
{
EditorGUILayout.Space();
var rect = GUILayoutUtility.GetRect(1f, 1f);
// Splitter rect should be full-width

62
ScriptableRenderPipeline/Core/Editor/PropertyFetcher.cs


using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using UnityEngine.Assertions;
namespace UnityEditor.Experimental.Rendering
{
public class PropertyFetcher<T> : IDisposable
{
public readonly SerializedObject obj;
public PropertyFetcher(SerializedObject obj)
{
Assert.IsNotNull(obj);
this.obj = obj;
}
public SerializedProperty FindProperty(string str)
{
return obj.FindProperty(str);
}
public SerializedProperty FindProperty<TValue>(Expression<Func<T, TValue>> expr)
{
// Get the field path as a string
MemberExpression me;
switch (expr.Body.NodeType)
{
case ExpressionType.MemberAccess:
me = expr.Body as MemberExpression;
break;
default:
throw new InvalidOperationException();
}
var members = new List<string>();
while (me != null)
{
members.Add(me.Member.Name);
me = me.Expression as MemberExpression;
}
var sb = new StringBuilder();
for (int i = members.Count - 1; i >= 0; i--)
{
sb.Append(members[i]);
if (i > 0) sb.Append('.');
}
var path = sb.ToString();
// Fetch the SerializedProperty using Unity's method
return obj.FindProperty(path);
}
public void Dispose()
{
// Nothing to do here, still needed so we can rely on the using/IDisposable pattern
}
}
}

13
ScriptableRenderPipeline/Core/Editor/PropertyFetcher.cs.meta


fileFormatVersion: 2
guid: ac00489121556c741bc0e67dfb460a8e
timeCreated: 1507034431
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

79
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Editor/HDLightEditor.Styles.cs


using System;
using System.Linq;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
// TODO: Missing UI tooltips
partial class HDLightEditor
{
sealed class Styles
{
// Base
public readonly GUIContent range = new GUIContent("Range", "Controls how far the light is emitted from the center of the object.");
public readonly GUIContent color = new GUIContent("Color", "Controls the color being emitted by the light.");
public readonly GUIContent spotAngle = new GUIContent("Angle", "Controls the angle in degrees at the base of a Spot light's cone.");
public readonly GUIContent useColorTemperature = new GUIContent("Use Color Temperature", "Choose between RGB and temperature mode for light's color.");
public readonly GUIContent colorFilter = new GUIContent("Filter", "A colored gel can be put in front of the light source to tint the light.");
public readonly GUIContent colorTemperature = new GUIContent("Temperature", "Also known as CCT (Correlated color temperature). The color temperature of the electromagnetic radiation emitted from an ideal black body is defined as its surface temperature in Kelvin. White is 6500K");
public readonly GUIContent intensity = new GUIContent("Intensity", "Controls the brightness of the light. Light color is multiplied by this value.");
public readonly GUIContent lightmappingMode = new GUIContent("Mode", "Specifies the light mode used to determine if and how a light will be baked. Possible modes are Baked, Mixed, and Realtime.");
public readonly GUIContent lightBounceIntensity = new GUIContent("Indirect Multiplier", "Controls the intensity of indirect light being contributed to the scene. A value of 0 will cause Realtime lights to be removed from realtime global illumination and Baked and Mixed lights to no longer emit indirect lighting. Has no effect when both Realtime and Baked Global Illumination are disabled.");
public readonly GUIContent cookie = new GUIContent("Cookie", "Specifies the Texture mask to cast shadows, create silhouettes, or patterned illumination for the light.");
public readonly GUIContent cookieSizeX = new GUIContent("Size X", "Controls the size of the cookie mask currently assigned to the light.");
public readonly GUIContent cookieSizeY = new GUIContent("Size Y", "Controls the size of the cookie mask currently assigned to the light.");
public readonly GUIContent shadowBias = new GUIContent("Bias", "Controls the distance at which the shadows will be pushed away from the light. Useful for avoiding false self-shadowing artifacts.");
public readonly GUIContent shadowNormalBias = new GUIContent("Normal Bias", "Controls distance at which the shadow casting surfaces will be shrunk along the surface normal. Useful for avoiding false self-shadowing artifacts.");
public readonly GUIContent shadowNearPlane = new GUIContent("Near Plane", "Controls the value for the near clip plane when rendering shadows. Currently clamped to 0.1 units or 1% of the lights range property, whichever is lower.");
public readonly GUIContent bakedShadowRadius = new GUIContent("Baked Shadow Radius", "Controls the amount of artificial softening applied to the edges of shadows cast by the Point or Spot light.");
public readonly GUIContent bakedShadowAngle = new GUIContent("Baked Shadow Angle", "Controls the amount of artificial softening applied to the edges of shadows cast by directional lights.");
public readonly GUIContent bakingWarning = new GUIContent("Light mode is currently overridden to Realtime mode. Enable Baked Global Illumination to use Mixed or Baked light modes.");
public readonly GUIContent indirectBounceShadowWarning = new GUIContent("Realtime indirect bounce shadowing is not supported for Spot and Point lights.");
public readonly GUIContent cookieWarning = new GUIContent("Cookie textures for spot lights should be set to clamp, not repeat, to avoid artifacts.");
// Additional light data
public readonly GUIContent maxSmoothness = new GUIContent("Max Smoothness", "Very low cost way of faking spherical area lighting. This will modify the roughness of the material lit. This is useful when the specular highlight is too small or too sharp.");
public readonly GUIContent affectDiffuse = new GUIContent("Affect Diffuse", "This will disable diffuse lighting for this light. Doesn't save performance, diffuse lighting is still computed.");
public readonly GUIContent affectSpecular = new GUIContent("Affect Specular", "This will disable specular lighting for this light. Doesn't save performance, specular lighting is still computed.");
public readonly GUIContent lightDimmer = new GUIContent("Dimmer", "Aim to be used with script, timeline or animation. It allows dimming one or multiple lights of heterogeneous intensity easily (without needing to know the intensity of each light).");
public readonly GUIContent fadeDistance = new GUIContent("Fade Distance", "The distance at which the light will smoothly fade before being culled to minimize popping.");
public readonly GUIContent spotInnerPercent = new GUIContent("Inner Percent", "Controls size of the angular attenuation in percent of the base angle of the Spot light's cone.");
public readonly GUIContent spotLightShape = new GUIContent("Shape", "The shape use for the spotlight. Has an impact on the cookie transformation and light angular attenuation.");
public readonly GUIContent shapeLengthLine = new GUIContent("Length", "Length of the line light");
public readonly GUIContent shapeLengthRect = new GUIContent("Size X", "SizeX of the rectangle light");
public readonly GUIContent shapeWidthRect = new GUIContent("Size Y", "SizeY of the rectangle light");
public readonly GUIContent shapeLengthPyramid = new GUIContent("Size X", "");
public readonly GUIContent shapeWidthPyramid = new GUIContent("Size Y", "");
public readonly GUIContent shapeLengthBox = new GUIContent("Size X", "");
public readonly GUIContent shapeWidthBox = new GUIContent("Size Y", "");
public readonly GUIContent applyRangeAttenuation = new GUIContent("Apply Range Attenuation", "Allows disabling range attenuation. This is useful indoor (like a room) to avoid having to setup a large range for a light to get correct inverse square attenuation that may leak out of the indoor");
public readonly GUIContent shape = new GUIContent("Type", "Specifies the current type of light. Possible types are Directional, Spot, Point, Rectangle and Line lights.");
public readonly GUIContent[] shapeNames;
// Additional shadow data
public readonly GUIContent shadowCascadeCount = new GUIContent("Cascade Count", "");
public readonly GUIContent[] shadowCascadeRatios = { new GUIContent("Cascade 1"), new GUIContent("Cascade 2"), new GUIContent("Cascade 3") };
public readonly GUIContent shadowResolution = new GUIContent("Resolution", "Controls the rendered resolution of the shadow maps. A higher resolution will increase the fidelity of shadows at the cost of GPU performance and memory usage.");
public readonly GUIContent shadowFadeDistance = new GUIContent("Fade Distance", "The shadow will fade at distance ShadowFadeDistance before being culled to minimize popping.");
public readonly GUIContent shadowDimmer = new GUIContent("Dimmer", "Aim to be use with script, timeline or animation. It allows dimming one or multiple shadows. This can also be used as an optimization to fit in shadow budget manually and minimize popping.");
public Styles()
{
shapeNames = Enum.GetNames(typeof(LightShape))
.Select(x => new GUIContent(x))
.ToArray();
}
}
static Styles s_Styles;
// Can't use a static initializer in case we need to create GUIStyle in the Styles class as
// these can only be created with an active GUI rendering context
void CheckStyles()
{
if (s_Styles == null)
s_Styles = new Styles();
}
}
}

13
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Editor/HDLightEditor.Styles.cs.meta


fileFormatVersion: 2
guid: b9462695cb5957648b93fc9755779d81
timeCreated: 1507034709
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存