From 2be6a6be9ec00b233345dfce4df786bd49b023be Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:48:15 -0400 Subject: [PATCH 01/35] add basic options --- .../CustomEditors/Dedicated/SplineEditor.cs | 326 ++++++++++++++++++ Source/Editor/SceneGraph/Actors/SplineNode.cs | 4 +- 2 files changed, 328 insertions(+), 2 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 877342154..8f6dccd39 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -4,6 +4,8 @@ using FlaxEditor.Actions; using FlaxEditor.SceneGraph.Actors; using FlaxEngine; using FlaxEngine.GUI; +using FlaxEditor.CustomEditors.Elements; +using System; namespace FlaxEditor.CustomEditors.Dedicated { @@ -14,6 +16,214 @@ namespace FlaxEditor.CustomEditors.Dedicated [CustomEditor(typeof(Spline)), DefaultEditor] public class SplineEditor : ActorEditor { + /// + /// Basis for creating tangent manipulation types for bezier curves. + /// + public abstract class TangentModeBase + { + /// + /// Called when user set selected tangent mode. + /// + /// Current spline selected on editor viewport. + /// Index of current keyframe selected on spline. + public abstract void OnSetMode(Spline spline, int index); + + /// + /// Called when user select a keyframe (spline point) of current selected spline on editor viewport. + /// + /// Current spline selected on editor viewport. + /// Index of current keyframe selected on spline. + public abstract void OnSelectKeyframe(Spline spline, int index); + + /// + /// Called when user select a tangent of current keyframe selected from spline. + /// + /// Current spline selected on editor viewport. + /// Index of current keyframe selected on spline. + public abstract void OnSelectTangent(Spline spline, int index); + + /// + /// Called when the tangent in from current keyframe selected from spline is moved on editor viewport. + /// + /// Current spline selected on editor viewport. + /// Index of current keyframe selected on spline. + public abstract void OnMoveTangentIn(Spline spline, int index); + + /// + /// Called when the tangent out from current keyframe selected from spline is moved on editor viewport. + /// + /// Current spline selected on editor viewport. + /// Current spline selected on editor viewport. + public abstract void OnMoveTangentOut(Spline spline, int index); + } + + /// + /// Edit curve options manipulate the curve as free mode + /// + public sealed class FreeTangentMode : TangentModeBase + { + /// + public override void OnMoveTangentIn(Spline spline, int index) { } + + /// + public override void OnMoveTangentOut(Spline spline, int index) { } + + /// + public override void OnSelectKeyframe(Spline spline, int index) { } + + /// + public override void OnSelectTangent(Spline spline, int index) { } + + /// + public override void OnSetMode(Spline spline, int index) { } + } + + /// + /// Edit curve options to set tangents to linear + /// + public sealed class LinearTangentMode : TangentModeBase + { + /// + public override void OnMoveTangentIn(Spline spline, int index) { } + + /// + public override void OnMoveTangentOut(Spline spline, int index) { } + + /// + public override void OnSelectKeyframe(Spline spline, int index) { } + + /// + public override void OnSelectTangent(Spline spline, int index) { } + + /// + public override void OnSetMode(Spline spline, int index) + { + SetKeyframeLinear(spline, index); + } + + private void SetKeyframeLinear(Spline spline, int index) + { + var tangentIn = spline.GetSplineTangent(index, true); + var tangentOut = spline.GetSplineTangent(index, false); + tangentIn.Translation = spline.GetSplinePoint(index); + tangentOut.Translation = spline.GetSplinePoint(index); + spline.SetSplineTangent(index, tangentIn, true, false); + spline.SetSplineTangent(index, tangentOut, false, false); + spline.UpdateSpline(); + } + } + + /// + /// Edit curve options to align tangents of selected spline + /// + public sealed class AlignedTangentMode : TangentModeBase + { + /// + public override void OnSetMode(Spline spline, int index) + { + SmoothIfNotAligned(spline, index); + } + + /// + public override void OnSelectKeyframe(Spline spline, int index) + { + SmoothIfNotAligned(spline, index); + } + + /// + public override void OnSelectTangent(Spline selectedSpline, int index) { } + + /// + public override void OnMoveTangentIn(Spline spline, int index) + { + SetPointAligned(spline, index, true); + } + + /// + public override void OnMoveTangentOut(Spline spline, int index) + { + SetPointAligned(spline, index, false); + } + + private void SmoothIfNotAligned(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + var isAligned = Vector3.Dot(keyframe.TangentIn.Translation.Normalized, keyframe.TangentOut.Translation.Normalized) == 1f; + + if (!isAligned) + { + SetPointSmooth(spline, index); + } + } + + private void SetPointSmooth(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + var tangentIn = keyframe.TangentIn; + var tangentOut = keyframe.TangentOut; + var tangentInSize = tangentIn.Translation.Length; + var tangentOutSize = tangentOut.Translation.Length; + + var isLastKeyframe = index >= spline.SplinePointsCount - 1; + var isFirstKeyframe = index <= 0; + + if (!isLastKeyframe && !isFirstKeyframe) + { + var nextKeyframe = spline.GetSplineKeyframe(++index); + var previousKeyframe = spline.GetSplineKeyframe(--index); + + // calc form from Spline.cpp -> SetTangentsSmooth + var slop = (keyframe.Value.Translation - previousKeyframe.Value.Translation + nextKeyframe.Value.Translation - keyframe.Value.Translation).Normalized; + + keyframe.TangentIn.Translation = -slop * tangentInSize; + keyframe.TangentOut.Translation = slop * tangentOutSize; + spline.SetSplineKeyframe(index, keyframe); + } + } + + private void SetPointAligned(Spline spline, int index, bool isIn) + { + var keyframe = spline.GetSplineKeyframe(index); + var referenceTangent = isIn ? keyframe.TangentIn : keyframe.TangentOut; + var otherTangent = !isIn ? keyframe.TangentIn : keyframe.TangentOut; + + // inverse of reference tangent + otherTangent.Translation = -referenceTangent.Translation.Normalized * otherTangent.Translation.Length; + + if (isIn) keyframe.TangentOut = otherTangent; + if (!isIn) keyframe.TangentIn = otherTangent; + + spline.SetSplineKeyframe(index, keyframe); + } + } + + private TangentModeBase _currentTangentMode; + + private ButtonElement _freeTangentButton; + private ButtonElement _linearTangentButton; + private ButtonElement _alignedTangentButton; + + private bool _tanInChanged; + private bool _tanOutChanged; + private Vector3 _lastTanInPos; + private Vector3 _lastTanOutPos; + private SplineNode.SplinePointNode _lastPointSelected; + private SplineNode.SplinePointTangentNode _selectedTangentIn; + private SplineNode.SplinePointTangentNode _selectedTangentOut; + + /// + /// Current selected spline on editor, if has + /// + public Spline SelectedSpline => !Values.HasDifferentValues && Values[0] is Spline ? (Spline)Values[0] : null; + + /// + /// Create a Spline editor + /// + public SplineEditor() + { + _currentTangentMode = new FreeTangentMode(); + } + /// public override void Initialize(LayoutElementsContainer layout) { @@ -22,6 +232,21 @@ namespace FlaxEditor.CustomEditors.Dedicated if (Values.HasDifferentTypes == false) { layout.Space(10); + + layout.Header("Selected spline point"); + var selectedPointsGrid = layout.CustomContainer(); + selectedPointsGrid.CustomControl.SlotsHorizontally = 3; + selectedPointsGrid.CustomControl.SlotsVertically = 1; + + _linearTangentButton = selectedPointsGrid.Button("Linear"); + _freeTangentButton = selectedPointsGrid.Button("Free"); + _alignedTangentButton = selectedPointsGrid.Button("Aligned"); + + _linearTangentButton.Button.Clicked += SetModeLinear; + _freeTangentButton.Button.Clicked += SetModeFree; + _alignedTangentButton.Button.Clicked += SetModeAligned; + + layout.Header("All spline points"); var grid = layout.CustomContainer(); grid.CustomControl.SlotsHorizontally = 2; grid.CustomControl.SlotsVertically = 1; @@ -30,6 +255,107 @@ namespace FlaxEditor.CustomEditors.Dedicated } } + /// + public override void Refresh() + { + base.Refresh(); + + UpdateSelectedPoint(); + UpdateSelectedTangent(); + + var index = _lastPointSelected.Index; + var currentTangentInPosition = SelectedSpline.GetSplineLocalTangent(index, true).Translation; + var currentTangentOutPosition = SelectedSpline.GetSplineLocalTangent(index, false).Translation; + + if (_selectedTangentIn != null) + { + _tanInChanged = _lastTanInPos != currentTangentInPosition; + _lastTanInPos = currentTangentInPosition; + } + + if (_selectedTangentOut != null) + { + _tanOutChanged = _lastTanOutPos != currentTangentOutPosition; + _lastTanOutPos = currentTangentOutPosition; + } + + if (_tanInChanged) _currentTangentMode.OnMoveTangentIn(SelectedSpline, index); + if (_tanOutChanged) _currentTangentMode.OnMoveTangentOut(SelectedSpline, index); + + currentTangentInPosition = SelectedSpline.GetSplineLocalTangent(index, true).Translation; + currentTangentOutPosition = SelectedSpline.GetSplineLocalTangent(index, false).Translation; + + // update last tangents position after changes + if (SelectedSpline) _lastTanInPos = currentTangentInPosition; + if (SelectedSpline) _lastTanOutPos = currentTangentOutPosition; + _tanInChanged = false; + _tanOutChanged = false; + } + + private void SetModeLinear() + { + _currentTangentMode = new LinearTangentMode(); + _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + } + + private void SetModeFree() + { + _currentTangentMode = new FreeTangentMode(); + _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + } + + private void SetModeAligned() + { + _currentTangentMode = new AlignedTangentMode(); + _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + } + + private void UpdateSelectedPoint() + { + // works only if select one spline + if (Editor.Instance.SceneEditing.SelectionCount != 1) return; + + var currentSelected = Editor.Instance.SceneEditing.Selection[0]; + + if (currentSelected == _lastPointSelected) return; + if (currentSelected is not SplineNode.SplinePointNode) return; + + _lastPointSelected = currentSelected as SplineNode.SplinePointNode; + var index = _lastPointSelected.Index; + _currentTangentMode.OnSelectKeyframe(SelectedSpline, index); + } + + private void UpdateSelectedTangent() + { + // works only if select one spline + if (_lastPointSelected == null || Editor.Instance.SceneEditing.SelectionCount != 1) return; + + var currentSelected = Editor.Instance.SceneEditing.Selection[0]; + + if (currentSelected is not SplineNode.SplinePointTangentNode) return; + if (currentSelected == _selectedTangentIn) return; + if (currentSelected == _selectedTangentOut) return; + + var index = _lastPointSelected.Index; + + if (currentSelected.Transform == SelectedSpline.GetSplineTangent(index, true)) + { + _selectedTangentIn = currentSelected as SplineNode.SplinePointTangentNode; + _currentTangentMode.OnSelectTangent(SelectedSpline, index); + return; + } + + if (currentSelected.Transform == SelectedSpline.GetSplineTangent(index, false)) + { + _selectedTangentOut = currentSelected as SplineNode.SplinePointTangentNode; + _currentTangentMode.OnSelectTangent(SelectedSpline, index); + return; + } + + _selectedTangentIn = null; + _selectedTangentOut = null; + } + private void OnSetTangentsLinear() { var enableUndo = Presenter.Undo != null && Presenter.Undo.Enabled; diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index eebee0cd9..3ba1d14c3 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -21,7 +21,7 @@ namespace FlaxEditor.SceneGraph.Actors [HideInEditor] public sealed class SplineNode : ActorNode { - private sealed class SplinePointNode : ActorChildNode + public sealed class SplinePointNode : ActorChildNode { public unsafe SplinePointNode(SplineNode node, Guid id, int index) : base(node, id, index) @@ -219,7 +219,7 @@ namespace FlaxEditor.SceneGraph.Actors } } - private sealed class SplinePointTangentNode : ActorChildNode + public sealed class SplinePointTangentNode : ActorChildNode { private SplineNode _node; private int _index; From 2fac4c9284c394db180fcab07987972c31d4cf36 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Tue, 18 Jul 2023 20:28:28 -0400 Subject: [PATCH 02/35] add smooth tangent on first and last keyframe --- .../CustomEditors/Dedicated/SplineEditor.cs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 8f6dccd39..4ddf5c26c 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -19,7 +19,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// Basis for creating tangent manipulation types for bezier curves. /// - public abstract class TangentModeBase + private abstract class TangentModeBase { /// /// Called when user set selected tangent mode. @@ -60,7 +60,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// Edit curve options manipulate the curve as free mode /// - public sealed class FreeTangentMode : TangentModeBase + private sealed class FreeTangentMode : TangentModeBase { /// public override void OnMoveTangentIn(Spline spline, int index) { } @@ -81,7 +81,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// Edit curve options to set tangents to linear /// - public sealed class LinearTangentMode : TangentModeBase + private sealed class LinearTangentMode : TangentModeBase { /// public override void OnMoveTangentIn(Spline spline, int index) { } @@ -116,7 +116,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// Edit curve options to align tangents of selected spline /// - public sealed class AlignedTangentMode : TangentModeBase + private sealed class AlignedTangentMode : TangentModeBase { /// public override void OnSetMode(Spline spline, int index) @@ -167,18 +167,19 @@ namespace FlaxEditor.CustomEditors.Dedicated var isLastKeyframe = index >= spline.SplinePointsCount - 1; var isFirstKeyframe = index <= 0; - if (!isLastKeyframe && !isFirstKeyframe) - { - var nextKeyframe = spline.GetSplineKeyframe(++index); - var previousKeyframe = spline.GetSplineKeyframe(--index); + // force smooth it's linear point + if (tangentInSize == 0f && !isFirstKeyframe) tangentInSize = 100; + if (tangentOutSize == 0f && !isLastKeyframe) tangentOutSize = 100; - // calc form from Spline.cpp -> SetTangentsSmooth - var slop = (keyframe.Value.Translation - previousKeyframe.Value.Translation + nextKeyframe.Value.Translation - keyframe.Value.Translation).Normalized; + var nextKeyframe = !isLastKeyframe ? spline.GetSplineKeyframe(index + 1) : keyframe; + var previousKeyframe = !isFirstKeyframe ? spline.GetSplineKeyframe(index - 1) : keyframe; - keyframe.TangentIn.Translation = -slop * tangentInSize; - keyframe.TangentOut.Translation = slop * tangentOutSize; - spline.SetSplineKeyframe(index, keyframe); - } + // calc form from Spline.cpp -> SetTangentsSmooth + var slop = (keyframe.Value.Translation - previousKeyframe.Value.Translation + nextKeyframe.Value.Translation - keyframe.Value.Translation).Normalized; + + keyframe.TangentIn.Translation = -slop * tangentInSize; + keyframe.TangentOut.Translation = slop * tangentOutSize; + spline.SetSplineKeyframe(index, keyframe); } private void SetPointAligned(Spline spline, int index, bool isIn) From 590a892f16345217231cdca96bfdad2cf08acfd7 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Tue, 18 Jul 2023 21:54:30 -0400 Subject: [PATCH 03/35] set spline point as selected when has a tangent selected and set as linear --- Source/Editor/CustomEditors/Dedicated/SplineEditor.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 4ddf5c26c..4dc0643d3 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -6,6 +6,7 @@ using FlaxEngine; using FlaxEngine.GUI; using FlaxEditor.CustomEditors.Elements; using System; +using FlaxEditor.SceneGraph; namespace FlaxEditor.CustomEditors.Dedicated { @@ -99,6 +100,14 @@ namespace FlaxEditor.CustomEditors.Dedicated public override void OnSetMode(Spline spline, int index) { SetKeyframeLinear(spline, index); + + // if has a tangent selected, change the selection to tangent parent (a spline point / keyframe) + var currentSelection = Editor.Instance.SceneEditing.Selection; + if (currentSelection.Count == 1 && currentSelection[0] is SplineNode.SplinePointTangentNode) + { + var selectedTangentNode = currentSelection[0] as SplineNode.SplinePointTangentNode; + Editor.Instance.SceneEditing.Select(selectedTangentNode.ParentNode); + } } private void SetKeyframeLinear(Spline spline, int index) From 1ec2df1a298ecf9981dbb2f0e7afe2d76aed07b7 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Wed, 19 Jul 2023 08:43:11 -0400 Subject: [PATCH 04/35] disable edit tangents buttons when don't have any tangent or point selected --- .../CustomEditors/Dedicated/SplineEditor.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 4dc0643d3..63f608eaa 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -226,6 +226,12 @@ namespace FlaxEditor.CustomEditors.Dedicated /// public Spline SelectedSpline => !Values.HasDifferentValues && Values[0] is Spline ? (Spline)Values[0] : null; + private bool HasTangentsSelected => _selectedTangentIn != null || _selectedTangentOut != null; + + private bool HasPointSelected => _lastPointSelected != null; + + private bool CanSetTangentMode => HasPointSelected || HasTangentsSelected; + /// /// Create a Spline editor /// @@ -273,6 +279,15 @@ namespace FlaxEditor.CustomEditors.Dedicated UpdateSelectedPoint(); UpdateSelectedTangent(); + _freeTangentButton.Button.Enabled = CanSetTangentMode; + _linearTangentButton.Button.Enabled = CanSetTangentMode; + _alignedTangentButton.Button.Enabled = CanSetTangentMode; + + if (_lastPointSelected == null) + { + return; + } + var index = _lastPointSelected.Index; var currentTangentInPosition = SelectedSpline.GetSplineLocalTangent(index, true).Translation; var currentTangentOutPosition = SelectedSpline.GetSplineLocalTangent(index, false).Translation; @@ -366,6 +381,8 @@ namespace FlaxEditor.CustomEditors.Dedicated _selectedTangentOut = null; } + + private void OnSetTangentsLinear() { var enableUndo = Presenter.Undo != null && Presenter.Undo.Enabled; From a42dc8f434277d7285049a94acf5791b944cbfee Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Wed, 19 Jul 2023 08:44:22 -0400 Subject: [PATCH 05/35] change tangent edit option base class name --- Source/Editor/CustomEditors/Dedicated/SplineEditor.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 63f608eaa..9d8ead2a6 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -20,7 +20,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// Basis for creating tangent manipulation types for bezier curves. /// - private abstract class TangentModeBase + private abstract class EditTangentOptionBase { /// /// Called when user set selected tangent mode. @@ -61,7 +61,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// Edit curve options manipulate the curve as free mode /// - private sealed class FreeTangentMode : TangentModeBase + private sealed class FreeTangentMode : EditTangentOptionBase { /// public override void OnMoveTangentIn(Spline spline, int index) { } @@ -82,7 +82,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// Edit curve options to set tangents to linear /// - private sealed class LinearTangentMode : TangentModeBase + private sealed class LinearTangentMode : EditTangentOptionBase { /// public override void OnMoveTangentIn(Spline spline, int index) { } @@ -125,7 +125,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// Edit curve options to align tangents of selected spline /// - private sealed class AlignedTangentMode : TangentModeBase + private sealed class AlignedTangentMode : EditTangentOptionBase { /// public override void OnSetMode(Spline spline, int index) @@ -207,7 +207,7 @@ namespace FlaxEditor.CustomEditors.Dedicated } } - private TangentModeBase _currentTangentMode; + private EditTangentOptionBase _currentTangentMode; private ButtonElement _freeTangentButton; private ButtonElement _linearTangentButton; From 95c934d6b4c80f073af17d0b300d77e6f2d6e6dc Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Wed, 19 Jul 2023 09:07:40 -0400 Subject: [PATCH 06/35] se button color when set tangent mode --- .../CustomEditors/Dedicated/SplineEditor.cs | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 9d8ead2a6..5650f9b8f 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -1,12 +1,10 @@ // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. -using FlaxEditor.Actions; -using FlaxEditor.SceneGraph.Actors; using FlaxEngine; using FlaxEngine.GUI; +using FlaxEditor.Actions; +using FlaxEditor.SceneGraph.Actors; using FlaxEditor.CustomEditors.Elements; -using System; -using FlaxEditor.SceneGraph; namespace FlaxEditor.CustomEditors.Dedicated { @@ -232,6 +230,16 @@ namespace FlaxEditor.CustomEditors.Dedicated private bool CanSetTangentMode => HasPointSelected || HasTangentsSelected; + private Color SelectedButtonColor => FlaxEngine.GUI.Style.Current.BackgroundSelected; + + private Color NormalButtonColor => FlaxEngine.GUI.Style.Current.BackgroundNormal; + + private bool IsFreeTangentMode => _currentTangentMode is FreeTangentMode; + + private bool IsLinearTangentMode => _currentTangentMode is LinearTangentMode; + + private bool IsAlignedTangentMode => _currentTangentMode is AlignedTangentMode; + /// /// Create a Spline editor /// @@ -262,6 +270,10 @@ namespace FlaxEditor.CustomEditors.Dedicated _freeTangentButton.Button.Clicked += SetModeFree; _alignedTangentButton.Button.Clicked += SetModeAligned; + _linearTangentButton.Button.Clicked += UpdateButtonsColors; + _freeTangentButton.Button.Clicked += UpdateButtonsColors; + _alignedTangentButton.Button.Clicked += UpdateButtonsColors; + layout.Header("All spline points"); var grid = layout.CustomContainer(); grid.CustomControl.SlotsHorizontally = 2; @@ -381,7 +393,12 @@ namespace FlaxEditor.CustomEditors.Dedicated _selectedTangentOut = null; } - + private void UpdateButtonsColors() + { + _linearTangentButton.Button.BackgroundColor = IsLinearTangentMode ? SelectedButtonColor : NormalButtonColor; + _freeTangentButton.Button.BackgroundColor = IsFreeTangentMode ? SelectedButtonColor : NormalButtonColor; + _alignedTangentButton.Button.BackgroundColor = IsAlignedTangentMode ? SelectedButtonColor : NormalButtonColor; + } private void OnSetTangentsLinear() { From 7036e77d60067164ed7ac0926d22765116b54898 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Wed, 19 Jul 2023 10:20:30 -0400 Subject: [PATCH 07/35] fix auto smooth point on click --- Source/Editor/CustomEditors/Dedicated/SplineEditor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 5650f9b8f..a3b0495cf 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -155,7 +155,8 @@ namespace FlaxEditor.CustomEditors.Dedicated private void SmoothIfNotAligned(Spline spline, int index) { var keyframe = spline.GetSplineKeyframe(index); - var isAligned = Vector3.Dot(keyframe.TangentIn.Translation.Normalized, keyframe.TangentOut.Translation.Normalized) == 1f; + var angle = Vector3.Dot(keyframe.TangentIn.Translation.Normalized, keyframe.TangentOut.Translation.Normalized); + var isAligned = angle <= -0.99f; if (!isAligned) { From 7855db951ef1236bdce98ae93906dbac76ed5408 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Wed, 19 Jul 2023 16:01:05 -0400 Subject: [PATCH 08/35] auto detect tangent type when click on spline keyframe --- .../CustomEditors/Dedicated/SplineEditor.cs | 68 ++++++++++++++++--- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index a3b0495cf..b4cac340f 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -235,12 +235,6 @@ namespace FlaxEditor.CustomEditors.Dedicated private Color NormalButtonColor => FlaxEngine.GUI.Style.Current.BackgroundNormal; - private bool IsFreeTangentMode => _currentTangentMode is FreeTangentMode; - - private bool IsLinearTangentMode => _currentTangentMode is LinearTangentMode; - - private bool IsAlignedTangentMode => _currentTangentMode is AlignedTangentMode; - /// /// Create a Spline editor /// @@ -348,6 +342,43 @@ namespace FlaxEditor.CustomEditors.Dedicated _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); } + private bool IsFreeTangentMode(Spline spline, int index) + { + if (IsLinearTangentMode(spline, index) || IsAlignedTangentMode(spline, index)) + { + return false; + } + + return true; + } + + private bool IsLinearTangentMode(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + return keyframe.TangentIn.Translation.Length == 0 && keyframe.TangentOut.Translation.Length == 0; + } + + private bool IsAlignedTangentMode(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + var tangentIn = keyframe.TangentIn.Translation; + var tangentOut = keyframe.TangentOut.Translation; + + if (tangentIn.Length == 0 || tangentOut.Length == 0) + { + return false; + } + + var angleBetweenTwoTangents = Vector3.Dot(tangentIn.Normalized,tangentOut.Normalized); + + if (angleBetweenTwoTangents < -0.99f) + { + return true; + } + + return false; + } + private void UpdateSelectedPoint() { // works only if select one spline @@ -360,6 +391,10 @@ namespace FlaxEditor.CustomEditors.Dedicated _lastPointSelected = currentSelected as SplineNode.SplinePointNode; var index = _lastPointSelected.Index; + + SetSelectedTangentTypeAsCurrent(); + UpdateButtonsColors(); + _currentTangentMode.OnSelectKeyframe(SelectedSpline, index); } @@ -396,9 +431,24 @@ namespace FlaxEditor.CustomEditors.Dedicated private void UpdateButtonsColors() { - _linearTangentButton.Button.BackgroundColor = IsLinearTangentMode ? SelectedButtonColor : NormalButtonColor; - _freeTangentButton.Button.BackgroundColor = IsFreeTangentMode ? SelectedButtonColor : NormalButtonColor; - _alignedTangentButton.Button.BackgroundColor = IsAlignedTangentMode ? SelectedButtonColor : NormalButtonColor; + var isFree = IsFreeTangentMode(SelectedSpline, _lastPointSelected.Index); + var isLinear = IsLinearTangentMode(SelectedSpline, _lastPointSelected.Index); + var isAligned = IsAlignedTangentMode(SelectedSpline, _lastPointSelected.Index); + + _linearTangentButton.Button.BackgroundColor = isLinear ? SelectedButtonColor : NormalButtonColor; + _freeTangentButton.Button.BackgroundColor = isFree ? SelectedButtonColor : NormalButtonColor; + _alignedTangentButton.Button.BackgroundColor = isAligned ? SelectedButtonColor : NormalButtonColor; + } + + private void SetSelectedTangentTypeAsCurrent() + { + var isFree = IsFreeTangentMode(SelectedSpline, _lastPointSelected.Index); + var isLinear = IsLinearTangentMode(SelectedSpline, _lastPointSelected.Index); + var isAligned = IsAlignedTangentMode(SelectedSpline, _lastPointSelected.Index); + + if (isFree) SetModeFree(); + else if (isLinear) SetModeLinear(); + else if (isAligned) SetModeAligned(); } private void OnSetTangentsLinear() From 8a9b76a468d740636af96ddb3d9afdffaaa56770 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Wed, 19 Jul 2023 16:28:15 -0400 Subject: [PATCH 09/35] clean code --- .../CustomEditors/Dedicated/SplineEditor.cs | 80 +++++++++---------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index b4cac340f..694a51bf9 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -154,11 +154,7 @@ namespace FlaxEditor.CustomEditors.Dedicated private void SmoothIfNotAligned(Spline spline, int index) { - var keyframe = spline.GetSplineKeyframe(index); - var angle = Vector3.Dot(keyframe.TangentIn.Translation.Normalized, keyframe.TangentOut.Translation.Normalized); - var isAligned = angle <= -0.99f; - - if (!isAligned) + if (!IsAlignedTangentMode(spline, index)) { SetPointSmooth(spline, index); } @@ -342,43 +338,6 @@ namespace FlaxEditor.CustomEditors.Dedicated _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); } - private bool IsFreeTangentMode(Spline spline, int index) - { - if (IsLinearTangentMode(spline, index) || IsAlignedTangentMode(spline, index)) - { - return false; - } - - return true; - } - - private bool IsLinearTangentMode(Spline spline, int index) - { - var keyframe = spline.GetSplineKeyframe(index); - return keyframe.TangentIn.Translation.Length == 0 && keyframe.TangentOut.Translation.Length == 0; - } - - private bool IsAlignedTangentMode(Spline spline, int index) - { - var keyframe = spline.GetSplineKeyframe(index); - var tangentIn = keyframe.TangentIn.Translation; - var tangentOut = keyframe.TangentOut.Translation; - - if (tangentIn.Length == 0 || tangentOut.Length == 0) - { - return false; - } - - var angleBetweenTwoTangents = Vector3.Dot(tangentIn.Normalized,tangentOut.Normalized); - - if (angleBetweenTwoTangents < -0.99f) - { - return true; - } - - return false; - } - private void UpdateSelectedPoint() { // works only if select one spline @@ -484,5 +443,42 @@ namespace FlaxEditor.CustomEditors.Dedicated } } } + + private static bool IsFreeTangentMode(Spline spline, int index) + { + if (IsLinearTangentMode(spline, index) || IsAlignedTangentMode(spline, index)) + { + return false; + } + + return true; + } + + private static bool IsLinearTangentMode(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + return keyframe.TangentIn.Translation.Length == 0 && keyframe.TangentOut.Translation.Length == 0; + } + + private static bool IsAlignedTangentMode(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + var tangentIn = keyframe.TangentIn.Translation; + var tangentOut = keyframe.TangentOut.Translation; + + if (tangentIn.Length == 0 || tangentOut.Length == 0) + { + return false; + } + + var angleBetweenTwoTangents = Vector3.Dot(tangentIn.Normalized, tangentOut.Normalized); + + if (angleBetweenTwoTangents < -0.99f) + { + return true; + } + + return false; + } } } From e40c0be00db33386c137ded6c5044a5e3398d9cf Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Thu, 20 Jul 2023 09:25:48 -0400 Subject: [PATCH 10/35] fix set type on press edit buttons not working --- Source/Editor/CustomEditors/Dedicated/SplineEditor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 694a51bf9..e26a05f69 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -390,9 +390,9 @@ namespace FlaxEditor.CustomEditors.Dedicated private void UpdateButtonsColors() { - var isFree = IsFreeTangentMode(SelectedSpline, _lastPointSelected.Index); - var isLinear = IsLinearTangentMode(SelectedSpline, _lastPointSelected.Index); - var isAligned = IsAlignedTangentMode(SelectedSpline, _lastPointSelected.Index); + var isFree = _currentTangentMode is FreeTangentMode; + var isLinear = _currentTangentMode is LinearTangentMode; + var isAligned = _currentTangentMode is AlignedTangentMode; _linearTangentButton.Button.BackgroundColor = isLinear ? SelectedButtonColor : NormalButtonColor; _freeTangentButton.Button.BackgroundColor = isFree ? SelectedButtonColor : NormalButtonColor; From 902a3c1eed974f9ca1ef58c47cc5c7cf013b9b83 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Thu, 20 Jul 2023 09:36:05 -0400 Subject: [PATCH 11/35] smooth point on set linear point to free --- .../CustomEditors/Dedicated/SplineEditor.cs | 88 ++++++++++--------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index e26a05f69..4df665b15 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -61,6 +61,15 @@ namespace FlaxEditor.CustomEditors.Dedicated /// private sealed class FreeTangentMode : EditTangentOptionBase { + /// + public override void OnSetMode(Spline spline, int index) + { + if (IsLinearTangentMode(spline, index)) + { + SetPointSmooth(spline, index); + } + } + /// public override void OnMoveTangentIn(Spline spline, int index) { } @@ -72,9 +81,6 @@ namespace FlaxEditor.CustomEditors.Dedicated /// public override void OnSelectTangent(Spline spline, int index) { } - - /// - public override void OnSetMode(Spline spline, int index) { } } /// @@ -82,18 +88,6 @@ namespace FlaxEditor.CustomEditors.Dedicated /// private sealed class LinearTangentMode : EditTangentOptionBase { - /// - public override void OnMoveTangentIn(Spline spline, int index) { } - - /// - public override void OnMoveTangentOut(Spline spline, int index) { } - - /// - public override void OnSelectKeyframe(Spline spline, int index) { } - - /// - public override void OnSelectTangent(Spline spline, int index) { } - /// public override void OnSetMode(Spline spline, int index) { @@ -108,6 +102,18 @@ namespace FlaxEditor.CustomEditors.Dedicated } } + /// + public override void OnMoveTangentIn(Spline spline, int index) { } + + /// + public override void OnMoveTangentOut(Spline spline, int index) { } + + /// + public override void OnSelectKeyframe(Spline spline, int index) { } + + /// + public override void OnSelectTangent(Spline spline, int index) { } + private void SetKeyframeLinear(Spline spline, int index) { var tangentIn = spline.GetSplineTangent(index, true); @@ -160,32 +166,6 @@ namespace FlaxEditor.CustomEditors.Dedicated } } - private void SetPointSmooth(Spline spline, int index) - { - var keyframe = spline.GetSplineKeyframe(index); - var tangentIn = keyframe.TangentIn; - var tangentOut = keyframe.TangentOut; - var tangentInSize = tangentIn.Translation.Length; - var tangentOutSize = tangentOut.Translation.Length; - - var isLastKeyframe = index >= spline.SplinePointsCount - 1; - var isFirstKeyframe = index <= 0; - - // force smooth it's linear point - if (tangentInSize == 0f && !isFirstKeyframe) tangentInSize = 100; - if (tangentOutSize == 0f && !isLastKeyframe) tangentOutSize = 100; - - var nextKeyframe = !isLastKeyframe ? spline.GetSplineKeyframe(index + 1) : keyframe; - var previousKeyframe = !isFirstKeyframe ? spline.GetSplineKeyframe(index - 1) : keyframe; - - // calc form from Spline.cpp -> SetTangentsSmooth - var slop = (keyframe.Value.Translation - previousKeyframe.Value.Translation + nextKeyframe.Value.Translation - keyframe.Value.Translation).Normalized; - - keyframe.TangentIn.Translation = -slop * tangentInSize; - keyframe.TangentOut.Translation = slop * tangentOutSize; - spline.SetSplineKeyframe(index, keyframe); - } - private void SetPointAligned(Spline spline, int index, bool isIn) { var keyframe = spline.GetSplineKeyframe(index); @@ -480,5 +460,31 @@ namespace FlaxEditor.CustomEditors.Dedicated return false; } + + private static void SetPointSmooth(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + var tangentIn = keyframe.TangentIn; + var tangentOut = keyframe.TangentOut; + var tangentInSize = tangentIn.Translation.Length; + var tangentOutSize = tangentOut.Translation.Length; + + var isLastKeyframe = index >= spline.SplinePointsCount - 1; + var isFirstKeyframe = index <= 0; + + // force smooth it's linear point + if (tangentInSize == 0f && !isFirstKeyframe) tangentInSize = 100; + if (tangentOutSize == 0f && !isLastKeyframe) tangentOutSize = 100; + + var nextKeyframe = !isLastKeyframe ? spline.GetSplineKeyframe(index + 1) : keyframe; + var previousKeyframe = !isFirstKeyframe ? spline.GetSplineKeyframe(index - 1) : keyframe; + + // calc form from Spline.cpp -> SetTangentsSmooth + var slop = (keyframe.Value.Translation - previousKeyframe.Value.Translation + nextKeyframe.Value.Translation - keyframe.Value.Translation).Normalized; + + keyframe.TangentIn.Translation = -slop * tangentInSize; + keyframe.TangentOut.Translation = slop * tangentOutSize; + spline.SetSplineKeyframe(index, keyframe); + } } } From 50f16881409b76085bd476514fd80c97ab7c1246 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Thu, 20 Jul 2023 10:52:07 -0400 Subject: [PATCH 12/35] add smooth in tangent and smooth out tangent --- .../CustomEditors/Dedicated/SplineEditor.cs | 136 +++++++++++++++++- 1 file changed, 134 insertions(+), 2 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 4df665b15..8c3d03b2b 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -182,11 +182,100 @@ namespace FlaxEditor.CustomEditors.Dedicated } } + /// + /// Edit curve options manipulate the curve setting selected point + /// tangent in as smoothed but tangent out as linear + /// + private sealed class SmoothInTangentMode : EditTangentOptionBase + { + /// + public override void OnSetMode(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + + // auto smooth tangent if's linear + if (keyframe.TangentIn.Translation.Length == 0) + { + var isLastKeyframe = index == spline.SplinePointsCount - 1; + var isFirstKeyframe = index == 0; + + if (!isLastKeyframe) + { + var nexKeyframe = spline.GetSplineKeyframe(index + 1); + var directionToNextKeyframe = keyframe.Value.WorldToLocalVector(keyframe.Value.Translation - nexKeyframe.Value.Translation); + directionToNextKeyframe = directionToNextKeyframe.Normalized * 100f; + keyframe.TangentIn.Translation = directionToNextKeyframe; + } + } + + keyframe.TangentOut.Translation = Vector3.Zero; + + spline.SetSplineKeyframe(index, keyframe); + } + + /// + public override void OnMoveTangentIn(Spline spline, int index) { } + + /// + public override void OnMoveTangentOut(Spline spline, int index) { } + + /// + public override void OnSelectKeyframe(Spline spline, int index) { } + + /// + public override void OnSelectTangent(Spline spline, int index) { } + } + + /// + /// Edit curve options manipulate the curve setting selected point + /// tangent in as linear but tangent out as smoothed + /// + private sealed class SmoothOutTangentMode : EditTangentOptionBase + { + /// + public override void OnSetMode(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + + // auto smooth tangent if's linear + if (keyframe.TangentOut.Translation.Length == 0) + { + var isFirstKeyframe = index == 0; + + if (!isFirstKeyframe) + { + var previousKeyframe = spline.GetSplineKeyframe(index - 1); + var directionToPreviousKeyframe = keyframe.Value.WorldToLocalVector(keyframe.Value.Translation - previousKeyframe.Value.Translation); + directionToPreviousKeyframe = directionToPreviousKeyframe.Normalized * 100f; + keyframe.TangentOut.Translation = directionToPreviousKeyframe; + } + } + + keyframe.TangentIn.Translation = Vector3.Zero; + + spline.SetSplineKeyframe(index, keyframe); + } + + /// + public override void OnMoveTangentIn(Spline spline, int index) { } + + /// + public override void OnMoveTangentOut(Spline spline, int index) { } + + /// + public override void OnSelectKeyframe(Spline spline, int index) { } + + /// + public override void OnSelectTangent(Spline spline, int index) { } + } + private EditTangentOptionBase _currentTangentMode; private ButtonElement _freeTangentButton; private ButtonElement _linearTangentButton; private ButtonElement _alignedTangentButton; + private ButtonElement _smoothInTangentButton; + private ButtonElement _smoothOutTangentButton; private bool _tanInChanged; private bool _tanOutChanged; @@ -231,19 +320,25 @@ namespace FlaxEditor.CustomEditors.Dedicated layout.Header("Selected spline point"); var selectedPointsGrid = layout.CustomContainer(); selectedPointsGrid.CustomControl.SlotsHorizontally = 3; - selectedPointsGrid.CustomControl.SlotsVertically = 1; + selectedPointsGrid.CustomControl.SlotsVertically = 2; _linearTangentButton = selectedPointsGrid.Button("Linear"); _freeTangentButton = selectedPointsGrid.Button("Free"); _alignedTangentButton = selectedPointsGrid.Button("Aligned"); + _smoothInTangentButton = selectedPointsGrid.Button("Smooth In"); + _smoothOutTangentButton = selectedPointsGrid.Button("Smooth Out"); _linearTangentButton.Button.Clicked += SetModeLinear; _freeTangentButton.Button.Clicked += SetModeFree; _alignedTangentButton.Button.Clicked += SetModeAligned; + _smoothInTangentButton.Button.Clicked += SetModeSmoothIn; + _smoothOutTangentButton.Button.Clicked += SetModeSmoothOut; _linearTangentButton.Button.Clicked += UpdateButtonsColors; _freeTangentButton.Button.Clicked += UpdateButtonsColors; _alignedTangentButton.Button.Clicked += UpdateButtonsColors; + _smoothInTangentButton.Button.Clicked += UpdateButtonsColors; + _smoothOutTangentButton.Button.Clicked += UpdateButtonsColors; layout.Header("All spline points"); var grid = layout.CustomContainer(); @@ -265,6 +360,8 @@ namespace FlaxEditor.CustomEditors.Dedicated _freeTangentButton.Button.Enabled = CanSetTangentMode; _linearTangentButton.Button.Enabled = CanSetTangentMode; _alignedTangentButton.Button.Enabled = CanSetTangentMode; + _smoothInTangentButton.Button.Enabled = CanSetTangentMode; + _smoothOutTangentButton.Button.Enabled = CanSetTangentMode; if (_lastPointSelected == null) { @@ -318,6 +415,18 @@ namespace FlaxEditor.CustomEditors.Dedicated _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); } + private void SetModeSmoothIn() + { + _currentTangentMode = new SmoothInTangentMode(); + _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + } + + private void SetModeSmoothOut() + { + _currentTangentMode = new SmoothOutTangentMode(); + _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + } + private void UpdateSelectedPoint() { // works only if select one spline @@ -373,10 +482,14 @@ namespace FlaxEditor.CustomEditors.Dedicated var isFree = _currentTangentMode is FreeTangentMode; var isLinear = _currentTangentMode is LinearTangentMode; var isAligned = _currentTangentMode is AlignedTangentMode; + var isSmoothIn = _currentTangentMode is SmoothInTangentMode; + var isSmoothOut = _currentTangentMode is SmoothOutTangentMode; _linearTangentButton.Button.BackgroundColor = isLinear ? SelectedButtonColor : NormalButtonColor; _freeTangentButton.Button.BackgroundColor = isFree ? SelectedButtonColor : NormalButtonColor; _alignedTangentButton.Button.BackgroundColor = isAligned ? SelectedButtonColor : NormalButtonColor; + _smoothInTangentButton.Button.BackgroundColor = isSmoothIn ? SelectedButtonColor : NormalButtonColor; + _smoothOutTangentButton.Button.BackgroundColor = isSmoothOut ? SelectedButtonColor : NormalButtonColor; } private void SetSelectedTangentTypeAsCurrent() @@ -384,10 +497,14 @@ namespace FlaxEditor.CustomEditors.Dedicated var isFree = IsFreeTangentMode(SelectedSpline, _lastPointSelected.Index); var isLinear = IsLinearTangentMode(SelectedSpline, _lastPointSelected.Index); var isAligned = IsAlignedTangentMode(SelectedSpline, _lastPointSelected.Index); + var isSmoothIn = IsSmoothInTangentMode(SelectedSpline, _lastPointSelected.Index); + var isSmoothOut = IsSmoothOutTangentMode(SelectedSpline, _lastPointSelected.Index); if (isFree) SetModeFree(); else if (isLinear) SetModeLinear(); else if (isAligned) SetModeAligned(); + else if (isSmoothIn) SetModeSmoothIn(); + else if (isSmoothOut) SetModeSmoothIn(); } private void OnSetTangentsLinear() @@ -426,7 +543,10 @@ namespace FlaxEditor.CustomEditors.Dedicated private static bool IsFreeTangentMode(Spline spline, int index) { - if (IsLinearTangentMode(spline, index) || IsAlignedTangentMode(spline, index)) + if (IsLinearTangentMode(spline, index) || + IsAlignedTangentMode(spline, index) || + IsSmoothInTangentMode(spline, index) || + IsSmoothOutTangentMode(spline, index)) { return false; } @@ -461,6 +581,18 @@ namespace FlaxEditor.CustomEditors.Dedicated return false; } + private static bool IsSmoothInTangentMode(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + return keyframe.TangentIn.Translation.Length > 0 && keyframe.TangentOut.Translation.Length == 0; + } + + private static bool IsSmoothOutTangentMode(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + return keyframe.TangentOut.Translation.Length > 0 && keyframe.TangentIn.Translation.Length == 0; + } + private static void SetPointSmooth(Spline spline, int index) { var keyframe = spline.GetSplineKeyframe(index); From e6715ad095b10283cac12d5a4bea05892c3df9dd Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Thu, 20 Jul 2023 13:05:56 -0400 Subject: [PATCH 13/35] add methods to auto select tangents or points on change edit mode on spline editor --- .../CustomEditors/Dedicated/SplineEditor.cs | 69 ++++++++++++++++--- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 8c3d03b2b..6d954949c 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -3,6 +3,7 @@ using FlaxEngine; using FlaxEngine.GUI; using FlaxEditor.Actions; +using FlaxEditor.SceneGraph; using FlaxEditor.SceneGraph.Actors; using FlaxEditor.CustomEditors.Elements; @@ -93,13 +94,8 @@ namespace FlaxEditor.CustomEditors.Dedicated { SetKeyframeLinear(spline, index); - // if has a tangent selected, change the selection to tangent parent (a spline point / keyframe) - var currentSelection = Editor.Instance.SceneEditing.Selection; - if (currentSelection.Count == 1 && currentSelection[0] is SplineNode.SplinePointTangentNode) - { - var selectedTangentNode = currentSelection[0] as SplineNode.SplinePointTangentNode; - Editor.Instance.SceneEditing.Select(selectedTangentNode.ParentNode); - } + // change the selection to tangent parent (a spline point / keyframe) + SetSelectSplinePointNode(spline, index); } /// @@ -197,7 +193,6 @@ namespace FlaxEditor.CustomEditors.Dedicated if (keyframe.TangentIn.Translation.Length == 0) { var isLastKeyframe = index == spline.SplinePointsCount - 1; - var isFirstKeyframe = index == 0; if (!isLastKeyframe) { @@ -211,6 +206,7 @@ namespace FlaxEditor.CustomEditors.Dedicated keyframe.TangentOut.Translation = Vector3.Zero; spline.SetSplineKeyframe(index, keyframe); + SetSelectTangentIn(spline, index); } /// @@ -254,6 +250,7 @@ namespace FlaxEditor.CustomEditors.Dedicated keyframe.TangentIn.Translation = Vector3.Zero; spline.SetSplineKeyframe(index, keyframe); + SetSelectTangentOut(spline, index); } /// @@ -618,5 +615,61 @@ namespace FlaxEditor.CustomEditors.Dedicated keyframe.TangentOut.Translation = slop * tangentOutSize; spline.SetSplineKeyframe(index, keyframe); } + + private static SplineNode.SplinePointNode GetSplinePointNode(Spline spline, int index) + { + return (SplineNode.SplinePointNode)SceneGraphFactory.FindNode(spline.ID).ChildNodes[index]; + } + + private static SplineNode.SplinePointTangentNode GetSplineTangentInNode(Spline spline, int index) + { + var point = GetSplinePointNode(spline, index); + var tangentIn = spline.GetSplineTangent(index, true); + var tangentNodes = point.ChildNodes; + + // find tangent in node comparing all child nodes position + for (int i = 0; i < tangentNodes.Count; i++) + { + if (tangentNodes[i].Transform.Translation == tangentIn.Translation) + { + return (SplineNode.SplinePointTangentNode)tangentNodes[i]; + } + } + + return null; + } + + private static SplineNode.SplinePointTangentNode GetSplineTangentOutNode(Spline spline, int index) + { + var point = GetSplinePointNode(spline, index); + var tangentOut = spline.GetSplineTangent(index, false); + var tangentNodes = point.ChildNodes; + + // find tangent out node comparing all child nodes position + for (int i = 0; i < tangentNodes.Count; i++) + { + if (tangentNodes[i].Transform.Translation == tangentOut.Translation) + { + return (SplineNode.SplinePointTangentNode)tangentNodes[i]; + } + } + + return null; + } + + private static void SetSelectSplinePointNode(Spline spline, int index) + { + Editor.Instance.SceneEditing.Select(GetSplinePointNode(spline, index)); + } + + private static void SetSelectTangentIn(Spline spline, int index) + { + Editor.Instance.SceneEditing.Select(GetSplineTangentInNode(spline, index)); + } + + private static void SetSelectTangentOut(Spline spline, int index) + { + Editor.Instance.SceneEditing.Select(GetSplineTangentOutNode(spline, index)); + } } } From 4cf2bba84061c4edb5a982fa214f83ed79f484f9 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Thu, 20 Jul 2023 13:19:18 -0400 Subject: [PATCH 14/35] fix edit buttons style on spline editor --- Source/Editor/CustomEditors/Dedicated/SplineEditor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 6d954949c..0803f93d9 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -319,6 +319,8 @@ namespace FlaxEditor.CustomEditors.Dedicated selectedPointsGrid.CustomControl.SlotsHorizontally = 3; selectedPointsGrid.CustomControl.SlotsVertically = 2; + selectedPointsGrid.Control.Size *= new Float2(1, 2); + _linearTangentButton = selectedPointsGrid.Button("Linear"); _freeTangentButton = selectedPointsGrid.Button("Free"); _alignedTangentButton = selectedPointsGrid.Button("Aligned"); From 5c7faf7262cf02bad1d7d0e58263af0abf070210 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Thu, 20 Jul 2023 16:40:05 -0400 Subject: [PATCH 15/35] disable edit tangent options when deselect tangents or spline points on spline editor --- .../CustomEditors/Dedicated/SplineEditor.cs | 62 +++++++++++++++---- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 0803f93d9..ba0eff06f 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -278,6 +278,7 @@ namespace FlaxEditor.CustomEditors.Dedicated private bool _tanOutChanged; private Vector3 _lastTanInPos; private Vector3 _lastTanOutPos; + private SplineNode.SplinePointNode _selectedPoint; private SplineNode.SplinePointNode _lastPointSelected; private SplineNode.SplinePointTangentNode _selectedTangentIn; private SplineNode.SplinePointTangentNode _selectedTangentOut; @@ -289,7 +290,7 @@ namespace FlaxEditor.CustomEditors.Dedicated private bool HasTangentsSelected => _selectedTangentIn != null || _selectedTangentOut != null; - private bool HasPointSelected => _lastPointSelected != null; + private bool HasPointSelected => _selectedPoint != null; private bool CanSetTangentMode => HasPointSelected || HasTangentsSelected; @@ -362,7 +363,7 @@ namespace FlaxEditor.CustomEditors.Dedicated _smoothInTangentButton.Button.Enabled = CanSetTangentMode; _smoothOutTangentButton.Button.Enabled = CanSetTangentMode; - if (_lastPointSelected == null) + if (!CanSetTangentMode) { return; } @@ -429,30 +430,54 @@ namespace FlaxEditor.CustomEditors.Dedicated private void UpdateSelectedPoint() { // works only if select one spline - if (Editor.Instance.SceneEditing.SelectionCount != 1) return; + if (Editor.Instance.SceneEditing.SelectionCount != 1) + { + _selectedPoint = null; + UpdateButtonsColors(); + return; + } var currentSelected = Editor.Instance.SceneEditing.Selection[0]; - if (currentSelected == _lastPointSelected) return; - if (currentSelected is not SplineNode.SplinePointNode) return; + if (currentSelected == _selectedPoint) return; + if (currentSelected is SplineNode.SplinePointNode) + { + _selectedPoint = currentSelected as SplineNode.SplinePointNode; + _lastPointSelected = _selectedPoint; - _lastPointSelected = currentSelected as SplineNode.SplinePointNode; - var index = _lastPointSelected.Index; + var index = _lastPointSelected.Index; - SetSelectedTangentTypeAsCurrent(); - UpdateButtonsColors(); + SetSelectedTangentTypeAsCurrent(); + UpdateButtonsColors(); - _currentTangentMode.OnSelectKeyframe(SelectedSpline, index); + _currentTangentMode.OnSelectKeyframe(SelectedSpline, index); + } + else + { + _selectedPoint = null; + UpdateButtonsColors(); + } } private void UpdateSelectedTangent() { // works only if select one spline - if (_lastPointSelected == null || Editor.Instance.SceneEditing.SelectionCount != 1) return; + if (_lastPointSelected == null || Editor.Instance.SceneEditing.SelectionCount != 1) + { + _selectedTangentIn = null; + _selectedTangentOut = null; + return; + } var currentSelected = Editor.Instance.SceneEditing.Selection[0]; - if (currentSelected is not SplineNode.SplinePointTangentNode) return; + if (currentSelected is not SplineNode.SplinePointTangentNode) + { + _selectedTangentIn = null; + _selectedTangentOut = null; + return; + } + if (currentSelected == _selectedTangentIn) return; if (currentSelected == _selectedTangentOut) return; @@ -461,13 +486,16 @@ namespace FlaxEditor.CustomEditors.Dedicated if (currentSelected.Transform == SelectedSpline.GetSplineTangent(index, true)) { _selectedTangentIn = currentSelected as SplineNode.SplinePointTangentNode; + _selectedTangentOut = null; _currentTangentMode.OnSelectTangent(SelectedSpline, index); + return; } if (currentSelected.Transform == SelectedSpline.GetSplineTangent(index, false)) { _selectedTangentOut = currentSelected as SplineNode.SplinePointTangentNode; + _selectedTangentIn = null; _currentTangentMode.OnSelectTangent(SelectedSpline, index); return; } @@ -478,6 +506,16 @@ namespace FlaxEditor.CustomEditors.Dedicated private void UpdateButtonsColors() { + if (!CanSetTangentMode) + { + _linearTangentButton.Button.BackgroundColor = NormalButtonColor; + _freeTangentButton.Button.BackgroundColor = NormalButtonColor; + _alignedTangentButton.Button.BackgroundColor = NormalButtonColor; + _smoothInTangentButton.Button.BackgroundColor = NormalButtonColor; + _smoothOutTangentButton.Button.BackgroundColor = NormalButtonColor; + return; + } + var isFree = _currentTangentMode is FreeTangentMode; var isLinear = _currentTangentMode is LinearTangentMode; var isAligned = _currentTangentMode is AlignedTangentMode; From 008f219883b60add1247617aec69cad9a1abf6f5 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Fri, 21 Jul 2023 10:25:55 -0400 Subject: [PATCH 16/35] organize smooth in and smooth out tangents code --- .../CustomEditors/Dedicated/SplineEditor.cs | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index ba0eff06f..9b5d420b3 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -187,25 +187,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// public override void OnSetMode(Spline spline, int index) { - var keyframe = spline.GetSplineKeyframe(index); - - // auto smooth tangent if's linear - if (keyframe.TangentIn.Translation.Length == 0) - { - var isLastKeyframe = index == spline.SplinePointsCount - 1; - - if (!isLastKeyframe) - { - var nexKeyframe = spline.GetSplineKeyframe(index + 1); - var directionToNextKeyframe = keyframe.Value.WorldToLocalVector(keyframe.Value.Translation - nexKeyframe.Value.Translation); - directionToNextKeyframe = directionToNextKeyframe.Normalized * 100f; - keyframe.TangentIn.Translation = directionToNextKeyframe; - } - } - - keyframe.TangentOut.Translation = Vector3.Zero; - - spline.SetSplineKeyframe(index, keyframe); + SetSelectTangentIn(spline, index); SetSelectTangentIn(spline, index); } @@ -231,25 +213,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// public override void OnSetMode(Spline spline, int index) { - var keyframe = spline.GetSplineKeyframe(index); - - // auto smooth tangent if's linear - if (keyframe.TangentOut.Translation.Length == 0) - { - var isFirstKeyframe = index == 0; - - if (!isFirstKeyframe) - { - var previousKeyframe = spline.GetSplineKeyframe(index - 1); - var directionToPreviousKeyframe = keyframe.Value.WorldToLocalVector(keyframe.Value.Translation - previousKeyframe.Value.Translation); - directionToPreviousKeyframe = directionToPreviousKeyframe.Normalized * 100f; - keyframe.TangentOut.Translation = directionToPreviousKeyframe; - } - } - - keyframe.TangentIn.Translation = Vector3.Zero; - - spline.SetSplineKeyframe(index, keyframe); + SetTangentSmoothOut(spline, index); SetSelectTangentOut(spline, index); } @@ -630,6 +594,51 @@ namespace FlaxEditor.CustomEditors.Dedicated return keyframe.TangentOut.Translation.Length > 0 && keyframe.TangentIn.Translation.Length == 0; } + private static void SetTangentSmoothIn(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + + // auto smooth tangent if's linear + if (keyframe.TangentIn.Translation.Length == 0) + { + var isLastKeyframe = index == spline.SplinePointsCount - 1; + + if (!isLastKeyframe) + { + var nexKeyframe = spline.GetSplineKeyframe(index + 1); + var directionToNextKeyframe = keyframe.Value.WorldToLocalVector(keyframe.Value.Translation - nexKeyframe.Value.Translation); + directionToNextKeyframe = directionToNextKeyframe.Normalized * 100f; + keyframe.TangentIn.Translation = directionToNextKeyframe; + } + } + + keyframe.TangentOut.Translation = Vector3.Zero; + spline.SetSplineKeyframe(index, keyframe); + } + + private static void SetTangentSmoothOut(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + + // auto smooth tangent if's linear + if (keyframe.TangentOut.Translation.Length == 0) + { + var isFirstKeyframe = index == 0; + + if (!isFirstKeyframe) + { + var previousKeyframe = spline.GetSplineKeyframe(index - 1); + var directionToPreviousKeyframe = keyframe.Value.WorldToLocalVector(keyframe.Value.Translation - previousKeyframe.Value.Translation); + directionToPreviousKeyframe = directionToPreviousKeyframe.Normalized * 100f; + keyframe.TangentOut.Translation = directionToPreviousKeyframe; + } + } + + keyframe.TangentIn.Translation = Vector3.Zero; + + spline.SetSplineKeyframe(index, keyframe); + } + private static void SetPointSmooth(Spline spline, int index) { var keyframe = spline.GetSplineKeyframe(index); From 6872f35add9c03ea2ca5e42438ea3eba189b9d07 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Fri, 21 Jul 2023 21:00:08 -0400 Subject: [PATCH 17/35] don't let set smooth tangent in/out on start/end spline if isn't loop --- .../CustomEditors/Dedicated/SplineEditor.cs | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 9b5d420b3..56aaf5d7c 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -187,7 +187,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// public override void OnSetMode(Spline spline, int index) { - SetSelectTangentIn(spline, index); + SetTangentSmoothIn(spline, index); SetSelectTangentIn(spline, index); } @@ -252,11 +252,8 @@ namespace FlaxEditor.CustomEditors.Dedicated /// public Spline SelectedSpline => !Values.HasDifferentValues && Values[0] is Spline ? (Spline)Values[0] : null; - private bool HasTangentsSelected => _selectedTangentIn != null || _selectedTangentOut != null; - private bool HasPointSelected => _selectedPoint != null; - - private bool CanSetTangentMode => HasPointSelected || HasTangentsSelected; + private bool HasTangentsSelected => _selectedTangentIn != null || _selectedTangentOut != null; private Color SelectedButtonColor => FlaxEngine.GUI.Style.Current.BackgroundSelected; @@ -321,18 +318,19 @@ namespace FlaxEditor.CustomEditors.Dedicated UpdateSelectedPoint(); UpdateSelectedTangent(); - _freeTangentButton.Button.Enabled = CanSetTangentMode; - _linearTangentButton.Button.Enabled = CanSetTangentMode; - _alignedTangentButton.Button.Enabled = CanSetTangentMode; - _smoothInTangentButton.Button.Enabled = CanSetTangentMode; - _smoothOutTangentButton.Button.Enabled = CanSetTangentMode; + _freeTangentButton.Button.Enabled = CanSetTangentMode(); + _linearTangentButton.Button.Enabled = CanSetTangentMode(); + _alignedTangentButton.Button.Enabled = CanSetTangentMode(); + _smoothInTangentButton.Button.Enabled = CanSetTangentSmoothIn(); + _smoothOutTangentButton.Button.Enabled = CanSetTangentSmoothOut(); - if (!CanSetTangentMode) + if (!CanSetTangentMode()) { return; } var index = _lastPointSelected.Index; + var currentTangentInPosition = SelectedSpline.GetSplineLocalTangent(index, true).Translation; var currentTangentOutPosition = SelectedSpline.GetSplineLocalTangent(index, false).Translation; @@ -361,6 +359,23 @@ namespace FlaxEditor.CustomEditors.Dedicated _tanOutChanged = false; } + private bool CanSetTangentMode() + { + return HasPointSelected || HasTangentsSelected; + } + + private bool CanSetTangentSmoothIn() + { + if (!CanSetTangentMode()) return false; + return _lastPointSelected.Index != 0; + } + + private bool CanSetTangentSmoothOut() + { + if (!CanSetTangentMode()) return false; + return _lastPointSelected.Index < SelectedSpline.SplinePointsCount - 1; + } + private void SetModeLinear() { _currentTangentMode = new LinearTangentMode(); @@ -470,7 +485,7 @@ namespace FlaxEditor.CustomEditors.Dedicated private void UpdateButtonsColors() { - if (!CanSetTangentMode) + if (!CanSetTangentMode()) { _linearTangentButton.Button.BackgroundColor = NormalButtonColor; _freeTangentButton.Button.BackgroundColor = NormalButtonColor; @@ -505,7 +520,7 @@ namespace FlaxEditor.CustomEditors.Dedicated else if (isLinear) SetModeLinear(); else if (isAligned) SetModeAligned(); else if (isSmoothIn) SetModeSmoothIn(); - else if (isSmoothOut) SetModeSmoothIn(); + else if (isSmoothOut) SetModeSmoothOut(); } private void OnSetTangentsLinear() @@ -601,15 +616,10 @@ namespace FlaxEditor.CustomEditors.Dedicated // auto smooth tangent if's linear if (keyframe.TangentIn.Translation.Length == 0) { - var isLastKeyframe = index == spline.SplinePointsCount - 1; - - if (!isLastKeyframe) - { - var nexKeyframe = spline.GetSplineKeyframe(index + 1); - var directionToNextKeyframe = keyframe.Value.WorldToLocalVector(keyframe.Value.Translation - nexKeyframe.Value.Translation); - directionToNextKeyframe = directionToNextKeyframe.Normalized * 100f; - keyframe.TangentIn.Translation = directionToNextKeyframe; - } + var previousKeyframe = spline.GetSplineKeyframe(index - 1); + var tangentDirection = keyframe.Value.WorldToLocalVector(previousKeyframe.Value.Translation - keyframe.Value.Translation); + tangentDirection = tangentDirection.Normalized * 100f; + keyframe.TangentIn.Translation = tangentDirection; } keyframe.TangentOut.Translation = Vector3.Zero; @@ -623,15 +633,10 @@ namespace FlaxEditor.CustomEditors.Dedicated // auto smooth tangent if's linear if (keyframe.TangentOut.Translation.Length == 0) { - var isFirstKeyframe = index == 0; - - if (!isFirstKeyframe) - { - var previousKeyframe = spline.GetSplineKeyframe(index - 1); - var directionToPreviousKeyframe = keyframe.Value.WorldToLocalVector(keyframe.Value.Translation - previousKeyframe.Value.Translation); - directionToPreviousKeyframe = directionToPreviousKeyframe.Normalized * 100f; - keyframe.TangentOut.Translation = directionToPreviousKeyframe; - } + var nextKeyframe = spline.GetSplineKeyframe(index + 1); + var tangentDirection = keyframe.Value.WorldToLocalVector(nextKeyframe.Value.Translation - keyframe.Value.Translation); + tangentDirection = tangentDirection.Normalized * 100f; + keyframe.TangentOut.Translation = tangentDirection; } keyframe.TangentIn.Translation = Vector3.Zero; From 1bd7210107069270c419a62ab8a4642540f9b367 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Fri, 21 Jul 2023 21:05:36 -0400 Subject: [PATCH 18/35] don't let aligned or free mode on first or end spline point --- .../CustomEditors/Dedicated/SplineEditor.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 56aaf5d7c..d83aa1acc 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -318,9 +318,9 @@ namespace FlaxEditor.CustomEditors.Dedicated UpdateSelectedPoint(); UpdateSelectedTangent(); - _freeTangentButton.Button.Enabled = CanSetTangentMode(); + _freeTangentButton.Button.Enabled = CanSetTangentFree(); _linearTangentButton.Button.Enabled = CanSetTangentMode(); - _alignedTangentButton.Button.Enabled = CanSetTangentMode(); + _alignedTangentButton.Button.Enabled = CanSetTangentAligned(); _smoothInTangentButton.Button.Enabled = CanSetTangentSmoothIn(); _smoothOutTangentButton.Button.Enabled = CanSetTangentSmoothOut(); @@ -376,6 +376,18 @@ namespace FlaxEditor.CustomEditors.Dedicated return _lastPointSelected.Index < SelectedSpline.SplinePointsCount - 1; } + private bool CanSetTangentFree() + { + if (!CanSetTangentMode()) return false; + return _lastPointSelected.Index < SelectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; + } + + private bool CanSetTangentAligned() + { + if (!CanSetTangentMode()) return false; + return _lastPointSelected.Index < SelectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; + } + private void SetModeLinear() { _currentTangentMode = new LinearTangentMode(); From f8da0708e1f0645b40d7527bfc9b0389b491f2a5 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Fri, 21 Jul 2023 22:11:15 -0400 Subject: [PATCH 19/35] add suport to loop spline on set tangent linear --- .../CustomEditors/Dedicated/SplineEditor.cs | 30 +++++++++++-------- Source/Editor/SceneGraph/Actors/SplineNode.cs | 1 + 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index d83aa1acc..ca442d66f 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -109,17 +109,6 @@ namespace FlaxEditor.CustomEditors.Dedicated /// public override void OnSelectTangent(Spline spline, int index) { } - - private void SetKeyframeLinear(Spline spline, int index) - { - var tangentIn = spline.GetSplineTangent(index, true); - var tangentOut = spline.GetSplineTangent(index, false); - tangentIn.Translation = spline.GetSplinePoint(index); - tangentOut.Translation = spline.GetSplinePoint(index); - spline.SetSplineTangent(index, tangentIn, true, false); - spline.SetSplineTangent(index, tangentOut, false, false); - spline.UpdateSpline(); - } } /// @@ -330,7 +319,6 @@ namespace FlaxEditor.CustomEditors.Dedicated } var index = _lastPointSelected.Index; - var currentTangentInPosition = SelectedSpline.GetSplineLocalTangent(index, true).Translation; var currentTangentOutPosition = SelectedSpline.GetSplineLocalTangent(index, false).Translation; @@ -621,6 +609,24 @@ namespace FlaxEditor.CustomEditors.Dedicated return keyframe.TangentOut.Translation.Length > 0 && keyframe.TangentIn.Translation.Length == 0; } + private static void SetKeyframeLinear(Spline spline, int index) + { + var keyframe = spline.GetSplineKeyframe(index); + keyframe.TangentIn.Translation = Vector3.Zero; + keyframe.TangentOut.Translation = Vector3.Zero; + + var lastSplineIndex = spline.SplinePointsCount - 1; + if (index == lastSplineIndex && spline.IsLoop) + { + var lastPoint = spline.GetSplineKeyframe(lastSplineIndex); + lastPoint.TangentIn.Translation = Vector3.Zero; + lastPoint.TangentOut.Translation = Vector3.Zero; + spline.SetSplineKeyframe(lastSplineIndex, lastPoint); + } + + spline.SetSplineKeyframe(index, keyframe); + } + private static void SetTangentSmoothIn(Spline spline, int index) { var keyframe = spline.GetSplineKeyframe(index); diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index 3ba1d14c3..1c47c7d98 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -257,6 +257,7 @@ namespace FlaxEditor.SceneGraph.Actors public override void OnDebugDraw(ViewportDebugDrawData data) { + Debug.Log(Name); // Draw spline and spline point ParentNode.OnDebugDraw(data); From bd8c5985b12ed919d4da91a198c21814683f53c1 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Fri, 21 Jul 2023 22:11:30 -0400 Subject: [PATCH 20/35] remove debug --- Source/Editor/SceneGraph/Actors/SplineNode.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index 1c47c7d98..3ba1d14c3 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -257,7 +257,6 @@ namespace FlaxEditor.SceneGraph.Actors public override void OnDebugDraw(ViewportDebugDrawData data) { - Debug.Log(Name); // Draw spline and spline point ParentNode.OnDebugDraw(data); From 1a72aeeb24635cd87fd091bc0a263e2baf072abc Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Fri, 21 Jul 2023 22:15:43 -0400 Subject: [PATCH 21/35] disable edit tangent buttons when select multiple values --- Source/Editor/CustomEditors/Dedicated/SplineEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index ca442d66f..c33690e25 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -349,7 +349,7 @@ namespace FlaxEditor.CustomEditors.Dedicated private bool CanSetTangentMode() { - return HasPointSelected || HasTangentsSelected; + return !HasDifferentTypes && !HasDifferentValues && (HasPointSelected || HasTangentsSelected); } private bool CanSetTangentSmoothIn() From c79c91a19a90b0f6fd10c33aae0f45f52e4eddd1 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sun, 23 Jul 2023 20:27:45 -0400 Subject: [PATCH 22/35] add undo / redo to edit spline options and some small changes --- .../CustomEditors/Dedicated/SplineEditor.cs | 263 +++++++++++------- 1 file changed, 166 insertions(+), 97 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index c33690e25..4e0234974 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -1,5 +1,6 @@ // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. +using System.Collections.Generic; using FlaxEngine; using FlaxEngine.GUI; using FlaxEditor.Actions; @@ -16,6 +17,15 @@ namespace FlaxEditor.CustomEditors.Dedicated [CustomEditor(typeof(Spline)), DefaultEditor] public class SplineEditor : ActorEditor { + /// + /// Storage undo spline data + /// + private struct UndoData + { + public Spline spline; + public BezierCurve.Keyframe[] beforeKeyframes; + } + /// /// Basis for creating tangent manipulation types for bezier curves. /// @@ -151,17 +161,17 @@ namespace FlaxEditor.CustomEditors.Dedicated } } - private void SetPointAligned(Spline spline, int index, bool isIn) + private void SetPointAligned(Spline spline, int index, bool alignWithIn) { var keyframe = spline.GetSplineKeyframe(index); - var referenceTangent = isIn ? keyframe.TangentIn : keyframe.TangentOut; - var otherTangent = !isIn ? keyframe.TangentIn : keyframe.TangentOut; + var referenceTangent = alignWithIn ? keyframe.TangentIn : keyframe.TangentOut; + var otherTangent = !alignWithIn ? keyframe.TangentIn : keyframe.TangentOut; // inverse of reference tangent otherTangent.Translation = -referenceTangent.Translation.Normalized * otherTangent.Translation.Length; - if (isIn) keyframe.TangentOut = otherTangent; - if (!isIn) keyframe.TangentIn = otherTangent; + if (alignWithIn) keyframe.TangentOut = otherTangent; + if (!alignWithIn) keyframe.TangentIn = otherTangent; spline.SetSplineKeyframe(index, keyframe); } @@ -219,6 +229,10 @@ namespace FlaxEditor.CustomEditors.Dedicated public override void OnSelectTangent(Spline spline, int index) { } } + private readonly Color HighlightedColor = FlaxEngine.GUI.Style.Current.BackgroundSelected; + private readonly Color SelectedButtonColor = FlaxEngine.GUI.Style.Current.BackgroundSelected; + private readonly Color NormalButtonColor = FlaxEngine.GUI.Style.Current.BackgroundNormal; + private EditTangentOptionBase _currentTangentMode; private ButtonElement _freeTangentButton; @@ -226,43 +240,35 @@ namespace FlaxEditor.CustomEditors.Dedicated private ButtonElement _alignedTangentButton; private ButtonElement _smoothInTangentButton; private ButtonElement _smoothOutTangentButton; + private ButtonElement _setLinearAllTangentsButton; + private ButtonElement _setSmoothAllTangentsButton; private bool _tanInChanged; private bool _tanOutChanged; private Vector3 _lastTanInPos; private Vector3 _lastTanOutPos; + private Spline _selectedSpline; private SplineNode.SplinePointNode _selectedPoint; private SplineNode.SplinePointNode _lastPointSelected; private SplineNode.SplinePointTangentNode _selectedTangentIn; private SplineNode.SplinePointTangentNode _selectedTangentOut; - /// - /// Current selected spline on editor, if has - /// - public Spline SelectedSpline => !Values.HasDifferentValues && Values[0] is Spline ? (Spline)Values[0] : null; + private UndoData[] selectedSplinesUndoData; private bool HasPointSelected => _selectedPoint != null; private bool HasTangentsSelected => _selectedTangentIn != null || _selectedTangentOut != null; - private Color SelectedButtonColor => FlaxEngine.GUI.Style.Current.BackgroundSelected; - - private Color NormalButtonColor => FlaxEngine.GUI.Style.Current.BackgroundNormal; - - /// - /// Create a Spline editor - /// - public SplineEditor() - { - _currentTangentMode = new FreeTangentMode(); - } - /// public override void Initialize(LayoutElementsContainer layout) { base.Initialize(layout); + _currentTangentMode = new FreeTangentMode(); + if (Values.HasDifferentTypes == false) { + _selectedSpline = !Values.HasDifferentValues && Values[0] is Spline ? (Spline)Values[0] : null; + layout.Space(10); layout.Header("Selected spline point"); @@ -278,27 +284,65 @@ namespace FlaxEditor.CustomEditors.Dedicated _smoothInTangentButton = selectedPointsGrid.Button("Smooth In"); _smoothOutTangentButton = selectedPointsGrid.Button("Smooth Out"); + _linearTangentButton.Button.BackgroundColorHighlighted = HighlightedColor; + _freeTangentButton.Button.BackgroundColorHighlighted = HighlightedColor; + _alignedTangentButton.Button.BackgroundColorHighlighted = HighlightedColor; + _smoothInTangentButton.Button.BackgroundColorHighlighted = HighlightedColor; + _smoothOutTangentButton.Button.BackgroundColorHighlighted = HighlightedColor; + + _linearTangentButton.Button.Clicked += StartEditSpline; + _freeTangentButton.Button.Clicked += StartEditSpline; + _alignedTangentButton.Button.Clicked += StartEditSpline; + _smoothInTangentButton.Button.Clicked += StartEditSpline; + _smoothOutTangentButton.Button.Clicked += StartEditSpline; + _linearTangentButton.Button.Clicked += SetModeLinear; _freeTangentButton.Button.Clicked += SetModeFree; _alignedTangentButton.Button.Clicked += SetModeAligned; _smoothInTangentButton.Button.Clicked += SetModeSmoothIn; _smoothOutTangentButton.Button.Clicked += SetModeSmoothOut; - _linearTangentButton.Button.Clicked += UpdateButtonsColors; - _freeTangentButton.Button.Clicked += UpdateButtonsColors; - _alignedTangentButton.Button.Clicked += UpdateButtonsColors; - _smoothInTangentButton.Button.Clicked += UpdateButtonsColors; - _smoothOutTangentButton.Button.Clicked += UpdateButtonsColors; + _linearTangentButton.Button.Clicked += EndEditSpline; + _freeTangentButton.Button.Clicked += EndEditSpline; + _alignedTangentButton.Button.Clicked += EndEditSpline; + _smoothInTangentButton.Button.Clicked += EndEditSpline; + _smoothOutTangentButton.Button.Clicked += EndEditSpline; layout.Header("All spline points"); var grid = layout.CustomContainer(); grid.CustomControl.SlotsHorizontally = 2; grid.CustomControl.SlotsVertically = 1; - grid.Button("Set Linear Tangents").Button.Clicked += OnSetTangentsLinear; - grid.Button("Set Smooth Tangents").Button.Clicked += OnSetTangentsSmooth; + + _setLinearAllTangentsButton = grid.Button("Set Linear Tangents"); + _setSmoothAllTangentsButton = grid.Button("Set Smooth Tangents"); + _setLinearAllTangentsButton.Button.BackgroundColorHighlighted = HighlightedColor; + _setSmoothAllTangentsButton.Button.BackgroundColorHighlighted = HighlightedColor; + + _setLinearAllTangentsButton.Button.Clicked += StartEditSpline; + _setSmoothAllTangentsButton.Button.Clicked += StartEditSpline; + + _setLinearAllTangentsButton.Button.Clicked += OnSetTangentsLinear; + _setSmoothAllTangentsButton.Button.Clicked += OnSetTangentsSmooth; + + _setLinearAllTangentsButton.Button.Clicked += EndEditSpline; + _setSmoothAllTangentsButton.Button.Clicked += EndEditSpline; + + if (_selectedSpline) _selectedSpline.SplineUpdated += OnSplineEdited; } } + /// + protected override void Deinitialize() + { + if (_selectedSpline) _selectedSpline.SplineUpdated -= OnSplineEdited; + } + + private void OnSplineEdited() + { + SetSelectedTangentTypeAsCurrent(); + UpdateButtonsColors(); + } + /// public override void Refresh() { @@ -307,20 +351,22 @@ namespace FlaxEditor.CustomEditors.Dedicated UpdateSelectedPoint(); UpdateSelectedTangent(); + _linearTangentButton.Button.Enabled = CanEditTangent(); _freeTangentButton.Button.Enabled = CanSetTangentFree(); - _linearTangentButton.Button.Enabled = CanSetTangentMode(); _alignedTangentButton.Button.Enabled = CanSetTangentAligned(); _smoothInTangentButton.Button.Enabled = CanSetTangentSmoothIn(); _smoothOutTangentButton.Button.Enabled = CanSetTangentSmoothOut(); + _setLinearAllTangentsButton.Button.Enabled = CanEditTangent(); + _setSmoothAllTangentsButton.Button.Enabled = CanEditTangent(); - if (!CanSetTangentMode()) + if (!CanEditTangent()) { return; } var index = _lastPointSelected.Index; - var currentTangentInPosition = SelectedSpline.GetSplineLocalTangent(index, true).Translation; - var currentTangentOutPosition = SelectedSpline.GetSplineLocalTangent(index, false).Translation; + var currentTangentInPosition = _selectedSpline.GetSplineLocalTangent(index, true).Translation; + var currentTangentOutPosition = _selectedSpline.GetSplineLocalTangent(index, false).Translation; if (_selectedTangentIn != null) { @@ -334,76 +380,81 @@ namespace FlaxEditor.CustomEditors.Dedicated _lastTanOutPos = currentTangentOutPosition; } - if (_tanInChanged) _currentTangentMode.OnMoveTangentIn(SelectedSpline, index); - if (_tanOutChanged) _currentTangentMode.OnMoveTangentOut(SelectedSpline, index); + if (_tanInChanged) _currentTangentMode.OnMoveTangentIn(_selectedSpline, index); + if (_tanOutChanged) _currentTangentMode.OnMoveTangentOut(_selectedSpline, index); - currentTangentInPosition = SelectedSpline.GetSplineLocalTangent(index, true).Translation; - currentTangentOutPosition = SelectedSpline.GetSplineLocalTangent(index, false).Translation; + currentTangentInPosition = _selectedSpline.GetSplineLocalTangent(index, true).Translation; + currentTangentOutPosition = _selectedSpline.GetSplineLocalTangent(index, false).Translation; // update last tangents position after changes - if (SelectedSpline) _lastTanInPos = currentTangentInPosition; - if (SelectedSpline) _lastTanOutPos = currentTangentOutPosition; + if (_selectedSpline) _lastTanInPos = currentTangentInPosition; + if (_selectedSpline) _lastTanOutPos = currentTangentOutPosition; _tanInChanged = false; _tanOutChanged = false; } - private bool CanSetTangentMode() + private bool CanEditTangent() { return !HasDifferentTypes && !HasDifferentValues && (HasPointSelected || HasTangentsSelected); } private bool CanSetTangentSmoothIn() { - if (!CanSetTangentMode()) return false; + if (!CanEditTangent()) return false; return _lastPointSelected.Index != 0; } private bool CanSetTangentSmoothOut() { - if (!CanSetTangentMode()) return false; - return _lastPointSelected.Index < SelectedSpline.SplinePointsCount - 1; + if (!CanEditTangent()) return false; + return _lastPointSelected.Index < _selectedSpline.SplinePointsCount - 1; } private bool CanSetTangentFree() { - if (!CanSetTangentMode()) return false; - return _lastPointSelected.Index < SelectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; + if (!CanEditTangent()) return false; + return _lastPointSelected.Index < _selectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; } private bool CanSetTangentAligned() { - if (!CanSetTangentMode()) return false; - return _lastPointSelected.Index < SelectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; + if (!CanEditTangent()) return false; + return _lastPointSelected.Index < _selectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; } private void SetModeLinear() { + if (_currentTangentMode is LinearTangentMode) return; _currentTangentMode = new LinearTangentMode(); - _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + _currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index); } private void SetModeFree() { + if (_currentTangentMode is FreeTangentMode) return; _currentTangentMode = new FreeTangentMode(); - _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + _currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index); } private void SetModeAligned() { + if (_currentTangentMode is AlignedTangentMode) return; _currentTangentMode = new AlignedTangentMode(); - _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + _currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index); } private void SetModeSmoothIn() { + if (_currentTangentMode is SmoothInTangentMode) return; _currentTangentMode = new SmoothInTangentMode(); - _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + _currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index); } private void SetModeSmoothOut() { + if (_currentTangentMode is SmoothOutTangentMode) return; _currentTangentMode = new SmoothOutTangentMode(); - _currentTangentMode.OnSetMode(SelectedSpline, _lastPointSelected.Index); + _currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index); } private void UpdateSelectedPoint() @@ -429,7 +480,7 @@ namespace FlaxEditor.CustomEditors.Dedicated SetSelectedTangentTypeAsCurrent(); UpdateButtonsColors(); - _currentTangentMode.OnSelectKeyframe(SelectedSpline, index); + _currentTangentMode.OnSelectKeyframe(_selectedSpline, index); } else { @@ -462,20 +513,20 @@ namespace FlaxEditor.CustomEditors.Dedicated var index = _lastPointSelected.Index; - if (currentSelected.Transform == SelectedSpline.GetSplineTangent(index, true)) + if (currentSelected.Transform == _selectedSpline.GetSplineTangent(index, true)) { _selectedTangentIn = currentSelected as SplineNode.SplinePointTangentNode; _selectedTangentOut = null; - _currentTangentMode.OnSelectTangent(SelectedSpline, index); + _currentTangentMode.OnSelectTangent(_selectedSpline, index); return; } - if (currentSelected.Transform == SelectedSpline.GetSplineTangent(index, false)) + if (currentSelected.Transform == _selectedSpline.GetSplineTangent(index, false)) { _selectedTangentOut = currentSelected as SplineNode.SplinePointTangentNode; _selectedTangentIn = null; - _currentTangentMode.OnSelectTangent(SelectedSpline, index); + _currentTangentMode.OnSelectTangent(_selectedSpline, index); return; } @@ -485,7 +536,7 @@ namespace FlaxEditor.CustomEditors.Dedicated private void UpdateButtonsColors() { - if (!CanSetTangentMode()) + if (!CanEditTangent()) { _linearTangentButton.Button.BackgroundColor = NormalButtonColor; _freeTangentButton.Button.BackgroundColor = NormalButtonColor; @@ -510,51 +561,67 @@ namespace FlaxEditor.CustomEditors.Dedicated private void SetSelectedTangentTypeAsCurrent() { - var isFree = IsFreeTangentMode(SelectedSpline, _lastPointSelected.Index); - var isLinear = IsLinearTangentMode(SelectedSpline, _lastPointSelected.Index); - var isAligned = IsAlignedTangentMode(SelectedSpline, _lastPointSelected.Index); - var isSmoothIn = IsSmoothInTangentMode(SelectedSpline, _lastPointSelected.Index); - var isSmoothOut = IsSmoothOutTangentMode(SelectedSpline, _lastPointSelected.Index); + if (_lastPointSelected == null || _selectedPoint == null) return; + if (IsLinearTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeLinear(); + else if (IsAlignedTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeAligned(); + else if (IsSmoothInTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeSmoothIn(); + else if (IsSmoothOutTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeSmoothOut(); + else if (IsFreeTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeFree(); + } - if (isFree) SetModeFree(); - else if (isLinear) SetModeLinear(); - else if (isAligned) SetModeAligned(); - else if (isSmoothIn) SetModeSmoothIn(); - else if (isSmoothOut) SetModeSmoothOut(); + private void StartEditSpline() + { + var enableUndo = Presenter.Undo != null && Presenter.Undo.Enabled; + + if (!enableUndo) + { + return; + } + + var splines = new List(); + + for (int i = 0; i < Values.Count; i++) + { + if (Values[i] is Spline spline) + { + splines.Add(new UndoData { + spline = spline, + beforeKeyframes = spline.SplineKeyframes.Clone() as BezierCurve.Keyframe[] + }); + } + } + + selectedSplinesUndoData = splines.ToArray(); + } + + private void EndEditSpline() + { + var enableUndo = Presenter.Undo != null && Presenter.Undo.Enabled; + + if (!enableUndo) + { + return; + } + + for (int i = 0; i < selectedSplinesUndoData.Length; i++) + { + var splineUndoData = selectedSplinesUndoData[i]; + Presenter.Undo.AddAction(new EditSplineAction(_selectedSpline, splineUndoData.beforeKeyframes)); + SplineNode.OnSplineEdited(splineUndoData.spline); + Editor.Instance.Scene.MarkSceneEdited(splineUndoData.spline.Scene); + } } private void OnSetTangentsLinear() { - var enableUndo = Presenter.Undo != null && Presenter.Undo.Enabled; - for (int i = 0; i < Values.Count; i++) - { - if (Values[i] is Spline spline) - { - var before = enableUndo ? (BezierCurve.Keyframe[])spline.SplineKeyframes.Clone() : null; - spline.SetTangentsLinear(); - if (enableUndo) - Presenter.Undo.AddAction(new EditSplineAction(spline, before)); - SplineNode.OnSplineEdited(spline); - Editor.Instance.Scene.MarkSceneEdited(spline.Scene); - } - } + _selectedSpline.SetTangentsLinear(); + _selectedSpline.UpdateSpline(); } private void OnSetTangentsSmooth() { - var enableUndo = Presenter.Undo != null && Presenter.Undo.Enabled; - for (int i = 0; i < Values.Count; i++) - { - if (Values[i] is Spline spline) - { - var before = enableUndo ? (BezierCurve.Keyframe[])spline.SplineKeyframes.Clone() : null; - spline.SetTangentsSmooth(); - if (enableUndo) - Presenter.Undo.AddAction(new EditSplineAction(spline, before)); - SplineNode.OnSplineEdited(spline); - Editor.Instance.Scene.MarkSceneEdited(spline.Scene); - } - } + _selectedSpline.SetTangentsSmooth(); + _selectedSpline.UpdateSpline(); } private static bool IsFreeTangentMode(Spline spline, int index) @@ -625,6 +692,7 @@ namespace FlaxEditor.CustomEditors.Dedicated } spline.SetSplineKeyframe(index, keyframe); + spline.UpdateSpline(); } private static void SetTangentSmoothIn(Spline spline, int index) @@ -642,6 +710,7 @@ namespace FlaxEditor.CustomEditors.Dedicated keyframe.TangentOut.Translation = Vector3.Zero; spline.SetSplineKeyframe(index, keyframe); + spline.UpdateSpline(); } private static void SetTangentSmoothOut(Spline spline, int index) @@ -660,15 +729,14 @@ namespace FlaxEditor.CustomEditors.Dedicated keyframe.TangentIn.Translation = Vector3.Zero; spline.SetSplineKeyframe(index, keyframe); + spline.UpdateSpline(); } private static void SetPointSmooth(Spline spline, int index) { var keyframe = spline.GetSplineKeyframe(index); - var tangentIn = keyframe.TangentIn; - var tangentOut = keyframe.TangentOut; - var tangentInSize = tangentIn.Translation.Length; - var tangentOutSize = tangentOut.Translation.Length; + var tangentInSize = keyframe.TangentIn.Translation.Length; + var tangentOutSize = keyframe.TangentOut.Translation.Length; var isLastKeyframe = index >= spline.SplinePointsCount - 1; var isFirstKeyframe = index <= 0; @@ -686,6 +754,7 @@ namespace FlaxEditor.CustomEditors.Dedicated keyframe.TangentIn.Translation = -slop * tangentInSize; keyframe.TangentOut.Translation = slop * tangentOutSize; spline.SetSplineKeyframe(index, keyframe); + spline.UpdateSpline(); } private static SplineNode.SplinePointNode GetSplinePointNode(Spline spline, int index) From 56285e544e4996265b254e7c4c9effc448bb324b Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 24 Jul 2023 08:54:53 -0400 Subject: [PATCH 23/35] disable set all linear / smooth when select many splines --- .../Editor/CustomEditors/Dedicated/SplineEditor.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 4e0234974..8d2644378 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -356,8 +356,8 @@ namespace FlaxEditor.CustomEditors.Dedicated _alignedTangentButton.Button.Enabled = CanSetTangentAligned(); _smoothInTangentButton.Button.Enabled = CanSetTangentSmoothIn(); _smoothOutTangentButton.Button.Enabled = CanSetTangentSmoothOut(); - _setLinearAllTangentsButton.Button.Enabled = CanEditTangent(); - _setSmoothAllTangentsButton.Button.Enabled = CanEditTangent(); + _setLinearAllTangentsButton.Button.Enabled = CanSetAllTangentsLinear(); + _setSmoothAllTangentsButton.Button.Enabled = CanSetAllTangentsSmooth(); if (!CanEditTangent()) { @@ -422,6 +422,16 @@ namespace FlaxEditor.CustomEditors.Dedicated return _lastPointSelected.Index < _selectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; } + private bool CanSetAllTangentsSmooth() + { + return _selectedSpline != null; + } + + private bool CanSetAllTangentsLinear() + { + return _selectedSpline != null; + } + private void SetModeLinear() { if (_currentTangentMode is LinearTangentMode) return; From 7b0e9b9e06a2fd03e7a85db61c91de24b4fd8b1e Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:30:31 -0400 Subject: [PATCH 24/35] simplify code --- .../CustomEditors/Dedicated/SplineEditor.cs | 115 ++++++++++-------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 8d2644378..2f9eaf0d0 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -328,6 +328,10 @@ namespace FlaxEditor.CustomEditors.Dedicated _setSmoothAllTangentsButton.Button.Clicked += EndEditSpline; if (_selectedSpline) _selectedSpline.SplineUpdated += OnSplineEdited; + + SetSelectedTangentTypeAsCurrent(); + SetEditButtonsColor(); + SetEditButtonsEnabled(); } } @@ -340,7 +344,8 @@ namespace FlaxEditor.CustomEditors.Dedicated private void OnSplineEdited() { SetSelectedTangentTypeAsCurrent(); - UpdateButtonsColors(); + SetEditButtonsColor(); + SetEditButtonsEnabled(); } /// @@ -351,14 +356,6 @@ namespace FlaxEditor.CustomEditors.Dedicated UpdateSelectedPoint(); UpdateSelectedTangent(); - _linearTangentButton.Button.Enabled = CanEditTangent(); - _freeTangentButton.Button.Enabled = CanSetTangentFree(); - _alignedTangentButton.Button.Enabled = CanSetTangentAligned(); - _smoothInTangentButton.Button.Enabled = CanSetTangentSmoothIn(); - _smoothOutTangentButton.Button.Enabled = CanSetTangentSmoothOut(); - _setLinearAllTangentsButton.Button.Enabled = CanSetAllTangentsLinear(); - _setSmoothAllTangentsButton.Button.Enabled = CanSetAllTangentsSmooth(); - if (!CanEditTangent()) { return; @@ -393,6 +390,52 @@ namespace FlaxEditor.CustomEditors.Dedicated _tanOutChanged = false; } + private void SetSelectedTangentTypeAsCurrent() + { + if (_lastPointSelected == null || _selectedPoint == null) return; + if (IsLinearTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeLinear(); + else if (IsAlignedTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeAligned(); + else if (IsSmoothInTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeSmoothIn(); + else if (IsSmoothOutTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeSmoothOut(); + else if (IsFreeTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeFree(); + } + + private void SetEditButtonsColor() + { + if (!CanEditTangent()) + { + _linearTangentButton.Button.BackgroundColor = NormalButtonColor; + _freeTangentButton.Button.BackgroundColor = NormalButtonColor; + _alignedTangentButton.Button.BackgroundColor = NormalButtonColor; + _smoothInTangentButton.Button.BackgroundColor = NormalButtonColor; + _smoothOutTangentButton.Button.BackgroundColor = NormalButtonColor; + return; + } + + var isFree = _currentTangentMode is FreeTangentMode; + var isLinear = _currentTangentMode is LinearTangentMode; + var isAligned = _currentTangentMode is AlignedTangentMode; + var isSmoothIn = _currentTangentMode is SmoothInTangentMode; + var isSmoothOut = _currentTangentMode is SmoothOutTangentMode; + + _linearTangentButton.Button.BackgroundColor = isLinear ? SelectedButtonColor : NormalButtonColor; + _freeTangentButton.Button.BackgroundColor = isFree ? SelectedButtonColor : NormalButtonColor; + _alignedTangentButton.Button.BackgroundColor = isAligned ? SelectedButtonColor : NormalButtonColor; + _smoothInTangentButton.Button.BackgroundColor = isSmoothIn ? SelectedButtonColor : NormalButtonColor; + _smoothOutTangentButton.Button.BackgroundColor = isSmoothOut ? SelectedButtonColor : NormalButtonColor; + } + + private void SetEditButtonsEnabled() + { + _linearTangentButton.Button.Enabled = CanEditTangent(); + _freeTangentButton.Button.Enabled = CanSetTangentFree(); + _alignedTangentButton.Button.Enabled = CanSetTangentAligned(); + _smoothInTangentButton.Button.Enabled = CanSetTangentSmoothIn(); + _smoothOutTangentButton.Button.Enabled = CanSetTangentSmoothOut(); + _setLinearAllTangentsButton.Button.Enabled = CanSetAllTangentsLinear(); + _setSmoothAllTangentsButton.Button.Enabled = CanSetAllTangentsSmooth(); + } + private bool CanEditTangent() { return !HasDifferentTypes && !HasDifferentValues && (HasPointSelected || HasTangentsSelected); @@ -470,10 +513,12 @@ namespace FlaxEditor.CustomEditors.Dedicated private void UpdateSelectedPoint() { // works only if select one spline - if (Editor.Instance.SceneEditing.SelectionCount != 1) + if (!_selectedSpline) { _selectedPoint = null; - UpdateButtonsColors(); + SetSelectedTangentTypeAsCurrent(); + SetEditButtonsColor(); + SetEditButtonsEnabled(); return; } @@ -484,19 +529,16 @@ namespace FlaxEditor.CustomEditors.Dedicated { _selectedPoint = currentSelected as SplineNode.SplinePointNode; _lastPointSelected = _selectedPoint; - - var index = _lastPointSelected.Index; - - SetSelectedTangentTypeAsCurrent(); - UpdateButtonsColors(); - - _currentTangentMode.OnSelectKeyframe(_selectedSpline, index); + _currentTangentMode.OnSelectKeyframe(_selectedSpline, _lastPointSelected.Index); } else { _selectedPoint = null; - UpdateButtonsColors(); } + + SetSelectedTangentTypeAsCurrent(); + SetEditButtonsColor(); + SetEditButtonsEnabled(); } private void UpdateSelectedTangent() @@ -544,41 +586,6 @@ namespace FlaxEditor.CustomEditors.Dedicated _selectedTangentOut = null; } - private void UpdateButtonsColors() - { - if (!CanEditTangent()) - { - _linearTangentButton.Button.BackgroundColor = NormalButtonColor; - _freeTangentButton.Button.BackgroundColor = NormalButtonColor; - _alignedTangentButton.Button.BackgroundColor = NormalButtonColor; - _smoothInTangentButton.Button.BackgroundColor = NormalButtonColor; - _smoothOutTangentButton.Button.BackgroundColor = NormalButtonColor; - return; - } - - var isFree = _currentTangentMode is FreeTangentMode; - var isLinear = _currentTangentMode is LinearTangentMode; - var isAligned = _currentTangentMode is AlignedTangentMode; - var isSmoothIn = _currentTangentMode is SmoothInTangentMode; - var isSmoothOut = _currentTangentMode is SmoothOutTangentMode; - - _linearTangentButton.Button.BackgroundColor = isLinear ? SelectedButtonColor : NormalButtonColor; - _freeTangentButton.Button.BackgroundColor = isFree ? SelectedButtonColor : NormalButtonColor; - _alignedTangentButton.Button.BackgroundColor = isAligned ? SelectedButtonColor : NormalButtonColor; - _smoothInTangentButton.Button.BackgroundColor = isSmoothIn ? SelectedButtonColor : NormalButtonColor; - _smoothOutTangentButton.Button.BackgroundColor = isSmoothOut ? SelectedButtonColor : NormalButtonColor; - } - - private void SetSelectedTangentTypeAsCurrent() - { - if (_lastPointSelected == null || _selectedPoint == null) return; - if (IsLinearTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeLinear(); - else if (IsAlignedTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeAligned(); - else if (IsSmoothInTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeSmoothIn(); - else if (IsSmoothOutTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeSmoothOut(); - else if (IsFreeTangentMode(_selectedSpline, _lastPointSelected.Index)) SetModeFree(); - } - private void StartEditSpline() { var enableUndo = Presenter.Undo != null && Presenter.Undo.Enabled; From ea48a89e005e888fddaa3479a55719545bf93750 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:34:48 -0400 Subject: [PATCH 25/35] improve auto smooth --- .../CustomEditors/Dedicated/SplineEditor.cs | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 2f9eaf0d0..a844cdf05 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -75,7 +75,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// public override void OnSetMode(Spline spline, int index) { - if (IsLinearTangentMode(spline, index)) + if (IsLinearTangentMode(spline, index) || IsSmoothInTangentMode(spline, index) || IsSmoothOutTangentMode(spline, index)) { SetPointSmooth(spline, index); } @@ -428,8 +428,8 @@ namespace FlaxEditor.CustomEditors.Dedicated private void SetEditButtonsEnabled() { _linearTangentButton.Button.Enabled = CanEditTangent(); - _freeTangentButton.Button.Enabled = CanSetTangentFree(); - _alignedTangentButton.Button.Enabled = CanSetTangentAligned(); + _freeTangentButton.Button.Enabled = CanEditTangent(); + _alignedTangentButton.Button.Enabled = CanEditTangent(); _smoothInTangentButton.Button.Enabled = CanSetTangentSmoothIn(); _smoothOutTangentButton.Button.Enabled = CanSetTangentSmoothOut(); _setLinearAllTangentsButton.Button.Enabled = CanSetAllTangentsLinear(); @@ -453,18 +453,6 @@ namespace FlaxEditor.CustomEditors.Dedicated return _lastPointSelected.Index < _selectedSpline.SplinePointsCount - 1; } - private bool CanSetTangentFree() - { - if (!CanEditTangent()) return false; - return _lastPointSelected.Index < _selectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; - } - - private bool CanSetTangentAligned() - { - if (!CanEditTangent()) return false; - return _lastPointSelected.Index < _selectedSpline.SplinePointsCount - 1 && _lastPointSelected.Index != 0; - } - private bool CanSetAllTangentsSmooth() { return _selectedSpline != null; @@ -759,17 +747,23 @@ namespace FlaxEditor.CustomEditors.Dedicated var isFirstKeyframe = index <= 0; // force smooth it's linear point - if (tangentInSize == 0f && !isFirstKeyframe) tangentInSize = 100; - if (tangentOutSize == 0f && !isLastKeyframe) tangentOutSize = 100; + if (tangentInSize == 0f) tangentInSize = 100; + if (tangentOutSize == 0f) tangentOutSize = 100; + // try get next / last keyframe var nextKeyframe = !isLastKeyframe ? spline.GetSplineKeyframe(index + 1) : keyframe; var previousKeyframe = !isFirstKeyframe ? spline.GetSplineKeyframe(index - 1) : keyframe; // calc form from Spline.cpp -> SetTangentsSmooth - var slop = (keyframe.Value.Translation - previousKeyframe.Value.Translation + nextKeyframe.Value.Translation - keyframe.Value.Translation).Normalized; + // get tangent direction + var tangentDirection = (keyframe.Value.Translation - previousKeyframe.Value.Translation + nextKeyframe.Value.Translation - keyframe.Value.Translation).Normalized; + + keyframe.TangentIn.Translation = -tangentDirection; + keyframe.TangentOut.Translation = tangentDirection; + + keyframe.TangentIn.Translation *= tangentInSize; + keyframe.TangentOut.Translation *= tangentOutSize; - keyframe.TangentIn.Translation = -slop * tangentInSize; - keyframe.TangentOut.Translation = slop * tangentOutSize; spline.SetSplineKeyframe(index, keyframe); spline.UpdateSpline(); } From 714d0c2ca00f30b62256cd673f6ac7198db44d40 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:41:45 -0400 Subject: [PATCH 26/35] small fix --- Source/Editor/CustomEditors/Dedicated/SplineEditor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index a844cdf05..8aa7b421a 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -343,7 +343,6 @@ namespace FlaxEditor.CustomEditors.Dedicated private void OnSplineEdited() { - SetSelectedTangentTypeAsCurrent(); SetEditButtonsColor(); SetEditButtonsEnabled(); } From b5eadbc5314699c651a3fdb5e66b9f4c6e93ef79 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 31 Jul 2023 09:06:39 -0400 Subject: [PATCH 27/35] test --- Source/Editor/SceneGraph/Actors/SplineNode.cs | 172 ++++++++++++++---- 1 file changed, 138 insertions(+), 34 deletions(-) diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index 3ba1d14c3..940b51757 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -12,6 +12,8 @@ using FlaxEditor.Modules; using FlaxEngine; using FlaxEngine.Json; using Object = FlaxEngine.Object; +using System.Collections.Generic; +using System.Security.Cryptography; namespace FlaxEditor.SceneGraph.Actors { @@ -21,16 +23,27 @@ namespace FlaxEditor.SceneGraph.Actors [HideInEditor] public sealed class SplineNode : ActorNode { - public sealed class SplinePointNode : ActorChildNode + public unsafe sealed class SplinePointNode : ActorChildNode { + private Guid* splineNodeId; + + private Spline _spline; + private SplineNode _splineNode; + private SplinePointTangentNode _tangentInNode; + private SplinePointTangentNode _tangentOutNode; + public unsafe SplinePointNode(SplineNode node, Guid id, int index) : base(node, id, index) { - var g = (JsonSerializer.GuidInterop*)&id; - g->D++; - AddChild(new SplinePointTangentNode(node, id, index, true)); - g->D++; - AddChild(new SplinePointTangentNode(node, id, index, false)); + splineNodeId = &id; + _splineNode = node; + _spline = (Spline)_splineNode.Actor; + _spline.SplineUpdated += AddTangentIn; + _spline.SplineUpdated += AddTangentOut; + + + void AddTangentIn() => AddTangentNode(true, splineNodeId); + void AddTangentOut() => AddTangentNode(false, splineNodeId); } public override bool CanBeSelectedDirectly => true; @@ -89,6 +102,54 @@ namespace FlaxEditor.SceneGraph.Actors actor.RemoveSplinePoint(Index); } + public override void OnDispose() + { + base.OnDispose(); + } + + private unsafe void AddTangentNode(bool isIn, Guid* id) + { + if (_tangentInNode != null && _tangentOutNode != null) + { + return; + } + + var g = (JsonSerializer.GuidInterop*)&id; + + if (isIn && _tangentInNode == null) + { + g->D++; + _tangentInNode = new SplinePointTangentNode(_splineNode, *id, Index, true); + AddChild(_tangentInNode); + } + + if (!isIn && _tangentOutNode == null) + { + + g->D++; + _tangentOutNode = new SplinePointTangentNode(_splineNode, *id, Index, false); + AddChild(_tangentOutNode); + } + } + + //private unsafe void RemoveTangentNodes() + //{ + // var id = _splineNode.ID; + // var g = (JsonSerializer.GuidInterop*)&id; + + // if (_tangentInNode != null) + // { + // _tangentInNode.Delete(); + // g->D--; + // } + + // if (_tangentOutNode != null) + // { + // g->D--; + // _tangentOutNode.Delete(); + // } + //} + class DuplicateUndoAction : IUndoAction, ISceneEditAction { public Guid SplineId; @@ -225,12 +286,15 @@ namespace FlaxEditor.SceneGraph.Actors private int _index; private bool _isIn; + + public SplinePointTangentNode(SplineNode node, Guid id, int index, bool isIn) : base(id, isIn ? 0 : 1) { _node = node; _index = index; _isIn = isIn; + } public override Transform Transform @@ -279,44 +343,84 @@ namespace FlaxEditor.SceneGraph.Actors } } + private List _pointNodes; + /// public SplineNode(Actor actor) : base(actor) { - OnUpdate(); + _pointNodes = new List(); FlaxEngine.Scripting.Update += OnUpdate; + + + var spline = (Spline)Actor; + spline.SplineUpdated += UpdateNodesCount; + + UpdateNodesCount(); + } + + private unsafe void UpdateNodesCount() + { + var spline = (Spline)Actor; + var id = ID; + var g = (JsonSerializer.GuidInterop*)&id; + var splinePointsCount = spline.SplinePointsCount; + var splineNodePointsCount = _pointNodes.Count; + g->D += (uint)splineNodePointsCount; + while (splineNodePointsCount < splinePointsCount) + { + g->D++; + var newPoint = new SplinePointNode(this, id, splineNodePointsCount); + AddChildNode(newPoint); + _pointNodes.Add(newPoint); + splineNodePointsCount++; + } + + while (splineNodePointsCount > splinePointsCount) + { + splineNodePointsCount--; + var lastPoint = _pointNodes[splineNodePointsCount]; + _pointNodes.Remove(lastPoint); + lastPoint.Dispose(); + } } private unsafe void OnUpdate() { - // Sync spline points with gizmo handles - var actor = (Spline)Actor; - var dstCount = actor.SplinePointsCount; - if (dstCount > 1 && actor.IsLoop) - dstCount--; // The last point is the same as the first one for loop mode - var srcCount = ActorChildNodes?.Count ?? 0; - if (dstCount != srcCount) - { - // Remove unused points - while (srcCount > dstCount) - { - var node = ActorChildNodes[srcCount-- - 1]; - // TODO: support selection interface inside SceneGraph nodes (eg. on Root) so prefab editor can handle this too - if (Editor.Instance.SceneEditing.Selection.Contains(node)) - Editor.Instance.SceneEditing.Deselect(); - node.Dispose(); - } + //for (int i = 0; i < splineNodePointsCount; i++) + //{ + // _pointNodes[i].Transform = new Transform(spline.GetSplinePoint(i)); + //} + + // Sync spline points with gizmo handles + //var actor = (Spline)Actor; + //var dstCount = actor.SplinePointsCount; + //if (dstCount > 1 && actor.IsLoop) + // dstCount--; // The last point is the same as the first one for loop mode + //var srcCount = ActorChildNodes?.Count ?? 0; + //if (dstCount != srcCount) + //{ + // // Remove unused points + // while (srcCount > dstCount) + // { + // var node = ActorChildNodes[srcCount-- - 1]; + // // TODO: support selection interface inside SceneGraph nodes (eg. on Root) so prefab editor can handle this too + // if (Editor.Instance.SceneEditing.Selection.Contains(node)) + // Editor.Instance.SceneEditing.Deselect(); + // node.Dispose(); + // } + + // // Add new points + // var id = ID; + // var g = (JsonSerializer.GuidInterop*)&id; + // g->D += (uint)srcCount * 3; + // while (srcCount < dstCount) + // { + // g->D += 3; + // AddChildNode(new SplinePointNode(this, id, srcCount++)); + // } + //} - // Add new points - var id = ID; - var g = (JsonSerializer.GuidInterop*)&id; - g->D += (uint)srcCount * 3; - while (srcCount < dstCount) - { - g->D += 3; - AddChildNode(new SplinePointNode(this, id, srcCount++)); - } - } } /// From 84bed5b1c9a87137f3873eef9fc2153c362e7251 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:02:03 -0400 Subject: [PATCH 28/35] Revert "test" This reverts commit b5eadbc5314699c651a3fdb5e66b9f4c6e93ef79. --- Source/Editor/SceneGraph/Actors/SplineNode.cs | 170 ++++-------------- 1 file changed, 33 insertions(+), 137 deletions(-) diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index 940b51757..3ba1d14c3 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -12,8 +12,6 @@ using FlaxEditor.Modules; using FlaxEngine; using FlaxEngine.Json; using Object = FlaxEngine.Object; -using System.Collections.Generic; -using System.Security.Cryptography; namespace FlaxEditor.SceneGraph.Actors { @@ -23,27 +21,16 @@ namespace FlaxEditor.SceneGraph.Actors [HideInEditor] public sealed class SplineNode : ActorNode { - public unsafe sealed class SplinePointNode : ActorChildNode + public sealed class SplinePointNode : ActorChildNode { - private Guid* splineNodeId; - - private Spline _spline; - private SplineNode _splineNode; - private SplinePointTangentNode _tangentInNode; - private SplinePointTangentNode _tangentOutNode; - public unsafe SplinePointNode(SplineNode node, Guid id, int index) : base(node, id, index) { - splineNodeId = &id; - _splineNode = node; - _spline = (Spline)_splineNode.Actor; - _spline.SplineUpdated += AddTangentIn; - _spline.SplineUpdated += AddTangentOut; - - - void AddTangentIn() => AddTangentNode(true, splineNodeId); - void AddTangentOut() => AddTangentNode(false, splineNodeId); + var g = (JsonSerializer.GuidInterop*)&id; + g->D++; + AddChild(new SplinePointTangentNode(node, id, index, true)); + g->D++; + AddChild(new SplinePointTangentNode(node, id, index, false)); } public override bool CanBeSelectedDirectly => true; @@ -102,54 +89,6 @@ namespace FlaxEditor.SceneGraph.Actors actor.RemoveSplinePoint(Index); } - public override void OnDispose() - { - base.OnDispose(); - } - - private unsafe void AddTangentNode(bool isIn, Guid* id) - { - if (_tangentInNode != null && _tangentOutNode != null) - { - return; - } - - var g = (JsonSerializer.GuidInterop*)&id; - - if (isIn && _tangentInNode == null) - { - g->D++; - _tangentInNode = new SplinePointTangentNode(_splineNode, *id, Index, true); - AddChild(_tangentInNode); - } - - if (!isIn && _tangentOutNode == null) - { - - g->D++; - _tangentOutNode = new SplinePointTangentNode(_splineNode, *id, Index, false); - AddChild(_tangentOutNode); - } - } - - //private unsafe void RemoveTangentNodes() - //{ - // var id = _splineNode.ID; - // var g = (JsonSerializer.GuidInterop*)&id; - - // if (_tangentInNode != null) - // { - // _tangentInNode.Delete(); - // g->D--; - // } - - // if (_tangentOutNode != null) - // { - // g->D--; - // _tangentOutNode.Delete(); - // } - //} - class DuplicateUndoAction : IUndoAction, ISceneEditAction { public Guid SplineId; @@ -286,15 +225,12 @@ namespace FlaxEditor.SceneGraph.Actors private int _index; private bool _isIn; - - public SplinePointTangentNode(SplineNode node, Guid id, int index, bool isIn) : base(id, isIn ? 0 : 1) { _node = node; _index = index; _isIn = isIn; - } public override Transform Transform @@ -343,84 +279,44 @@ namespace FlaxEditor.SceneGraph.Actors } } - private List _pointNodes; - /// public SplineNode(Actor actor) : base(actor) { - _pointNodes = new List(); + OnUpdate(); FlaxEngine.Scripting.Update += OnUpdate; - - - var spline = (Spline)Actor; - spline.SplineUpdated += UpdateNodesCount; - - UpdateNodesCount(); - } - - private unsafe void UpdateNodesCount() - { - var spline = (Spline)Actor; - var id = ID; - var g = (JsonSerializer.GuidInterop*)&id; - var splinePointsCount = spline.SplinePointsCount; - var splineNodePointsCount = _pointNodes.Count; - g->D += (uint)splineNodePointsCount; - while (splineNodePointsCount < splinePointsCount) - { - g->D++; - var newPoint = new SplinePointNode(this, id, splineNodePointsCount); - AddChildNode(newPoint); - _pointNodes.Add(newPoint); - splineNodePointsCount++; - } - - while (splineNodePointsCount > splinePointsCount) - { - splineNodePointsCount--; - var lastPoint = _pointNodes[splineNodePointsCount]; - _pointNodes.Remove(lastPoint); - lastPoint.Dispose(); - } } private unsafe void OnUpdate() { - //for (int i = 0; i < splineNodePointsCount; i++) - //{ - // _pointNodes[i].Transform = new Transform(spline.GetSplinePoint(i)); - //} - // Sync spline points with gizmo handles - //var actor = (Spline)Actor; - //var dstCount = actor.SplinePointsCount; - //if (dstCount > 1 && actor.IsLoop) - // dstCount--; // The last point is the same as the first one for loop mode - //var srcCount = ActorChildNodes?.Count ?? 0; - //if (dstCount != srcCount) - //{ - // // Remove unused points - // while (srcCount > dstCount) - // { - // var node = ActorChildNodes[srcCount-- - 1]; - // // TODO: support selection interface inside SceneGraph nodes (eg. on Root) so prefab editor can handle this too - // if (Editor.Instance.SceneEditing.Selection.Contains(node)) - // Editor.Instance.SceneEditing.Deselect(); - // node.Dispose(); - // } - - // // Add new points - // var id = ID; - // var g = (JsonSerializer.GuidInterop*)&id; - // g->D += (uint)srcCount * 3; - // while (srcCount < dstCount) - // { - // g->D += 3; - // AddChildNode(new SplinePointNode(this, id, srcCount++)); - // } - //} + var actor = (Spline)Actor; + var dstCount = actor.SplinePointsCount; + if (dstCount > 1 && actor.IsLoop) + dstCount--; // The last point is the same as the first one for loop mode + var srcCount = ActorChildNodes?.Count ?? 0; + if (dstCount != srcCount) + { + // Remove unused points + while (srcCount > dstCount) + { + var node = ActorChildNodes[srcCount-- - 1]; + // TODO: support selection interface inside SceneGraph nodes (eg. on Root) so prefab editor can handle this too + if (Editor.Instance.SceneEditing.Selection.Contains(node)) + Editor.Instance.SceneEditing.Deselect(); + node.Dispose(); + } + // Add new points + var id = ID; + var g = (JsonSerializer.GuidInterop*)&id; + g->D += (uint)srcCount * 3; + while (srcCount < dstCount) + { + g->D += 3; + AddChildNode(new SplinePointNode(this, id, srcCount++)); + } + } } /// From b80682c97e42f94a4f9080f63f80bd7df8a5fa3d Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 31 Jul 2023 19:21:26 -0400 Subject: [PATCH 29/35] set spline points / tangents size by camera distance --- Source/Editor/SceneGraph/Actors/SplineNode.cs | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index 3ba1d14c3..75b86950c 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -12,6 +12,7 @@ using FlaxEditor.Modules; using FlaxEngine; using FlaxEngine.Json; using Object = FlaxEngine.Object; +using FlaxEditor.Viewport.Cameras; namespace FlaxEditor.SceneGraph.Actors { @@ -167,10 +168,11 @@ namespace FlaxEditor.SceneGraph.Actors public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal) { + normal = -ray.Ray.Direction; var actor = (Spline)_node.Actor; var pos = actor.GetSplinePoint(Index); - normal = -ray.Ray.Direction; - return new BoundingSphere(pos, 7.0f).Intersects(ref ray.Ray, out distance); + var nodeSize = NodeSizeByDistance(Transform.Translation, PointNodeSize); + return new BoundingSphere(pos, nodeSize).Intersects(ref ray.Ray, out distance); } public override void OnDebugDraw(ViewportDebugDrawData data) @@ -179,23 +181,26 @@ namespace FlaxEditor.SceneGraph.Actors var pos = actor.GetSplinePoint(Index); var tangentIn = actor.GetSplineTangent(Index, true).Translation; var tangentOut = actor.GetSplineTangent(Index, false).Translation; + var pointSize = NodeSizeByDistance(pos, PointNodeSize); + var tangentInSize = NodeSizeByDistance(tangentIn, TangentNodeSize); + var tangentOutSize = NodeSizeByDistance(tangentOut, TangentNodeSize); // Draw spline path ParentNode.OnDebugDraw(data); // Draw selected point highlight - DebugDraw.DrawSphere(new BoundingSphere(pos, 5.0f), Color.Yellow, 0, false); + DebugDraw.DrawSphere(new BoundingSphere(pos, pointSize), Color.Yellow, 0, false); // Draw tangent points if (tangentIn != pos) { DebugDraw.DrawLine(pos, tangentIn, Color.Blue.AlphaMultiplied(0.6f), 0, false); - DebugDraw.DrawWireSphere(new BoundingSphere(tangentIn, 4.0f), Color.Blue, 0, false); + DebugDraw.DrawWireSphere(new BoundingSphere(tangentIn, tangentInSize), Color.Blue, 0, false); } if (tangentOut != pos) { DebugDraw.DrawLine(pos, tangentOut, Color.Red.AlphaMultiplied(0.6f), 0, false); - DebugDraw.DrawWireSphere(new BoundingSphere(tangentOut, 4.0f), Color.Red, 0, false); + DebugDraw.DrawWireSphere(new BoundingSphere(tangentOut, tangentOutSize), Color.Red, 0, false); } } @@ -249,10 +254,11 @@ namespace FlaxEditor.SceneGraph.Actors public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal) { + normal = -ray.Ray.Direction; var actor = (Spline)_node.Actor; var pos = actor.GetSplineTangent(_index, _isIn).Translation; - normal = -ray.Ray.Direction; - return new BoundingSphere(pos, 7.0f).Intersects(ref ray.Ray, out distance); + var tangentSize = NodeSizeByDistance(Transform.Translation, TangentNodeSize); + return new BoundingSphere(pos, tangentSize).Intersects(ref ray.Ray, out distance); } public override void OnDebugDraw(ViewportDebugDrawData data) @@ -263,7 +269,8 @@ namespace FlaxEditor.SceneGraph.Actors // Draw selected tangent highlight var actor = (Spline)_node.Actor; var pos = actor.GetSplineTangent(_index, _isIn).Translation; - DebugDraw.DrawSphere(new BoundingSphere(pos, 5.0f), Color.YellowGreen, 0, false); + var tangentSize = NodeSizeByDistance(Transform.Translation, TangentNodeSize); + DebugDraw.DrawSphere(new BoundingSphere(pos, tangentSize), Color.YellowGreen, 0, false); } public override void OnContextMenu(ContextMenu contextMenu) @@ -279,6 +286,9 @@ namespace FlaxEditor.SceneGraph.Actors } } + private const float PointNodeSize = 2; + private const float TangentNodeSize = 1.6f; + /// public SplineNode(Actor actor) : base(actor) @@ -398,6 +408,14 @@ namespace FlaxEditor.SceneGraph.Actors } } + private static float NodeSizeByDistance(Vector3 nodePosition, float nodeSize) + { + var cameraTransform = Editor.Instance.Windows.EditWin.Viewport.ViewportCamera.Viewport.ViewTransform; + var distance = Vector3.Distance(cameraTransform.Translation, nodePosition) / 100; + return distance * nodeSize; + } + + /// public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal) { From 2b7b80ad38906ac277dd6dc32ae9a06720e3b9d0 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 31 Jul 2023 22:05:13 -0400 Subject: [PATCH 30/35] makes more easy select a spline point or spline tangent --- Source/Editor/CustomEditors/Dedicated/SplineEditor.cs | 11 +++++++---- Source/Editor/SceneGraph/Actors/SplineNode.cs | 7 +++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index 8aa7b421a..d4eb2f1e0 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -706,9 +706,10 @@ namespace FlaxEditor.CustomEditors.Dedicated // auto smooth tangent if's linear if (keyframe.TangentIn.Translation.Length == 0) { + var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f); var previousKeyframe = spline.GetSplineKeyframe(index - 1); var tangentDirection = keyframe.Value.WorldToLocalVector(previousKeyframe.Value.Translation - keyframe.Value.Translation); - tangentDirection = tangentDirection.Normalized * 100f; + tangentDirection = tangentDirection.Normalized * smoothRange; keyframe.TangentIn.Translation = tangentDirection; } @@ -724,9 +725,10 @@ namespace FlaxEditor.CustomEditors.Dedicated // auto smooth tangent if's linear if (keyframe.TangentOut.Translation.Length == 0) { + var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f); var nextKeyframe = spline.GetSplineKeyframe(index + 1); var tangentDirection = keyframe.Value.WorldToLocalVector(nextKeyframe.Value.Translation - keyframe.Value.Translation); - tangentDirection = tangentDirection.Normalized * 100f; + tangentDirection = tangentDirection.Normalized * smoothRange; keyframe.TangentOut.Translation = tangentDirection; } @@ -744,10 +746,11 @@ namespace FlaxEditor.CustomEditors.Dedicated var isLastKeyframe = index >= spline.SplinePointsCount - 1; var isFirstKeyframe = index <= 0; + var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplinePoint(index), 10f); // force smooth it's linear point - if (tangentInSize == 0f) tangentInSize = 100; - if (tangentOutSize == 0f) tangentOutSize = 100; + if (tangentInSize == 0f) tangentInSize = smoothRange; + if (tangentOutSize == 0f) tangentOutSize = smoothRange; // try get next / last keyframe var nextKeyframe = !isLastKeyframe ? spline.GetSplineKeyframe(index + 1) : keyframe; diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index 75b86950c..fe96ad4e8 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -286,8 +286,8 @@ namespace FlaxEditor.SceneGraph.Actors } } - private const float PointNodeSize = 2; - private const float TangentNodeSize = 1.6f; + private const float PointNodeSize = 1.5f; + private const float TangentNodeSize = 1.0f; /// public SplineNode(Actor actor) @@ -408,14 +408,13 @@ namespace FlaxEditor.SceneGraph.Actors } } - private static float NodeSizeByDistance(Vector3 nodePosition, float nodeSize) + internal static float NodeSizeByDistance(Vector3 nodePosition, float nodeSize) { var cameraTransform = Editor.Instance.Windows.EditWin.Viewport.ViewportCamera.Viewport.ViewTransform; var distance = Vector3.Distance(cameraTransform.Translation, nodePosition) / 100; return distance * nodeSize; } - /// public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal) { From 600659e4536e3cc6932f52358f93ce0e9ec8b16f Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 31 Jul 2023 22:34:50 -0400 Subject: [PATCH 31/35] Move DrawSpline from Spline.cpp to SplineNode.cs --- Source/Editor/SceneGraph/Actors/SplineNode.cs | 29 ++++++++++++ Source/Engine/Level/Actors/Spline.cpp | 47 ------------------- Source/Engine/Level/Actors/Spline.h | 4 -- 3 files changed, 29 insertions(+), 51 deletions(-) diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index fe96ad4e8..24ea60f21 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -415,6 +415,35 @@ namespace FlaxEditor.SceneGraph.Actors return distance * nodeSize; } + public override void OnDebugDraw(ViewportDebugDrawData data) + { + DrawSpline((Spline)Actor, Color.White, Actor.Transform, false); + } + + private void DrawSpline(Spline spline, Color color, Transform transform, bool depthTest) + { + var count = spline.SplineKeyframes.Length; + if (count == 0) + return; + var keyframes = spline.SplineKeyframes; + var pointIndex = 0; + var prev = spline.GetSplineKeyframe(0); + + Vector3 prevPos = transform.LocalToWorld(prev.Value.Translation); + DebugDraw.DrawWireSphere(new BoundingSphere(prevPos, 5.0f), color, 0.0f, depthTest); + for (int i = 1; i < count; i++) + { + var next = keyframes[pointIndex]; + Vector3 nextPos = transform.LocalToWorld(next.Value.Translation); + DebugDraw.DrawWireSphere(new BoundingSphere(nextPos, 5.0f), color, 0.0f, depthTest); + var d = (next.Time - prev.Time) / 3.0f; + DebugDraw.DrawBezier(prevPos, prevPos + prev.TangentOut.Translation * d, nextPos + next.TangentIn.Translation * d, nextPos, color, 0.0f, depthTest); + prev = next; + prevPos = nextPos; + pointIndex++; + } + } + /// public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal) { diff --git a/Source/Engine/Level/Actors/Spline.cpp b/Source/Engine/Level/Actors/Spline.cpp index dbd7ef045..2923463b0 100644 --- a/Source/Engine/Level/Actors/Spline.cpp +++ b/Source/Engine/Level/Actors/Spline.cpp @@ -455,53 +455,6 @@ void Spline::SetKeyframes(MArray* data) #endif -#if USE_EDITOR - -#include "Engine/Debug/DebugDraw.h" - -namespace -{ - void DrawSpline(Spline* spline, const Color& color, const Transform& transform, bool depthTest) - { - const int32 count = spline->Curve.GetKeyframes().Count(); - if (count == 0) - return; - Spline::Keyframe* prev = spline->Curve.GetKeyframes().Get(); - Vector3 prevPos = transform.LocalToWorld(prev->Value.Translation); - DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(prevPos, 5.0f), color, 0.0f, depthTest); - for (int32 i = 1; i < count; i++) - { - Spline::Keyframe* next = prev + 1; - Vector3 nextPos = transform.LocalToWorld(next->Value.Translation); - DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(nextPos, 5.0f), color, 0.0f, depthTest); - const float d = (next->Time - prev->Time) / 3.0f; - DEBUG_DRAW_BEZIER(prevPos, prevPos + prev->TangentOut.Translation * d, nextPos + next->TangentIn.Translation * d, nextPos, color, 0.0f, depthTest); - prev = next; - prevPos = nextPos; - } - } -} - -void Spline::OnDebugDraw() -{ - const Color color = GetSplineColor(); - DrawSpline(this, color.AlphaMultiplied(0.7f), _transform, true); - - // Base - Actor::OnDebugDraw(); -} - -void Spline::OnDebugDrawSelected() -{ - const Color color = GetSplineColor(); - DrawSpline(this, color.AlphaMultiplied(0.3f), _transform, false); - - // Base - Actor::OnDebugDrawSelected(); -} - -#endif - void Spline::OnTransformChanged() { // Base diff --git a/Source/Engine/Level/Actors/Spline.h b/Source/Engine/Level/Actors/Spline.h index ea3cf8569..426304fb9 100644 --- a/Source/Engine/Level/Actors/Spline.h +++ b/Source/Engine/Level/Actors/Spline.h @@ -369,10 +369,6 @@ private: public: // [Actor] -#if USE_EDITOR - void OnDebugDraw() override; - void OnDebugDrawSelected() override; -#endif void OnTransformChanged() override; void Initialize() override; void Serialize(SerializeStream& stream, const void* otherObj) override; From f511259a33be31ee45c9bac00823bacb971c54df Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Mon, 31 Jul 2023 22:43:33 -0400 Subject: [PATCH 32/35] draw spline point size by distance from camera --- Source/Editor/SceneGraph/Actors/SplineNode.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index 24ea60f21..cbc8911a8 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -417,7 +417,7 @@ namespace FlaxEditor.SceneGraph.Actors public override void OnDebugDraw(ViewportDebugDrawData data) { - DrawSpline((Spline)Actor, Color.White, Actor.Transform, false); + DrawSpline((Spline)Actor, Color.White, Actor.Transform, true); } private void DrawSpline(Spline spline, Color color, Transform transform, bool depthTest) @@ -428,15 +428,16 @@ namespace FlaxEditor.SceneGraph.Actors var keyframes = spline.SplineKeyframes; var pointIndex = 0; var prev = spline.GetSplineKeyframe(0); - - Vector3 prevPos = transform.LocalToWorld(prev.Value.Translation); - DebugDraw.DrawWireSphere(new BoundingSphere(prevPos, 5.0f), color, 0.0f, depthTest); - for (int i = 1; i < count; i++) + var prevPos = transform.LocalToWorld(prev.Value.Translation); + var pointSize = NodeSizeByDistance(spline.GetSplinePoint(0), PointNodeSize); + DebugDraw.DrawWireSphere(new BoundingSphere(prevPos, pointSize), color, 0.0f, depthTest); + for (int i = 0; i < count; i++) { var next = keyframes[pointIndex]; - Vector3 nextPos = transform.LocalToWorld(next.Value.Translation); - DebugDraw.DrawWireSphere(new BoundingSphere(nextPos, 5.0f), color, 0.0f, depthTest); + var nextPos = transform.LocalToWorld(next.Value.Translation); var d = (next.Time - prev.Time) / 3.0f; + pointSize = NodeSizeByDistance(spline.GetSplinePoint(i), PointNodeSize); + DebugDraw.DrawWireSphere(new BoundingSphere(nextPos, pointSize), color, 0.0f, depthTest); DebugDraw.DrawBezier(prevPos, prevPos + prev.TangentOut.Translation * d, nextPos + next.TangentIn.Translation * d, nextPos, color, 0.0f, depthTest); prev = next; prevPos = nextPos; From 38492ffe70102d93341ef9f41ed7a35b131c3e88 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sat, 5 Aug 2023 11:01:15 -0400 Subject: [PATCH 33/35] small adjust --- .../CustomEditors/Dedicated/SplineEditor.cs | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs index d4eb2f1e0..2fe601108 100644 --- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs @@ -474,6 +474,7 @@ namespace FlaxEditor.CustomEditors.Dedicated if (_currentTangentMode is FreeTangentMode) return; _currentTangentMode = new FreeTangentMode(); _currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index); + SetEditButtonsColor(); } private void SetModeAligned() @@ -500,23 +501,21 @@ namespace FlaxEditor.CustomEditors.Dedicated private void UpdateSelectedPoint() { // works only if select one spline - if (!_selectedSpline) + if (_selectedSpline) { - _selectedPoint = null; - SetSelectedTangentTypeAsCurrent(); - SetEditButtonsColor(); - SetEditButtonsEnabled(); - return; - } + var currentSelected = Editor.Instance.SceneEditing.Selection[0]; - var currentSelected = Editor.Instance.SceneEditing.Selection[0]; - - if (currentSelected == _selectedPoint) return; - if (currentSelected is SplineNode.SplinePointNode) - { - _selectedPoint = currentSelected as SplineNode.SplinePointNode; - _lastPointSelected = _selectedPoint; - _currentTangentMode.OnSelectKeyframe(_selectedSpline, _lastPointSelected.Index); + if (currentSelected == _selectedPoint) return; + if (currentSelected is SplineNode.SplinePointNode) + { + _selectedPoint = currentSelected as SplineNode.SplinePointNode; + _lastPointSelected = _selectedPoint; + _currentTangentMode.OnSelectKeyframe(_selectedSpline, _lastPointSelected.Index); + } + else + { + _selectedPoint = null; + } } else { From 6b1cc5bf2fec3829c031be2dd64550205259c8ef Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sat, 5 Aug 2023 12:07:40 -0400 Subject: [PATCH 34/35] adjust again... --- Source/Engine/Level/Actors/Spline.cpp | 47 +++++++++++++++++++++++++++ Source/Engine/Level/Actors/Spline.h | 4 +++ 2 files changed, 51 insertions(+) diff --git a/Source/Engine/Level/Actors/Spline.cpp b/Source/Engine/Level/Actors/Spline.cpp index 2923463b0..dbd7ef045 100644 --- a/Source/Engine/Level/Actors/Spline.cpp +++ b/Source/Engine/Level/Actors/Spline.cpp @@ -455,6 +455,53 @@ void Spline::SetKeyframes(MArray* data) #endif +#if USE_EDITOR + +#include "Engine/Debug/DebugDraw.h" + +namespace +{ + void DrawSpline(Spline* spline, const Color& color, const Transform& transform, bool depthTest) + { + const int32 count = spline->Curve.GetKeyframes().Count(); + if (count == 0) + return; + Spline::Keyframe* prev = spline->Curve.GetKeyframes().Get(); + Vector3 prevPos = transform.LocalToWorld(prev->Value.Translation); + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(prevPos, 5.0f), color, 0.0f, depthTest); + for (int32 i = 1; i < count; i++) + { + Spline::Keyframe* next = prev + 1; + Vector3 nextPos = transform.LocalToWorld(next->Value.Translation); + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(nextPos, 5.0f), color, 0.0f, depthTest); + const float d = (next->Time - prev->Time) / 3.0f; + DEBUG_DRAW_BEZIER(prevPos, prevPos + prev->TangentOut.Translation * d, nextPos + next->TangentIn.Translation * d, nextPos, color, 0.0f, depthTest); + prev = next; + prevPos = nextPos; + } + } +} + +void Spline::OnDebugDraw() +{ + const Color color = GetSplineColor(); + DrawSpline(this, color.AlphaMultiplied(0.7f), _transform, true); + + // Base + Actor::OnDebugDraw(); +} + +void Spline::OnDebugDrawSelected() +{ + const Color color = GetSplineColor(); + DrawSpline(this, color.AlphaMultiplied(0.3f), _transform, false); + + // Base + Actor::OnDebugDrawSelected(); +} + +#endif + void Spline::OnTransformChanged() { // Base diff --git a/Source/Engine/Level/Actors/Spline.h b/Source/Engine/Level/Actors/Spline.h index 426304fb9..ea3cf8569 100644 --- a/Source/Engine/Level/Actors/Spline.h +++ b/Source/Engine/Level/Actors/Spline.h @@ -369,6 +369,10 @@ private: public: // [Actor] +#if USE_EDITOR + void OnDebugDraw() override; + void OnDebugDrawSelected() override; +#endif void OnTransformChanged() override; void Initialize() override; void Serialize(SerializeStream& stream, const void* otherObj) override; From dc3e71a262e3cc832b45d3f766b4512d6fa9c193 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sat, 5 Aug 2023 21:26:27 -0400 Subject: [PATCH 35/35] fix for large worlds --- Source/Editor/SceneGraph/Actors/SplineNode.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index cbc8911a8..9af736fac 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -286,8 +286,8 @@ namespace FlaxEditor.SceneGraph.Actors } } - private const float PointNodeSize = 1.5f; - private const float TangentNodeSize = 1.0f; + private const Real PointNodeSize = 1.5f; + private const Real TangentNodeSize = 1.0f; /// public SplineNode(Actor actor) @@ -408,7 +408,7 @@ namespace FlaxEditor.SceneGraph.Actors } } - internal static float NodeSizeByDistance(Vector3 nodePosition, float nodeSize) + internal static Real NodeSizeByDistance(Vector3 nodePosition, Real nodeSize) { var cameraTransform = Editor.Instance.Windows.EditWin.Viewport.ViewportCamera.Viewport.ViewTransform; var distance = Vector3.Distance(cameraTransform.Translation, nodePosition) / 100;