using Unity.Mathematics; using UnityEngine; using UnityEngine.UIElements; #if !UNITY_2022_1_OR_NEWER using UnityEditor.UIElements; #endif namespace UnityEditor.Splines { sealed class TangentDrawer : ElementDrawer { const string k_TangentDrawerStyle = "tangent-drawer"; const string k_TangentLabelStyle = "tangent-label"; const string k_TangentFillerStyle = "tangent-filler"; readonly Label m_TangentLabel; readonly TangentModeStrip m_Mode; FloatField m_Magnitude; Label m_DirectionLabel; Vector3Field m_Direction; FloatField m_DirectionX; FloatField m_DirectionY; FloatField m_DirectionZ; public TangentDrawer() { AddToClassList(k_TangentDrawerStyle); Add(m_TangentLabel = new Label()); m_TangentLabel.style.height = 24; m_TangentLabel.style.unityTextAlign = TextAnchor.MiddleLeft; Add(m_Mode = new TangentModeStrip()); CreateTangentFields(); m_Magnitude.RegisterValueChangedCallback((evt) => { UpdateTangentMagnitude(evt.newValue); m_Direction.SetValueWithoutNotify(target.localPosition); RoundFloatFieldsValues(); }); m_Direction.RegisterValueChangedCallback((evt) => { IgnoreKnotCallbacks(true); target.localPosition = evt.newValue; IgnoreKnotCallbacks(false); m_Magnitude.SetValueWithoutNotify(Round(math.length(target.localPosition))); }); } public override void Update() { base.Update(); m_TangentLabel.text = GetTangentLabel(); m_Mode.SetElement(target); m_Magnitude.SetValueWithoutNotify(math.length(target.localPosition)); m_Direction.SetValueWithoutNotify(target.localPosition); RoundFloatFieldsValues(); //Disabling edition when using linear, mirrored or continuous tangents EnableElements(m_Mode.GetMode()); } void CreateTangentFields() { m_Magnitude = new FloatField("Magnitude",6); m_DirectionLabel = new Label("Direction"); m_DirectionLabel.AddToClassList(k_TangentLabelStyle); var filler = new VisualElement(); filler.AddToClassList(k_TangentFillerStyle); m_Direction = new Vector3Field(){name = "direction"}; m_DirectionX = m_Direction.Q("unity-x-input"); m_DirectionY = m_Direction.Q("unity-y-input"); m_DirectionZ = m_Direction.Q("unity-z-input"); //Build UI Hierarchy Add(m_Magnitude); Add(m_DirectionLabel); Add(filler); filler.Add(m_Direction); } string GetTangentLabel() { var inOutLabel = target.tangentIndex == 0 ? "In" : "Out"; string label = "Tangent "+inOutLabel+" selected (Knot "+target.owner.index+")"; return label; } void UpdateTangentMagnitude(float value) { var direction = new float3(0, 0, 1); if(math.length(target.localPosition) > 0) direction = math.normalize(target.localPosition); IgnoreKnotCallbacks(true); target.localPosition = value * direction; IgnoreKnotCallbacks(false); } void RoundFloatFieldsValues() { m_Magnitude.SetValueWithoutNotify(Round(m_Magnitude.value)); m_DirectionX.SetValueWithoutNotify(Round(m_DirectionX.value)); m_DirectionY.SetValueWithoutNotify(Round(m_DirectionY.value)); m_DirectionZ.SetValueWithoutNotify(Round(m_DirectionZ.value)); } void EnableElements(BezierEditableKnot.Mode mode) { var bezierTangent = m_Mode.GetMode() != BezierEditableKnot.Mode.Linear; var brokenMode = m_Mode.GetMode() == BezierEditableKnot.Mode.Broken; m_Magnitude.SetEnabled(bezierTangent); m_DirectionLabel.SetEnabled(brokenMode); m_Direction.SetEnabled(brokenMode); } } }