using System.Collections.Generic; using UnityEngine; using UnityEditor; using UnityEditor.EditorTools; using UnityObject = UnityEngine.Object; namespace UnityEditor { /// /// LightAnchorEditorTool /// [EditorTool("Light Anchor", typeof(LightAnchor))] public class LightAnchorEditorTool : EditorTool { GUIContent m_IconContent; Dictionary m_SerializedObjects = new Dictionary(); Dictionary m_LightAnchorHandles = new Dictionary(); /// /// Icon for LightAnchor Tool /// public override GUIContent toolbarIcon { get { return m_IconContent; } } /// /// Checks whether the custom editor tool is available based on the state of the editor. /// /// Always return true // (case 1396843) The availability is checked only when a component gains focus. So if the tool availability // while the focus is the same, the change won't be propagated to the toolbar, which can be very confusing. public override bool IsAvailable() => true; /// /// Use this method to implement a custom editor tool. /// /// The window that is displaying the custom editor tool. public override void OnToolGUI(EditorWindow window) { if (target is not LightAnchor l) return; // (case 1396843) When the anchor override is assigned, the handle must not modify the overriden transform // so still display it to avoid confusion, but keep it disabled. var isHandleEnabled = l.anchorPositionOverride == null; using (new EditorGUI.DisabledScope(!isHandleEnabled)) { DoTargetGUI(target); } } void OnEnable() { m_IconContent = new GUIContent(UnityEditor.Rendering.CoreEditorUtils.LoadIcon(@"Packages/com.unity.render-pipelines.core/Editor/Lighting/Icons/", "LightAnchor_Icon", ".png", false)); } void DoTargetGUI(UnityObject target) { var lightAnchor = target as LightAnchor; Transform transform = lightAnchor.transform; ; Vector3 lightPosition = transform.position; ; Vector3 anchorPosition = transform.TransformPoint(Vector3.forward * lightAnchor.distance); var handles = GetHandles(target); handles.lightPosition = lightPosition; handles.anchorPosition = anchorPosition; using (var change = new EditorGUI.ChangeCheckScope()) { handles.OnGUI(); if (change.changed) { if (handles.anchorPosition != anchorPosition) { var parent = transform.parent; var so = GetSerializedObject(transform); so.Update(); var prop = so.FindProperty("m_LocalPosition"); var localPosition = handles.anchorPosition - transform.forward * lightAnchor.distance; if (parent != null) localPosition = parent.InverseTransformPoint(localPosition); prop.vector3Value = localPosition; so.ApplyModifiedProperties(); } if (handles.lightPosition != lightPosition) { { var so = GetSerializedObject(lightAnchor); var prop = so.FindProperty("m_Distance"); so.Update(); prop.floatValue = (handles.lightPosition - handles.anchorPosition).magnitude; so.ApplyModifiedProperties(); } { var parent = transform.parent; var so = GetSerializedObject(transform); var prop = so.FindProperty("m_LocalPosition"); so.Update(); var localPosition = handles.lightPosition; if (parent != null) localPosition = parent.InverseTransformPoint(localPosition); prop.vector3Value = localPosition; so.ApplyModifiedProperties(); } } } } } LightAnchorHandles GetHandles(UnityObject obj) { LightAnchorHandles handles; if (!m_LightAnchorHandles.TryGetValue(obj, out handles)) { handles = new LightAnchorHandles(obj as LightAnchor); m_LightAnchorHandles.Add(obj, handles); } return handles; } SerializedObject GetSerializedObject(UnityObject obj) { SerializedObject so; if (!m_SerializedObjects.TryGetValue(obj, out so)) { so = new SerializedObject(obj); m_SerializedObjects.Add(obj, so); } return so; } } }