diff --git a/Source/Editor/Surface/ResizableSurfaceNode.cs b/Source/Editor/Surface/ResizableSurfaceNode.cs
index 2a1f549fe..ed79c90d2 100644
--- a/Source/Editor/Surface/ResizableSurfaceNode.cs
+++ b/Source/Editor/Surface/ResizableSurfaceNode.cs
@@ -13,15 +13,204 @@ namespace FlaxEditor.Surface
[HideInEditor]
public class ResizableSurfaceNode : SurfaceNode
{
- private Float2 _resizeWeight;
- private Float2 _startResizingSize;
- private Float2 _surfaceMouseLocation;
- private bool _isMouseOverResizeBorder;
+ private class ResizeBorder : Control
+ {
+ private const float BorderWidth = 15f;
+ private const float ResizeOnAxisThreshold = 0.85f;
- ///
- /// Indicates whether the node is currently being resized.
- ///
- protected bool _isResizing;
+ public VisjectSurface Surface;
+ public ResizableSurfaceNode ResizeableNode;
+
+ private Float2 _surfaceMouseLocation;
+ private Float2 startResizingSize;
+
+ public bool IsMouseOverResizeBorder { get; private set; }
+ public bool IsResizing { get; private set; }
+
+ public Action StartResize;
+ public Action EndResize;
+
+ public Float2 ResizeWeight { get; private set; }
+ public CursorType CursorType
+ {
+ get
+ {
+ if ((ResizeWeight.X == 1 && ResizeWeight.Y == 0) || (ResizeWeight.X == -1 && ResizeWeight.Y == 0))
+ return CursorType.SizeWE;
+ if ((ResizeWeight.X == 0 && ResizeWeight.Y == 1) || (ResizeWeight.X == 0 && ResizeWeight.Y == -1))
+ return CursorType.SizeNS;
+ if ((ResizeWeight.X == -1 && ResizeWeight.Y == -1) || (ResizeWeight.X == 1 && ResizeWeight.Y == 1))
+ return CursorType.SizeNWSE;
+ if ((ResizeWeight.X == 1 && ResizeWeight.Y == -1) || (ResizeWeight.X == -1 && ResizeWeight.Y == 1))
+ return CursorType.SizeNESW;
+
+ return CursorType.Default;
+ }
+ }
+
+
+
+ public ResizeBorder(VisjectSurface surface, ResizableSurfaceNode resizeableNode)
+ {
+ Surface = surface;
+ ResizeableNode = resizeableNode;
+ }
+
+ ///
+ /// Updates location and size to match the resizeable node with the additional padding.
+ ///
+ /// The node size.
+ /// The node location.
+ public void MatchResizeableNode(Float2 nodeSize, Float2 nodeLocation)
+ {
+ Size = nodeSize + new Float2(BorderWidth);
+ Location = nodeLocation - new Float2(BorderWidth * 0.5f);
+ }
+
+ private void UpdateSurfaceMouseLocation()
+ {
+ _surfaceMouseLocation = Surface.PointFromScreen(Input.MouseScreenPosition);
+ }
+
+ private void UpdateResizeFlags(Float2 location)
+ {
+ var borderRect = Bounds with { Location = Float2.Zero };
+ bool onBorder = borderRect.Contains(location);
+
+ Float2 rawResizeWeight = (location - borderRect.Center) / (borderRect.Size * 0.5f);
+ ResizeWeight = new Float2(Mathf.Abs(rawResizeWeight.X) >= ResizeOnAxisThreshold ? Mathf.Sign(rawResizeWeight.X) : 0,
+ Mathf.Abs(rawResizeWeight.Y) >= ResizeOnAxisThreshold ? Mathf.Sign(rawResizeWeight.Y) : 0);
+
+ IsMouseOverResizeBorder = onBorder && !ResizeableNode.IsMouseOver;
+ }
+
+ private Float2 GetControlDelta(Control control, ref Float2 start, ref Float2 end)
+ {
+ var pointOrigin = control.Parent ?? control;
+ var startPos = pointOrigin.PointFromParent(ResizeableNode, start);
+ var endPos = pointOrigin.PointFromParent(ResizeableNode, end);
+ return endPos - startPos;
+ }
+
+ private void EndResizing()
+ {
+ EndMouseCapture();
+ IsResizing = false;
+ if (startResizingSize != ResizeableNode.Size)
+ {
+ var emptySize = ResizeableNode.CalculateNodeSize(0, 0);
+ ResizeableNode.SizeValue = ResizeableNode.Size - emptySize;
+ Surface.MarkAsEdited(false);
+ }
+ }
+
+ public override void OnMouseLeave()
+ {
+ Cursor = CursorType.Default;
+ IsMouseOverResizeBorder = false;
+ base.OnMouseLeave();
+ }
+
+ ///
+ public override void OnMouseMove(Float2 location)
+ {
+ if (!IsResizing)
+ {
+ UpdateResizeFlags(location);
+ }
+ else
+ {
+ var resizeAxisAbs = ResizeWeight.Absolute;
+ var resizeAxisPos = Float2.Clamp(ResizeWeight, Float2.Zero, Float2.One);
+ var resizeAxisNeg = Float2.Clamp(-ResizeWeight, Float2.Zero, Float2.One);
+
+ var currentSurfaceMouse = Surface.PointFromScreen(Input.MouseScreenPosition);
+ var delta = currentSurfaceMouse - _surfaceMouseLocation;
+ // TODO: scale/size snapping?
+ delta *= resizeAxisAbs;
+
+ var moveLocation = _surfaceMouseLocation + delta;
+
+ // TODO: Do I need GetControlDelta?
+ var uiControlDelta = GetControlDelta(this, ref _surfaceMouseLocation, ref moveLocation);
+ var emptySize = ResizeableNode.CalculateNodeSize(0, 0);
+ ResizeableNode.Size += uiControlDelta * resizeAxisPos - uiControlDelta * resizeAxisNeg;
+ Float2 oldSize = ResizeableNode.Size;
+ ResizeableNode.Size = new Float2(Mathf.Max(ResizeableNode.Size.X, ResizeableNode.sizeMin.X), Mathf.Max(ResizeableNode.Size.Y, ResizeableNode.sizeMin.Y));
+ if (oldSize == ResizeableNode.Size) // Only move if size wasn't clamped
+ {
+ ResizeableNode.Location += uiControlDelta * resizeAxisNeg;
+ }
+ ResizeableNode.SizeValue = ResizeableNode.Size - emptySize;
+ ResizeableNode.SizeValue = new Float2(Mathf.Max(ResizeableNode.SizeValue.X, ResizeableNode.sizeMin.X), Mathf.Max(ResizeableNode.SizeValue.Y, ResizeableNode.sizeMin.Y));
+ ResizeableNode.CalculateNodeSize(ResizeableNode.Size.X, ResizeableNode.Size.Y);
+ UpdateSurfaceMouseLocation();
+ MatchResizeableNode(ResizeableNode.Size, ResizeableNode.Location);
+ }
+
+ if (IsMouseOverResizeBorder)
+ Cursor = CursorType;
+ else
+ Cursor = CursorType.Default;
+
+
+
+ base.OnMouseMove(location);
+ }
+
+ public override bool OnMouseDown(Float2 location, MouseButton button)
+ {
+ if (button == MouseButton.Left && IsMouseOverResizeBorder && !IsResizing)
+ {
+ // Start resizing
+ UpdateSurfaceMouseLocation();
+ IsResizing = true;
+ startResizingSize = ResizeableNode.Size;
+ StartMouseCapture();
+ return true;
+ }
+
+ return base.OnMouseDown(location, button);
+ }
+
+ public override bool OnMouseUp(Float2 location, MouseButton button)
+ {
+ if (button == MouseButton.Left && IsResizing)
+ {
+ Cursor = CursorType.Default;
+ EndResizing();
+ return true;
+ }
+
+ return base.OnMouseUp(location, button);
+ }
+
+ ///
+ public override void OnLostFocus()
+ {
+ if (IsResizing)
+ EndResizing();
+
+ base.OnLostFocus();
+ }
+
+ ///
+ public override void OnEndMouseCapture()
+ {
+ if (IsResizing)
+ EndResizing();
+
+ base.OnEndMouseCapture();
+ }
+
+ //public override void Draw()
+ //{
+ // Render2D.DrawRectangle(new Rectangle(Float2.Zero, Size), Color.Blue, 1f);
+ //}
+ }
+
+
+ private ResizeBorder resizeBorder;
///
/// Index of the Float2 value in the node values list to store node size.
@@ -31,7 +220,7 @@ namespace FlaxEditor.Surface
///
/// Minimum node size.
///
- protected Float2 _sizeMin = new Float2(240, 160);
+ protected Float2 sizeMin = new Float2(240, 160);
private Float2 SizeValue
{
@@ -43,12 +232,27 @@ namespace FlaxEditor.Surface
public ResizableSurfaceNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
: base(id, context, nodeArch, groupArch)
{
+ CullChildren = false;
+ ClipChildren = false;
+ resizeBorder = new ResizeBorder(Surface, this)
+ {
+ Parent = Surface.SurfaceRoot,
+ };
+
+ resizeBorder.MatchResizeableNode(Size, Location);
+ }
+
+ ///
+ protected override void OnLocationChanged()
+ {
+ resizeBorder.MatchResizeableNode(Size, Location);
+ base.OnLocationChanged();
}
///
public override bool CanSelect(ref Float2 location)
{
- return base.CanSelect(ref location);// && !_resizeButtonRect.MakeOffsetted(Location).Contains(ref location);
+ return base.CanSelect(ref location);
}
///
@@ -59,6 +263,7 @@ namespace FlaxEditor.Surface
if (Surface != null && Surface.GridSnappingEnabled)
size = Surface.SnapToGrid(size, true);
Resize(size.X, size.Y);
+ resizeBorder.MatchResizeableNode(Size, Location);
base.OnSurfaceLoaded(action);
}
@@ -77,161 +282,10 @@ namespace FlaxEditor.Surface
{
base.Draw();
- if (Surface.CanEdit && (_isResizing || _isMouseOverResizeBorder))
+ if (Surface.CanEdit && (resizeBorder.IsResizing || resizeBorder.IsMouseOverResizeBorder))
{
Render2D.DrawRectangle(new Rectangle(Float2.Zero, Size), Style.Current.Foreground, 2f);
}
}
-
- ///
- public override void OnLostFocus()
- {
- if (_isResizing)
- EndResizing();
-
- base.OnLostFocus();
- }
-
- ///
- public override void OnEndMouseCapture()
- {
- if (_isResizing)
- EndResizing();
-
- base.OnEndMouseCapture();
- }
-
- private bool UpdateIsOverResizeBorder(Float2 location)
- {
- const float ResizeBorderHalfWidth = 20f;
- const float ResizeOnAxisThreshold = 0.85f;
-
- var nodeRect = new Rectangle(Float2.Zero, Size);
- bool onBorder = nodeRect.MakeExpanded(ResizeBorderHalfWidth).Contains(location);
- var inNodeRect = nodeRect.MakeExpanded(-ResizeBorderHalfWidth);
- bool inNode = inNodeRect.Contains(location);
-
- Float2 rawResizeWeight = (location - nodeRect.Center) / (nodeRect.Size * 0.5f);
- _resizeWeight = new Float2(Mathf.Abs(rawResizeWeight.X) >= ResizeOnAxisThreshold ? Mathf.Sign(rawResizeWeight.X) : 0,
- Mathf.Abs(rawResizeWeight.Y) >= ResizeOnAxisThreshold ? Mathf.Sign(rawResizeWeight.Y) : 0);
-
- _isMouseOverResizeBorder = onBorder && !inNode;
- return onBorder && !inNode;
- }
-
- private CursorType ResizeWeightToCursorType()
- {
- if ((_resizeWeight.X == 1 && _resizeWeight.Y == 0) || (_resizeWeight.X == -1 && _resizeWeight.Y == 0))
- return CursorType.SizeWE;
- if ((_resizeWeight.X == 0 && _resizeWeight.Y == 1) || (_resizeWeight.X == 0 && _resizeWeight.Y == -1))
- return CursorType.SizeNS;
- if ((_resizeWeight.X == -1 && _resizeWeight.Y == -1) || (_resizeWeight.X == 1 && _resizeWeight.Y == 1))
- return CursorType.SizeNWSE;
- if ((_resizeWeight.X == 1 && _resizeWeight.Y == -1) || (_resizeWeight.X == -1 && _resizeWeight.Y == 1))
- return CursorType.SizeNESW;
- return CursorType.Default;
- }
-
- ///
- public override bool OnMouseDown(Float2 location, MouseButton button)
- {
- if (base.OnMouseDown(location, button))
- return true;
-
- if (button == MouseButton.Left && UpdateIsOverResizeBorder(location))
- {
- // Start resizing
- UpdateSurfaceMouseLocation();
- _isResizing = true;
- _startResizingSize = Size;
- StartMouseCapture();
- return true;
- }
-
- return false;
- }
-
- private Float2 GetControlDelta(Control control, ref Float2 start, ref Float2 end)
- {
- var pointOrigin = control.Parent ?? control;
- var startPos = pointOrigin.PointFromParent(this, start);
- var endPos = pointOrigin.PointFromParent(this, end);
- return endPos - startPos;
- }
-
- private void UpdateSurfaceMouseLocation()
- {
- _surfaceMouseLocation = Surface.PointFromScreen(Input.MouseScreenPosition);
- }
-
- ///
- public override void OnMouseMove(Float2 location)
- {
- if (_isResizing)
- {
- var resizeAxisAbs = _resizeWeight.Absolute;
- var resizeAxisPos = Float2.Clamp(_resizeWeight, Float2.Zero, Float2.One);
- var resizeAxisNeg = Float2.Clamp(-_resizeWeight, Float2.Zero, Float2.One);
-
- var delta = PointToParent(Surface, location) - _surfaceMouseLocation;
- // TODO: scale/size snapping?
- delta *= resizeAxisAbs;
-
- var moveLocation = _surfaceMouseLocation + delta;
-
- // TODO: Do I need GetControlDelta?
- var uiControlDelta = GetControlDelta(this, ref _surfaceMouseLocation, ref moveLocation);
- var emptySize = CalculateNodeSize(0, 0);
- Location += uiControlDelta * resizeAxisNeg;
- Size += uiControlDelta * resizeAxisPos - uiControlDelta * resizeAxisNeg;
- Size = new Float2(Mathf.Max(Size.X, _sizeMin.X), Mathf.Max(Size.Y, _sizeMin.Y));
- SizeValue = Size - emptySize;
- SizeValue = new Float2(Mathf.Max(SizeValue.X, _sizeMin.X), Mathf.Max(SizeValue.Y, _sizeMin.Y));
- CalculateNodeSize(Size.X, Size.Y);
- UpdateSurfaceMouseLocation();
- }
- else if (UpdateIsOverResizeBorder(location))
- {
- Cursor = ResizeWeightToCursorType();
- }
- else
- {
- Cursor = CursorType.Default;
- base.OnMouseMove(location);
- }
- }
-
- ///
- public override void OnMouseLeave()
- {
- Cursor = CursorType.Default;
- _isMouseOverResizeBorder = false;
- base.OnMouseLeave();
- }
-
- ///
- public override bool OnMouseUp(Float2 location, MouseButton button)
- {
- if (button == MouseButton.Left && _isResizing)
- {
- Cursor = CursorType.Default;
- EndResizing();
- return true;
- }
-
- return base.OnMouseUp(location, button);
- }
-
- private void EndResizing()
- {
- 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 aa0b0e811..05e89b705 100644
--- a/Source/Editor/Surface/SurfaceComment.cs
+++ b/Source/Editor/Surface/SurfaceComment.cs
@@ -56,7 +56,7 @@ namespace FlaxEditor.Surface
: base(id, context, nodeArch, groupArch)
{
_sizeValueIndex = 2; // Index of the Size stored in Values array
- _sizeMin = new Float2(140.0f, Constants.NodeHeaderSize);
+ sizeMin = new Float2(140.0f, Constants.NodeHeaderSize);
_renameTextBox = new TextBox(false, 0, 0, Width)
{
Height = Constants.NodeHeaderSize,