Fix spline node to support prefab editor

#3257
This commit is contained in:
Wojtek Figat
2025-03-03 23:38:41 +01:00
parent 819ce2222d
commit a3822b6669
2 changed files with 45 additions and 38 deletions

View File

@@ -92,7 +92,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{ {
if (IsLinearTangentMode(spline, index) || IsSmoothInTangentMode(spline, index) || IsSmoothOutTangentMode(spline, index)) if (IsLinearTangentMode(spline, index) || IsSmoothInTangentMode(spline, index) || IsSmoothOutTangentMode(spline, index))
{ {
SetPointSmooth(spline, index); SetPointSmooth(Editor, spline, index);
} }
} }
} }
@@ -145,7 +145,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{ {
if (!IsAlignedTangentMode(spline, index)) if (!IsAlignedTangentMode(spline, index))
{ {
SetPointSmooth(spline, index); SetPointSmooth(Editor, spline, index);
} }
} }
@@ -176,7 +176,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// <inheritdoc/> /// <inheritdoc/>
public override void OnSetMode(Spline spline, int index) public override void OnSetMode(Spline spline, int index)
{ {
SetTangentSmoothIn(spline, index); SetTangentSmoothIn(Editor, spline, index);
Editor.SetSelectTangentIn(spline, index); Editor.SetSelectTangentIn(spline, index);
} }
} }
@@ -190,7 +190,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// <inheritdoc/> /// <inheritdoc/>
public override void OnSetMode(Spline spline, int index) public override void OnSetMode(Spline spline, int index)
{ {
SetTangentSmoothOut(spline, index); SetTangentSmoothOut(Editor, spline, index);
Editor.SetSelectTangentOut(spline, index); Editor.SetSelectTangentOut(spline, index);
} }
} }
@@ -756,14 +756,15 @@ namespace FlaxEditor.CustomEditors.Dedicated
spline.UpdateSpline(); spline.UpdateSpline();
} }
private static void SetTangentSmoothIn(Spline spline, int index) private static void SetTangentSmoothIn(SplineEditor editor, Spline spline, int index)
{ {
var keyframe = spline.GetSplineKeyframe(index); var keyframe = spline.GetSplineKeyframe(index);
// Auto smooth tangent if's linear // Auto smooth tangent if's linear
if (keyframe.TangentIn.Translation.Length == 0) if (keyframe.TangentIn.Translation.Length == 0)
{ {
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f); var cameraTransform = editor.Presenter.Owner.PresenterViewport.ViewTransform.Translation;
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f, cameraTransform);
var previousKeyframe = spline.GetSplineKeyframe(index - 1); var previousKeyframe = spline.GetSplineKeyframe(index - 1);
var tangentDirection = keyframe.Value.WorldToLocalVector(previousKeyframe.Value.Translation - keyframe.Value.Translation); var tangentDirection = keyframe.Value.WorldToLocalVector(previousKeyframe.Value.Translation - keyframe.Value.Translation);
tangentDirection = tangentDirection.Normalized * smoothRange; tangentDirection = tangentDirection.Normalized * smoothRange;
@@ -775,14 +776,15 @@ namespace FlaxEditor.CustomEditors.Dedicated
spline.UpdateSpline(); spline.UpdateSpline();
} }
private static void SetTangentSmoothOut(Spline spline, int index) private static void SetTangentSmoothOut(SplineEditor editor, Spline spline, int index)
{ {
var keyframe = spline.GetSplineKeyframe(index); var keyframe = spline.GetSplineKeyframe(index);
// Auto smooth tangent if's linear // Auto smooth tangent if's linear
if (keyframe.TangentOut.Translation.Length == 0) if (keyframe.TangentOut.Translation.Length == 0)
{ {
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f); var cameraTransform = editor.Presenter.Owner.PresenterViewport.ViewTransform.Translation;
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f, cameraTransform);
var nextKeyframe = spline.GetSplineKeyframe(index + 1); var nextKeyframe = spline.GetSplineKeyframe(index + 1);
var tangentDirection = keyframe.Value.WorldToLocalVector(nextKeyframe.Value.Translation - keyframe.Value.Translation); var tangentDirection = keyframe.Value.WorldToLocalVector(nextKeyframe.Value.Translation - keyframe.Value.Translation);
tangentDirection = tangentDirection.Normalized * smoothRange; tangentDirection = tangentDirection.Normalized * smoothRange;
@@ -795,7 +797,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
spline.UpdateSpline(); spline.UpdateSpline();
} }
private static void SetPointSmooth(Spline spline, int index) private static void SetPointSmooth(SplineEditor editor, Spline spline, int index)
{ {
var keyframe = spline.GetSplineKeyframe(index); var keyframe = spline.GetSplineKeyframe(index);
var tangentInSize = keyframe.TangentIn.Translation.Length; var tangentInSize = keyframe.TangentIn.Translation.Length;
@@ -803,7 +805,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
var isLastKeyframe = index >= spline.SplinePointsCount - 1; var isLastKeyframe = index >= spline.SplinePointsCount - 1;
var isFirstKeyframe = index <= 0; var isFirstKeyframe = index <= 0;
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplinePoint(index), 10f); var cameraTransform = editor.Presenter.Owner.PresenterViewport.ViewTransform.Translation;
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplinePoint(index), 10f, cameraTransform);
// Force smooth it's linear point // Force smooth it's linear point
if (tangentInSize == 0f) if (tangentInSize == 0f)

