diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs
index 2b63bdfb2..6330b27dd 100644
--- a/Source/Editor/Surface/Archetypes/Tools.cs
+++ b/Source/Editor/Surface/Archetypes/Tools.cs
@@ -983,6 +983,115 @@ namespace FlaxEditor.Surface.Archetypes
}
}
+ private class RerouteNode : SurfaceNode
+ {
+ public static readonly Vector2 DefaultSize = new Vector2(16);
+
+ private bool _deleteNode;
+
+ ///
+ protected override bool ShowTooltip => false;
+
+ ///
+ public RerouteNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
+ : base(id, context, nodeArch, groupArch)
+ {
+ Size = DefaultSize;
+ Title = string.Empty;
+ BackgroundColor = Color.Transparent;
+ }
+
+ ///
+ public override void OnSurfaceLoaded()
+ {
+ base.OnSurfaceLoaded();
+
+ var inputBox = GetBox(0);
+ var outputBox = GetBox(1);
+ inputBox.Location = Vector2.Zero;
+ outputBox.Location = Vector2.Zero;
+
+ inputBox.Visible = false;
+ outputBox.Visible = false;
+ }
+
+ ///
+ public override void ConnectionTick(Box box)
+ {
+ base.ConnectionTick(box);
+
+ var inputBox = GetBox(0);
+ var outputBox = GetBox(1);
+
+ _deleteNode = !inputBox.HasAnyConnection;
+ outputBox.Visible = !outputBox.HasAnyConnection;
+ }
+
+ /*public override void OnDeleted()
+ {
+ var inputBox = GetBox(0);
+ var outputBox = GetBox(1);
+
+ var connectionA = inputBox.HasAnyConnection ? inputBox.Connections[0] : null; // This doesn't work
+ var connectionB = outputBox.HasAnyConnection ? outputBox.Connections[0] : null;
+
+ base.OnDeleted();
+
+ if (connectionA != null && connectionB != null)
+ {
+ connectionA.CreateConnection(connectionB); // TODO: handle undo
+ }
+ }*/
+
+ public override void Update(float deltaTime)
+ {
+ base.Update(deltaTime);
+
+ if (_deleteNode)
+ {
+ _deleteNode = false;
+ Surface.Delete(this); // TODO: handle undo
+ }
+ }
+
+
+ ///
+ public override bool CanSelect(ref Vector2 location)
+ {
+ return new Rectangle(Location, DefaultSize).Contains(ref location);
+ }
+
+ ///
+ protected override void UpdateRectangles()
+ {
+ _headerRect = Rectangle.Empty;
+ _closeButtonRect = Rectangle.Empty;
+ _footerRect = Rectangle.Empty;
+ }
+
+ public override void Draw()
+ {
+ var style = Surface.Style;
+ var inputBox = GetBox(0);
+ var connectionColor = style.Colors.Default;
+
+ if (inputBox.HasAnyConnection)
+ {
+ var hints = inputBox.Connections[0].ParentNode.Archetype.ConnectionsHints;
+ Surface.Style.GetConnectionColor(inputBox.Connections[0].CurrentType, hints, out connectionColor);
+ }
+
+ //float barHeight = 4;
+ //Render2D.FillRectangle(new Rectangle(DefaultSize.X / 2, (DefaultSize.Y - barHeight) / 2, barHeight * 4, barHeight), connectionColor);
+
+ SpriteHandle icon = style.Icons.BoxClose;
+ Render2D.DrawSprite(icon, new Rectangle(Vector2.Zero, DefaultSize), connectionColor);
+
+ base.Draw();
+
+ }
+ }
+
///
/// The nodes for that group.
///
@@ -1438,6 +1547,23 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Input(0, string.Empty, true, typeof(object), 1),
}
},
+ new NodeArchetype
+ {
+ TypeID = 29,
+ Title = "Reroute",
+ Create = (id, context, arch, groupArch) => new RerouteNode(id, context, arch, groupArch),
+ Description = "Reroute a connection.",
+ Flags = NodeFlags.NoCloseButton | NodeFlags.NoSpawnViaGUI | NodeFlags.AllGraphs,
+ Size = RerouteNode.DefaultSize,
+ ConnectionsHints = ConnectionsHint.All,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1 },
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, string.Empty, true, null, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 1),
+ }
+ },
};
}
}
diff --git a/Source/Editor/Surface/Elements/OutputBox.cs b/Source/Editor/Surface/Elements/OutputBox.cs
index 852132baf..683c7eebd 100644
--- a/Source/Editor/Surface/Elements/OutputBox.cs
+++ b/Source/Editor/Surface/Elements/OutputBox.cs
@@ -13,6 +13,11 @@ namespace FlaxEditor.Surface.Elements
[HideInEditor]
public class OutputBox : Box
{
+ ///
+ /// Distance for the mouse to be considered above the connection
+ ///
+ public float MouseOverConnectionDistance => 100f / Surface.ViewScale;
+
///
public OutputBox(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(parentNode, archetype, archetype.Position + new Vector2(parentNode.Archetype.Size.X, 0))
@@ -44,6 +49,18 @@ namespace FlaxEditor.Surface.Elements
*/
}
+ ///
+ /// Checks if a point intersects a connection
+ ///
+ /// The other box.
+ /// The mouse position
+ public bool IntersectsConnection(Box targetBox, ref Vector2 mousePosition)
+ {
+ var startPos = Parent.PointToParent(Center);
+ Vector2 endPos = targetBox.Parent.PointToParent(targetBox.Center);
+ return IntersectsConnection(ref startPos, ref endPos, ref mousePosition, MouseOverConnectionDistance);
+ }
+
///
/// Checks if a point intersects a bezier curve
///
@@ -53,8 +70,6 @@ namespace FlaxEditor.Surface.Elements
/// Distance at which its an intersection
public static bool IntersectsConnection(ref Vector2 start, ref Vector2 end, ref Vector2 point, float distance)
{
- // Maybe I should make this a non-static method and automatically read the Surface.ViewScale?
-
// Pretty much a point in rectangle check
if ((point.X - start.X) * (end.X - point.X) < 0) return false;
@@ -82,6 +97,7 @@ namespace FlaxEditor.Surface.Elements
float t = i * segmentCountInv;
Bezier(ref start, ref control1, ref control2, ref end, t, out p);
+ // Maybe it would be reasonable to return the point?
CollisionsHelper.ClosestPointPointLine(ref point, ref oldp, ref p, out Vector2 result);
if (Vector2.DistanceSquared(point, result) <= squaredDistance)
{
@@ -106,22 +122,21 @@ namespace FlaxEditor.Surface.Elements
///
public void DrawConnections(ref Vector2 mousePosition)
{
+ float mouseOverDistance = MouseOverConnectionDistance;
// Draw all the connections
- var center = Size * 0.5f;
- var tmp = PointToParent(ref center);
- var startPos = Parent.PointToParent(ref tmp);
+ var startPos = Parent.PointToParent(Center);
var startHighlight = ConnectionsHighlightIntensity;
for (int i = 0; i < Connections.Count; i++)
{
Box targetBox = Connections[i];
- tmp = targetBox.PointToParent(ref center);
- Vector2 endPos = targetBox.Parent.PointToParent(ref tmp);
+ Vector2 endPos = targetBox.Parent.PointToParent(targetBox.Center);
var highlight = 1 + Mathf.Max(startHighlight, targetBox.ConnectionsHighlightIntensity);
var color = _currentTypeColor * highlight;
- if (IntersectsConnection(ref startPos, ref endPos, ref mousePosition, 100f / Surface.ViewScale))
+ // TODO: Figure out how to only draw the topmost connection
+ if (IntersectsConnection(ref startPos, ref endPos, ref mousePosition, mouseOverDistance))
{
- highlight += 2;
+ highlight += 1;
}
DrawConnection(ref startPos, ref endPos, ref color, highlight);
@@ -134,11 +149,8 @@ namespace FlaxEditor.Surface.Elements
public void DrawSelectedConnection(Box targetBox)
{
// Draw all the connections
- var center = Size * 0.5f;
- var tmp = PointToParent(ref center);
- var startPos = Parent.PointToParent(ref tmp);
- tmp = targetBox.PointToParent(ref center);
- Vector2 endPos = targetBox.Parent.PointToParent(ref tmp);
+ var startPos = Parent.PointToParent(Center);
+ Vector2 endPos = targetBox.Parent.PointToParent(targetBox.Center);
DrawConnection(ref startPos, ref endPos, ref _currentTypeColor, 2);
}
diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs
index d1ea32da7..3c544dbdd 100644
--- a/Source/Editor/Surface/SurfaceNode.cs
+++ b/Source/Editor/Surface/SurfaceNode.cs
@@ -125,6 +125,7 @@ namespace FlaxEditor.Surface
AutoFocus = false;
TooltipText = nodeArch.Description;
CullChildren = false;
+ BackgroundColor = Style.Current.BackgroundNormal;
if (Archetype.DefaultValues != null)
{
@@ -947,7 +948,7 @@ namespace FlaxEditor.Surface
// Background
var backgroundRect = new Rectangle(Vector2.Zero, Size);
- Render2D.FillRectangle(backgroundRect, style.BackgroundNormal);
+ Render2D.FillRectangle(backgroundRect, BackgroundColor);
// Breakpoint hit
if (Breakpoint.Hit)
diff --git a/Source/Editor/Surface/VisjectSurface.Input.cs b/Source/Editor/Surface/VisjectSurface.Input.cs
index 28cff42b8..b28ac340f 100644
--- a/Source/Editor/Surface/VisjectSurface.Input.cs
+++ b/Source/Editor/Surface/VisjectSurface.Input.cs
@@ -274,12 +274,24 @@ namespace FlaxEditor.Surface
bool handled = base.OnMouseDoubleClick(location, button);
if (!handled)
CustomMouseDoubleClick?.Invoke(ref location, button, ref handled);
- if (handled)
+
+ if (!handled)
{
- return true;
+ var mousePos = _rootControl.PointFromParent(ref _mousePos);
+ if (IntersectsConnection(mousePos, out OutputBox outputBox, out Box connectedBox))
+ {
+ var rerouteNode = Context.SpawnNode(7, 29, mousePos);
+
+ // TODO: Undo action
+ outputBox.BreakConnection(connectedBox);
+ outputBox.CreateConnection(rerouteNode.GetBoxes().First(b => !b.IsOutput));
+ rerouteNode.GetBoxes().First(b => b.IsOutput).CreateConnection(connectedBox);
+
+ handled = true;
+ }
}
- return false;
+ return handled;
}
///
@@ -815,5 +827,31 @@ namespace FlaxEditor.Surface
yLocation
);
}
+
+ private bool IntersectsConnection(Vector2 mousePosition, out OutputBox outputBox, out Box connectedBox)
+ {
+ for (int i = 0; i < Nodes.Count; i++)
+ {
+ for (int j = 0; j < Nodes[i].Elements.Count; j++)
+ {
+ if (Nodes[i].Elements[j] is OutputBox ob)
+ {
+ for (int k = 0; k < ob.Connections.Count; k++)
+ {
+ if (ob.IntersectsConnection(ob.Connections[k], ref mousePosition))
+ {
+ outputBox = ob;
+ connectedBox = ob.Connections[k];
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ outputBox = null;
+ connectedBox = null;
+ return false;
+ }
}
}