initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -0,0 +1,157 @@
|
|||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
using UnityEditor.UIElements;
|
||||
#endif
|
||||
|
||||
namespace UnityEditor.Splines
|
||||
{
|
||||
sealed class BezierKnotDrawer : KnotDrawer<BezierEditableKnot>
|
||||
{
|
||||
const string k_TangentFoldoutStyle = "tangent-drawer";
|
||||
|
||||
readonly TangentModeStrip m_Mode;
|
||||
|
||||
readonly FloatField m_InMagnitude;
|
||||
readonly Vector3Field m_In;
|
||||
readonly FloatField m_InX;
|
||||
readonly FloatField m_InY;
|
||||
readonly FloatField m_InZ;
|
||||
readonly FloatField m_OutMagnitude;
|
||||
readonly Vector3Field m_Out;
|
||||
readonly FloatField m_OutX;
|
||||
readonly FloatField m_OutY;
|
||||
readonly FloatField m_OutZ;
|
||||
|
||||
public BezierKnotDrawer()
|
||||
{
|
||||
Add(m_Mode = new TangentModeStrip());
|
||||
|
||||
( m_InMagnitude, m_In ) = CreateTangentFoldout("Tangent In", "TangentIn");
|
||||
m_InX = m_In.Q<FloatField>("unity-x-input");
|
||||
m_InY = m_In.Q<FloatField>("unity-y-input");
|
||||
m_InZ = m_In.Q<FloatField>("unity-z-input");
|
||||
|
||||
( m_OutMagnitude, m_Out ) = CreateTangentFoldout("Tangent Out", "TangentOut");
|
||||
m_OutX = m_Out.Q<FloatField>("unity-x-input");
|
||||
m_OutY = m_Out.Q<FloatField>("unity-y-input");
|
||||
m_OutZ = m_Out.Q<FloatField>("unity-z-input");
|
||||
|
||||
m_InMagnitude.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
UpdateTangentMagnitude(target.tangentIn, m_InMagnitude, evt.newValue, -1f);
|
||||
m_In.SetValueWithoutNotify(target.tangentIn.localPosition);
|
||||
m_Out.SetValueWithoutNotify(target.tangentOut.localPosition);
|
||||
m_OutMagnitude.SetValueWithoutNotify(Round(math.length(target.tangentOut.localPosition)));
|
||||
RoundFloatFieldsValues();
|
||||
});
|
||||
|
||||
m_In.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
IgnoreKnotCallbacks(true);
|
||||
target.tangentIn.localPosition = evt.newValue;
|
||||
IgnoreKnotCallbacks(false);
|
||||
m_InMagnitude.SetValueWithoutNotify(Round(math.length(target.tangentIn.localPosition)));
|
||||
});
|
||||
|
||||
m_OutMagnitude.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
UpdateTangentMagnitude(target.tangentOut, m_OutMagnitude, evt.newValue, 1f);
|
||||
m_Out.SetValueWithoutNotify(target.tangentOut.localPosition);
|
||||
m_In.SetValueWithoutNotify(target.tangentIn.localPosition);
|
||||
m_InMagnitude.SetValueWithoutNotify(Round(math.length(target.tangentIn.localPosition)));
|
||||
RoundFloatFieldsValues();
|
||||
});
|
||||
|
||||
m_Out.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
IgnoreKnotCallbacks(true);
|
||||
target.tangentOut.localPosition = evt.newValue;
|
||||
IgnoreKnotCallbacks(false);
|
||||
m_OutMagnitude.SetValueWithoutNotify(Round(math.length(target.tangentOut.localPosition)));
|
||||
});
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
m_Mode.SetElement(target);
|
||||
m_In.SetValueWithoutNotify(target.tangentIn.localPosition);
|
||||
m_Out.SetValueWithoutNotify(target.tangentOut.localPosition);
|
||||
m_InMagnitude.SetValueWithoutNotify(math.length(target.tangentIn.localPosition));
|
||||
m_OutMagnitude.SetValueWithoutNotify(math.length(target.tangentOut.localPosition));
|
||||
|
||||
RoundFloatFieldsValues();
|
||||
//Disabling edition when using linear tangents
|
||||
EnableElements(target.mode);
|
||||
}
|
||||
|
||||
void UpdateTangentMagnitude(EditableTangent tangent, FloatField magnitudeField, float value, float directionSign)
|
||||
{
|
||||
if (value < 0f)
|
||||
{
|
||||
magnitudeField.SetValueWithoutNotify(0f);
|
||||
value = 0f;
|
||||
}
|
||||
|
||||
var direction = new float3(0, 0, directionSign);
|
||||
if(math.length(tangent.localPosition) > 0)
|
||||
direction = math.normalize(tangent.localPosition);
|
||||
|
||||
IgnoreKnotCallbacks(true);
|
||||
tangent.localPosition = value * direction;
|
||||
IgnoreKnotCallbacks(false);
|
||||
}
|
||||
|
||||
void RoundFloatFieldsValues()
|
||||
{
|
||||
m_InMagnitude.SetValueWithoutNotify(Round(m_InMagnitude.value));
|
||||
m_InX.SetValueWithoutNotify(Round(m_InX.value));
|
||||
m_InY.SetValueWithoutNotify(Round(m_InY.value));
|
||||
m_InZ.SetValueWithoutNotify(Round(m_InZ.value));
|
||||
m_OutMagnitude.SetValueWithoutNotify(Round(m_OutMagnitude.value));
|
||||
m_OutX.SetValueWithoutNotify(Round(m_OutX.value));
|
||||
m_OutY.SetValueWithoutNotify(Round(m_OutY.value));
|
||||
m_OutZ.SetValueWithoutNotify(Round(m_OutZ.value));
|
||||
}
|
||||
|
||||
void EnableElements(BezierEditableKnot.Mode mode)
|
||||
{
|
||||
var bezierTangent = mode != BezierEditableKnot.Mode.Linear;
|
||||
var brokenTangents = mode == BezierEditableKnot.Mode.Broken;
|
||||
m_InMagnitude.SetEnabled(bezierTangent);
|
||||
m_OutMagnitude.SetEnabled(bezierTangent);
|
||||
m_In.SetEnabled(brokenTangents);
|
||||
m_Out.SetEnabled(brokenTangents);
|
||||
}
|
||||
|
||||
(FloatField,Vector3Field) CreateTangentFoldout(string text, string vect3name)
|
||||
{
|
||||
//Create Elements
|
||||
var foldoutRoot = new VisualElement();
|
||||
foldoutRoot.AddToClassList(k_TangentFoldoutStyle);
|
||||
|
||||
var foldout = new Foldout() { value = false };
|
||||
var foldoutToggle = foldout.Q<Toggle>();
|
||||
var magnitude = new FloatField(L10n.Tr(text), 3);
|
||||
var vector3Field = new Vector3Field() { name = vect3name };
|
||||
|
||||
//Build UI Hierarchy
|
||||
Add(foldoutRoot);
|
||||
foldoutRoot.Add(foldout);
|
||||
foldoutToggle.Add(magnitude);
|
||||
foldout.Add(vector3Field);
|
||||
|
||||
return (magnitude, vector3Field);
|
||||
}
|
||||
|
||||
public override void OnTargetSet()
|
||||
{
|
||||
m_In.parent.SetEnabled(SplineSelectionUtility.IsSelectable(target.spline, target.index, target.tangentIn));
|
||||
m_Out.parent.SetEnabled(SplineSelectionUtility.IsSelectable(target.spline, target.index, target.tangentOut));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e1dec5e4d3c4dd84aab4dfbb3c8e6b48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,41 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.Splines
|
||||
{
|
||||
interface IElementDrawer
|
||||
{
|
||||
void SetTarget(ISplineElement element);
|
||||
void Update();
|
||||
void OnTargetSet();
|
||||
}
|
||||
|
||||
abstract class ElementDrawer<T> : VisualElement, IElementDrawer where T : ISplineElement
|
||||
{
|
||||
const int k_FloatFieldsDigits = 3;
|
||||
|
||||
public T target { get; private set; }
|
||||
|
||||
public virtual void Update() {}
|
||||
|
||||
public void SetTarget(ISplineElement element)
|
||||
{
|
||||
target = (T) element;
|
||||
OnTargetSet();
|
||||
}
|
||||
|
||||
public static float Round(float value)
|
||||
{
|
||||
float mult = Mathf.Pow(10.0f, k_FloatFieldsDigits);
|
||||
return Mathf.Round(value * mult) / mult;
|
||||
}
|
||||
|
||||
public virtual void OnTargetSet() { }
|
||||
|
||||
protected void IgnoreKnotCallbacks(bool ignore)
|
||||
{
|
||||
if (parent is ElementInspector inspector)
|
||||
inspector.ignoreKnotCallbacks = ignore;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 95245c7aa2899544b8fe0daa4947e0be
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.Splines
|
||||
{
|
||||
sealed class ElementInspector : VisualElement, IDisposable
|
||||
{
|
||||
static readonly string k_NoSelectionMessage = L10n.Tr("No element selected");
|
||||
static readonly string k_MultiSelectNoAllowedMessage = L10n.Tr(" - not supported");
|
||||
|
||||
readonly Label m_ErrorMessage;
|
||||
|
||||
Type m_InspectedType;
|
||||
EditableKnot m_TargetKnot;
|
||||
IElementDrawer m_ElementDrawer;
|
||||
|
||||
static StyleSheet s_CommonStyleSheet;
|
||||
static StyleSheet s_ThemeStyleSheet;
|
||||
|
||||
bool m_InspectorDirty;
|
||||
public bool ignoreKnotCallbacks { get; set; }
|
||||
|
||||
public ElementInspector()
|
||||
{
|
||||
if (s_CommonStyleSheet == null)
|
||||
s_CommonStyleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Packages/com.unity.splines/Editor/Stylesheets/SplineInspectorCommon.uss");
|
||||
if (s_ThemeStyleSheet == null)
|
||||
s_ThemeStyleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>($"Packages/com.unity.splines/Editor/Stylesheets/SplineInspector{(EditorGUIUtility.isProSkin ? "Dark" : "Light")}.uss");
|
||||
|
||||
styleSheets.Add(s_CommonStyleSheet);
|
||||
styleSheets.Add(s_ThemeStyleSheet);
|
||||
|
||||
m_ErrorMessage = new Label();
|
||||
Add(m_ErrorMessage);
|
||||
|
||||
EditableKnot.knotModified += OnKnotModified;
|
||||
EditorApplication.update += UpdateIfDirty;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
EditableKnot.knotModified -= OnKnotModified;
|
||||
}
|
||||
|
||||
void OnKnotModified(EditableKnot knot)
|
||||
{
|
||||
if (!ignoreKnotCallbacks && m_TargetKnot == knot)
|
||||
m_InspectorDirty = true;
|
||||
}
|
||||
|
||||
void UpdateIfDirty()
|
||||
{
|
||||
if(m_InspectorDirty)
|
||||
{
|
||||
m_ElementDrawer?.Update();
|
||||
m_InspectorDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetElement(ISplineElement element, int selectCount)
|
||||
{
|
||||
UpdateDrawerForElementType(selectCount > 1 ? null : element?.GetType());
|
||||
|
||||
if (selectCount > 1)
|
||||
ShowErrorMessage(BuildMultiSelectError(selectCount)+k_MultiSelectNoAllowedMessage);
|
||||
else if (element == null || m_ElementDrawer == null)
|
||||
ShowErrorMessage(k_NoSelectionMessage);
|
||||
else
|
||||
{
|
||||
if (element is EditableKnot knot)
|
||||
m_TargetKnot = knot;
|
||||
else if (element is EditableTangent tangent)
|
||||
m_TargetKnot = tangent.owner;
|
||||
|
||||
HideErrorMessage();
|
||||
m_ElementDrawer.SetTarget(element);
|
||||
m_ElementDrawer.Update();
|
||||
}
|
||||
}
|
||||
|
||||
string BuildMultiSelectError(int selectCount)
|
||||
{
|
||||
string message = "(" + selectCount + ") ";
|
||||
var selectionList = new List<ISplineElement>();
|
||||
SplineSelection.GetSelectedElements(selectionList);
|
||||
var isLookingForKnots = selectionList.FirstOrDefault() is EditableKnot;
|
||||
foreach(var element in selectionList)
|
||||
{
|
||||
if(isLookingForKnots && element is EditableKnot)
|
||||
continue;
|
||||
if(!isLookingForKnots && element is EditableTangent)
|
||||
continue;
|
||||
|
||||
message += "Elements selected";
|
||||
return message;
|
||||
}
|
||||
|
||||
message += isLookingForKnots ? "Knots selected" : "Tangents selected";
|
||||
return message;
|
||||
}
|
||||
|
||||
void ShowErrorMessage(string error)
|
||||
{
|
||||
m_ErrorMessage.style.display = DisplayStyle.Flex;
|
||||
m_ErrorMessage.text = error;
|
||||
}
|
||||
|
||||
void HideErrorMessage()
|
||||
{
|
||||
m_ErrorMessage.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
void UpdateDrawerForElementType(Type targetType)
|
||||
{
|
||||
if (m_InspectedType == targetType)
|
||||
return;
|
||||
|
||||
if (m_ElementDrawer != null)
|
||||
((VisualElement)m_ElementDrawer).RemoveFromHierarchy();
|
||||
|
||||
if (targetType == null)
|
||||
m_ElementDrawer = null;
|
||||
else if (typeof(BezierEditableKnot).IsAssignableFrom(targetType))
|
||||
m_ElementDrawer = new BezierKnotDrawer();
|
||||
else if (typeof(EditableKnot).IsAssignableFrom(targetType))
|
||||
m_ElementDrawer = new KnotDrawer();
|
||||
else if (typeof(EditableTangent).IsAssignableFrom(targetType))
|
||||
m_ElementDrawer = new TangentDrawer();
|
||||
else
|
||||
m_ElementDrawer = null;
|
||||
|
||||
if (m_ElementDrawer != null)
|
||||
Add((VisualElement)m_ElementDrawer);
|
||||
|
||||
m_InspectedType = targetType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b5d8a953f9ef52441bd58f4c1e5853a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,83 @@
|
|||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.Splines
|
||||
{
|
||||
sealed class KnotDrawer : KnotDrawer<EditableKnot> {}
|
||||
|
||||
class KnotDrawer<T> : ElementDrawer<T> where T : EditableKnot
|
||||
{
|
||||
readonly Label m_KnotLabel;
|
||||
readonly Vector3Field m_Position;
|
||||
readonly FloatField m_PositionX;
|
||||
readonly FloatField m_PositionY;
|
||||
readonly FloatField m_PositionZ;
|
||||
readonly Vector3Field m_Rotation;
|
||||
readonly FloatField m_RotationX;
|
||||
readonly FloatField m_RotationY;
|
||||
readonly FloatField m_RotationZ;
|
||||
|
||||
public KnotDrawer()
|
||||
{
|
||||
Add(m_KnotLabel = new Label());
|
||||
m_KnotLabel.style.height = 24;
|
||||
m_KnotLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
|
||||
VisualElement row;
|
||||
Add(row = new VisualElement(){name = "Vector3WithIcon"});
|
||||
row.style.flexDirection = FlexDirection.Row;
|
||||
row.Add(new VisualElement(){name = "PositionIcon"});
|
||||
row.Add(m_Position = new Vector3Field() { name = "Position" });
|
||||
|
||||
m_Position.style.flexGrow = 1;
|
||||
m_PositionX = m_Position.Q<FloatField>("unity-x-input");
|
||||
m_PositionY = m_Position.Q<FloatField>("unity-y-input");
|
||||
m_PositionZ = m_Position.Q<FloatField>("unity-z-input");
|
||||
|
||||
Add(row = new VisualElement(){name = "Vector3WithIcon"});
|
||||
row.style.flexDirection = FlexDirection.Row;
|
||||
row.Add(new VisualElement(){name = "RotationIcon"});
|
||||
row.Add(m_Rotation = new Vector3Field() { name = "Rotation" });;
|
||||
|
||||
m_Rotation.style.flexGrow = 1;
|
||||
m_RotationX = m_Rotation.Q<FloatField>("unity-x-input");
|
||||
m_RotationY = m_Rotation.Q<FloatField>("unity-y-input");
|
||||
m_RotationZ = m_Rotation.Q<FloatField>("unity-z-input");
|
||||
|
||||
m_Position.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
IgnoreKnotCallbacks(true);
|
||||
target.localPosition = evt.newValue;
|
||||
IgnoreKnotCallbacks(false);
|
||||
});
|
||||
m_Rotation.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
IgnoreKnotCallbacks(true);
|
||||
target.localRotation = Quaternion.Euler(evt.newValue);
|
||||
IgnoreKnotCallbacks(false);
|
||||
});
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
m_KnotLabel.text = "Knot "+target.index.ToString()+" selected";
|
||||
m_Position.SetValueWithoutNotify(target.localPosition);
|
||||
m_Rotation.SetValueWithoutNotify(((Quaternion)target.localRotation).eulerAngles);
|
||||
|
||||
RoundFloatFieldsValues();
|
||||
}
|
||||
|
||||
void RoundFloatFieldsValues()
|
||||
{
|
||||
m_PositionX.SetValueWithoutNotify(Round(m_PositionX.value));
|
||||
m_PositionY.SetValueWithoutNotify(Round(m_PositionY.value));
|
||||
m_PositionZ.SetValueWithoutNotify(Round(m_PositionZ.value));
|
||||
m_RotationX.SetValueWithoutNotify(Round(m_RotationX.value));
|
||||
m_RotationY.SetValueWithoutNotify(Round(m_RotationY.value));
|
||||
m_RotationZ.SetValueWithoutNotify(Round(m_RotationZ.value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3018d9f76949a7f4c8ad97e48caff165
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,24 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.Splines
|
||||
{
|
||||
sealed class ReadOnlyField : BaseField<string>
|
||||
{
|
||||
readonly Label m_IndexField;
|
||||
|
||||
public ReadOnlyField(string label) : base(label, new Label() { name = "ReadOnlyValue" })
|
||||
{
|
||||
style.flexDirection = FlexDirection.Row;
|
||||
|
||||
m_IndexField = this.Q<Label>("ReadOnlyValue");
|
||||
m_IndexField.text = value;
|
||||
m_IndexField.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
}
|
||||
|
||||
public override void SetValueWithoutNotify(string newValue)
|
||||
{
|
||||
m_IndexField.text = newValue;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 37aa8727811c9e04785d9c0e4cafc5d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,125 @@
|
|||
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<EditableTangent>
|
||||
{
|
||||
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<FloatField>("unity-x-input");
|
||||
m_DirectionY = m_Direction.Q<FloatField>("unity-y-input");
|
||||
m_DirectionZ = m_Direction.Q<FloatField>("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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d01d6b9007f24984692322edf5415826
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,88 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c74ddef7e6e74f529a51b5ad71552fbd
|
||||
timeCreated: 1637605071
|
Loading…
Add table
Add a link
Reference in a new issue