diff --git a/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorEditor.cs b/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorEditor.cs
index 8c40551adc9..9e6660fbde7 100644
--- a/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorEditor.cs
+++ b/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorEditor.cs
@@ -30,6 +30,10 @@ public class LightAnchorEditor : Editor
VisualElement m_GameViewRootElement;
VisualElement m_ClickCatcher;
+ SerializedProperty m_DistanceProperty;
+ SerializedProperty m_FrameSpaceProperty;
+ SerializedProperty m_AnchorPositionOverrideProperty;
+
LightAnchor manipulator
{
get { return target as LightAnchor; }
@@ -62,6 +66,7 @@ public override void OnInspectorGUI()
bool pitchChanged = false;
bool rollChanged = false;
bool distanceChanged = false;
+ bool positionOverrideChanged = false;
bool upChanged = false;
using (var change = new EditorGUI.ChangeCheckScope())
@@ -126,14 +131,17 @@ public override void OnInspectorGUI()
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
- m_Distance = EditorGUILayout.FloatField(LightAnchorStyles.distanceProperty, manipulator.distance);
+ EditorGUILayout.PropertyField(m_DistanceProperty, LightAnchorStyles.distanceProperty);
distanceChanged = EditorGUI.EndChangeCheck();
EditorGUI.BeginChangeCheck();
- var dropRect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight);
- m_FrameSpace = (LightAnchor.UpDirection)EditorGUI.EnumPopup(dropRect, LightAnchorStyles.upDirectionProperty, manipulator.frameSpace);
+ EditorGUILayout.PropertyField(m_FrameSpaceProperty, LightAnchorStyles.upDirectionProperty);
upChanged = EditorGUI.EndChangeCheck();
+ EditorGUI.BeginChangeCheck();
+ EditorGUILayout.PropertyField(m_AnchorPositionOverrideProperty, LightAnchorStyles.anchorPositionOverrideProperty);
+ positionOverrideChanged = EditorGUI.EndChangeCheck();
+
if (m_FoldoutPreset = EditorGUILayout.Foldout(m_FoldoutPreset, "Common"))
{
Color cachedColor = GUI.backgroundColor;
@@ -266,11 +274,11 @@ public override void OnInspectorGUI()
{
Undo.RecordObjects(new UnityEngine.Object[] { target, manipulator.transform }, "Light Anchor Change");
- manipulator.frameSpace = m_FrameSpace;
+ manipulator.frameSpace = (LightAnchor.UpDirection)m_FrameSpaceProperty.intValue;
manipulator.SynchronizeOnTransform(camera);
UpdateCache();
}
- if (yawChanged || pitchChanged || rollChanged || distanceChanged)
+ if (yawChanged || pitchChanged || rollChanged || distanceChanged || positionOverrideChanged)
{
Undo.RecordObjects(new UnityEngine.Object[] { target, manipulator.transform }, "Light Anchor Change");
@@ -281,7 +289,32 @@ public override void OnInspectorGUI()
if (rollChanged)
manipulator.roll = m_Roll;
if (distanceChanged)
- manipulator.distance = m_Distance;
+ manipulator.distance = m_DistanceProperty.floatValue;
+ if (positionOverrideChanged)
+ {
+ var newTransform = m_AnchorPositionOverrideProperty.objectReferenceValue as Transform;
+
+ if (newTransform != null)
+ {
+ // Check that the assigned transform is not child of the light anchor, otherwise it would cause problems when moving the light position
+ if (newTransform.IsChildOf(manipulator.transform))
+ Debug.LogError($"Can't assign '{newTransform.name}' because it's a child of the Light Anchor component");
+ else
+ {
+ float newDistance = Vector3.Distance(manipulator.transform.position, newTransform.position);
+ manipulator.anchorPositionOverride = newTransform;
+ // Orient the object to face the new override position
+ manipulator.SynchronizeOnTransform(camera);
+ // And adjust it's distance to avoid modifying it's position.
+ manipulator.distance = newDistance;
+ }
+ }
+ else
+ manipulator.anchorPositionOverride = newTransform;
+ }
+
+ if (manipulator.anchorPositionOverride != null)
+ anchor = manipulator.anchorPosition;
manipulator.UpdateTransform(camera, anchor);
IsCacheInvalid(manipulator);
@@ -321,6 +354,10 @@ void OnEnable()
EnableClickCatcher(m_EnableClickCatcher);
}
}
+
+ m_DistanceProperty = serializedObject.FindProperty("m_Distance");
+ m_FrameSpaceProperty = serializedObject.FindProperty("m_FrameSpace");
+ m_AnchorPositionOverrideProperty = serializedObject.FindProperty("m_AnchorPositionOverride");
}
void EditorToolsOnactiveToolChanged()
@@ -561,6 +598,7 @@ static class LightAnchorStyles
static public GUIContent presetTextureRimRight = EditorGUIUtility.TrTextContent("", "Rim Right", UnityEditor.Rendering.CoreEditorUtils.LoadIcon(LightAnchorStyles.k_IconFolder, "PresetRim_Right", ".png", false));
static public GUIContent distanceProperty = EditorGUIUtility.TrTextContent("Distance", "Controls how far 'back', the light is placed from its anchor");
static public GUIContent upDirectionProperty = EditorGUIUtility.TrTextContent("Up direction", "Specifies the space in which the up direction of the anchor is defined. Local is relative to the camera.");
+ static public GUIContent anchorPositionOverrideProperty = EditorGUIUtility.TrTextContent("Anchor Position Override", "Specifies the anchor position manually instead of relying on the angles, distance and transform position to compute the anchor position.");
static public GUIContent[] angleSubContent = new[]
{
EditorGUIUtility.TrTextContent("Orbit"),
diff --git a/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorEditorTool.cs b/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorEditorTool.cs
index 4fc2c47dc20..206956d9e3c 100644
--- a/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorEditorTool.cs
+++ b/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorEditorTool.cs
@@ -30,7 +30,10 @@ public override GUIContent toolbarIcon
/// Always return true
public override bool IsAvailable()
{
- return true;
+ var lightAnchor = target as LightAnchor;
+
+ // Hide the transform if a position override object is assigned
+ return (lightAnchor?.anchorPositionOverride == null);
}
///
@@ -39,7 +42,7 @@ public override bool IsAvailable()
/// The window that is displaying the custom editor tool.
public override void OnToolGUI(EditorWindow window)
{
- if (target == null)
+ if (target is LightAnchor l && l?.anchorPositionOverride == null)
return;
DoTargetGUI(target);
@@ -112,7 +115,7 @@ LightAnchorHandles GetHandles(UnityObject obj)
LightAnchorHandles handles;
if (!m_LightAnchorHandles.TryGetValue(obj, out handles))
{
- handles = new LightAnchorHandles();
+ handles = new LightAnchorHandles(obj as LightAnchor);
m_LightAnchorHandles.Add(obj, handles);
}
diff --git a/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorHandles.cs b/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorHandles.cs
index 99bc7dd85e6..f01bc2d0394 100644
--- a/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorHandles.cs
+++ b/com.unity.render-pipelines.core/Editor/Lighting/LightAnchorHandles.cs
@@ -16,11 +16,15 @@ public class LightAnchorHandles
///
public Vector3 anchorPosition { get; set; }
+ LightAnchor target;
+
///
/// Initializes and returns an instance of LightAnchorHandles
///
- public LightAnchorHandles()
+ /// Target object
+ public LightAnchorHandles(LightAnchor target)
{
+ this.target = target;
}
///
@@ -31,7 +35,12 @@ public void OnGUI()
Handles.color = Color.yellow;
Handles.DrawDottedLine(lightPosition, anchorPosition, 2f);
- anchorPosition = Handles.PositionHandle(anchorPosition, Quaternion.identity);
+ // Orient the handle rotation depending on the editor pivot rotation mode
+ var handleRotation = Quaternion.identity;
+ if (Tools.pivotRotation == PivotRotation.Local && target != null)
+ handleRotation = target.transform.rotation;
+
+ anchorPosition = Handles.PositionHandle(anchorPosition, handleRotation);
}
}
}
diff --git a/com.unity.render-pipelines.core/Runtime/Lights/LightAnchor.cs b/com.unity.render-pipelines.core/Runtime/Lights/LightAnchor.cs
index df00a3ab726..e8a88932005 100644
--- a/com.unity.render-pipelines.core/Runtime/Lights/LightAnchor.cs
+++ b/com.unity.render-pipelines.core/Runtime/Lights/LightAnchor.cs
@@ -10,7 +10,6 @@ namespace UnityEngine
/// Represents camera-space light controls around a virtual pivot point.
///
[AddComponentMenu("Rendering/Light Anchor")]
- [RequireComponent(typeof(Light))]
[ExecuteInEditMode]
[DisallowMultipleComponent]
[CoreRPHelpURLAttribute("View-Lighting-Tool")]
@@ -19,13 +18,18 @@ public class LightAnchor : MonoBehaviour
const float k_ArcRadius = 5;
const float k_AxisLength = 10;
- [SerializeField]
+ [SerializeField, Min(0)]
float m_Distance = 0f;
[SerializeField]
UpDirection m_FrameSpace = UpDirection.World;
+ [SerializeField]
+ Transform m_AnchorPositionOverride;
+ [SerializeField]
float m_Yaw;
+ [SerializeField]
float m_Pitch;
+ [SerializeField]
float m_Roll;
///
@@ -69,8 +73,8 @@ public float roll
///
public float distance
{
- get { return m_Distance; }
- set { m_Distance = Mathf.Max(value, .01f); }
+ get => m_Distance;
+ set => m_Distance = Mathf.Max(0, value);
}
///
@@ -102,7 +106,13 @@ public UpDirection frameSpace
///
public Vector3 anchorPosition
{
- get { return transform.position + transform.forward * m_Distance; }
+ get
+ {
+ if (anchorPositionOverride != null)
+ return anchorPositionOverride.position;
+ else
+ return transform.position + transform.forward * distance;
+ }
}
struct Axes
@@ -112,6 +122,16 @@ struct Axes
public Vector3 forward;
}
+ ///
+ /// Overrides the pivot of used to compute the light position. This is useful to track an existing object in the scene.
+ /// The transform of the light will be automatically updated by the Update() method of the LightAnchor.
+ ///
+ public Transform anchorPositionOverride
+ {
+ get => m_AnchorPositionOverride;
+ set => m_AnchorPositionOverride = value;
+ }
+
///
/// Normalizes the input angle to be in the range of -180 and 180.
///
@@ -136,6 +156,10 @@ public void SynchronizeOnTransform(Camera camera)
Vector3 worldAnchorToLight = transform.position - anchorPosition;
+ // In case the distance is 0 or the anchor override is at the same position than the light anchor
+ if (worldAnchorToLight.magnitude == 0)
+ worldAnchorToLight = -transform.forward;
+
Vector3 projectOnGround = Vector3.ProjectOnPlane(worldAnchorToLight, axes.up);
projectOnGround.Normalize();
@@ -162,7 +186,28 @@ public void UpdateTransform(Camera camera, Vector3 anchor)
Axes GetWorldSpaceAxes(Camera camera)
{
+ // Fallback when the light anchor object is child of the camera (bad setup)
+ if (transform.IsChildOf(camera.transform))
+ {
+ return new Axes
+ {
+ up = Vector3.up,
+ right = Vector3.right,
+ forward = Vector3.forward,
+ };
+ }
+
Matrix4x4 viewToWorld = camera.cameraToWorldMatrix;
+
+ // Correct view to world for perspective
+ if (!camera.orthographic && camera.transform.position != anchorPosition)
+ {
+ var d = (anchorPosition - camera.transform.position).normalized;
+ var f = Quaternion.LookRotation(d);
+ viewToWorld = Matrix4x4.Scale(new Vector3(1, 1, -1)) * Matrix4x4.TRS(camera.transform.position, f, Vector3.one).inverse;
+ viewToWorld = viewToWorld.inverse;
+ }
+
if (m_FrameSpace == UpDirection.World)
{
Vector3 viewUp = (Vector3)(Camera.main.worldToCameraMatrix * Vector3.up);
@@ -182,6 +227,15 @@ Axes GetWorldSpaceAxes(Camera camera)
};
}
+ void Update()
+ {
+ if (anchorPositionOverride == null || Camera.main == null)
+ return;
+
+ if (anchorPositionOverride.hasChanged || Camera.main.transform.hasChanged)
+ UpdateTransform(Camera.main, anchorPosition);
+ }
+
void OnDrawGizmosSelected()
{
var camera = Camera.main;
@@ -191,6 +245,8 @@ void OnDrawGizmosSelected()
return;
}
+ // TODO: fix light rotated when camera rotates
+
Axes axes = GetWorldSpaceAxes(camera);
Vector3 anchor = anchorPosition;
Vector3 d = transform.position - anchor;
@@ -229,10 +285,10 @@ void UpdateTransform(Vector3 up, Vector3 right, Vector3 forward, Vector3 anchor)
{
Quaternion worldYawRot = Quaternion.AngleAxis(m_Yaw, up);
Quaternion worldPitchRot = Quaternion.AngleAxis(m_Pitch, right);
- Vector3 worldPosition = anchor + (worldYawRot * worldPitchRot) * forward * m_Distance;
+ Vector3 worldPosition = anchor + (worldYawRot * worldPitchRot) * forward * distance;
transform.position = worldPosition;
- Vector3 lookAt = (anchor - worldPosition).normalized;
+ Vector3 lookAt = -((worldYawRot * worldPitchRot) * forward).normalized;
Vector3 angles = Quaternion.LookRotation(lookAt, up).eulerAngles;
angles.z = m_Roll;
transform.eulerAngles = angles;
diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md
index 8111f5205bd..bf646ec3074 100644
--- a/com.unity.render-pipelines.high-definition/CHANGELOG.md
+++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed assert failure when enabling the probe volume system for the first time.
- Significantly improved performance of APV probe debug.
- Removed DLSS keyword in settings search when NVIDIA package is not installed. (case 1358409)
+- Fixed light anchor min distance value + properties not working with prefabs (case 1345509).
### changed
- Visual Environment ambient mode is now Dynamic by default.