add spline snap
This commit is contained in:
@@ -7,6 +7,7 @@ using Real = System.Single;
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
using FlaxEditor.Modules;
|
||||
using FlaxEngine;
|
||||
@@ -287,6 +288,10 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
|
||||
private const Real PointNodeSize = 1.5f;
|
||||
private const Real TangentNodeSize = 1.0f;
|
||||
private const Real SnapIndicatorSize = 1.7f;
|
||||
private const Real SnapPointIndicatorSize = 2f;
|
||||
|
||||
private static Spline _currentEditSpline;
|
||||
|
||||
/// <inheritdoc />
|
||||
public SplineNode(Actor actor)
|
||||
@@ -298,6 +303,11 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
|
||||
private unsafe void OnUpdate()
|
||||
{
|
||||
if (Input.Keyboard.GetKey(KeyboardKeys.Shift))
|
||||
{
|
||||
EditSplineWithSnap();
|
||||
}
|
||||
|
||||
// Sync spline points with gizmo handles
|
||||
var actor = (Spline)Actor;
|
||||
var dstCount = actor.SplinePointsCount;
|
||||
@@ -328,6 +338,56 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
}
|
||||
}
|
||||
|
||||
private void EditSplineWithSnap()
|
||||
{
|
||||
if (_currentEditSpline == null || _currentEditSpline != Actor)
|
||||
return;
|
||||
|
||||
var selectedNode = SelectedSplineNode();
|
||||
if (selectedNode == null)
|
||||
return;
|
||||
|
||||
var selectedNodeBounds = new BoundingSphere(selectedNode.Transform.Translation, 1f);
|
||||
var allSplinesInView = GetSplinesOnView();
|
||||
allSplinesInView.Remove(_currentEditSpline);
|
||||
|
||||
if (allSplinesInView.Count == 0 || selectedNode == null)
|
||||
return;
|
||||
|
||||
var snappedOnSplinePoint = false;
|
||||
for (int i = 0; i < allSplinesInView.Count; i++)
|
||||
{
|
||||
for (int x = 0; x < allSplinesInView[i].SplineKeyframes.Length; x++)
|
||||
{
|
||||
var keyframePosition = allSplinesInView[i].GetSplinePoint(x);
|
||||
var pointIndicatorSize = NodeSizeByDistance(keyframePosition, SnapPointIndicatorSize);
|
||||
var keyframeBounds = new BoundingSphere(keyframePosition, pointIndicatorSize);
|
||||
DebugDraw.DrawSphere(keyframeBounds, Color.Red, 0, false);
|
||||
|
||||
if (keyframeBounds.Intersects(selectedNodeBounds))
|
||||
{
|
||||
_currentEditSpline.SetSplinePoint(selectedNode.Index, keyframeBounds.Center);
|
||||
snappedOnSplinePoint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!snappedOnSplinePoint)
|
||||
{
|
||||
var nearSplineSnapPoint = GetNearSplineSnapPosition(selectedNode.Transform.Translation, allSplinesInView);
|
||||
var snapIndicatorSize = NodeSizeByDistance(nearSplineSnapPoint, SnapIndicatorSize);
|
||||
var snapBounds = new BoundingSphere(nearSplineSnapPoint, snapIndicatorSize);
|
||||
|
||||
if (snapBounds.Intersects(selectedNodeBounds))
|
||||
{
|
||||
_currentEditSpline.SetSplinePoint(selectedNode.Index, snapBounds.Center);
|
||||
}
|
||||
|
||||
DebugDraw.DrawSphere(snapBounds, Color.Yellow, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void PostSpawn()
|
||||
{
|
||||
@@ -396,6 +456,7 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
|
||||
internal static void OnSplineEdited(Spline spline)
|
||||
{
|
||||
_currentEditSpline = spline;
|
||||
var collider = spline.GetChild<SplineCollider>();
|
||||
if (collider && collider.Scene && collider.IsActiveInHierarchy && collider.HasStaticFlag(StaticFlags.Navigation) && !Editor.IsPlayMode)
|
||||
{
|
||||
@@ -407,6 +468,60 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
}
|
||||
}
|
||||
|
||||
private static SplinePointNode SelectedSplineNode()
|
||||
{
|
||||
var selection = Editor.Instance.SceneEditing.Selection;
|
||||
if (selection.Count != 1)
|
||||
return null;
|
||||
if (selection[0] is not SplineNode.SplinePointNode)
|
||||
return null;
|
||||
|
||||
return (SplinePointNode)selection[0];
|
||||
}
|
||||
|
||||
private static List<Spline> GetSplinesOnView()
|
||||
{
|
||||
var splines = Level.GetActors<Spline>();
|
||||
var splinesOnView = new List<Spline>();
|
||||
|
||||
var viewTransform = Editor.Instance.Windows.EditWin.Viewport.ViewTransform;
|
||||
var viewFov = Editor.Instance.Windows.EditWin.Viewport.FieldOfView;
|
||||
var viewNear = Editor.Instance.Windows.EditWin.Viewport.NearPlane;
|
||||
var viewFar = Editor.Instance.Windows.EditWin.Viewport.FarPlane;
|
||||
var viewAspect = Editor.Instance.Windows.EditWin.Width / Editor.Instance.Windows.EditWin.Height;
|
||||
var viewBounds = BoundingFrustum.FromCamera(viewTransform.Translation, viewTransform.Forward, viewTransform.Up, viewFov, viewNear, viewFar, viewAspect);
|
||||
|
||||
foreach (var s in splines)
|
||||
{
|
||||
var contains = viewBounds.Contains(s.EditorBox);
|
||||
if (contains == ContainmentType.Contains || contains == ContainmentType.Intersects)
|
||||
{
|
||||
splinesOnView.Add(s);
|
||||
}
|
||||
}
|
||||
|
||||
return splinesOnView;
|
||||
}
|
||||
|
||||
private static Vector3 GetNearSplineSnapPosition(Vector3 position, List<Spline> splines)
|
||||
{
|
||||
var nearPoint = splines[0].GetSplinePointClosestToPoint(position);
|
||||
var nearDistance = Vector3.Distance(nearPoint, position);
|
||||
|
||||
for (int i = 1; i < splines.Count; i++)
|
||||
{
|
||||
var point = splines[i].GetSplinePointClosestToPoint(position);
|
||||
var distance = Vector3.Distance(point, position);
|
||||
if (distance < nearDistance)
|
||||
{
|
||||
nearPoint = point;
|
||||
nearDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return nearPoint;
|
||||
}
|
||||
|
||||
internal static Real NodeSizeByDistance(Vector3 nodePosition, Real nodeSize)
|
||||
{
|
||||
var cameraTransform = Editor.Instance.Windows.EditWin.Viewport.ViewportCamera.Viewport.ViewTransform;
|
||||
|
||||
Reference in New Issue
Block a user