RoboticArms/Library/PackageCache/com.unity.splines@d3e1e500c9a0/Samples~/Editor/Tools/WidthTool.cs
2025-11-17 15:16:36 +07:00

148 lines
5.5 KiB
C#

using Unity.Mathematics;
using UnityEditor;
using UnityEditor.EditorTools;
using UnityEditor.Splines;
using UnityEngine;
using UnityEngine.Splines;
namespace Unity.Splines.Examples
{
[EditorTool("Width Tool", typeof(LoftRoadBehaviour))]
public class WidthTool : SplineDataToolBase<float>, IDrawSelectedHandles
{
GUIContent m_IconContent;
public override GUIContent toolbarIcon => m_IconContent;
bool m_DisableHandles = false;
void OnEnable()
{
m_IconContent = new GUIContent()
{
image = Resources.Load<Texture2D>("Icons/WidthTool"),
text = "Width Tool",
tooltip = "Adjust the width of the created road mesh."
};
}
public override void OnToolGUI(EditorWindow window)
{
var splineDataTarget = target as LoftRoadBehaviour;
if (splineDataTarget == null || splineDataTarget.Container == null)
return;
Handles.color = Color.blue;
m_DisableHandles = false;
var splines = splineDataTarget.Container.Splines;
for (var i = 0; i < splines.Count; i++)
{
if (i < splineDataTarget.Widths.Count)
{
var nativeSpline = new NativeSpline(splines[i], splineDataTarget.Container.transform.localToWorldMatrix);
Undo.RecordObject(splineDataTarget, "Modifying Widths SplineData");
// User defined handles to manipulate width
DrawDataPoints(nativeSpline, splineDataTarget.Widths[i]);
// Using the out-of the box behaviour to manipulate indexes
nativeSpline.DataPointHandles(splineDataTarget.Widths[i], false, i);
}
}
}
public void OnDrawHandles()
{
var splineDataTarget = target as LoftRoadBehaviour;
if (ToolManager.IsActiveTool(this) || splineDataTarget.Container == null)
return;
Color color = Color.blue;
color.a = 0.5f;
Handles.color = color;
m_DisableHandles = true;
var splines = splineDataTarget.Container.Splines;
for (var i = 0; i < splines.Count; i++)
{
if (i < splineDataTarget.Widths.Count)
{
var nativeSpline = new NativeSpline(splines[i], splineDataTarget.Container.transform.localToWorldMatrix);
DrawDataPoints(nativeSpline, splineDataTarget.Widths[i]);
}
}
}
protected override bool DrawDataPoint(
Vector3 position,
Vector3 tangent,
Vector3 up,
float inValue,
out float outValue)
{
int id1 = m_DisableHandles ? -1 : GUIUtility.GetControlID(FocusType.Passive);
int id2 = m_DisableHandles ? -1 : GUIUtility.GetControlID(FocusType.Passive);
outValue = 0f;
if (tangent == Vector3.zero)
return false;
if (Event.current.type == EventType.MouseUp
&& Event.current.button != 0
&& (GUIUtility.hotControl == id1 || GUIUtility.hotControl == id2))
{
Event.current.Use();
return false;
}
var handleColor = Handles.color;
if (GUIUtility.hotControl == id1 || GUIUtility.hotControl == id2)
handleColor = Handles.selectedColor;
else if (GUIUtility.hotControl == 0 && (HandleUtility.nearestControl == id1 || HandleUtility.nearestControl == id2))
handleColor = Handles.preselectionColor;
var normalDirection = math.normalize(math.cross(tangent, up));
var extremity1 = position - inValue * (Vector3)normalDirection;
var extremity2 = position + inValue * (Vector3)normalDirection;
Vector3 val1, val2;
using (new Handles.DrawingScope(handleColor))
{
if (Event.current.type == EventType.Repaint)
Handles.DrawLine(extremity1, extremity2);
val1 = Handles.Slider(id1, extremity1, normalDirection,
k_HandleSize * .5f * HandleUtility.GetHandleSize(position), CustomHandleCap, 0);
val2 = Handles.Slider(id2, extremity2, normalDirection,
k_HandleSize * .5f * HandleUtility.GetHandleSize(position), CustomHandleCap, 0);
}
if (GUIUtility.hotControl == id1 && math.abs((val1 - extremity1).magnitude) > 0)
{
outValue = math.abs((val1 - position).magnitude);
return true;
}
if (GUIUtility.hotControl == id2 && math.abs((val2 - extremity2).magnitude) > 0)
{
outValue = math.abs((val2 - position).magnitude);
return true;
}
return false;
}
public void CustomHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)
{
if (m_DisableHandles) // If disabled, do nothing unless it's a repaint event
{
if (Event.current.type == EventType.Repaint)
Handles.CubeHandleCap(controlID, position, rotation, size, eventType);
}
else
Handles.CubeHandleCap(controlID, position, rotation, size, eventType);
}
}
}