Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");

Expand All @@ -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);
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ public override GUIContent toolbarIcon
/// <returns>Always return true</returns>
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);
}

/// <summary>
Expand All @@ -39,7 +42,7 @@ public override bool IsAvailable()
/// <param name="window">The window that is displaying the custom editor tool.</param>
public override void OnToolGUI(EditorWindow window)
{
if (target == null)
if (target is LightAnchor l && l?.anchorPositionOverride == null)
return;

DoTargetGUI(target);
Expand Down Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ public class LightAnchorHandles
/// </summary>
public Vector3 anchorPosition { get; set; }

LightAnchor target;

/// <summary>
/// Initializes and returns an instance of LightAnchorHandles
/// </summary>
public LightAnchorHandles()
/// <param name="target">Target object</param>
public LightAnchorHandles(LightAnchor target)
{
this.target = target;
}

/// <summary>
Expand All @@ -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);
}
}
}
70 changes: 63 additions & 7 deletions com.unity.render-pipelines.core/Runtime/Lights/LightAnchor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace UnityEngine
/// Represents camera-space light controls around a virtual pivot point.
/// </summary>
[AddComponentMenu("Rendering/Light Anchor")]
[RequireComponent(typeof(Light))]
[ExecuteInEditMode]
[DisallowMultipleComponent]
[CoreRPHelpURLAttribute("View-Lighting-Tool")]
Expand All @@ -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;

/// <summary>
Expand Down Expand Up @@ -69,8 +73,8 @@ public float roll
/// </summary>
public float distance
{
get { return m_Distance; }
set { m_Distance = Mathf.Max(value, .01f); }
get => m_Distance;
set => m_Distance = Mathf.Max(0, value);
}

/// <summary>
Expand Down Expand Up @@ -102,7 +106,13 @@ public UpDirection frameSpace
/// </summary>
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
Expand All @@ -112,6 +122,16 @@ struct Axes
public Vector3 forward;
}

/// <summary>
/// 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.
/// </summary>
public Transform anchorPositionOverride
{
get => m_AnchorPositionOverride;
set => m_AnchorPositionOverride = value;
}

/// <summary>
/// Normalizes the input angle to be in the range of -180 and 180.
/// </summary>
Expand All @@ -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();

Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down