diff --git a/Source/Editor/Surface/Archetypes/Material.cs b/Source/Editor/Surface/Archetypes/Material.cs index e46038639..9ac43082e 100644 --- a/Source/Editor/Surface/Archetypes/Material.cs +++ b/Source/Editor/Surface/Archetypes/Material.cs @@ -304,25 +304,14 @@ namespace FlaxEditor.Surface.Archetypes } } - internal sealed class CustomCodeNode : SurfaceNode + internal sealed class CustomCodeNode : ResizableSurfaceNode { - private Rectangle _resizeButtonRect; - private Float2 _startResizingSize; - private Float2 _startResizingCornerOffset; - private bool _isResizing; private CustomCodeTextBox _textBox; - private int SizeValueIndex => Archetype.TypeID == 8 ? 1 : 3; // Index of the Size stored in Values array - - private Float2 SizeValue - { - get => (Float2)Values[SizeValueIndex]; - set => SetValue(SizeValueIndex, value, false); - } - public CustomCodeNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) : base(id, context, nodeArch, groupArch) { + _sizeValueIndex = Archetype.TypeID == 8 ? 1 : 3; // Index of the Size stored in Values array Float2 pos = new Float2(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize), size; if (nodeArch.TypeID == 8) { @@ -345,126 +334,19 @@ namespace FlaxEditor.Surface.Archetypes _textBox.EditEnd += () => SetValue(0, _textBox.Text); } - public override bool CanSelect(ref Float2 location) - { - return base.CanSelect(ref location) && !_resizeButtonRect.MakeOffsetted(Location).Contains(ref location); - } - public override void OnSurfaceLoaded(SurfaceNodeActions action) { base.OnSurfaceLoaded(action); _textBox.Text = (string)Values[0]; - - var size = SizeValue; - if (Surface != null && Surface.GridSnappingEnabled) - size = Surface.SnapToGrid(size, true); - Resize(size.X, size.Y); } public override void OnValuesChanged() { base.OnValuesChanged(); - var size = SizeValue; - Resize(size.X, size.Y); _textBox.Text = (string)Values[0]; } - - 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); - } - } } internal enum MaterialTemplateInputsMapping diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs index aacebd189..68a733197 100644 --- a/Source/Editor/Surface/Archetypes/Tools.cs +++ b/Source/Editor/Surface/Archetypes/Tools.cs @@ -453,7 +453,7 @@ namespace FlaxEditor.Surface.Archetypes } } - private class CurveNode : SurfaceNode where T : struct + private class CurveNode : ResizableSurfaceNode where T : struct { private BezierCurveEditor _curve; private bool _isSavingCurve; @@ -467,7 +467,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 +491,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[] { @@ -504,30 +506,52 @@ namespace FlaxEditor.Surface.Archetypes public CurveNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) : base(id, context, nodeArch, groupArch) { + _sizeValueIndex = 29; // Index of the Size stored in Values array } - + /// public override void OnLoaded(SurfaceNodeActions action) { base.OnLoaded(action); + // Create curve editor var upperLeft = GetBox(0).BottomLeft; var upperRight = GetBox(1).BottomRight; float curveMargin = 20.0f; - _curve = new BezierCurveEditor { 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(); + // Sync keyframes UpdateCurveKeyframes(); } + /// + public override void OnSurfaceLoaded(SurfaceNodeActions action) + { + base.OnSurfaceLoaded(action); + + // Ensure the whole curve is shown + _curve.ShowWholeCurve(); + } + + public override void OnValuesChanged() + { + base.OnValuesChanged(); + + if (!_isSavingCurve) + { + UpdateCurveKeyframes(); + } + } + private void OnCurveEdited() { if (_isSavingCurve) @@ -553,17 +577,6 @@ namespace FlaxEditor.Surface.Archetypes _isSavingCurve = false; } - /// - public override void OnValuesChanged() - { - base.OnValuesChanged(); - - if (!_isSavingCurve) - { - UpdateCurveKeyframes(); - } - } - private void UpdateCurveKeyframes() { var count = (int)Values[0]; @@ -1575,7 +1588,7 @@ namespace FlaxEditor.Surface.Archetypes DefaultValues = new object[] { Guid.Empty, - string.Empty + string.Empty, }, Elements = new[] { diff --git a/Source/Editor/Surface/ResizableSurfaceNode.cs b/Source/Editor/Surface/ResizableSurfaceNode.cs new file mode 100644 index 000000000..259c29836 --- /dev/null +++ b/Source/Editor/Surface/ResizableSurfaceNode.cs @@ -0,0 +1,182 @@ +// Copyright (c) Wojciech Figat. All rights reserved. + +using FlaxEngine; +using FlaxEngine.GUI; + +namespace FlaxEditor.Surface +{ + /// + /// Visject Surface node control that cna be resized. + /// + /// + [HideInEditor] + public class ResizableSurfaceNode : SurfaceNode + { + private Float2 _startResizingSize; + private Float2 _startResizingCornerOffset; + + /// + /// Indicates whether the node is currently being resized. + /// + protected bool _isResizing; + + /// + /// Index of the Float2 value in the node values list to store node size. + /// + protected int _sizeValueIndex = -1; + + /// + /// Minimum node size. + /// + protected Float2 _sizeMin = new Float2(240, 160); + + /// + /// Node resizing rectangle bounds. + /// + protected Rectangle _resizeButtonRect; + + private Float2 SizeValue + { + get => (Float2)Values[_sizeValueIndex]; + set => SetValue(_sizeValueIndex, value, false); + } + + /// + public ResizableSurfaceNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) + : base(id, context, nodeArch, groupArch) + { + } + + /// + public override bool CanSelect(ref Float2 location) + { + return base.CanSelect(ref location) && !_resizeButtonRect.MakeOffsetted(Location).Contains(ref location); + } + + /// + public override void OnSurfaceLoaded(SurfaceNodeActions action) + { + // Reapply the curve node size + var size = SizeValue; + if (Surface != null && Surface.GridSnappingEnabled) + size = Surface.SnapToGrid(size, true); + Resize(size.X, size.Y); + + base.OnSurfaceLoaded(action); + } + + /// + public override void OnValuesChanged() + { + base.OnValuesChanged(); + + var size = SizeValue; + Resize(size.X, size.Y); + } + + /// + public override void Draw() + { + base.Draw(); + + if (Surface.CanEdit) + { + var style = Style.Current; + if (_isResizing) + { + Render2D.FillRectangle(_resizeButtonRect, style.Selection); + Render2D.DrawRectangle(_resizeButtonRect, style.SelectionBorder); + } + Render2D.DrawSprite(style.Scale, _resizeButtonRect, _resizeButtonRect.Contains(_mousePosition) ? 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 resizing + _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, _sizeMin); + 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); + } + + /// + protected override void UpdateRectangles() + { + base.UpdateRectangles(); + + const float buttonMargin = Constants.NodeCloseButtonMargin; + const float buttonSize = Constants.NodeCloseButtonSize; + _resizeButtonRect = new Rectangle(_closeButtonRect.Left, Height - buttonSize - buttonMargin - 4, buttonSize, buttonSize); + } + + private void EndResizing() + { + Cursor = CursorType.Default; + EndMouseCapture(); + _isResizing = false; + if (_startResizingSize != Size) + { + var emptySize = CalculateNodeSize(0, 0); + SizeValue = Size - emptySize; + Surface.MarkAsEdited(false); + } + } + } +} diff --git a/Source/Editor/Surface/SurfaceComment.cs b/Source/Editor/Surface/SurfaceComment.cs index 10e9fc776..a76fa245d 100644 --- a/Source/Editor/Surface/SurfaceComment.cs +++ b/Source/Editor/Surface/SurfaceComment.cs @@ -14,18 +14,11 @@ namespace FlaxEditor.Surface /// /// [HideInEditor] - public class SurfaceComment : SurfaceNode + public class SurfaceComment : ResizableSurfaceNode { private Rectangle _colorButtonRect; - private Rectangle _resizeButtonRect; - private Float2 _startResizingSize; private readonly TextBox _renameTextBox; - /// - /// True if sizing tool is in use. - /// - protected bool _isResizing; - /// /// True if rename textbox is active in order to rename comment /// @@ -52,12 +45,6 @@ namespace FlaxEditor.Surface set => SetValue(1, value, false); } - private Float2 SizeValue - { - get => (Float2)Values[2]; - set => SetValue(2, value, false); - } - private int OrderValue { get => (int)Values[3]; @@ -68,6 +55,8 @@ namespace FlaxEditor.Surface public SurfaceComment(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) : base(id, context, nodeArch, groupArch) { + _sizeValueIndex = 2; // Index of the Size stored in Values array + _sizeMin = new Float2(140.0f, Constants.NodeHeaderSize); _renameTextBox = new TextBox(false, 0, 0, Width) { Height = Constants.NodeHeaderSize, @@ -86,10 +75,6 @@ namespace FlaxEditor.Surface // Read node data Title = TitleValue; Color = ColorValue; - var size = SizeValue; - if (Surface != null && Surface.GridSnappingEnabled) - size = Surface.SnapToGrid(size, true); - Size = size; // Order // Backwards compatibility - When opening with an older version send the old comments to the back @@ -126,27 +111,6 @@ namespace FlaxEditor.Surface // Read node data Title = TitleValue; Color = ColorValue; - Size = SizeValue; - } - - private void EndResizing() - { - // Clear state - _isResizing = false; - - if (_startResizingSize != Size) - { - SizeValue = Size; - Surface.MarkAsEdited(false); - } - - EndMouseCapture(); - } - - /// - public override bool CanSelect(ref Float2 location) - { - return _headerRect.MakeOffsetted(Location).Contains(ref location) && !_resizeButtonRect.MakeOffsetted(Location).Contains(ref location); } /// @@ -158,6 +122,8 @@ namespace FlaxEditor.Surface /// protected override void UpdateRectangles() { + base.UpdateRectangles(); + const float headerSize = Constants.NodeHeaderSize; const float buttonMargin = Constants.NodeCloseButtonMargin; const float buttonSize = Constants.NodeCloseButtonSize; @@ -222,16 +188,13 @@ namespace FlaxEditor.Surface // Color button Render2D.DrawSprite(style.Settings, _colorButtonRect, _colorButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey); - // Check if is resizing + // Resize button if (_isResizing) { - // Draw overlay Render2D.FillRectangle(_resizeButtonRect, style.Selection); Render2D.DrawRectangle(_resizeButtonRect, style.SelectionBorder); } - - // Resize button - Render2D.DrawSprite(style.Scale, _resizeButtonRect, _resizeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey); + Render2D.DrawSprite(style.Scale, _resizeButtonRect, _resizeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey); } // Selection outline @@ -247,88 +210,28 @@ namespace FlaxEditor.Surface /// protected override Float2 CalculateNodeSize(float width, float height) { - return Size; + // No margins or headers + return new Float2(width, height); } /// public override void OnLostFocus() { - // Check if was resizing - if (_isResizing) - { - EndResizing(); - } - - // Check if was renaming if (_isRenaming) { Rename(_renameTextBox.Text); StopRenaming(); } - // Base base.OnLostFocus(); } - /// - public override void OnEndMouseCapture() - { - // Check if was resizing - if (_isResizing) - { - EndResizing(); - } - else - { - base.OnEndMouseCapture(); - } - } - /// public override bool ContainsPoint(ref Float2 location, bool precise) { return _headerRect.Contains(ref location) || _resizeButtonRect.Contains(ref location); } - /// - public override bool OnMouseDown(Float2 location, MouseButton button) - { - if (base.OnMouseDown(location, button)) - return true; - - // Check if can start resizing - if (button == MouseButton.Left && _resizeButtonRect.Contains(ref location) && Surface.CanEdit) - { - // Start sliding - _isResizing = true; - _startResizingSize = Size; - StartMouseCapture(); - - return true; - } - - return false; - } - - /// - public override void OnMouseMove(Float2 location) - { - // Check if is resizing - if (_isResizing) - { - // Update size - var size = Float2.Max(location, new Float2(140.0f, _headerRect.Bottom)); - if (Surface.GridSnappingEnabled) - size = Surface.SnapToGrid(size, true); - Size = size; - } - else - { - // Base - base.OnMouseMove(location); - } - } - /// public override bool OnMouseDoubleClick(Float2 location, MouseButton button) { @@ -394,12 +297,6 @@ namespace FlaxEditor.Surface /// public override bool OnMouseUp(Float2 location, MouseButton button) { - if (button == MouseButton.Left && _isResizing) - { - EndResizing(); - return true; - } - if (base.OnMouseUp(location, button)) return true;