Rasagar/Library/PackageCache/com.unity.render-pipelines.high-definition/Editor/Lighting/HDLightEditor.cs
2024-08-26 23:07:20 +03:00

216 lines
7.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
namespace UnityEditor.Rendering.HighDefinition
{
[CanEditMultipleObjects]
[CustomEditor(typeof(Light))]
[SupportedOnRenderPipeline(typeof(HDRenderPipelineAsset))]
sealed partial class HDLightEditor : LightEditor
{
public SerializedHDLight m_SerializedHDLight;
HDAdditionalLightData[] m_AdditionalLightDatas;
HDAdditionalLightData targetAdditionalData
=> m_AdditionalLightDatas[ReferenceTargetIndex(this)];
public HDAdditionalLightData GetAdditionalDataForTargetIndex(int i)
=> m_AdditionalLightDatas[i];
static Func<Editor, int> ReferenceTargetIndex;
static HDLightEditor()
{
var type = typeof(UnityEditor.Editor);
var propertyInfo = type.GetProperty("referenceTargetIndex", BindingFlags.NonPublic | BindingFlags.Instance);
var getterMethodInfo = propertyInfo.GetGetMethod(true);
var instance = Expression.Parameter(typeof(Editor), "instance");
var getterCall = Expression.Call(instance, getterMethodInfo);
var lambda = Expression.Lambda<Func<Editor, int>>(getterCall, instance);
ReferenceTargetIndex = lambda.Compile();
}
protected override void OnEnable()
{
base.OnEnable();
// Get & automatically add additional HD data if not present
m_AdditionalLightDatas = CoreEditorUtils.GetAdditionalData<HDAdditionalLightData>(targets, HDAdditionalLightData.InitDefaultHDAdditionalLightData);
m_SerializedHDLight = new SerializedHDLight(m_AdditionalLightDatas, settings);
// Update emissive mesh and light intensity when undo/redo
Undo.undoRedoPerformed += OnUndoRedo;
HDLightUI.RegisterEditor(this);
}
void OnDisable()
{
// Update emissive mesh and light intensity when undo/redo
Undo.undoRedoPerformed -= OnUndoRedo;
HDLightUI.UnregisterEditor(this);
}
void OnUndoRedo()
{
// Serialized object is lossing references after an undo
if (m_SerializedHDLight.serializedObject.targetObject != null)
{
m_SerializedHDLight.serializedObject.Update();
foreach (var hdLightData in m_AdditionalLightDatas)
if (hdLightData != null)
{
hdLightData.UpdateAreaLightEmissiveMesh();
hdLightData.UpdateRenderEntity();
}
}
// if Type or ShowEmissive Mesh undone, we must fetxh again the emissive meshes
m_SerializedHDLight.FetchAreaLightEmissiveMeshComponents();
}
public override void OnInspectorGUI()
{
m_SerializedHDLight.Update();
// Add space before the first collapsible area
EditorGUILayout.Space();
ApplyAdditionalComponentsVisibility(true);
EditorGUI.BeginChangeCheck();
if (HDEditorUtils.IsPresetEditor(this))
{
HDLightUI.PresetInspector.Draw(m_SerializedHDLight, this);
}
else
{
using (new EditorGUILayout.VerticalScope())
HDLightUI.Inspector.Draw(m_SerializedHDLight, this);
}
if (EditorGUI.EndChangeCheck())
{
m_SerializedHDLight.Apply();
foreach (var hdLightData in m_AdditionalLightDatas)
{
hdLightData.UpdateAllLightValues();
hdLightData.UpdateRenderEntity();
}
}
if (m_SerializedHDLight.needUpdateAreaLightEmissiveMeshComponents)
UpdateAreaLightEmissiveMeshComponents();
}
void UpdateAreaLightEmissiveMeshComponents()
{
foreach (var hdLightData in m_AdditionalLightDatas)
{
hdLightData.UpdateAreaLightEmissiveMesh();
}
m_SerializedHDLight.needUpdateAreaLightEmissiveMeshComponents = false;
}
// Internal utilities
void ApplyAdditionalComponentsVisibility(bool hide)
{
// UX team decided that we should always show component in inspector.
// However already authored scene save this settings, so force the component to be visible
foreach (var t in m_SerializedHDLight.serializedObject.targetObjects)
if (((HDAdditionalLightData)t).hideFlags == HideFlags.HideInInspector)
((HDAdditionalLightData)t).hideFlags = HideFlags.None;
}
protected override void OnSceneGUI()
{
if (targetAdditionalData == null)
return;
// Each handles manipulate only one light
// Thus do not rely on serialized properties
LightType lightType = targetAdditionalData.legacyLight.type;
if (lightType == LightType.Directional || lightType == LightType.Point)
{
base.OnSceneGUI();
}
else if (lightType == LightType.Disc)
{
EditorGUI.BeginChangeCheck();
base.OnSceneGUI();
if (EditorGUI.EndChangeCheck())
{
// Necessary since the built-in disk light logic doesn't update the HDRP property when
// changing the radius through the disk's gizmo in the scene view.
m_SerializedHDLight.shapeWidth.floatValue = targetAdditionalData.legacyLight.areaSize.x;
m_SerializedHDLight.Apply();
}
}
else
HDLightUI.DrawHandles(targetAdditionalData, this);
if (lightType == LightType.Directional)
{
var hdriSkies = GetHDRISkys();
foreach (var sky in hdriSkies)
{
if (sky.lockSun.value)
{
Vector3 currentRot = targetAdditionalData.legacyLight.transform.rotation.eulerAngles;
if (Math.Abs(sky.rotation.value - currentRot.y) > 0.01f)
{
sky.sunInitialRotation.value = 0f - currentRot.y;
sky.rotation.value = currentRot.y;
EditorUtility.SetDirty(sky);
}
}
}
}
}
List<HDRISky> GetHDRISkys()
{
LayerMask volumesMask = LayerMask.NameToLayer("Everything");
var volumes = VolumeManager.instance.GetVolumes(volumesMask);
List<HDRISky> skies = new List<HDRISky>();
foreach (var volume in volumes)
{
var profile = volume.HasInstantiatedProfile() ? volume.profile : volume.sharedProfile;
if (profile == null)
continue;
foreach (var component in profile.components)
{
HDRISky sky = component as HDRISky;
if (sky != null)
{
skies.Add(sky);
}
}
}
return skies;
}
internal Color legacyLightColor
{
get
{
Light light = (Light)target;
return light.enabled ? LightEditor.kGizmoLight : LightEditor.kGizmoDisabledLight;
}
}
}
}