first commit

This commit is contained in:
lethanhsonvsp
2025-11-17 15:16:36 +07:00
commit a40d0921eb
17012 changed files with 2652386 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.Splines;
#if !UNITY_2022_1_OR_NEWER
using UnityEditor.UIElements;
#endif
namespace UnityEditor.Splines
{
sealed class BezierKnotDrawer : ElementDrawer<SelectableKnot>
{
static readonly string k_PositionTooltip = L10n.Tr("Knot Position");
static readonly string k_RotationTooltip = L10n.Tr("Knot Rotation");
readonly Float3PropertyField<SelectableKnot> m_Position;
readonly Float3PropertyField<SelectableKnot> m_Rotation;
readonly TangentModePropertyField<SelectableKnot> m_Mode;
readonly BezierTangentPropertyField<SelectableKnot> m_BezierMode;
readonly TangentPropertyField m_TangentIn;
readonly TangentPropertyField m_TangentOut;
public BezierKnotDrawer()
{
VisualElement row;
Add(row = new VisualElement(){name = "Vector3WithIcon"});
row.tooltip = k_PositionTooltip;
row.style.flexDirection = FlexDirection.Row;
row.Add(new VisualElement(){name = "PositionIcon"});
row.Add(m_Position = new Float3PropertyField<SelectableKnot>("",
(knot) => knot.LocalPosition,
(knot, value) => knot.LocalPosition = value)
{ name = "Position" });
m_Position.style.flexGrow = 1;
Add(row = new VisualElement(){name = "Vector3WithIcon"});
row.tooltip = k_RotationTooltip;
row.style.flexDirection = FlexDirection.Row;
row.Add(new VisualElement(){name = "RotationIcon"});
row.Add(m_Rotation = new Float3PropertyField<SelectableKnot>("",
(knot) => ((Quaternion)knot.LocalRotation).eulerAngles,
(knot, value) => knot.LocalRotation = Quaternion.Euler(value))
{ name = "Rotation" });
m_Rotation.style.flexGrow = 1;
Add(new Separator());
Add(m_Mode = new TangentModePropertyField<SelectableKnot>());
m_Mode.changed += Update;
Add(m_BezierMode = new BezierTangentPropertyField<SelectableKnot>());
m_BezierMode.changed += Update;
Add(m_TangentIn = new TangentPropertyField("In", "TangentIn", BezierTangent.In));
Add(m_TangentOut = new TangentPropertyField("Out", "TangentOut", BezierTangent.Out));
//Update opposite to take into account some tangent modes
m_TangentIn.changed += () => m_TangentOut.Update(targets);
m_TangentOut.changed += () => m_TangentIn.Update(targets);
}
public override string GetLabelForTargets()
{
if (targets.Count > 1)
return $"<b>({targets.Count}) Knots</b> selected";
return $"<b>Knot {target.KnotIndex}</b> (<b>Spline {target.SplineInfo.Index}</b>) selected";
}
public override void Update()
{
base.Update();
m_Position.Update(targets);
m_Rotation.Update(targets);
m_Mode.Update(targets);
m_BezierMode.Update(targets);
m_TangentIn.Update(targets);
m_TangentOut.Update(targets);
//Disabling edition when using linear tangents
UpdateTangentsState();
}
void UpdateTangentsState()
{
bool tangentsModifiable = true;
bool tangentsBroken = true;
bool tangentInSelectable = false;
bool tangentOutSelectable = false;
for (int i = 0; i < targets.Count; ++i)
{
var mode = targets[i].Mode;
tangentsModifiable &= SplineUtility.AreTangentsModifiable(mode);
tangentsBroken &= mode == TangentMode.Broken;
tangentInSelectable |= SplineSelectionUtility.IsSelectable(targets[i].TangentIn);
tangentOutSelectable |= SplineSelectionUtility.IsSelectable(targets[i].TangentOut);
}
m_TangentIn.SetEnabled(tangentsModifiable && tangentInSelectable);
m_TangentOut.SetEnabled(tangentsModifiable && tangentOutSelectable);
if(tangentsModifiable)
{
m_TangentIn.vector3field.SetEnabled(tangentsBroken);
m_TangentOut.vector3field.SetEnabled(tangentsBroken);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1dec5e4d3c4dd84aab4dfbb3c8e6b48
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using UnityEditor.Toolbars;
using UnityEngine;
using UnityEngine.Splines;
#if !UNITY_2022_1_OR_NEWER
#endif
namespace UnityEditor.Splines.Editor.GUI
{
[EditorToolbarElement("Spline Tool Settings/Default Knot Type")]
class DefaultKnotTypeDropdown : EditorToolbarDropdown
{
const string k_LinearIconPath = "Packages/com.unity.splines/Editor/Resources/Icons/Tangent_Linear.png";
const string k_AutoSmoothIconPath = "Packages/com.unity.splines/Editor/Resources/Icons/AutoSmoothKnot.png";
readonly GUIContent[] m_OptionContents = new GUIContent[2];
public DefaultKnotTypeDropdown()
{
name = "Default Knot Type";
var content = EditorGUIUtility.TrTextContent("Linear",
"Tangents are not used. A linear knot tries to connect to another by a path with no curvature.",
k_LinearIconPath);
m_OptionContents[0] = content;
content = EditorGUIUtility.TrTextContent("Auto Smooth",
"Tangents are calculated using the previous and next knot positions.",
k_AutoSmoothIconPath);
m_OptionContents[1] = content;
clicked += OpenContextMenu;
RefreshElementContent();
}
void OpenContextMenu()
{
var menu = new GenericMenu();
menu.AddItem(m_OptionContents[0], EditorSplineUtility.DefaultTangentMode == TangentMode.Linear,
() => SetTangentModeIfNeeded(TangentMode.Linear));
menu.AddItem(m_OptionContents[1], EditorSplineUtility.DefaultTangentMode == TangentMode.AutoSmooth,
() => SetTangentModeIfNeeded(TangentMode.AutoSmooth));
menu.DropDown(worldBound);
}
void SetTangentModeIfNeeded(TangentMode tangentMode)
{
if (EditorSplineUtility.DefaultTangentMode != tangentMode)
{
EditorSplineUtility.s_DefaultTangentMode.SetValue(tangentMode, true);
RefreshElementContent();
}
}
void RefreshElementContent()
{
var content = m_OptionContents[EditorSplineUtility.DefaultTangentMode == TangentMode.Linear ? 0 : 1];
text = content.text;
tooltip = content.tooltip;
icon = content.image as Texture2D;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: facf982a205a4c93830bb62332a75ceb
timeCreated: 1649792821

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine.UIElements;
#if !UNITY_2022_1_OR_NEWER
using UnityEditor.UIElements;
#endif
namespace UnityEditor.Splines
{
class Float3PropertyField<T> : Vector3Field
where T : ISelectableElement
{
static readonly List<float3> s_Float3Buffer = new List<float3>();
static readonly SplineGUIUtility.EqualityComparer<float3> s_ComparerX = (a, b) => a.x.Equals(b.x);
static readonly SplineGUIUtility.EqualityComparer<float3> s_ComparerY = (a, b) => a.y.Equals(b.y);
static readonly SplineGUIUtility.EqualityComparer<float3> s_ComparerZ = (a, b) => a.z.Equals(b.z);
readonly FloatField m_X;
readonly FloatField m_Y;
readonly FloatField m_Z;
readonly Func<T, float3> m_Get;
readonly Action<T, float3> m_Set;
IReadOnlyList<T> m_Elements = new List<T>(0);
public event Action changed;
public Float3PropertyField(string label, Func<T, float3> get, Action<T, float3> set) : base(label)
{
m_Get = get;
m_Set = set;
m_X = this.Q<FloatField>("unity-x-input");
m_Y = this.Q<FloatField>("unity-y-input");
m_Z = this.Q<FloatField>("unity-z-input");
m_X.RegisterValueChangedCallback(ApplyX);
m_Y.RegisterValueChangedCallback(ApplyY);
m_Z.RegisterValueChangedCallback(ApplyZ);
}
public void Update(IReadOnlyList<T> elements)
{
m_Elements = elements;
s_Float3Buffer.Clear();
for (int i = 0; i < elements.Count; ++i)
s_Float3Buffer.Add(m_Get.Invoke(elements[i]));
var value = s_Float3Buffer.Count > 0 ? s_Float3Buffer[0] : 0;
m_X.showMixedValue = SplineGUIUtility.HasMultipleValues(s_Float3Buffer, s_ComparerX);
if (!m_X.showMixedValue)
m_X.SetValueWithoutNotify(value[0]);
m_Y.showMixedValue = SplineGUIUtility.HasMultipleValues(s_Float3Buffer, s_ComparerY);
if (!m_Y.showMixedValue)
m_Y.SetValueWithoutNotify(value[1]);
m_Z.showMixedValue = SplineGUIUtility.HasMultipleValues(s_Float3Buffer, s_ComparerZ);
if (!m_Z.showMixedValue)
m_Z.SetValueWithoutNotify(value[2]);
}
void ApplyX(ChangeEvent<float> evt)
{
EditorSplineUtility.RecordObjects(m_Elements, SplineInspectorOverlay.SplineChangeUndoMessage);
ElementInspector.ignoreKnotCallbacks = true;
for (int i = 0; i < m_Elements.Count; ++i)
{
var value = m_Get.Invoke(m_Elements[i]);
value.x = evt.newValue;
m_Set.Invoke(m_Elements[i], value);
}
m_X.showMixedValue = false;
m_X.SetValueWithoutNotify(evt.newValue);
changed?.Invoke();
ElementInspector.ignoreKnotCallbacks = false;
}
void ApplyY(ChangeEvent<float> evt)
{
EditorSplineUtility.RecordObjects(m_Elements, SplineInspectorOverlay.SplineChangeUndoMessage);
ElementInspector.ignoreKnotCallbacks = true;
for (int i = 0; i < m_Elements.Count; ++i)
{
var value = m_Get.Invoke(m_Elements[i]);
value.y = evt.newValue;
m_Set.Invoke(m_Elements[i], value);
}
m_Y.showMixedValue = false;
m_Y.SetValueWithoutNotify(evt.newValue);
changed?.Invoke();
ElementInspector.ignoreKnotCallbacks = false;
}
void ApplyZ(ChangeEvent<float> evt)
{
EditorSplineUtility.RecordObjects(m_Elements, SplineInspectorOverlay.SplineChangeUndoMessage);
ElementInspector.ignoreKnotCallbacks = true;
for (int i = 0; i < m_Elements.Count; ++i)
{
var value = m_Get.Invoke(m_Elements[i]);
value.z = evt.newValue;
m_Set.Invoke(m_Elements[i], value);
}
m_Z.showMixedValue = false;
m_Z.SetValueWithoutNotify(evt.newValue);
changed?.Invoke();
ElementInspector.ignoreKnotCallbacks = false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ae3c8f89802f5a242813000e2c3b55a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,94 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.Toolbars;
namespace UnityEditor.Splines
{
[EditorToolbarElement("Spline Tool Settings/Handle Rotation")]
class HandleRotationDropdown : EditorToolbarDropdown
{
const string k_ParentRotationIconPath = "Packages/com.unity.splines/Editor/Resources/Icons/ToolHandleParent.png";
const string k_ElementRotationIconPath = "Packages/com.unity.splines/Editor/Resources/Icons/ToolHandleElement.png";
readonly List<GUIContent> m_OptionContents = new List<GUIContent>();
public HandleRotationDropdown()
{
name = "Handle Rotation";
var content = EditorGUIUtility.TrTextContent("Local",
"Toggle Tool Handle Rotation\n\nTool handles are in the active object's rotation.",
"ToolHandleLocal");
m_OptionContents.Add(content);
content = EditorGUIUtility.TrTextContent("Global",
"Toggle Tool Handle Rotation\n\nTool handles are in global rotation.",
"ToolHandleGlobal");
m_OptionContents.Add(content);
content = EditorGUIUtility.TrTextContent("Parent",
"Toggle Tool Handle Rotation\n\nTool handles are in active element's parent's rotation.",
k_ParentRotationIconPath);
m_OptionContents.Add(content);
content = EditorGUIUtility.TrTextContent("Element",
"Toggle Tool Handle Rotation\n\nTool handles are in active element's rotation.",
k_ElementRotationIconPath);
m_OptionContents.Add(content);
RegisterCallback<AttachToPanelEvent>(AttachedToPanel);
RegisterCallback<DetachFromPanelEvent>(DetachedFromPanel);
clicked += OpenContextMenu;
RefreshElementContent();
}
void OpenContextMenu()
{
var menu = new GenericMenu();
menu.AddItem(m_OptionContents[(int)HandleOrientation.Global], SplineTool.handleOrientation == HandleOrientation.Global,
() => SetHandleOrientationIfNeeded(HandleOrientation.Global));
menu.AddItem(m_OptionContents[(int)HandleOrientation.Local], SplineTool.handleOrientation == HandleOrientation.Local,
() => SetHandleOrientationIfNeeded(HandleOrientation.Local));
menu.AddItem(m_OptionContents[(int)HandleOrientation.Parent], SplineTool.handleOrientation == HandleOrientation.Parent,
() => SetHandleOrientationIfNeeded(HandleOrientation.Parent));
menu.AddItem(m_OptionContents[(int)HandleOrientation.Element], SplineTool.handleOrientation == HandleOrientation.Element,
() => SetHandleOrientationIfNeeded(HandleOrientation.Element));
menu.DropDown(worldBound);
}
void SetHandleOrientationIfNeeded(HandleOrientation handleOrientation)
{
if (SplineTool.handleOrientation != handleOrientation)
{
SplineTool.handleOrientation = handleOrientation;
RefreshElementContent();
}
}
void RefreshElementContent()
{
var content = m_OptionContents[(int)SplineTool.handleOrientation];
text = content.text;
tooltip = content.tooltip;
icon = content.image as Texture2D;
}
void AttachedToPanel(AttachToPanelEvent evt)
{
SplineTool.handleOrientationChanged += RefreshElementContent;
}
void DetachedFromPanel(DetachFromPanelEvent evt)
{
SplineTool.handleOrientationChanged -= RefreshElementContent;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29ae16933bbb94210b13408d3f86a072
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using UnityEngine.UIElements;
namespace UnityEditor.Splines
{
sealed class Separator : VisualElement
{
public Separator()
{
AddToClassList("unity-separator");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: be6977c835160b643b208844b583a89c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using UnityEditor.EditorTools;
using UnityEditor.Toolbars;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.Splines
{
[EditorToolbarElement("Spline Tool Settings/Handle Visuals")]
sealed class SplineHandleSettingsDropdown : EditorToolbarDropdown
{
public SplineHandleSettingsDropdown()
{
var content = EditorGUIUtility.TrTextContent("Visuals", "Visual settings for handles");
text = content.text;
tooltip = content.tooltip;
icon = (Texture2D)content.image;
clicked += OnClick;
RegisterCallback<AttachToPanelEvent>(AttachToPanel);
}
void OnClick()
{
SplineHandleSettingsWindow.Show(worldBound);
}
void AttachToPanel(AttachToPanelEvent evt)
{
var toolType = ToolManager.activeToolType;
SetEnabled(toolType != typeof(KnotPlacementTool));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9935a56c1434b7845abe3f2b8f6600f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,88 @@
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.Splines
{
sealed class SplineHandleSettingsWindow : EditorWindow
{
const float k_BorderWidth = 1;
Toggle m_FlowDirection;
Toggle m_AllTangents;
Toggle m_KnotIndices;
Toggle m_SplineMesh;
public static void Show(Rect buttonRect)
{
var window = CreateInstance<SplineHandleSettingsWindow>();
window.hideFlags = HideFlags.DontSave;
#if UNITY_2022_1_OR_NEWER
var popupWidth = 150;
#else
var popupWidth = 180;
#endif
window.ShowAsDropDown(GUIUtility.GUIToScreenRect(buttonRect), new Vector2(popupWidth, 80));
}
void OnEnable()
{
Color borderColor = EditorGUIUtility.isProSkin ? new Color(0.44f, 0.44f, 0.44f, 1f) : new Color(0.51f, 0.51f, 0.51f);
rootVisualElement.style.borderLeftWidth = k_BorderWidth;
rootVisualElement.style.borderTopWidth = k_BorderWidth;
rootVisualElement.style.borderRightWidth = k_BorderWidth;
rootVisualElement.style.borderBottomWidth = k_BorderWidth;
rootVisualElement.style.borderLeftColor = borderColor;
rootVisualElement.style.borderTopColor = borderColor;
rootVisualElement.style.borderRightColor = borderColor;
rootVisualElement.style.borderBottomColor = borderColor;
rootVisualElement.Add(m_FlowDirection = new Toggle(L10n.Tr("Flow Direction")));
m_FlowDirection.style.flexDirection = FlexDirection.RowReverse;
rootVisualElement.Add(m_AllTangents = new Toggle(L10n.Tr("All Tangents")));
m_AllTangents.style.flexDirection = FlexDirection.RowReverse;
rootVisualElement.Add(m_KnotIndices = new Toggle(L10n.Tr("Knot Indices")));
m_KnotIndices.style.flexDirection = FlexDirection.RowReverse;
rootVisualElement.Add(m_SplineMesh = new Toggle(L10n.Tr("Show Mesh")));
m_SplineMesh.style.flexDirection = FlexDirection.RowReverse;
m_FlowDirection.RegisterValueChangedCallback((evt) =>
{
SplineHandleSettings.FlowDirectionEnabled = evt.newValue;
SceneView.RepaintAll();
});
m_AllTangents.RegisterValueChangedCallback((evt) =>
{
SplineHandleSettings.ShowAllTangents = evt.newValue;
SceneView.RepaintAll();
});
m_KnotIndices.RegisterValueChangedCallback((evt) =>
{
SplineHandleSettings.ShowKnotIndices = evt.newValue;
SceneView.RepaintAll();
});
m_SplineMesh.RegisterValueChangedCallback((evt) =>
{
SplineHandleSettings.ShowMesh = evt.newValue;
SceneView.RepaintAll();
});
UpdateValues();
}
void UpdateValues()
{
m_FlowDirection.SetValueWithoutNotify(SplineHandleSettings.FlowDirectionEnabled);
m_AllTangents.SetValueWithoutNotify(SplineHandleSettings.ShowAllTangents);
m_KnotIndices.SetValueWithoutNotify(SplineHandleSettings.ShowKnotIndices);
m_SplineMesh.SetValueWithoutNotify(SplineHandleSettings.ShowMesh);
SceneView.RepaintAll();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b8c433db06b595546b18ebbe3e27c83f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using UnityEditor.EditorTools;
using UnityEditor.Overlays;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.Splines;
namespace UnityEditor.Splines
{
[Icon("UnityEditor.InspectorWindow")]
[Overlay(typeof(SceneView), "unity-spline-inspector", "Element Inspector", "SplineInspector")]
sealed class SplineInspectorOverlay : Overlay, ITransientOverlay
{
internal static readonly string SplineChangeUndoMessage = L10n.Tr("Apply Changes to Spline");
public static void ForceUpdate()
{
s_ForceUpdateRequested?.Invoke();
}
static event Action s_ForceUpdateRequested;
static bool s_FirstUpdateSinceDomainReload = true;
static IReadOnlyList<SplineInfo> m_SelectedSplines;
internal static void SetSelectedSplines(IReadOnlyList<SplineInfo> splines)
{
m_SelectedSplines = splines;
if (s_FirstUpdateSinceDomainReload)
{
s_FirstUpdateSinceDomainReload = false;
ForceUpdate();
}
}
public bool visible => ToolManager.activeContextType == typeof(SplineToolContext) && ToolManager.activeToolType != typeof(KnotPlacementTool);
ElementInspector m_ElementInspector;
public override VisualElement CreatePanelContent()
{
VisualElement root = new VisualElement();
root.Add(m_ElementInspector = new ElementInspector());
UpdateInspector();
return root;
}
public override void OnCreated()
{
displayedChanged += OnDisplayedChange;
SplineSelection.changed += UpdateInspector;
s_ForceUpdateRequested += UpdateInspector;
Undo.undoRedoPerformed += OnUndoRedoPerformed;
}
public override void OnWillBeDestroyed()
{
displayedChanged -= OnDisplayedChange;
SplineSelection.changed -= UpdateInspector;
s_ForceUpdateRequested -= UpdateInspector;
Undo.undoRedoPerformed -= OnUndoRedoPerformed;
}
void OnDisplayedChange(bool displayed)
{
UpdateInspector();
}
void UpdateInspector()
{
if (m_SelectedSplines == null)
return;
m_ElementInspector?.UpdateSelection(m_SelectedSplines);
}
void OnUndoRedoPerformed()
{
ForceUpdate();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5737da4b5db2be640adcc9bb3360aa91
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,135 @@
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine.Splines;
using UnityEngine.UIElements;
#if !UNITY_2022_1_OR_NEWER
using UnityEditor.UIElements;
#endif
namespace UnityEditor.Splines
{
sealed class TangentDrawer : ElementDrawer<SelectableTangent>
{
const string k_TangentDrawerStyle = "tangent-drawer";
static readonly List<float> s_LengthBuffer = new List<float>(0);
static readonly SplineGUIUtility.EqualityComparer<float> s_MagnitudeComparer = (a, b) => a.Equals(b);
readonly TangentModePropertyField<SelectableTangent> m_Mode;
readonly BezierTangentPropertyField<SelectableTangent> m_BezierMode;
FloatField m_Magnitude;
Float3PropertyField<SelectableTangent> m_Direction;
public TangentDrawer()
{
AddToClassList(k_TangentDrawerStyle);
Add(m_Mode = new TangentModePropertyField<SelectableTangent>());
m_Mode.changed += () =>
{
m_BezierMode.Update(targets);
EnableElements();
};
Add(m_BezierMode = new BezierTangentPropertyField<SelectableTangent>());
m_BezierMode.changed += () =>
{
m_Mode.Update(targets);
EnableElements();
};
CreateTangentFields();
m_Magnitude.RegisterValueChangedCallback((evt) =>
{
var value = evt.newValue;
if (evt.newValue < 0f)
{
m_Magnitude.SetValueWithoutNotify(0f);
value = 0f;
}
Undo.RecordObject(target.SplineInfo.Object, SplineInspectorOverlay.SplineChangeUndoMessage);
UpdateTangentMagnitude(value);
var tangent = target;
m_Direction.SetValueWithoutNotify(tangent.LocalPosition);
});
}
public override string GetLabelForTargets()
{
if (targets.Count > 1)
return $"<b>({targets.Count}) Tangents</b> selected";
var inOutLabel = target.TangentIndex == 0 ? "In" : "Out";
return $"Tangent <b>{inOutLabel}</b> selected (<b>Knot {target.KnotIndex}</b>, <b>Spline {target.SplineInfo.Index}</b>)";
}
public override void Update()
{
base.Update();
m_Mode.Update(targets);
m_BezierMode.Update(targets);
UpdateMagnitudeField(targets);
m_Direction.Update(targets);
EnableElements();
}
void CreateTangentFields()
{
Add(m_Magnitude = new FloatField(L10n.Tr("Length"), 6));
Add(m_Direction = new Float3PropertyField<SelectableTangent>(L10n.Tr("Direction"),
(tangent) => tangent.LocalDirection,
(tangent, value) => tangent.LocalDirection = value)
{ name = "direction" });
m_Direction.changed += () => { UpdateMagnitudeField(targets); };
}
void UpdateMagnitudeField(IReadOnlyList<SelectableTangent> tangents)
{
s_LengthBuffer.Clear();
for (int i = 0; i < tangents.Count; ++i)
s_LengthBuffer.Add(math.length(tangents[i].LocalPosition));
m_Magnitude.showMixedValue = SplineGUIUtility.HasMultipleValues(s_LengthBuffer, s_MagnitudeComparer);
if (!m_Magnitude.showMixedValue)
m_Magnitude.SetValueWithoutNotify(s_LengthBuffer[0]);
}
void UpdateTangentMagnitude(float value)
{
ElementInspector.ignoreKnotCallbacks = true;
for (int i = 0; i < targets.Count; ++i)
{
var direction = new float3(0, 0, 1);
var tangent = targets[i];
if (math.length(tangent.LocalPosition) > 0)
direction = math.normalize(tangent.LocalPosition);
tangent.LocalPosition = value * direction;
}
ElementInspector.ignoreKnotCallbacks = false;
}
void EnableElements()
{
bool tangentsModifiable = true;
bool tangentsBroken = true;
for (int i = 0; i < targets.Count; ++i)
{
var mode = targets[i].Owner.Mode;
tangentsModifiable &= SplineUtility.AreTangentsModifiable(mode);
tangentsBroken &= mode == TangentMode.Broken;
}
m_Direction.SetEnabled(tangentsModifiable && tangentsBroken);
m_Magnitude.SetEnabled(tangentsModifiable);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d01d6b9007f24984692322edf5415826
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: