88 lines
3.6 KiB
C#
88 lines
3.6 KiB
C#
using Unity.Mathematics;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace UnityEditor.Splines
|
|
{
|
|
sealed class TangentModeStrip : VisualElement
|
|
{
|
|
readonly GUIContent[] modes = new[]
|
|
{
|
|
EditorGUIUtility.TrTextContent("Linear", "Linear Tangents:\nTangents are pointing to the previous/next spline knot."),
|
|
EditorGUIUtility.TrTextContent("Mirrored", "Mirrored Tangents:\nIf Knot or InTangent is selected, OutTangent will be mirrored on InTangent. Else, InTangent will be mirrored on OutTangent."),
|
|
EditorGUIUtility.TrTextContent("Continuous", "Continuous Tangents:\nInTangent and OutTangent are always aligned."),
|
|
EditorGUIUtility.TrTextContent("Broken", "Broken Tangents:\nInTangent and OutTangent are dissociated.")
|
|
};
|
|
readonly ButtonStripField m_ModeStrip;
|
|
|
|
ISplineElement m_Target;
|
|
|
|
internal TangentModeStrip()
|
|
{
|
|
Add(m_ModeStrip = new ButtonStripField() { name = "TangentMode" });
|
|
m_ModeStrip.choices = modes;
|
|
}
|
|
|
|
internal BezierEditableKnot.Mode GetMode()
|
|
{
|
|
return (BezierEditableKnot.Mode)m_ModeStrip.value;
|
|
}
|
|
|
|
internal void SetElement(ISplineElement target)
|
|
{
|
|
if(m_Target != target)
|
|
{
|
|
m_Target = target;
|
|
BezierEditableKnot knot = null;
|
|
if(target is BezierEditableKnot targetedKnot)
|
|
knot = targetedKnot;
|
|
else if(m_Target is EditableTangent targetedTangent && targetedTangent.owner is BezierEditableKnot tangentOwner)
|
|
knot = tangentOwner;
|
|
|
|
m_ModeStrip.OnValueChanged += ((newMode) => UpdateMode(knot, (BezierEditableKnot.Mode) newMode));
|
|
}
|
|
|
|
if(m_Target is BezierEditableKnot tKnot)
|
|
UpdateValue((int)tKnot.mode);
|
|
else if(m_Target is EditableTangent tTangent && tTangent.owner is BezierEditableKnot tangentOwner)
|
|
UpdateValue((int)tangentOwner.mode);
|
|
}
|
|
|
|
void UpdateMode(BezierEditableKnot knot, BezierEditableKnot.Mode mode)
|
|
{
|
|
if(knot.mode == mode)
|
|
return;
|
|
|
|
if(mode is BezierEditableKnot.Mode.Mirrored or BezierEditableKnot.Mode.Continuous)
|
|
{
|
|
// m_Target is the knot "knot", use the InTangent to resolve the new mode
|
|
var refTangent = knot.GetTangent(0);
|
|
var otherTangent = knot.GetTangent(1);
|
|
|
|
//Else if target is a tangent, update the values regarding the selected tangent
|
|
if(m_Target is EditableTangent { owner: BezierEditableKnot owner } target)
|
|
{
|
|
refTangent = target;
|
|
for(int i = 0; i < owner.tangentCount; ++i)
|
|
{
|
|
var tangent = owner.GetTangent(i);
|
|
if(tangent != target)
|
|
otherTangent = tangent;
|
|
}
|
|
}
|
|
|
|
if(mode == BezierEditableKnot.Mode.Mirrored)
|
|
otherTangent.SetLocalPositionNoNotify(-refTangent.localPosition);
|
|
else //Continuous mode
|
|
otherTangent.SetLocalPositionNoNotify(-math.normalize(refTangent.localPosition) * math.length(otherTangent.localPosition));
|
|
}
|
|
|
|
knot.SetMode(mode);
|
|
}
|
|
|
|
internal void UpdateValue(int modeValue)
|
|
{
|
|
m_ModeStrip.SetValueWithoutNotify(modeValue);
|
|
}
|
|
}
|
|
}
|