Singularity/Library/PackageCache/com.unity.render-pipelines..../Editor/PostProcessing/LensFlareDataSRPEditor.cs
2024-05-06 11:45:45 -07:00

1260 lines
64 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
[CustomEditorForRenderPipeline(typeof(LensFlareDataSRP), typeof(RenderPipelineAsset))]
class LensFlareDataSRPEditor : Editor
{
static class Styles
{
public const int sizeWidth = 47;
public const int sizeOffset = 5;
public static readonly int headerHeight = (int)EditorGUIUtility.singleLineHeight;
public static readonly int cathegorySpacing = 5;
public const int footerSeparatorHeight = 5;
public const int thumbnailSize = 52;
public const int iconMargin = 6; //margin for icon be ing at 75% of 52 thumbnail size
public const int horiwontalSpaceBetweenThumbnailAndInspector = 5;
public const int shrinkingLabel = 10;
public static readonly Color elementBackgroundColor = EditorGUIUtility.isProSkin
? new Color32(65, 65, 65, 255)
: new Color32(200, 200, 200, 255);
public static readonly GUIContent mainHeader = EditorGUIUtility.TrTextContent("Elements", "List of elements in the Lens Flare.");
public static readonly GUIContent elementHeader = EditorGUIUtility.TrTextContent("Lens Flare Element", "Elements in the Lens Flare.");
// Cathegory headers
static public readonly string typeCathegory = L10n.Tr("Type");
static public readonly string colorCathegory = L10n.Tr("Color");
static public readonly string transformCathegory = L10n.Tr("Transform");
static public readonly string axisTransformCathegory = L10n.Tr("Axis Transform");
static public readonly string radialDistortionCathegory = L10n.Tr("Radial Distortion");
static public readonly string multipleElementsCathegory = L10n.Tr("Multiple Elements");
// Type
static public readonly GUIContent type = EditorGUIUtility.TrTextContent("Type", "Specifies the type of this lens flare element.");
static public readonly GUIContent flareTexture = EditorGUIUtility.TrTextContent("Flare Texture", "Specifies the Texture this element uses.");
static public readonly GUIContent preserveAspectRatio = EditorGUIUtility.TrTextContent("Use Aspect Ratio", "When enabled, uses original aspect ratio of the width and height of the element's Flare Texture (or 1 for shape).");
static public readonly GUIContent gradient = EditorGUIUtility.TrTextContent("Gradient", "Controls the offset of the Procedural Flare gradient relative to its starting point. A higher value means the gradient starts further from the center of the shape.");
static public readonly GUIContent fallOff = EditorGUIUtility.TrTextContent("Falloff", "Controls the smoothness of the gradient. A higher value creates a sharper gradient.");
static public readonly GUIContent sideCount = EditorGUIUtility.TrTextContent("Side Count", "Specifies the number of sides of the lens flare polygon.");
static public readonly GUIContent sdfRoundness = EditorGUIUtility.TrTextContent("Roundness", "Specifies the roundness of the polygon flare. A value of 0 creates a sharp polygon, a value of 1 creates a circle.");
static public readonly GUIContent inverseSDF = EditorGUIUtility.TrTextContent("Invert", "When enabled, will invert the gradient direction.");
// Color
static public readonly GUIContent tint = EditorGUIUtility.TrTextContent("Tint", "Specifies the tint of the element. If the element type is set to Image, the Flare Texture is multiplied by this color.");
static public readonly GUIContent modulateByLightColor = EditorGUIUtility.TrTextContent("Modulate By Light Color", "When enabled,changes the color of the elements based on the light color, if this asset is attached to a light.");
static public readonly GUIContent intensity = EditorGUIUtility.TrTextContent("Intensity", "Sets the intensity of the element.");
static public readonly GUIContent blendMode = EditorGUIUtility.TrTextContent("Blend Mode", "Specifies the blend mode this element uses.");
// Transform
static public readonly GUIContent positionOffset = EditorGUIUtility.TrTextContent("Position Offset", "Sets the offset of this element in screen space relative to its source.");
static public readonly GUIContent autoRotate = EditorGUIUtility.TrTextContent("Auto Rotate", "When enabled, automatically rotates the element between its position and the center of the screen. Requires the Starting Position property to have a value greater than 0.");
static public readonly GUIContent rotation = EditorGUIUtility.TrTextContent("Rotation", "Sets the local rotation of the elements.");
static public readonly GUIContent sizeXY = EditorGUIUtility.TrTextContent("Scale", "Sets the stretch of each dimension in relative to the scale. You can use this with Radial Distortion.");
static public readonly GUIContent uniformScale = EditorGUIUtility.TrTextContent("Uniform Scale", "Sets the scale of this element.");
// Axis Transform
static public readonly GUIContent position = EditorGUIUtility.TrTextContent("Starting Position", "Sets the starting position of this element in screen space relative to its source.");
static public readonly GUIContent angularOffset = EditorGUIUtility.TrTextContent("Angular Offset", "Sets the angular offset of this element in degrees relative to its current position.");
static public readonly GUIContent translationScale = EditorGUIUtility.TrTextContent("Translation Scale", "Controls the direction and speed the element appears to move. For example, values of (1,0) make the lens flare move horizontally.");
// Radial Distortion
static public readonly GUIContent enableDistortion = EditorGUIUtility.TrTextContent("Enable", "When enabled, distorts the element relative to its distance from the flare position in screen space.");
static public readonly GUIContent targetSizeDistortion = EditorGUIUtility.TrTextContent("Radial Edge Size", "Sets the target size of the edge of the screen. Values of (1, 1) match the actual screen size.");
static public readonly GUIContent distortionCurve = EditorGUIUtility.TrTextContent("Radial Edge Curve", "Controls the amount of distortion between the position of the lens flare and the edge of the screen.");
static public readonly GUIContent distortionRelativeToCenter = EditorGUIUtility.TrTextContent("Relative To Center", "When enabled, the amount of radial distortion changes between the center of the screen and the edge of the screen.");
// Multiple Elements
static public readonly GUIContent allowMultipleElement = EditorGUIUtility.TrTextContent("Enable", "When enabled, allows multiple lens flare elements.");
static public readonly GUIContent count = EditorGUIUtility.TrTextContent("Count", "Sets the number of elements.");
static public readonly GUIContent distribution = EditorGUIUtility.TrTextContent("Distribution", "Controls how multiple lens flare elements are distributed.");
static public readonly GUIContent lengthSpread = EditorGUIUtility.TrTextContent("Length Spread", "Sets the length lens flare elements are spread across in screen space.");
static public readonly GUIContent seed = EditorGUIUtility.TrTextContent("Seed", "Sets the seed value used to define randomness.");
static public readonly GUIContent intensityVariation = EditorGUIUtility.TrTextContent("Intensity Variation", "Controls the offset of the intensities. A value of 0 means no variations, a value of 1 means variations between 0 and 1.");
static public readonly GUIContent colorGradient = EditorGUIUtility.TrTextContent("Colors", "Specifies the gradient applied across all the elements.");
static public readonly GUIContent positionVariation = EditorGUIUtility.TrTextContent("Position Variation", "Sets the offset applied to the current position of the element.");
static public readonly GUIContent rotationVariation = EditorGUIUtility.TrTextContent("Rotation Variation", "Sets the offset applied to the current element rotation.");
static public readonly GUIContent scaleVariation = EditorGUIUtility.TrTextContent("Scale Variation", "Sets the offset applied to the current scale of the element.");
static public readonly GUIContent positionCurve = EditorGUIUtility.TrTextContent("Position Variation", "Defines how the multiple elements are placed along the spread using a curve.");
static public readonly GUIContent scaleCurve = EditorGUIUtility.TrTextContent("Scale", "Defines how the multiple elements are scaled along the spread.");
static public readonly GUIContent uniformAngleCurve = EditorGUIUtility.TrTextContent("Rotation", "The uniform angle of rotation (in degrees) applied to each element distributed along the curve.");
static public readonly GUIContent uniformAngle = EditorGUIUtility.TrTextContent("Rotation", "The angle of rotation (in degrees) applied to each element incrementally.");
static GUIStyle m_BlueFocusedBoldLabel;
public static GUIStyle blueFocusedBoldLabel
{
get
{
if (m_BlueFocusedBoldLabel == null)
{
m_BlueFocusedBoldLabel = new GUIStyle(EditorStyles.boldLabel);
//Note: GUI.skin.settings.selectionColor don't have the right color. Use the one from foldoutHeader instead
m_BlueFocusedBoldLabel.focused.textColor = EditorStyles.foldoutHeader.focused.textColor;
}
return m_BlueFocusedBoldLabel;
}
}
}
#region Reflection
static Func<SerializedProperty, GenericMenu> FillPropertyContextMenu;
static LensFlareDataSRPEditor()
{
MethodInfo FillPropertyContextMenuInfo = typeof(EditorGUI).GetMethod("FillPropertyContextMenu", BindingFlags.Static | BindingFlags.NonPublic);
var propertyParam = Expression.Parameter(typeof(SerializedProperty), "property");
var FillPropertyContextMenuBlock = Expression.Block(
Expression.Call(null, FillPropertyContextMenuInfo, propertyParam, Expression.Constant(null, typeof(SerializedProperty)), Expression.Constant(null, typeof(GenericMenu)))
);
var FillPropertyContextMenuLambda = Expression.Lambda<Func<SerializedProperty, GenericMenu>>(FillPropertyContextMenuBlock, propertyParam);
FillPropertyContextMenu = FillPropertyContextMenuLambda.Compile();
}
#endregion
SerializedProperty m_Elements;
ReorderableList m_List;
Rect? m_ReservedListSizeRect;
static Shader s_ProceduralThumbnailShader;
static readonly int k_PreviewSize = 128;
static readonly int k_FlareColorValue = Shader.PropertyToID("_FlareColorValue");
static readonly int k_FlareTex = Shader.PropertyToID("_FlareTex");
// cf. LensFlareCommon.hlsl
static readonly int k_FlareData0 = Shader.PropertyToID("_FlareData0");
static readonly int k_FlareData1 = Shader.PropertyToID("_FlareData1");
static readonly int k_FlareData2 = Shader.PropertyToID("_FlareData2");
static readonly int k_FlareData3 = Shader.PropertyToID("_FlareData3");
static readonly int k_FlareData4 = Shader.PropertyToID("_FlareData4");
static readonly int k_FlarePreviewData = Shader.PropertyToID("_FlarePreviewData");
class TextureCacheElement
{
public int hash = 0;
public Texture2D computedTexture = new Texture2D(k_PreviewSize, k_PreviewSize, UnityEngine.Experimental.Rendering.GraphicsFormat.R8G8B8A8_SRGB, UnityEngine.Experimental.Rendering.TextureCreationFlags.None);
}
RTHandle m_PreviewTexture;
List<TextureCacheElement> m_PreviewTextureCache;
Material m_PreviewLensFlare = null;
void OnEnable()
{
m_Elements = serializedObject.FindProperty("elements");
m_List = new ReorderableList(serializedObject, m_Elements, true, true, true, true);
m_List.drawHeaderCallback = DrawListHeader;
m_List.drawFooterCallback = DrawListFooter;
m_List.onAddCallback = OnAdd;
m_List.onRemoveCallback = OnRemove;
m_List.drawElementBackgroundCallback = DrawElementBackground;
m_List.drawElementCallback = DrawElement;
m_List.elementHeightCallback = ElementHeight;
if (s_ProceduralThumbnailShader == null)
s_ProceduralThumbnailShader = Shader.Find("Hidden/Core/LensFlareDataDrivenPreview");
m_PreviewLensFlare = new Material(s_ProceduralThumbnailShader);
if (m_PreviewTexture == null)
{
m_PreviewTexture = RTHandles.Alloc(k_PreviewSize, k_PreviewSize, colorFormat: UnityEngine.Experimental.Rendering.GraphicsFormat.R8G8B8A8_SRGB);
}
if (m_PreviewTextureCache == null)
{
m_PreviewTextureCache = new List<TextureCacheElement>(m_Elements.arraySize);
for (int i = 0; i < m_Elements.arraySize; ++i)
{
m_PreviewTextureCache.Add(new TextureCacheElement());
}
}
}
void OnDisable()
{
m_PreviewTexture?.Release();
m_PreviewTexture = null;
if (m_PreviewTextureCache != null)
{
foreach (TextureCacheElement tce in m_PreviewTextureCache)
DestroyImmediate(tce.computedTexture);
m_PreviewTextureCache = null;
}
}
public override void OnInspectorGUI()
{
serializedObject.Update();
m_List.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
void OnAdd(ReorderableList list)
{
int newIndex = list.count;
m_Elements.arraySize = newIndex + 1;
serializedObject.ApplyModifiedProperties();
m_PreviewTextureCache.Add(new TextureCacheElement());
// Set Default values
(target as LensFlareDataSRP).elements[newIndex] = new LensFlareDataElementSRP();
serializedObject.Update();
}
void OnRemove(ReorderableList list)
{
int deletedIndex = list.index;
list.serializedProperty.DeleteArrayElementAtIndex(deletedIndex);
list.serializedProperty.serializedObject.ApplyModifiedProperties();
DestroyImmediate(m_PreviewTextureCache[deletedIndex].computedTexture);
m_PreviewTextureCache.RemoveAt(deletedIndex);
list.index = Mathf.Clamp(deletedIndex - 1, 0, list.count - 1);
}
#region Header and Footer
void DrawListHeader(Rect rect)
{
Rect sizeRect = rect;
sizeRect.x += Styles.sizeOffset;
sizeRect.xMin = sizeRect.xMax - Styles.sizeWidth;
// If we draw the size now, and the user decrease it,
// it can lead to out of range issue. See Footer.
m_ReservedListSizeRect = sizeRect;
Rect labelRect = rect;
labelRect.xMax = sizeRect.xMin;
EditorGUI.LabelField(labelRect, Styles.mainHeader, EditorStyles.boldLabel);
}
void DrawListSize(Rect rect)
{
int previousCount = m_List.count;
int newCount = EditorGUI.DelayedIntField(rect, previousCount);
if (newCount < 0)
newCount = 0;
if (newCount != previousCount)
{
m_Elements.arraySize = newCount;
serializedObject.ApplyModifiedProperties();
// Set Default values
if (newCount > previousCount)
{
LensFlareDataSRP lensFlareData = target as LensFlareDataSRP;
for (int i = previousCount; i < newCount; ++i)
lensFlareData.elements[i] = new LensFlareDataElementSRP();
m_Elements.serializedObject.Update();
}
}
}
void DrawListFooter(Rect rect)
{
// Default footer
ReorderableList.defaultBehaviours.DrawFooter(rect, m_List);
// Display the size in the footer. So the list will be able to refresh and
// it should not do out of range when removing.
if (!m_ReservedListSizeRect.HasValue)
return;
DrawListSize(m_ReservedListSizeRect.Value);
}
#endregion
#region Heights computation
float ElementHeight(int index)
{
if (m_Elements.arraySize <= index)
return 0;
SerializedProperty element = m_Elements.GetArrayElementAtIndex(index);
SerializedProperty isFoldOpened = element.FindPropertyRelative("isFoldOpened");
SerializedProperty allowMultipleElement = element.FindPropertyRelative("allowMultipleElement");
int titleLine = 0;
int line = 0;
if (isFoldOpened.boolValue)
{
SerializedProperty distribution = element.FindPropertyRelative("distribution");
SerializedProperty type = element.FindPropertyRelative("flareType");
SerializedProperty enableRadialDistortion = element.FindPropertyRelative("enableRadialDistortion");
titleLine = 6;
line = GetTypeCathegoryLines(type)
+ GetColorCathegoryLines()
+ GetTransformCathegoryLines()
+ GetAxisTransformCathegoryLines()
+ GetRadialDistortionCathegoryLines(enableRadialDistortion)
+ GetMultipleElementsCathegoryLines(allowMultipleElement, distribution);
}
else
{
line = 3; //Type, Tint, Intensity
if (allowMultipleElement.boolValue)
line += 1; //Count
}
return (line + titleLine) * (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing)
+ (Mathf.Max(titleLine - 1, 0)) * (Styles.cathegorySpacing)
+ Styles.footerSeparatorHeight + Styles.headerHeight + EditorGUIUtility.standardVerticalSpacing;
}
int GetTypeCathegoryLines(SerializedProperty type)
{
int line = 1; //Type
switch (GetEnum<SRPLensFlareType>(type))
{
case SRPLensFlareType.Circle:
line += 3;
break; //Gradient, Falloff, Invert
case SRPLensFlareType.Image:
line += 2;
break; //Flare Texture, Use Aspect Ratio
case SRPLensFlareType.Polygon:
line += 5;
break; //Gradient, Falloff, Side count, Roundness, Invert
}
return line;
}
int GetColorCathegoryLines()
=> 4; //Tint, Modulate by Light Color, Intensity, Blend Mode
int GetTransformCathegoryLines()
=> 5; //Position Offset, Auto Rotate, Rotation, Scale, Uniform Scale
int GetAxisTransformCathegoryLines()
=> 3; //Starting Position, Angular Offset, Translation Scale
int GetRadialDistortionCathegoryLines(SerializedProperty enabled)
=> enabled.boolValue ? 4 : 1; //[Enable], Radial Edge Size, Radial Edge Curve, Relative to Center
int GetMultipleElementsCathegoryLines(SerializedProperty enabled, SerializedProperty distribution)
{
if (!enabled.boolValue)
return 1; //[Enable]
int line = 5; //[Enable], Count, Distribution, Length Spread, Colors
switch (GetEnum<SRPLensFlareDistribution>(distribution))
{
case SRPLensFlareDistribution.Uniform:
line += 1;
break; //UniformAngle
case SRPLensFlareDistribution.Curve:
line += 3;
break; //Position Variation, Rotation, Scale
case SRPLensFlareDistribution.Random:
line += 5;
break; //Seed, Intensity Variation, Position Variation, Rotation Variation, Scale Variation
}
return line;
}
#endregion
#region Draw element
void DrawElementBackground(Rect rect, int index, bool isActive, bool isFocused)
=> EditorGUI.DrawRect(rect, Styles.elementBackgroundColor);
static Gradient SafeGradientValue(SerializedProperty sp)
{
BindingFlags instanceAnyPrivacyBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
PropertyInfo propertyInfo = typeof(SerializedProperty).GetProperty(
"gradientValue",
instanceAnyPrivacyBindingFlags,
null,
typeof(Gradient),
new Type[0],
null
);
if (propertyInfo == null)
return null;
Gradient gradientValue = propertyInfo.GetValue(sp, null) as Gradient;
return gradientValue;
}
void ComputeThumbnail(ref Texture2D computedTexture, SerializedProperty element, SRPLensFlareType type, int index)
{
SerializedProperty colorProp = element.FindPropertyRelative("tint");
SerializedProperty intensityProp = element.FindPropertyRelative("m_LocalIntensity");
SerializedProperty sideCountProp = element.FindPropertyRelative("m_SideCount");
SerializedProperty rotationProp = element.FindPropertyRelative("rotation");
SerializedProperty edgeOffsetProp = element.FindPropertyRelative("m_EdgeOffset");
SerializedProperty fallOffProp = element.FindPropertyRelative("m_FallOff");
SerializedProperty sdfRoundnessProp = element.FindPropertyRelative("m_SdfRoundness");
SerializedProperty inverseSDFProp = element.FindPropertyRelative("inverseSDF");
SerializedProperty flareTextureProp = element.FindPropertyRelative("lensFlareTexture");
SerializedProperty preserveAspectRatioProp = element.FindPropertyRelative("preserveAspectRatio");
SerializedProperty sizeXYProp = element.FindPropertyRelative("sizeXY");
SerializedProperty countProp = element.FindPropertyRelative("m_Count");
SerializedProperty allowMultipleElementProp = element.FindPropertyRelative("allowMultipleElement");
float invSideCount = 1f / ((float)sideCountProp.intValue);
float intensity = intensityProp.floatValue;
float usedSDFRoundness = sdfRoundnessProp.floatValue;
Vector2 sizeXY = sizeXYProp.vector2Value;
Vector2 sizeXYAbs = new Vector2(Mathf.Abs(sizeXY.x), Mathf.Abs(sizeXY.y));
Vector2 localSize = new Vector2(sizeXY.x / Mathf.Max(sizeXYAbs.x, sizeXYAbs.y), sizeXY.y / Mathf.Max(sizeXYAbs.x, sizeXYAbs.y));
const float maxStretch = 50.0f;
localSize = new Vector2(Mathf.Min(localSize.x, maxStretch), Mathf.Min(localSize.y, maxStretch));
Texture2D flareTex = flareTextureProp.objectReferenceValue as Texture2D;
float usedAspectRatio;
if (type == SRPLensFlareType.Image)
usedAspectRatio = flareTex ? ((((float)flareTex.height) / (float)flareTex.width)) : 1.0f;
else
usedAspectRatio = 1.0f;
if (type == SRPLensFlareType.Image && preserveAspectRatioProp.boolValue)
{
if (usedAspectRatio >= 1.0f)
{
localSize = new Vector2(localSize.x / usedAspectRatio, localSize.y);
}
else
{
localSize = new Vector2(localSize.x, localSize.y * usedAspectRatio);
}
}
float usedGradientPosition = Mathf.Clamp01((1.0f - edgeOffsetProp.floatValue) - 1e-6f);
if (type == SRPLensFlareType.Polygon)
usedGradientPosition = Mathf.Pow(usedGradientPosition + 1.0f, 5);
if (allowMultipleElementProp.boolValue && countProp.intValue > 1)
{
SerializedProperty distributionProp = element.FindPropertyRelative("distribution");
SerializedProperty lengthSpreadProp = element.FindPropertyRelative("lengthSpread");
SerializedProperty colorGradientProp = element.FindPropertyRelative("colorGradient");
SerializedProperty seedProp = element.FindPropertyRelative("seed");
SerializedProperty intensityVariationProp = element.FindPropertyRelative("m_IntensityVariation");
SerializedProperty scaleVariationProp = element.FindPropertyRelative("scaleVariation");
SerializedProperty rotationVariationProp = element.FindPropertyRelative("rotationVariation");
SerializedProperty uniformAngleProp = element.FindPropertyRelative("uniformAngle");
float RandomRange(float min, float max)
{
return UnityEngine.Random.Range(min, max);
}
float rescale = float.MaxValue;
UnityEngine.Random.State backupRandState = UnityEngine.Random.state;
UnityEngine.Random.InitState(seedProp.intValue);
float currentAngle = 0.0f;
for (int idx = 0; idx < countProp.intValue; ++idx)
{
Vector4 flareData0 = LensFlareCommonSRP.GetFlareData0(Vector2.zero, Vector2.zero, Vector2.one, Vector2.zero, rotationProp.floatValue + currentAngle, 0f, 0f, Vector2.zero, false);
float cos0 = flareData0.x;
float sin0 = flareData0.y;
if (GetEnum<SRPLensFlareDistribution>(distributionProp) == SRPLensFlareDistribution.Random)
RandomRange(-1.0f, 1.0f); // Local Intensity
Vector2 localLocalSize;
if (GetEnum<SRPLensFlareDistribution>(distributionProp) == SRPLensFlareDistribution.Uniform)
localLocalSize = localSize;
else if (GetEnum<SRPLensFlareDistribution>(distributionProp) == SRPLensFlareDistribution.Random)
localLocalSize = localSize + localSize * (scaleVariationProp.floatValue * RandomRange(-1.0f, 1.0f));
else
localLocalSize = localSize;
Vector2 rotQuadCorner = new Vector2(cos0 * localLocalSize.x - sin0 * localLocalSize.y, sin0 * localLocalSize.x + cos0 * localLocalSize.y);
rescale = Mathf.Min(rescale, 1.0f / Mathf.Max(Mathf.Abs(rotQuadCorner.x), Mathf.Abs(rotQuadCorner.y)));
if (lengthSpreadProp.floatValue == 0.0f)
{
switch (GetEnum<SRPLensFlareDistribution>(distributionProp))
{
case SRPLensFlareDistribution.Uniform:
currentAngle += uniformAngleProp.floatValue;
break;
case SRPLensFlareDistribution.Curve:
RandomRange(0.0f, 1.0f); // Color
RandomRange(-1.0f, 1.0f); // Position
currentAngle = rotationProp.floatValue + RandomRange(-Mathf.PI, Mathf.PI) * rotationVariationProp.floatValue;
RandomRange(-1.0f, 1.0f); // Position Offset
break;
case SRPLensFlareDistribution.Random:
break;
}
}
}
UnityEngine.Random.InitState(seedProp.intValue);
float localIntensity = intensity;
currentAngle = 0.0f;
for (int idx = 0; idx < countProp.intValue; ++idx)
{
if (GetEnum<SRPLensFlareDistribution>(distributionProp) == SRPLensFlareDistribution.Random)
{
localIntensity = intensity * RandomRange(-1.0f, 1.0f) * intensityVariationProp.floatValue + 1.0f;
}
Vector2 localLocalSize;
if (GetEnum<SRPLensFlareDistribution>(distributionProp) == SRPLensFlareDistribution.Uniform)
localLocalSize = localSize;
else if (GetEnum<SRPLensFlareDistribution>(distributionProp) == SRPLensFlareDistribution.Random)
localLocalSize = localSize + localSize * (scaleVariationProp.floatValue * RandomRange(-1.0f, 1.0f));
else
localLocalSize = localSize;
// Set here what need to be setup in the material
if (type == SRPLensFlareType.Image)
{
if (flareTextureProp.objectReferenceValue != null)
m_PreviewLensFlare.SetTexture(k_FlareTex, flareTextureProp.objectReferenceValue as Texture2D);
else
m_PreviewLensFlare.SetTexture(k_FlareTex, Texture2D.blackTexture);
}
else
{
m_PreviewLensFlare.SetTexture(k_FlareTex, null);
}
Color usedColor = colorProp.colorValue;
if (GetEnum<SRPLensFlareDistribution>(distributionProp) == SRPLensFlareDistribution.Random)
{
UnityEngine.Gradient colorGradient = SafeGradientValue(colorGradientProp);
Color randCol = colorGradient.Evaluate(RandomRange(0.0f, 1.0f));
RandomRange(-1.0f, 1.0f); // Position
currentAngle = RandomRange(-Mathf.PI, Mathf.PI) * rotationVariationProp.floatValue;
RandomRange(-1.0f, 1.0f); // Position Offset
usedColor *= randCol;
}
m_PreviewLensFlare.SetVector(k_FlareColorValue, new Vector4(usedColor.r * localIntensity, usedColor.g * localIntensity, usedColor.b * localIntensity, 1f));
Vector4 flareData0 = LensFlareCommonSRP.GetFlareData0(Vector2.zero, Vector2.zero, Vector2.one, Vector2.zero, rotationProp.floatValue + currentAngle, 0f, 0f, Vector2.zero, false);
m_PreviewLensFlare.SetVector(k_FlareData0, flareData0);
// x: OcclusionRadius, y: OcclusionSampleCount, z: ScreenPosZ, w: ScreenRatio
m_PreviewLensFlare.SetVector(k_FlareData1, new Vector4(0f, 0f, 0f, 1f));
// xy: ScreenPos, zw: FlareSize
m_PreviewLensFlare.SetVector(k_FlareData2, new Vector4(0f, 0f, rescale * localLocalSize.x, rescale * localLocalSize.y));
// x: Allow Offscreen, y: Edge Offset, z: Falloff, w: invSideCount
m_PreviewLensFlare.SetVector(k_FlareData3, new Vector4(0f, usedGradientPosition, Mathf.Exp(Mathf.Lerp(0.0f, 4.0f, Mathf.Clamp01(1.0f - fallOffProp.floatValue))), invSideCount));
if (type == SRPLensFlareType.Polygon)
{
// Precompute data for Polygon SDF (cf. LensFlareCommon.hlsl)
float rCos = Mathf.Cos(Mathf.PI * invSideCount);
float roundValue = rCos * usedSDFRoundness;
float r = rCos - roundValue;
float an = 2.0f * Mathf.PI * invSideCount;
float he = r * Mathf.Tan(0.5f * an);
// x: SDF Roundness, y: Poly Radius, z: PolyParam0, w: PolyParam1
m_PreviewLensFlare.SetVector(k_FlareData4, new Vector4(usedSDFRoundness, r, an, he));
}
else
{
// x: SDF Roundness, yzw: Unused
m_PreviewLensFlare.SetVector(k_FlareData4, new Vector4(usedSDFRoundness, 0f, 0f, 0f));
}
// xy: _FlarePreviewData.xy, z: ScreenRatio
m_PreviewLensFlare.SetVector(k_FlarePreviewData, new Vector4(k_PreviewSize, k_PreviewSize, 1f, 0f));
m_PreviewLensFlare.SetPass((int)type + ((type != SRPLensFlareType.Image && inverseSDFProp.boolValue) ? 2 : 0));
if (localIntensity > 0.0f)
RenderToTexture2D(ref computedTexture, idx == 0);
if (lengthSpreadProp.floatValue == 0.0f)
{
switch (GetEnum<SRPLensFlareDistribution>(distributionProp))
{
case SRPLensFlareDistribution.Uniform:
currentAngle += uniformAngleProp.floatValue;
break;
}
}
}
UnityEngine.Random.state = backupRandState;
}
else
{
Vector4 flareData0 = LensFlareCommonSRP.GetFlareData0(Vector2.zero, Vector2.zero, Vector2.one, Vector2.zero, rotationProp.floatValue, 0f, 0f, Vector2.zero, false);
float cos0 = flareData0.x;
float sin0 = flareData0.y;
Vector2 rotQuadCorner = new Vector2(cos0 * localSize.x - sin0 * localSize.y, sin0 * localSize.x + cos0 * localSize.y);
float rescale = 1.0f / Mathf.Max(Mathf.Abs(rotQuadCorner.x), Mathf.Abs(rotQuadCorner.y));
// Set here what need to be setup in the material
if (type == SRPLensFlareType.Image)
{
if (flareTextureProp.objectReferenceValue != null)
m_PreviewLensFlare.SetTexture(k_FlareTex, flareTextureProp.objectReferenceValue as Texture2D);
else
m_PreviewLensFlare.SetTexture(k_FlareTex, Texture2D.blackTexture);
}
else
{
m_PreviewLensFlare.SetTexture(k_FlareTex, null);
}
m_PreviewLensFlare.SetVector(k_FlareColorValue, new Vector4(colorProp.colorValue.r * intensity, colorProp.colorValue.g * intensity, colorProp.colorValue.b * intensity, 1f));
m_PreviewLensFlare.SetVector(k_FlareData0, flareData0);
// x: OcclusionRadius, y: OcclusionSampleCount, z: ScreenPosZ, w: ScreenRatio
m_PreviewLensFlare.SetVector(k_FlareData1, new Vector4(0f, 0f, 0f, 1f));
// xy: ScreenPos, zw: FlareSize
m_PreviewLensFlare.SetVector(k_FlareData2, new Vector4(0f, 0f, rescale * localSize.x, rescale * localSize.y));
// x: Allow Offscreen, y: Edge Offset, z: Falloff, w: invSideCount
m_PreviewLensFlare.SetVector(k_FlareData3, new Vector4(0f, usedGradientPosition, Mathf.Exp(Mathf.Lerp(0.0f, 4.0f, Mathf.Clamp01(1.0f - fallOffProp.floatValue))), invSideCount));
if (type == SRPLensFlareType.Polygon)
{
// Precompute data for Polygon SDF (cf. LensFlareCommon.hlsl)
float rCos = Mathf.Cos(Mathf.PI * invSideCount);
float roundValue = rCos * usedSDFRoundness;
float r = rCos - roundValue;
float an = 2.0f * Mathf.PI * invSideCount;
float he = r * Mathf.Tan(0.5f * an);
// x: SDF Roundness, y: Poly Radius, z: PolyParam0, w: PolyParam1
m_PreviewLensFlare.SetVector(k_FlareData4, new Vector4(usedSDFRoundness, r, an, he));
}
else
{
// x: SDF Roundness, yzw: Unused
m_PreviewLensFlare.SetVector(k_FlareData4, new Vector4(usedSDFRoundness, 0f, 0f, 0f));
}
// xy: _FlarePreviewData.xy, z: ScreenRatio
m_PreviewLensFlare.SetVector(k_FlarePreviewData, new Vector4(k_PreviewSize, k_PreviewSize, 1f, 0f));
m_PreviewLensFlare.SetPass((int)type + ((type != SRPLensFlareType.Image && inverseSDFProp.boolValue) ? 2 : 0));
RenderToTexture2D(ref computedTexture);
}
}
void RenderToTexture2D(ref Texture2D computedTexture, bool clear = true)
{
RenderTexture oldActive = RenderTexture.active;
RenderTexture.active = m_PreviewTexture.rt;
if (clear)
GL.Clear(false, true, Color.black);
GL.PushMatrix();
GL.LoadOrtho();
GL.Viewport(new Rect(0, 0, k_PreviewSize, k_PreviewSize));
GL.Begin(GL.QUADS);
GL.TexCoord2(0, 0);
GL.Vertex3(0f, 0f, 0);
GL.TexCoord2(0, 1);
GL.Vertex3(0f, 1f, 0);
GL.TexCoord2(1, 1);
GL.Vertex3(1f, 1f, 0);
GL.TexCoord2(1, 0);
GL.Vertex3(1f, 0f, 0);
GL.End();
GL.PopMatrix();
computedTexture.ReadPixels(new Rect(0, 0, k_PreviewSize, k_PreviewSize), 0, 0, false);
computedTexture.Apply(false);
RenderTexture.active = oldActive;
}
int GetElementHash(SerializedProperty element, SRPLensFlareType type, int index)
{
SerializedProperty sizeXYProp = element.FindPropertyRelative("sizeXY");
SerializedProperty colorProp = element.FindPropertyRelative("tint");
SerializedProperty intensityProp = element.FindPropertyRelative("m_LocalIntensity");
SerializedProperty rotationProp = element.FindPropertyRelative("rotation");
SerializedProperty uniformScaleProp = element.FindPropertyRelative("uniformScale");
int hash = index.GetHashCode();
hash = hash * 23 + intensityProp.floatValue.GetHashCode();
hash = hash * 23 + uniformScaleProp.floatValue.GetHashCode();
hash = hash * 23 + sizeXYProp.vector2Value.GetHashCode();
hash = hash * 23 + type.GetHashCode();
hash = hash * 23 + colorProp.colorValue.GetHashCode();
hash = hash * 23 + rotationProp.floatValue.GetHashCode();
SerializedProperty allowMultipleElement = element.FindPropertyRelative("allowMultipleElement");
hash = hash * 23 + allowMultipleElement.boolValue.GetHashCode();
if (allowMultipleElement.boolValue)
{
SerializedProperty count = element.FindPropertyRelative("m_Count");
SerializedProperty seedProp = element.FindPropertyRelative("seed");
SerializedProperty distributionProp = element.FindPropertyRelative("distribution");
SerializedProperty intensityVariationProp = element.FindPropertyRelative("m_IntensityVariation");
SerializedProperty rotationVariationProp = element.FindPropertyRelative("rotationVariation");
SerializedProperty scaleVariationProp = element.FindPropertyRelative("scaleVariation");
hash = hash * 23 + count.intValue.GetHashCode();
hash = hash * 23 + seedProp.intValue.GetHashCode();
hash = hash * 23 + distributionProp.intValue.GetHashCode();
hash = hash * 23 + intensityVariationProp.floatValue.GetHashCode();
hash = hash * 23 + rotationVariationProp.floatValue.GetHashCode();
hash = hash * 23 + scaleVariationProp.floatValue.GetHashCode();
}
if (type == SRPLensFlareType.Image)
{
SerializedProperty flareTextureProp = element.FindPropertyRelative("lensFlareTexture");
SerializedProperty preserveAspectRatioProp = element.FindPropertyRelative("preserveAspectRatio");
if (flareTextureProp.objectReferenceValue != null)
hash = hash * 23 + (flareTextureProp.objectReferenceValue as Texture2D).GetHashCode();
hash = hash * 23 + preserveAspectRatioProp.boolValue.GetHashCode();
}
else
{
SerializedProperty inverseSDFProp = element.FindPropertyRelative("inverseSDF");
SerializedProperty sdfRoundnessProp = element.FindPropertyRelative("m_SdfRoundness");
SerializedProperty edgeOffsetProp = element.FindPropertyRelative("m_EdgeOffset");
SerializedProperty fallOffProp = element.FindPropertyRelative("m_FallOff");
hash = hash * 23 + inverseSDFProp.boolValue.GetHashCode();
hash = hash * 23 + sdfRoundnessProp.floatValue.GetHashCode();
hash = hash * 23 + fallOffProp.floatValue.GetHashCode();
hash = hash * 23 + edgeOffsetProp.floatValue.GetHashCode();
if (type == SRPLensFlareType.Polygon)
{
SerializedProperty sideCountProp = element.FindPropertyRelative("m_SideCount");
hash = hash * 23 + sideCountProp.intValue.GetHashCode();
}
}
return hash;
}
Texture2D GetCachedThumbnailProceduralTexture(SerializedProperty element, SRPLensFlareType type, int index)
{
if (m_PreviewTextureCache.Count <= index)
{
m_PreviewTextureCache.Add(new TextureCacheElement());
}
TextureCacheElement tce = m_PreviewTextureCache[index];
int currentHash = GetElementHash(element, type, index);
if (tce.hash == currentHash)
return tce.computedTexture;
ComputeThumbnail(ref tce.computedTexture, element, type, index);
tce.hash = currentHash;
return tce.computedTexture;
}
void DrawThumbnailProcedural(Rect rect, SerializedProperty element, SRPLensFlareType type, int index)
{
EditorGUI.DrawRect(rect, Color.black);
Color oldGuiColor = GUI.color;
GUI.color = Color.black; //set background color for transparency
if (type != SRPLensFlareType.Image)
{
EditorGUI.DrawRect(rect, GUI.color); //draw margin
rect.xMin += Styles.iconMargin;
rect.xMax -= Styles.iconMargin;
rect.yMin += Styles.iconMargin;
rect.yMax -= Styles.iconMargin;
}
Texture2D previewTecture = GetCachedThumbnailProceduralTexture(element, type, index);
EditorGUI.DrawTextureTransparent(rect, previewTecture, ScaleMode.ScaleToFit, 1f);
GUI.color = oldGuiColor;
}
void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
Rect headerRect = rect;
headerRect.height = Styles.headerHeight;
Rect contentRect = rect;
contentRect.yMin += Styles.headerHeight + EditorGUIUtility.standardVerticalSpacing;
contentRect.xMin -= 12;
bool oldWideMode = EditorGUIUtility.wideMode;
EditorGUIUtility.wideMode = true;
SerializedProperty element = m_Elements.GetArrayElementAtIndex(index);
SerializedProperty isFoldOpened = element.FindPropertyRelative("isFoldOpened");
if (DrawElementHeader(headerRect, isFoldOpened, selectedInList: isActive, element))
DrawFull(contentRect, element);
else
DrawSummary(contentRect, element, index);
EditorGUIUtility.wideMode = oldWideMode;
}
bool DrawElementHeader(Rect headerRect, SerializedProperty isFoldOpened, bool selectedInList, SerializedProperty element)
{
Rect visibilityRect = headerRect;
visibilityRect.xMin += 16;
visibilityRect.width = 13;
visibilityRect.y += 2;
visibilityRect.height = 13;
Rect labelRect = headerRect;
labelRect.xMin = visibilityRect.xMax + 5;
labelRect.xMax -= 16;
Rect contextMenuRect = labelRect;
contextMenuRect.xMin = labelRect.xMax;
contextMenuRect.width = 16;
contextMenuRect.y += 1;
contextMenuRect.height = 16;
EditorGUI.BeginProperty(headerRect, Styles.elementHeader, element); //handle contextual menu on name
Rect foldoutRect = headerRect;
foldoutRect.y += 3f;
foldoutRect.width = 13;
foldoutRect.height = 13;
// Title
if (Event.current.type == EventType.Repaint)
Styles.blueFocusedBoldLabel.Draw(labelRect, Styles.elementHeader, hasKeyboardFocus: selectedInList, isActive: false, on: false, isHover: false);
// Collapsable behaviour
bool previousState = isFoldOpened.boolValue;
bool newState = GUI.Toggle(foldoutRect, previousState, GUIContent.none, EditorStyles.foldout);
var e = Event.current;
if (e.type == EventType.MouseDown && labelRect.Contains(e.mousePosition) && e.button == 0)
{
newState = !previousState;
GUI.changed = true;
e.Use();
}
// ellipsis menu
if (GUI.Button(contextMenuRect, CoreEditorStyles.contextMenuIcon, CoreEditorStyles.contextMenuStyle))
{
GenericMenu menu = FillPropertyContextMenu(element);
menu.DropDown(new Rect(new Vector2(contextMenuRect.x, contextMenuRect.yMax), Vector2.zero));
}
if (newState ^ previousState)
isFoldOpened.boolValue = newState;
EditorGUI.EndProperty();
SerializedProperty visible = element.FindPropertyRelative("visible");
EditorGUI.BeginChangeCheck();
bool newVisibility = GUI.Toggle(visibilityRect, visible.boolValue, GUIContent.none, CoreEditorStyles.smallTickbox);
if (EditorGUI.EndChangeCheck())
visible.boolValue = newVisibility;
return newState;
}
void DrawSummary(Rect summaryRect, SerializedProperty element, int index)
{
SerializedProperty type = element.FindPropertyRelative("flareType");
SerializedProperty tint = element.FindPropertyRelative("tint");
SerializedProperty intensity = element.FindPropertyRelative("m_LocalIntensity");
SerializedProperty allowMultipleElement = element.FindPropertyRelative("allowMultipleElement");
SerializedProperty count = element.FindPropertyRelative("m_Count");
Rect thumbnailRect = OffsetForThumbnail(ref summaryRect);
DrawThumbnailProcedural(thumbnailRect, element, GetEnum<SRPLensFlareType>(type), index);
IEnumerator<Rect> fieldRect = ReserveFields(summaryRect, allowMultipleElement.boolValue ? 4 : 3);
float oldLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth -= thumbnailRect.width + Styles.horiwontalSpaceBetweenThumbnailAndInspector + Styles.shrinkingLabel;
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, type, Styles.type);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, tint, Styles.tint);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, intensity, Styles.intensity);
if (allowMultipleElement.boolValue)
{
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, count, Styles.count);
}
EditorGUIUtility.labelWidth = oldLabelWidth;
}
void DrawFull(Rect remainingRect, SerializedProperty element)
{
float oldLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth -= Styles.shrinkingLabel;
DrawTypeCathegory(ref remainingRect, element);
DrawColorCathegory(ref remainingRect, element);
DrawTransformCathegory(ref remainingRect, element);
DrawAxisTransformCathegory(ref remainingRect, element);
DrawRadialDistortionCathegory(ref remainingRect, element);
DrawMultipleElementsCathegory(ref remainingRect, element);
EditorGUIUtility.labelWidth = oldLabelWidth;
}
void DrawTypeCathegory(ref Rect remainingRect, SerializedProperty element)
{
SerializedProperty type = element.FindPropertyRelative("flareType");
IEnumerator<Rect> fieldRect = ReserveCathegory(remainingRect, GetTypeCathegoryLines(type));
fieldRect.MoveNext();
EditorGUI.LabelField(fieldRect.Current, Styles.typeCathegory, EditorStyles.boldLabel);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, type, Styles.type);
SRPLensFlareType flareType = GetEnum<SRPLensFlareType>(type);
switch (flareType)
{
case SRPLensFlareType.Image:
{
SerializedProperty flareTexture = element.FindPropertyRelative("lensFlareTexture");
SerializedProperty preserveAspectRatio = element.FindPropertyRelative("preserveAspectRatio");
// display it with texture icon
fieldRect.MoveNext();
EditorGUI.BeginChangeCheck();
Texture newTexture = EditorGUI.ObjectField(fieldRect.Current, Styles.flareTexture, flareTexture.objectReferenceValue, typeof(Texture), false) as Texture;
if (EditorGUI.EndChangeCheck())
flareTexture.objectReferenceValue = newTexture;
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, preserveAspectRatio, Styles.preserveAspectRatio);
}
break;
case SRPLensFlareType.Circle:
case SRPLensFlareType.Polygon:
{
SerializedProperty gradient = element.FindPropertyRelative("m_EdgeOffset");
SerializedProperty fallOff = element.FindPropertyRelative("m_FallOff");
SerializedProperty inverseSDF = element.FindPropertyRelative("inverseSDF");
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, gradient, Styles.gradient);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, fallOff, Styles.fallOff);
if (flareType == SRPLensFlareType.Polygon)
{
SerializedProperty sideCount = element.FindPropertyRelative("m_SideCount");
SerializedProperty sdfRoundness = element.FindPropertyRelative("m_SdfRoundness");
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, sideCount, Styles.sideCount);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, sdfRoundness, Styles.sdfRoundness);
}
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, inverseSDF, Styles.inverseSDF);
}
break;
}
// update remaining
fieldRect.MoveNext();
remainingRect = fieldRect.Current;
}
void DrawColorCathegory(ref Rect remainingRect, SerializedProperty element)
{
SerializedProperty tint = element.FindPropertyRelative("tint");
SerializedProperty modulateByLightColor = element.FindPropertyRelative("modulateByLightColor");
SerializedProperty intensity = element.FindPropertyRelative("m_LocalIntensity");
SerializedProperty blendMode = element.FindPropertyRelative("blendMode");
IEnumerator<Rect> fieldRect = ReserveCathegory(remainingRect, GetColorCathegoryLines());
fieldRect.MoveNext();
EditorGUI.LabelField(fieldRect.Current, Styles.colorCathegory, EditorStyles.boldLabel);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, tint, Styles.tint);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, modulateByLightColor, Styles.modulateByLightColor);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, intensity, Styles.intensity);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, blendMode, Styles.blendMode);
// update remaining
fieldRect.MoveNext();
remainingRect = fieldRect.Current;
}
void DrawTransformCathegory(ref Rect remainingRect, SerializedProperty element)
{
SerializedProperty positionOffset = element.FindPropertyRelative("positionOffset");
SerializedProperty autoRotate = element.FindPropertyRelative("autoRotate");
SerializedProperty rotation = element.FindPropertyRelative("rotation");
SerializedProperty sizeXY = element.FindPropertyRelative("sizeXY");
SerializedProperty uniformScale = element.FindPropertyRelative("uniformScale");
IEnumerator<Rect> fieldRect = ReserveCathegory(remainingRect, GetTransformCathegoryLines());
fieldRect.MoveNext();
EditorGUI.LabelField(fieldRect.Current, Styles.transformCathegory, EditorStyles.boldLabel);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, positionOffset, Styles.positionOffset);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, autoRotate, Styles.autoRotate);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, rotation, Styles.rotation);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, sizeXY, Styles.sizeXY);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, uniformScale, Styles.uniformScale);
// update remaining
fieldRect.MoveNext();
remainingRect = fieldRect.Current;
}
void DrawAxisTransformCathegory(ref Rect remainingRect, SerializedProperty element)
{
SerializedProperty position = element.FindPropertyRelative("position");
SerializedProperty angularOffset = element.FindPropertyRelative("angularOffset");
SerializedProperty translationScale = element.FindPropertyRelative("translationScale");
IEnumerator<Rect> fieldRect = ReserveCathegory(remainingRect, GetAxisTransformCathegoryLines());
fieldRect.MoveNext();
EditorGUI.LabelField(fieldRect.Current, Styles.axisTransformCathegory, EditorStyles.boldLabel);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, position, Styles.position);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, angularOffset, Styles.angularOffset);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, translationScale, Styles.translationScale);
// update remaining
fieldRect.MoveNext();
remainingRect = fieldRect.Current;
}
void DrawRadialDistortionCathegory(ref Rect remainingRect, SerializedProperty element)
{
SerializedProperty enableDistortion = element.FindPropertyRelative("enableRadialDistortion");
IEnumerator<Rect> fieldRect = ReserveCathegory(remainingRect, GetRadialDistortionCathegoryLines(enableDistortion));
fieldRect.MoveNext();
EditorGUI.LabelField(fieldRect.Current, Styles.radialDistortionCathegory, EditorStyles.boldLabel);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, enableDistortion, Styles.enableDistortion);
if (enableDistortion.boolValue)
{
SerializedProperty targetSizeDistortion = element.FindPropertyRelative("targetSizeDistortion");
SerializedProperty distortionCurve = element.FindPropertyRelative("distortionCurve");
SerializedProperty distortionRelativeToCenter = element.FindPropertyRelative("distortionRelativeToCenter");
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, targetSizeDistortion, Styles.targetSizeDistortion);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, distortionCurve, Styles.distortionCurve);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, distortionRelativeToCenter, Styles.distortionRelativeToCenter);
}
// update remaining
fieldRect.MoveNext();
remainingRect = fieldRect.Current;
}
void DrawMultipleElementsCathegory(ref Rect remainingRect, SerializedProperty element)
{
SerializedProperty allowMultipleElement = element.FindPropertyRelative("allowMultipleElement");
SerializedProperty distribution = element.FindPropertyRelative("distribution"); //needed for lines computation
IEnumerator<Rect> fieldRect = ReserveCathegory(remainingRect, GetMultipleElementsCathegoryLines(allowMultipleElement, distribution));
fieldRect.MoveNext();
EditorGUI.LabelField(fieldRect.Current, Styles.multipleElementsCathegory, EditorStyles.boldLabel);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, allowMultipleElement, Styles.allowMultipleElement);
if (allowMultipleElement.boolValue)
{
SerializedProperty count = element.FindPropertyRelative("m_Count");
SerializedProperty colorGradient = element.FindPropertyRelative("colorGradient"); //used in all 3 case
SerializedProperty lengthSpread = element.FindPropertyRelative("lengthSpread");
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, count, Styles.count);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, distribution, Styles.distribution);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, lengthSpread, Styles.lengthSpread);
switch (GetEnum<SRPLensFlareDistribution>(distribution))
{
case SRPLensFlareDistribution.Uniform:
SerializedProperty uniformAngle = element.FindPropertyRelative("uniformAngle");
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, colorGradient, Styles.colorGradient);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, uniformAngle, Styles.uniformAngle);
break;
case SRPLensFlareDistribution.Curve:
SerializedProperty positionCurve = element.FindPropertyRelative("positionCurve");
SerializedProperty scaleCurve = element.FindPropertyRelative("scaleCurve");
SerializedProperty uniformAngleCurve = element.FindPropertyRelative("uniformAngleCurve");
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, colorGradient, Styles.colorGradient);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, positionCurve, Styles.positionCurve);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, uniformAngleCurve, Styles.uniformAngleCurve);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, scaleCurve, Styles.scaleCurve);
break;
case SRPLensFlareDistribution.Random:
SerializedProperty seed = element.FindPropertyRelative("seed");
SerializedProperty intensityVariation = element.FindPropertyRelative("m_IntensityVariation");
SerializedProperty positionVariation = element.FindPropertyRelative("positionVariation");
SerializedProperty rotationVariation = element.FindPropertyRelative("rotationVariation");
SerializedProperty scaleVariation = element.FindPropertyRelative("scaleVariation");
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, seed, Styles.seed);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, intensityVariation, Styles.intensityVariation);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, colorGradient, Styles.colorGradient);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, positionVariation, Styles.positionVariation);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, rotationVariation, Styles.rotationVariation);
fieldRect.MoveNext();
EditorGUI.PropertyField(fieldRect.Current, scaleVariation, Styles.scaleVariation);
break;
}
}
// update remaining
fieldRect.MoveNext();
remainingRect = fieldRect.Current;
}
#endregion
#region Utility
IEnumerator<Rect> ReserveFields(Rect rect, int fields)
{
Rect nextRect = rect;
nextRect.height = EditorGUIUtility.singleLineHeight;
yield return nextRect;
--fields;
for (; fields > 0; --fields)
{
nextRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
yield return nextRect;
}
}
IEnumerator<Rect> ReserveCathegory(Rect remaining, int fields)
{
Rect headerRect = remaining;
headerRect.height = EditorGUIUtility.singleLineHeight;
yield return headerRect;
remaining.yMin = headerRect.yMax + EditorGUIUtility.standardVerticalSpacing;
IEnumerator<Rect> fieldEnumerator = ReserveFields(remaining, fields);
while (fieldEnumerator.MoveNext())
{
remaining.yMin = fieldEnumerator.Current.yMax + EditorGUIUtility.standardVerticalSpacing;
yield return fieldEnumerator.Current;
}
//lastly, return updated remaining. Return it because Iterator cannot use ref parameters
remaining.yMin += Styles.cathegorySpacing;
yield return remaining;
}
Rect OffsetForThumbnail(ref Rect remainingRect)
{
Rect thumbnailRect = remainingRect;
thumbnailRect.width = Styles.thumbnailSize;
thumbnailRect.height = Styles.thumbnailSize;
thumbnailRect.y += ((int)remainingRect.height - Styles.thumbnailSize - Styles.footerSeparatorHeight) >> 1;
remainingRect.xMin += Styles.thumbnailSize + Styles.horiwontalSpaceBetweenThumbnailAndInspector;
return thumbnailRect;
}
// enumValueIndex is not the underling int but the index in enum names.
// if enum don't start at 0, or skip a value, comparing int with enumValueIndex will fail.
T GetEnum<T>(SerializedProperty property)
=> (T)(object)property.intValue;
void SetEnum<T>(SerializedProperty property, T value)
=> property.intValue = (int)(object)value;
#endregion
}
}