From f2699892e076461bde4f49fe88308688e0e26986 Mon Sep 17 00:00:00 2001 From: Saas Date: Sun, 17 Aug 2025 15:42:54 +0200 Subject: [PATCH] add support for resizing visject curve nodes --- Source/Editor/Surface/Archetypes/Tools.cs | 155 ++++++++++++++++++++-- 1 file changed, 141 insertions(+), 14 deletions(-) diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs index 0e4b567b9..3bca332f8 100644 --- a/Source/Editor/Surface/Archetypes/Tools.cs +++ b/Source/Editor/Surface/Archetypes/Tools.cs @@ -455,9 +455,22 @@ namespace FlaxEditor.Surface.Archetypes private class CurveNode : SurfaceNode where T : struct { + private Rectangle _resizeButtonRect; + private Float2 _startResizingSize; + private Float2 _startResizingCornerOffset; + private bool _isResizing; + private BezierCurveEditor _curve; private bool _isSavingCurve; + private int SizeValueIndex => 29; // Index of the Size stored in Values array + + private Float2 SizeValue + { + get => (Float2)Values[SizeValueIndex]; + set => SetValue(SizeValueIndex, value, false); + } + public static NodeArchetype GetArchetype(ushort typeId, string title, Type valueType, T zero, T one) { return new NodeArchetype @@ -467,7 +480,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new CurveNode(id, context, arch, groupArch), Description = "An animation spline represented by a set of keyframes, each representing an endpoint of a Bezier curve.", Flags = NodeFlags.AllGraphs, - Size = new Float2(400, 180.0f), + Size = new Float2(400, 180), DefaultValues = new object[] { // Keyframes count @@ -491,6 +504,8 @@ namespace FlaxEditor.Surface.Archetypes 0.0f, zero, zero, zero, 0.0f, zero, zero, zero, 0.0f, zero, zero, zero, + + new Float2(400, 180), }, Elements = new[] { @@ -506,6 +521,11 @@ namespace FlaxEditor.Surface.Archetypes { } + public override bool CanSelect(ref Float2 location) + { + return base.CanSelect(ref location) && !_resizeButtonRect.MakeOffsetted(Location).Contains(ref location); + } + /// public override void OnLoaded(SurfaceNodeActions action) { @@ -519,13 +539,131 @@ namespace FlaxEditor.Surface.Archetypes { MaxKeyframes = 7, Bounds = new Rectangle(upperLeft + new Float2(curveMargin, 10.0f), upperRight.X - upperLeft.X - curveMargin * 2.0f, 140.0f), - Parent = this + Parent = this, + AnchorMax = Float2.One, }; _curve.Edited += OnCurveEdited; _curve.UnlockChildrenRecursive(); _curve.PerformLayout(); UpdateCurveKeyframes(); + + // Reapply the curve node size + var size = SizeValue; + if (Surface != null && Surface.GridSnappingEnabled) + size = Surface.SnapToGrid(size, true); + Resize(size.X, size.Y); + + // Ensure the whole curve is shown + _curve.ShowWholeCurve(); + } + + public override void OnValuesChanged() + { + base.OnValuesChanged(); + + var size = SizeValue; + Resize(size.X, size.Y); + + if (!_isSavingCurve) + { + UpdateCurveKeyframes(); + } + } + + protected override void UpdateRectangles() + { + base.UpdateRectangles(); + + const float buttonMargin = FlaxEditor.Surface.Constants.NodeCloseButtonMargin; + const float buttonSize = FlaxEditor.Surface.Constants.NodeCloseButtonSize; + _resizeButtonRect = new Rectangle(_closeButtonRect.Left, Height - buttonSize - buttonMargin - 4, buttonSize, buttonSize); + } + + public override void Draw() + { + base.Draw(); + + var style = Style.Current; + if (_isResizing) + { + Render2D.FillRectangle(_resizeButtonRect, style.Selection); + Render2D.DrawRectangle(_resizeButtonRect, style.SelectionBorder); + } + Render2D.DrawSprite(style.Scale, _resizeButtonRect, _resizeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey); + } + + public override void OnLostFocus() + { + if (_isResizing) + EndResizing(); + + base.OnLostFocus(); + } + + public override void OnEndMouseCapture() + { + if (_isResizing) + EndResizing(); + + base.OnEndMouseCapture(); + } + + public override bool OnMouseDown(Float2 location, MouseButton button) + { + if (base.OnMouseDown(location, button)) + return true; + + if (button == MouseButton.Left && _resizeButtonRect.Contains(ref location) && Surface.CanEdit) + { + // Start sliding + _isResizing = true; + _startResizingSize = Size; + _startResizingCornerOffset = Size - location; + StartMouseCapture(); + Cursor = CursorType.SizeNWSE; + return true; + } + + return false; + } + + public override void OnMouseMove(Float2 location) + { + if (_isResizing) + { + var emptySize = CalculateNodeSize(0, 0); + var size = Float2.Max(location - emptySize + _startResizingCornerOffset, new Float2(240, 160)); + Resize(size.X, size.Y); + } + else + { + base.OnMouseMove(location); + } + } + + public override bool OnMouseUp(Float2 location, MouseButton button) + { + if (button == MouseButton.Left && _isResizing) + { + EndResizing(); + return true; + } + + return base.OnMouseUp(location, button); + } + + private void EndResizing() + { + Cursor = CursorType.Default; + EndMouseCapture(); + _isResizing = false; + if (_startResizingSize != Size) + { + var emptySize = CalculateNodeSize(0, 0); + SizeValue = Size - emptySize; + Surface.MarkAsEdited(false); + } } private void OnCurveEdited() @@ -553,17 +691,6 @@ namespace FlaxEditor.Surface.Archetypes _isSavingCurve = false; } - /// - public override void OnValuesChanged() - { - base.OnValuesChanged(); - - if (!_isSavingCurve) - { - UpdateCurveKeyframes(); - } - } - private void UpdateCurveKeyframes() { var count = (int)Values[0]; @@ -1571,7 +1698,7 @@ namespace FlaxEditor.Surface.Archetypes DefaultValues = new object[] { Guid.Empty, - string.Empty + string.Empty, }, Elements = new[] {