WuhuIslandTesting/Library/PackageCache/com.unity.splines@1.0.1/Editor/Tools/SplineToolContext.cs
2025-01-07 02:06:59 +01:00

242 lines
8.3 KiB
C#

using System;
using System.Collections.Generic;
using UnityEditor.EditorTools;
using UnityEngine;
using UnityEngine.Splines;
namespace UnityEditor.Splines
{
[Flags]
enum SplineHandlesOptions
{
ShowTangents = 1 << 0,
SelectableKnots = 1 << 1,
SelectableTangents = 1 << 2,
KnotInsert = 1 << 3,
SelectableElements = SelectableKnots | SelectableTangents,
None = 0,
ManipulationDefault = ShowTangents | SelectableElements
}
/// <summary>
/// Defines a tool context for editing splines. When authoring tools for splines, pass the SplineToolContext type
/// to the EditorToolAttribute.editorToolContext parameter to register as a spline tool.
/// </summary>
#if UNITY_2021_2_OR_NEWER
[EditorToolContext("Spline", typeof(ISplineProvider)), Icon(k_IconPath)]
#else
[EditorToolContext("Spline", typeof(ISplineProvider))]
#endif
public sealed class SplineToolContext : EditorToolContext
{
const string k_IconPath = "Packages/com.unity.splines/Editor/Resources/Icons/SplineContext.png";
static SplineHandlesOptions s_SplineHandlesOptions = SplineHandlesOptions.None;
static bool s_UseCustomSplineHandles = false;
static bool s_IsSplineTool = true;
readonly SplineElementRectSelector m_RectSelector = new SplineElementRectSelector();
readonly List<IEditableSpline> m_Splines = new List<IEditableSpline>();
readonly List<EditableKnot> m_KnotBuffer = new List<EditableKnot>();
bool m_WasActiveAfterDeserialize;
internal static void SetHandlesOptions(SplineHandlesOptions options)
{
s_SplineHandlesOptions = options;
}
internal static void UseCustomSplineHandles(bool useCustomSplineHandle)
{
s_UseCustomSplineHandles = useCustomSplineHandle;
}
/// <summary>
/// Returns the matching EditorTool type for the specified Tool given the context.
/// </summary>
/// <param name="tool">The Tool to resolve to an EditorTool type.</param>
/// <returns> An EditorTool type for the requested Tool.</returns>
protected override Type GetEditorToolType(Tool tool)
{
if (tool == Tool.Move)
return typeof(SplineMoveTool);
if (tool == Tool.Rotate)
return typeof(SplineRotateTool);
if (tool == Tool.Scale)
return typeof(SplineScaleTool);
return null;
}
/// <summary>
/// Invoked for each window where this context is active. The spline context uses this method to implement
/// common functionality for working with splines, ex gizmo drawing and selection.
/// </summary>
/// <param name="window"></param>
public override void OnToolGUI(EditorWindow window)
{
if(!s_IsSplineTool)
return;
m_RectSelector.OnGUI(m_Splines);
if(!s_UseCustomSplineHandles)
SplineHandles.DrawSplineHandles(m_Splines, s_SplineHandlesOptions);
HandleSelectionFraming();
HandleSelectAll();
HandleDeleteSelectedKnots();
}
void OnEnable()
{
AssemblyReloadEvents.afterAssemblyReload += OnAfterDomainReload;
}
/// <summary>
/// Invoked after this EditorToolContext becomes the active tool context.
/// </summary>
public override void OnActivated()
{
// Sync handleOrientation to Tools.pivotRotation only if we're switching from a different context.
// This ensures that Parent/Element handleOrientation is retained after domain reload.
if(!m_WasActiveAfterDeserialize)
SplineTool.handleOrientation = (HandleOrientation)Tools.pivotRotation;
else
m_WasActiveAfterDeserialize = false;
OnSelectionChanged();
ToolManager.activeToolChanged += OnActiveToolChanged;
Selection.selectionChanged += OnSelectionChanged;
Spline.afterSplineWasModified += OnSplineWasModified;
Undo.undoRedoPerformed += UndoRedoPerformed;
SplineConversionUtility.splinesUpdated += SceneView.RepaintAll;
SplineConversionUtility.UpdateEditableSplinesForTargets(targets);
}
/// <summary>
/// Invoked before this EditorToolContext stops being the active tool context.
/// </summary>
public override void OnWillBeDeactivated()
{
ToolManager.activeToolChanged -= OnActiveToolChanged;
Selection.selectionChanged -= OnSelectionChanged;
Spline.afterSplineWasModified -= OnSplineWasModified;
Undo.undoRedoPerformed -= UndoRedoPerformed;
SplineConversionUtility.splinesUpdated -= SceneView.RepaintAll;
EditableSplineManager.FreeEntireCache();
SplineSelection.ClearNoUndo(false);
}
void OnActiveToolChanged()
{
if(ToolManager.activeToolType == typeof(KnotPlacementTool))
SplineSelection.Clear();
s_IsSplineTool = typeof(SplineTool).IsAssignableFrom(ToolManager.activeToolType);
}
void OnSplineWasModified(Spline spline) => UpdateSelection();
void OnSelectionChanged() => UpdateSelection();
void UndoRedoPerformed() => UpdateSelection();
void UpdateSelection()
{
EditableSplineUtility.GetSelectedSplines(targets, m_Splines);
EditableSplineManager.UpdateSelection(targets);
SplineSelection.UpdateObjectSelection(targets);
SceneView.RepaintAll();
}
void HandleDeleteSelectedKnots()
{
Event evt = Event.current;
if (evt.type == EventType.KeyDown && evt.keyCode == KeyCode.Delete)
{
SplineSelection.GetSelectedKnots(m_KnotBuffer);
//Sort knots index so removing them doesn't cause the rest of the indices to be invalid
m_KnotBuffer.Sort((a, b) => a.index.CompareTo(b.index));
for (int i = m_KnotBuffer.Count - 1; i >= 0; --i)
{
EditableKnot knot = m_KnotBuffer[i];
knot.spline.RemoveKnotAt(knot.index);
}
evt.Use();
}
}
void HandleSelectionFraming()
{
if (TransformOperation.canManipulate)
{
Event evt = Event.current;
if (evt.commandName.Equals("FrameSelected"))
{
var execute = evt.type == EventType.ExecuteCommand;
if (evt.type == EventType.ValidateCommand || execute)
{
if (execute)
{
var selectionBounds = TransformOperation.GetSelectionBounds(false);
selectionBounds.Encapsulate(TransformOperation.pivotPosition);
var size = selectionBounds.size;
if (selectionBounds.size.x < 1f)
size.x = 1f;
if (selectionBounds.size.y < 1f)
size.y = 1f;
if (selectionBounds.size.z < 1f)
size.z = 1f;
selectionBounds.size = size;
SceneView.lastActiveSceneView.Frame(selectionBounds, false);
}
evt.Use();
}
}
}
}
void HandleSelectAll()
{
Event evt = Event.current;
if (evt.commandName.Equals("SelectAll"))
{
var execute = evt.type == EventType.ExecuteCommand;
if (evt.type == EventType.ValidateCommand || execute)
{
var allElements = new List<ISplineElement>();
foreach (var spline in m_Splines)
{
for (int knotIdx = 0; knotIdx < spline.knotCount; ++knotIdx)
{
var knot = spline.GetKnot(knotIdx);
allElements.Add(knot);
for (int tangentIdx = 0; tangentIdx < knot.tangentCount; ++tangentIdx)
{
var tangent = knot.GetTangent(tangentIdx);
if (SplineSelectionUtility.IsSelectable(spline, knotIdx, tangent))
allElements.Add(tangent);
}
}
}
SplineSelection.Add(allElements);
evt.Use();
}
}
}
void OnAfterDomainReload()
{
m_WasActiveAfterDeserialize = ToolManager.activeContextType == typeof(SplineToolContext);
AssemblyReloadEvents.afterAssemblyReload -= OnAfterDomainReload;
}
}
}