diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs
index 9ed131f58..d924f69f5 100644
--- a/Source/Editor/Surface/Archetypes/Tools.cs
+++ b/Source/Editor/Surface/Archetypes/Tools.cs
@@ -1007,10 +1007,13 @@ namespace FlaxEditor.Surface.Archetypes
}
}
- private class RerouteNode : SurfaceNode
+ internal class RerouteNode : SurfaceNode, IConnectionInstigator
{
internal static readonly Float2 DefaultSize = new Float2(FlaxEditor.Surface.Constants.BoxSize);
private Rectangle _localBounds;
+ private InputBox _input;
+ private OutputBox _output;
+ private bool _isMouseDown, _isConnecting;
///
public RerouteNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
@@ -1023,7 +1026,7 @@ namespace FlaxEditor.Surface.Archetypes
}
///
- protected override bool ShowTooltip => _localBounds.Contains(ref _mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened;
+ protected override bool ShowTooltip => !string.IsNullOrEmpty(TooltipText) && _localBounds.Contains(ref _mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened;
///
public override bool OnTestTooltipOverControl(ref Float2 location)
@@ -1047,11 +1050,21 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnSurfaceLoaded();
- var inputBox = GetBox(0);
- var outputBox = GetBox(1);
- inputBox.Location = Float2.Zero;
- outputBox.Location = Float2.Zero;
+ _input = (InputBox)GetBox(0);
+ _output = (OutputBox)GetBox(1);
+ _input.Location = Float2.Zero;
+ _output.Location = Float2.Zero;
+ _input.Visible = false;
+ _output.Visible = false;
+
+ _input.CurrentTypeChanged += OnInputBoxTypeChanged;
+
+ UpdateBoxes();
+ }
+
+ private void OnInputBoxTypeChanged(Box inputBox)
+ {
UpdateBoxes();
}
@@ -1065,15 +1078,23 @@ namespace FlaxEditor.Surface.Archetypes
private void UpdateBoxes()
{
- var inputBox = GetBox(0);
- var outputBox = GetBox(1);
+ if (Surface == null)
+ return;
- inputBox.Visible = !inputBox.HasAnyConnection;
- outputBox.Visible = !outputBox.HasAnyConnection;
- if (Surface != null)
+ var type = _input.CurrentType;
+ if (_input.TooltipText != null)
{
- TooltipText = Surface.GetTypeName(inputBox.HasAnyConnection ? inputBox.CurrentType : outputBox.CurrentType);
+ TooltipText = _input.TooltipText;
}
+ else
+ {
+ type = _input.HasAnyConnection ? _input.CurrentType : _output.CurrentType;
+ TooltipText = Surface.GetTypeName(type);
+ }
+
+ var isImpulse = type.IsVoid;
+ _input.IsSingle = !isImpulse;
+ _output.IsSingle = isImpulse;
}
///
@@ -1090,42 +1111,153 @@ namespace FlaxEditor.Surface.Archetypes
_footerRect = Rectangle.Empty;
}
+ ///
public override void Draw()
{
var style = Surface.Style;
- var inputBox = GetBox(0);
- var outputBox = GetBox(1);
var connectionColor = style.Colors.Default;
+ var type = ScriptType.Null;
float barHorizontalOffset = -2;
float barHeight = 3;
- if (inputBox.HasAnyConnection)
+ if (_input.HasAnyConnection)
{
- var hints = inputBox.Connections[0].ParentNode.Archetype.ConnectionsHints;
- Surface.Style.GetConnectionColor(inputBox.Connections[0].CurrentType, hints, out connectionColor);
- }
-
- if (!inputBox.HasAnyConnection)
- {
- Render2D.FillRectangle(new Rectangle(-barHorizontalOffset - barHeight * 2, (DefaultSize.Y - barHeight) / 2, barHeight * 2, barHeight), connectionColor);
- }
-
- if (!outputBox.HasAnyConnection)
- {
- Render2D.FillRectangle(new Rectangle(DefaultSize.X + barHorizontalOffset, (DefaultSize.Y - barHeight) / 2, barHeight * 2, barHeight), connectionColor);
- }
-
- if (inputBox.HasAnyConnection && outputBox.HasAnyConnection)
- {
- var type = inputBox.Connections[0].CurrentType;
- var hints = inputBox.Connections[0].ParentNode.Archetype.ConnectionsHints;
+ type = _input.Connections[0].CurrentType;
+ var hints = _input.Connections[0].ParentNode.Archetype.ConnectionsHints;
Surface.Style.GetConnectionColor(type, hints, out connectionColor);
- var icon = type.IsVoid ? style.Icons.ArrowClose : style.Icons.BoxClose;
- Render2D.DrawSprite(icon, _localBounds, connectionColor);
}
+ if (!_input.HasAnyConnection)
+ Render2D.FillRectangle(new Rectangle(-barHorizontalOffset - barHeight * 2, (DefaultSize.Y - barHeight) / 2, barHeight * 2, barHeight), connectionColor);
+ if (!_output.HasAnyConnection)
+ Render2D.FillRectangle(new Rectangle(DefaultSize.X + barHorizontalOffset, (DefaultSize.Y - barHeight) / 2, barHeight * 2, barHeight), connectionColor);
+
+ SpriteHandle icon;
+ if (_input.HasAnyConnection && _output.HasAnyConnection)
+ icon = type.IsVoid ? style.Icons.ArrowClose : style.Icons.BoxClose;
+ else
+ icon = type.IsVoid ? style.Icons.ArrowOpen : style.Icons.BoxOpen;
+ Render2D.DrawSprite(icon, _localBounds, connectionColor);
+
base.Draw();
}
+
+ ///
+ public override bool OnMouseDown(Float2 location, MouseButton button)
+ {
+ if (base.OnMouseDown(location, button))
+ return true;
+
+ if (button == MouseButton.Left)
+ {
+ _isMouseDown = true;
+ _isConnecting = _localBounds.MakeExpanded(-10.0f).Contains(ref location); // Inner area for connecting, outer area for moving
+ if (_isConnecting)
+ {
+ Focus();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ public override void OnMouseLeave()
+ {
+ if (_isMouseDown)
+ {
+ _isMouseDown = false;
+ if (Surface.CanEdit && _isConnecting)
+ Surface.ConnectingStart(this);
+ }
+ base.OnMouseLeave();
+ }
+
+ ///
+ public override void OnMouseMove(Float2 location)
+ {
+ Surface.ConnectingOver(this);
+ base.OnMouseMove(location);
+ }
+
+ ///
+ public override bool OnMouseUp(Float2 location, MouseButton button)
+ {
+ if (base.OnMouseUp(location, button))
+ return true;
+
+ if (button == MouseButton.Left)
+ {
+ _isMouseDown = false;
+ if (Surface.IsConnecting)
+ Surface.ConnectingEnd(this);
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ public Float2 ConnectionOrigin
+ {
+ get
+ {
+ var center = _localBounds.Center;
+ return PointToParent(ref center);
+ }
+ }
+
+ ///
+ public bool AreConnected(IConnectionInstigator other)
+ {
+ return _input.AreConnected(other) || _output.AreConnected(other);
+ }
+
+ ///
+ public bool CanConnectWith(IConnectionInstigator other)
+ {
+ if (other is InputBox otherInput)
+ {
+ return _output.CanConnectWith(otherInput);
+ }
+ if (other is OutputBox otherOutput)
+ {
+ return _input.CanConnectWith(otherOutput);
+ }
+ if (other is RerouteNode otherReroute)
+ {
+ if (_output.CurrentType.IsVoid)
+ return otherReroute._input.CanConnectWith(_output);
+ return otherReroute._output.CanConnectWith(_input);
+ }
+ return false;
+ }
+
+ ///
+ public void DrawConnectingLine(ref Float2 startPos, ref Float2 endPos, ref Color color)
+ {
+ OutputBox.DrawConnection(ref startPos, ref endPos, ref color, 2);
+ }
+
+ ///
+ public void Connect(IConnectionInstigator other)
+ {
+ if (other is InputBox otherInput)
+ {
+ _output.Connect(otherInput);
+ }
+ if (other is OutputBox otherOutput)
+ {
+ _input.Connect(otherOutput);
+ }
+ if (other is RerouteNode otherReroute)
+ {
+ if (_output.CurrentType.IsVoid)
+ otherReroute._input.Connect(_output);
+ else
+ otherReroute._output.Connect(_input);
+ }
+ }
}
///
diff --git a/Source/Editor/Surface/Elements/Box.cs b/Source/Editor/Surface/Elements/Box.cs
index 49340afb1..ddf8e59d0 100644
--- a/Source/Editor/Surface/Elements/Box.cs
+++ b/Source/Editor/Surface/Elements/Box.cs
@@ -17,7 +17,7 @@ namespace FlaxEditor.Surface.Elements
[HideInEditor]
public abstract class Box : SurfaceNodeElementControl, IConnectionInstigator
{
- private bool _isMouseDown;
+ private bool _isMouseDown, _isSingle;
private DateTime _lastHighlightConnectionsTime = DateTime.MinValue;
private string _originalTooltipText;
@@ -180,6 +180,7 @@ namespace FlaxEditor.Surface.Elements
: base(parentNode, archetype, location, new Float2(Constants.BoxSize), false)
{
_currentType = DefaultType;
+ _isSingle = Archetype.Single;
Text = Archetype.Text;
if (Surface != null)
{
@@ -317,18 +318,18 @@ namespace FlaxEditor.Surface.Elements
///
/// Removes all existing connections of that box.
///
- public void RemoveConnections()
+ /// Amount of connection to skip from removing.
+ public void RemoveConnections(int skipCount = 0)
{
- // Check if sth is connected
- if (HasAnyConnection)
+ if (Connections.Count > skipCount)
{
// Remove all connections
- var toUpdate = new List(1 + Connections.Count)
+ var toUpdate = new List(1 + skipCount)
{
this
};
- for (int i = 0; i < Connections.Count; i++)
+ for (int i = skipCount; i < Connections.Count; i++)
{
var targetBox = Connections[i];
targetBox.Connections.Remove(this);
@@ -419,7 +420,34 @@ namespace FlaxEditor.Surface.Elements
///
/// True if box can use only single connection.
///
- public bool IsSingle => Archetype.Single;
+ public bool IsSingle
+ {
+ get => _isSingle;
+ set
+ {
+ if (_isSingle != value)
+ {
+ _isSingle = value;
+
+ // Limit connections COUNT
+ if (_isSingle && Connections.Count > 0)
+ {
+ if (Surface.Undo != null)
+ {
+ var action = new EditNodeConnections(ParentNode.Context, ParentNode);
+ RemoveConnections(1);
+ action.End();
+ Surface.Undo.AddAction(action);
+ }
+ else
+ {
+ RemoveConnections(1);
+ }
+ Surface.MarkAsEdited();
+ }
+ }
+ }
+ }
///
/// True if box type depends on other boxes types of the node.
@@ -710,6 +738,9 @@ namespace FlaxEditor.Surface.Elements
///
public bool CanConnectWith(IConnectionInstigator other)
{
+ if (other is Archetypes.Tools.RerouteNode reroute)
+ return reroute.CanConnectWith(this);
+
var start = this;
var end = other as Box;
@@ -788,6 +819,12 @@ namespace FlaxEditor.Surface.Elements
///
public void Connect(IConnectionInstigator other)
{
+ if (other is Archetypes.Tools.RerouteNode reroute)
+ {
+ reroute.Connect(this);
+ return;
+ }
+
var start = this;
var end = (Box)other;
var areConnected = start.AreConnected(end);
diff --git a/Source/Editor/Surface/VisjectSurface.Input.cs b/Source/Editor/Surface/VisjectSurface.Input.cs
index e359715e0..ddd4ae565 100644
--- a/Source/Editor/Surface/VisjectSurface.Input.cs
+++ b/Source/Editor/Surface/VisjectSurface.Input.cs
@@ -312,6 +312,7 @@ namespace FlaxEditor.Surface
var mousePos = _rootControl.PointFromParent(ref _mousePos);
if (IntersectsConnection(mousePos, out InputBox inputBox, out OutputBox outputBox) && GetControlUnderMouse() == null)
{
+ // Insert reroute node
if (Undo != null)
{
bool undoEnabled = Undo.Enabled;