View File

@@ -39,7 +39,7 @@ namespace FlaxEditor.SceneGraph.Actors
public override bool CanBeSelectedDirectly => true; public override bool CanBeSelectedDirectly => true;
public override bool CanDuplicate => !Root?.Selection.Contains(ParentNode) ?? true; public override bool CanDuplicate => !Root?.SceneContext.Selection.Contains(ParentNode) ?? true;
public override bool CanDelete => true; public override bool CanDelete => true;
@@ -176,7 +176,7 @@ namespace FlaxEditor.SceneGraph.Actors
normal = -ray.Ray.Direction; normal = -ray.Ray.Direction;
var actor = (Spline)_node.Actor; var actor = (Spline)_node.Actor;
var pos = actor.GetSplinePoint(Index); var pos = actor.GetSplinePoint(Index);
var nodeSize = NodeSizeByDistance(Transform.Translation, PointNodeSize); var nodeSize = NodeSizeByDistance(Transform.Translation, PointNodeSize, ray.View.Position);
return new BoundingSphere(pos, nodeSize).Intersects(ref ray.Ray, out distance); return new BoundingSphere(pos, nodeSize).Intersects(ref ray.Ray, out distance);
} }
@@ -186,9 +186,10 @@ namespace FlaxEditor.SceneGraph.Actors
var pos = actor.GetSplinePoint(Index); var pos = actor.GetSplinePoint(Index);
var tangentIn = actor.GetSplineTangent(Index, true).Translation; var tangentIn = actor.GetSplineTangent(Index, true).Translation;
var tangentOut = actor.GetSplineTangent(Index, false).Translation; var tangentOut = actor.GetSplineTangent(Index, false).Translation;
var pointSize = NodeSizeByDistance(pos, PointNodeSize); var cameraTransform = Root.SceneContext.Viewport.ViewTransform.Translation;
var tangentInSize = NodeSizeByDistance(tangentIn, TangentNodeSize); var pointSize = NodeSizeByDistance(pos, PointNodeSize, cameraTransform);
var tangentOutSize = NodeSizeByDistance(tangentOut, TangentNodeSize); var tangentInSize = NodeSizeByDistance(tangentIn, TangentNodeSize, cameraTransform);
var tangentOutSize = NodeSizeByDistance(tangentOut, TangentNodeSize, cameraTransform);
// Draw spline path // Draw spline path
ParentNode.OnDebugDraw(data); ParentNode.OnDebugDraw(data);
@@ -262,7 +263,7 @@ namespace FlaxEditor.SceneGraph.Actors
normal = -ray.Ray.Direction; normal = -ray.Ray.Direction;
var actor = (Spline)_node.Actor; var actor = (Spline)_node.Actor;
var pos = actor.GetSplineTangent(_index, _isIn).Translation; var pos = actor.GetSplineTangent(_index, _isIn).Translation;
var tangentSize = NodeSizeByDistance(Transform.Translation, TangentNodeSize); var tangentSize = NodeSizeByDistance(Transform.Translation, TangentNodeSize, ray.View.Position);
return new BoundingSphere(pos, tangentSize).Intersects(ref ray.Ray, out distance); return new BoundingSphere(pos, tangentSize).Intersects(ref ray.Ray, out distance);
} }
@@ -274,7 +275,8 @@ namespace FlaxEditor.SceneGraph.Actors
// Draw selected tangent highlight // Draw selected tangent highlight
var actor = (Spline)_node.Actor; var actor = (Spline)_node.Actor;
var pos = actor.GetSplineTangent(_index, _isIn).Translation; var pos = actor.GetSplineTangent(_index, _isIn).Translation;
var tangentSize = NodeSizeByDistance(Transform.Translation, TangentNodeSize); var cameraTransform = Root.SceneContext.Viewport.ViewTransform.Translation;
var tangentSize = NodeSizeByDistance(Transform.Translation, TangentNodeSize, cameraTransform);
DebugDraw.DrawSphere(new BoundingSphere(pos, tangentSize), Color.YellowGreen, 0, false); DebugDraw.DrawSphere(new BoundingSphere(pos, tangentSize), Color.YellowGreen, 0, false);
} }
@@ -314,8 +316,8 @@ namespace FlaxEditor.SceneGraph.Actors
} }
// If this node's point is selected // If this node's point is selected
var selection = Editor.Instance.SceneEditing.Selection; var selection = Root?.SceneContext.Selection;
if (selection.Count == 1 && selection[0] is SplinePointNode selectedPoint && selectedPoint.ParentNode == this) if (selection != null && selection.Count == 1 && selection[0] is SplinePointNode selectedPoint && selectedPoint.ParentNode == this)
{ {
var mouse = Input.Mouse; var mouse = Input.Mouse;
var keyboard = Input.Keyboard; var keyboard = Input.Keyboard;
@@ -324,7 +326,7 @@ namespace FlaxEditor.SceneGraph.Actors
EditSplineWithSnap(selectedPoint); EditSplineWithSnap(selectedPoint);
var canAddSplinePoint = mouse.PositionDelta == Float2.Zero && mouse.Position != Float2.Zero; var canAddSplinePoint = mouse.PositionDelta == Float2.Zero && mouse.Position != Float2.Zero;
var requestAddSplinePoint = Input.Keyboard.GetKey(KeyboardKeys.Control) && mouse.GetButtonDown(MouseButton.Right); var requestAddSplinePoint = keyboard.GetKey(KeyboardKeys.Control) && mouse.GetButtonDown(MouseButton.Right);
if (requestAddSplinePoint && canAddSplinePoint) if (requestAddSplinePoint && canAddSplinePoint)
AddSplinePoint(selectedPoint); AddSplinePoint(selectedPoint);
} }
@@ -345,9 +347,7 @@ namespace FlaxEditor.SceneGraph.Actors
while (srcCount > dstCount) while (srcCount > dstCount)
{ {
var node = ActorChildNodes[srcCount-- - 1]; var node = ActorChildNodes[srcCount-- - 1];
// TODO: support selection interface inside SceneGraph nodes (eg. on Root) so prefab editor can handle this too Root?.SceneContext.Deselect(node);
if (Editor.Instance.SceneEditing.Selection.Contains(node))
Editor.Instance.SceneEditing.Deselect();
node.Dispose(); node.Dispose();
} }
@@ -363,22 +363,23 @@ namespace FlaxEditor.SceneGraph.Actors
} }
} }
private unsafe void AddSplinePoint(SplinePointNode selectedPoint) private void AddSplinePoint(SplinePointNode selectedPoint)
{ {
// Check mouse hit on scene // Check mouse hit on scene
var root = Root;
var spline = (Spline)Actor; var spline = (Spline)Actor;
var viewport = Editor.Instance.Windows.EditWin.Viewport; var viewport = root.SceneContext.Viewport;
var mouseRay = viewport.MouseRay; var mouseRay = viewport.MouseRay;
var viewRay = viewport.ViewRay; var viewRay = viewport.ViewRay;
var flags = RayCastData.FlagTypes.SkipColliders | RayCastData.FlagTypes.SkipEditorPrimitives; var flags = RayCastData.FlagTypes.SkipColliders | RayCastData.FlagTypes.SkipEditorPrimitives;
var hit = Editor.Instance.Scene.Root.RayCast(ref mouseRay, ref viewRay, out var closest, out var normal, flags); var hit = root.RayCast(ref mouseRay, ref viewRay, out var closest, out var normal, flags);
if (hit == null) if (hit == null)
return; return;
// Undo data // Undo data
var oldSpline = spline.SplineKeyframes; var oldSpline = spline.SplineKeyframes;
var editAction = new EditSplineAction(spline, oldSpline); var editAction = new EditSplineAction(spline, oldSpline);
Root.Undo.AddAction(editAction); root.Undo.AddAction(editAction);
// Get spline point to duplicate // Get spline point to duplicate
var hitPoint = mouseRay.Position + mouseRay.Direction * closest; var hitPoint = mouseRay.Position + mouseRay.Direction * closest;
@@ -430,7 +431,7 @@ namespace FlaxEditor.SceneGraph.Actors
// Select new point node // Select new point node
SyncSplineKeyframeWithNodes(); SyncSplineKeyframeWithNodes();
Editor.Instance.SceneEditing.Select(ChildNodes[newPointIndex]); root.SceneContext.Select(ChildNodes[newPointIndex]);
spline.UpdateSpline(); spline.UpdateSpline();
} }
@@ -443,6 +444,7 @@ namespace FlaxEditor.SceneGraph.Actors
allSplinesInView.Remove(spline); allSplinesInView.Remove(spline);
if (allSplinesInView.Count == 0) if (allSplinesInView.Count == 0)
return; return;
var cameraTransform = Root.SceneContext.Viewport.ViewTransform.Translation;
var snappedOnSplinePoint = false; var snappedOnSplinePoint = false;
for (int i = 0; i < allSplinesInView.Count; i++) for (int i = 0; i < allSplinesInView.Count; i++)
@@ -450,7 +452,7 @@ namespace FlaxEditor.SceneGraph.Actors
for (int x = 0; x < allSplinesInView[i].SplineKeyframes.Length; x++) for (int x = 0; x < allSplinesInView[i].SplineKeyframes.Length; x++)
{ {
var keyframePosition = allSplinesInView[i].GetSplinePoint(x); var keyframePosition = allSplinesInView[i].GetSplinePoint(x);
var pointIndicatorSize = NodeSizeByDistance(keyframePosition, SnapPointIndicatorSize); var pointIndicatorSize = NodeSizeByDistance(keyframePosition, SnapPointIndicatorSize, cameraTransform);
var keyframeBounds = new BoundingSphere(keyframePosition, pointIndicatorSize); var keyframeBounds = new BoundingSphere(keyframePosition, pointIndicatorSize);
DebugDraw.DrawSphere(keyframeBounds, Color.Red, 0, false); DebugDraw.DrawSphere(keyframeBounds, Color.Red, 0, false);
@@ -466,7 +468,7 @@ namespace FlaxEditor.SceneGraph.Actors
if (!snappedOnSplinePoint) if (!snappedOnSplinePoint)
{ {
var nearSplineSnapPoint = GetNearSplineSnapPosition(selectedPoint.Transform.Translation, allSplinesInView); var nearSplineSnapPoint = GetNearSplineSnapPosition(selectedPoint.Transform.Translation, allSplinesInView);
var snapIndicatorSize = NodeSizeByDistance(nearSplineSnapPoint, SnapIndicatorSize); var snapIndicatorSize = NodeSizeByDistance(nearSplineSnapPoint, SnapIndicatorSize, cameraTransform);
var snapBounds = new BoundingSphere(nearSplineSnapPoint, snapIndicatorSize); var snapBounds = new BoundingSphere(nearSplineSnapPoint, snapIndicatorSize);
if (snapBounds.Intersects(selectedPointBounds)) if (snapBounds.Intersects(selectedPointBounds))
{ {
@@ -558,11 +560,16 @@ namespace FlaxEditor.SceneGraph.Actors
} }
} }
private static List<Spline> GetSplinesInView() private List<Spline> GetSplinesInView()
{ {
var splines = Level.GetActors<Spline>(true); Spline[] splines;
var sceneContext = Root.SceneContext;
if (sceneContext is Windows.Assets.PrefabWindow prefabWindow)
splines = new Spline[0]; // TODO: add GetActors or similar utility to SceneContext and use Level.GetActors<Spline>(..) with specific root actor
else
splines = Level.GetActors<Spline>(true);
var result = new List<Spline>(); var result = new List<Spline>();
var viewBounds = Editor.Instance.Windows.EditWin.Viewport.ViewFrustum; var viewBounds = sceneContext.Viewport.ViewFrustum;
foreach (var s in splines) foreach (var s in splines)
{ {
var contains = viewBounds.Contains(s.EditorBox); var contains = viewBounds.Contains(s.EditorBox);
@@ -576,7 +583,6 @@ namespace FlaxEditor.SceneGraph.Actors
{ {
var nearPoint = splines[0].GetSplinePointClosestToPoint(position); var nearPoint = splines[0].GetSplinePointClosestToPoint(position);
var nearDistance = Vector3.Distance(nearPoint, position); var nearDistance = Vector3.Distance(nearPoint, position);
for (int i = 1; i < splines.Count; i++) for (int i = 1; i < splines.Count; i++)
{ {
var point = splines[i].GetSplinePointClosestToPoint(position); var point = splines[i].GetSplinePointClosestToPoint(position);
@@ -587,14 +593,12 @@ namespace FlaxEditor.SceneGraph.Actors
nearDistance = distance; nearDistance = distance;
} }
} }
return nearPoint; return nearPoint;
} }
internal static Real NodeSizeByDistance(Vector3 nodePosition, Real nodeSize) internal static Real NodeSizeByDistance(Vector3 nodePosition, Real nodeSize, Vector3 viewPosition)
{ {
var cameraTransform = Editor.Instance.Windows.EditWin.Viewport.ViewportCamera.Viewport.ViewTransform; var distance = Vector3.Distance(viewPosition, nodePosition) / 100;
var distance = Vector3.Distance(cameraTransform.Translation, nodePosition) / 100;
return distance * nodeSize; return distance * nodeSize;
} }