Merge branch 'visject-improvements-6' of git://github.com/stefnotch/FlaxEngine into stefnotch-visject-improvements-6
This commit is contained in:
@@ -983,6 +983,103 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
}
|
||||
}
|
||||
|
||||
private class RerouteNode : SurfaceNode
|
||||
{
|
||||
public static readonly Vector2 DefaultSize = new Vector2(16);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool ShowTooltip => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public RerouteNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
|
||||
: base(id, context, nodeArch, groupArch)
|
||||
{
|
||||
Size = DefaultSize;
|
||||
Title = string.Empty;
|
||||
BackgroundColor = Color.Transparent;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnSurfaceLoaded()
|
||||
{
|
||||
base.OnSurfaceLoaded();
|
||||
|
||||
var inputBox = GetBox(0);
|
||||
var outputBox = GetBox(1);
|
||||
inputBox.Location = Vector2.Zero;
|
||||
outputBox.Location = Vector2.Zero;
|
||||
|
||||
UpdateBoxes();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ConnectionTick(Box box)
|
||||
{
|
||||
base.ConnectionTick(box);
|
||||
|
||||
UpdateBoxes();
|
||||
}
|
||||
|
||||
private void UpdateBoxes()
|
||||
{
|
||||
var inputBox = GetBox(0);
|
||||
var outputBox = GetBox(1);
|
||||
|
||||
inputBox.Visible = !inputBox.HasAnyConnection;
|
||||
outputBox.Visible = !outputBox.HasAnyConnection;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool CanSelect(ref Vector2 location)
|
||||
{
|
||||
return new Rectangle(Location, DefaultSize).Contains(ref location);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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 outputBox = GetBox(1);
|
||||
var connectionColor = style.Colors.Default;
|
||||
float barHorizontalOffset = -2;
|
||||
float barHeight = 3;
|
||||
|
||||
if (inputBox.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 hints = inputBox.Connections[0].ParentNode.Archetype.ConnectionsHints;
|
||||
Surface.Style.GetConnectionColor(inputBox.Connections[0].CurrentType, hints, out connectionColor);
|
||||
SpriteHandle icon = style.Icons.BoxClose;
|
||||
Render2D.DrawSprite(icon, new Rectangle(Vector2.Zero, DefaultSize), connectionColor);
|
||||
}
|
||||
|
||||
base.Draw();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The nodes for that group.
|
||||
/// </summary>
|
||||
@@ -1438,6 +1535,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, true),
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@ namespace FlaxEditor.Surface.ContextMenu
|
||||
var start = font.GetCharPosition(_archetype.Title, 0);
|
||||
var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
|
||||
_highlights.Add(new Rectangle(start.X + 2, 0, end.X - start.X, Height));
|
||||
_isFullMatch = true;
|
||||
Visible = true;
|
||||
}
|
||||
else if (NodeArchetype.TryParseText != null && NodeArchetype.TryParseText(filterText, out var data))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using System;
|
||||
|
||||
namespace FlaxEditor.Surface.Elements
|
||||
{
|
||||
@@ -12,6 +13,11 @@ namespace FlaxEditor.Surface.Elements
|
||||
[HideInEditor]
|
||||
public class OutputBox : Box
|
||||
{
|
||||
/// <summary>
|
||||
/// Distance for the mouse to be considered above the connection
|
||||
/// </summary>
|
||||
public float MouseOverConnectionDistance => 100f / Surface.ViewScale;
|
||||
|
||||
/// <inheritdoc />
|
||||
public OutputBox(SurfaceNode parentNode, NodeElementArchetype archetype)
|
||||
: base(parentNode, archetype, archetype.Position + new Vector2(parentNode.Archetype.Size.X, 0))
|
||||
@@ -43,23 +49,96 @@ namespace FlaxEditor.Surface.Elements
|
||||
*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a point intersects a connection
|
||||
/// </summary>
|
||||
/// <param name="targetBox">The other box.</param>
|
||||
/// <param name="mousePosition">The mouse position</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a point intersects a bezier curve
|
||||
/// </summary>
|
||||
/// <param name="start">The start location.</param>
|
||||
/// <param name="end">The end location.</param>
|
||||
/// <param name="point">The point</param>
|
||||
/// <param name="distance">Distance at which its an intersection</param>
|
||||
public static bool IntersectsConnection(ref Vector2 start, ref Vector2 end, ref Vector2 point, float distance)
|
||||
{
|
||||
// Pretty much a point in rectangle check
|
||||
if ((point.X - start.X) * (end.X - point.X) < 0) return false;
|
||||
|
||||
float offset = Mathf.Sign(end.Y - start.Y) * distance;
|
||||
if ((point.Y - (start.Y - offset)) * ((end.Y + offset) - point.Y) < 0) return false;
|
||||
|
||||
// Taken from the Render2D.DrawBezier code
|
||||
float squaredDistance = distance;
|
||||
|
||||
var dst = (end - start) * new Vector2(0.5f, 0.05f);
|
||||
Vector2 control1 = new Vector2(start.X + dst.X, start.Y + dst.Y);
|
||||
Vector2 control2 = new Vector2(end.X - dst.X, end.Y + dst.Y);
|
||||
|
||||
Vector2 d1 = control1 - start;
|
||||
Vector2 d2 = control2 - control1;
|
||||
Vector2 d3 = end - control2;
|
||||
float len = d1.Length + d2.Length + d3.Length;
|
||||
int segmentCount = Math.Min(Math.Max(Mathf.CeilToInt(len * 0.05f), 1), 100);
|
||||
float segmentCountInv = 1.0f / segmentCount;
|
||||
|
||||
Bezier(ref start, ref control1, ref control2, ref end, 0, out Vector2 p);
|
||||
for (int i = 1; i <= segmentCount; i++)
|
||||
{
|
||||
Vector2 oldp = p;
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void Bezier(ref Vector2 p0, ref Vector2 p1, ref Vector2 p2, ref Vector2 p3, float alpha, out Vector2 result)
|
||||
{
|
||||
Vector2.Lerp(ref p0, ref p1, alpha, out var p01);
|
||||
Vector2.Lerp(ref p1, ref p2, alpha, out var p12);
|
||||
Vector2.Lerp(ref p2, ref p3, alpha, out var p23);
|
||||
Vector2.Lerp(ref p01, ref p12, alpha, out var p012);
|
||||
Vector2.Lerp(ref p12, ref p23, alpha, out var p123);
|
||||
Vector2.Lerp(ref p012, ref p123, alpha, out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw all connections coming from this box.
|
||||
/// </summary>
|
||||
public void DrawConnections()
|
||||
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;
|
||||
|
||||
// TODO: Figure out how to only draw the topmost connection
|
||||
if (IntersectsConnection(ref startPos, ref endPos, ref mousePosition, mouseOverDistance))
|
||||
{
|
||||
highlight += 0.5f;
|
||||
}
|
||||
|
||||
DrawConnection(ref startPos, ref endPos, ref color, highlight);
|
||||
}
|
||||
}
|
||||
@@ -70,12 +149,9 @@ 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);
|
||||
DrawConnection(ref startPos, ref endPos, ref _currentTypeColor, 2);
|
||||
var startPos = Parent.PointToParent(Center);
|
||||
Vector2 endPos = targetBox.Parent.PointToParent(targetBox.Center);
|
||||
DrawConnection(ref startPos, ref endPos, ref _currentTypeColor, 2.5f);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -125,6 +125,7 @@ namespace FlaxEditor.Surface
|
||||
AutoFocus = false;
|
||||
TooltipText = nodeArch.Description;
|
||||
CullChildren = false;
|
||||
BackgroundColor = Style.Current.BackgroundNormal;
|
||||
|
||||
if (Archetype.DefaultValues != null)
|
||||
{
|
||||
@@ -552,19 +553,22 @@ namespace FlaxEditor.Surface
|
||||
|
||||
internal Box GetNextBox(Box box)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < Elements.Count; i++)
|
||||
// Get the one after it
|
||||
for (int i = box.IndexInParent + 1; i < Elements.Count; i++)
|
||||
{
|
||||
if (Elements[i] == box)
|
||||
if (Elements[i] is Box b)
|
||||
{
|
||||
// We found the box
|
||||
break;
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the one after it
|
||||
i++;
|
||||
for (; i < Elements.Count; i++)
|
||||
return null;
|
||||
}
|
||||
|
||||
internal Box GetPreviousBox(Box box)
|
||||
{
|
||||
// Get the one before it
|
||||
for (int i = box.IndexInParent - 1; i >= 0; i--)
|
||||
{
|
||||
if (Elements[i] is Box b)
|
||||
{
|
||||
@@ -754,29 +758,33 @@ namespace FlaxEditor.Surface
|
||||
{
|
||||
if (Elements[j] is OutputBox ob && ob.HasAnyConnection)
|
||||
{
|
||||
ob.DrawConnections();
|
||||
ob.DrawConnections(ref mousePosition);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws all selected connections between surface objects related to this node.
|
||||
/// </summary>
|
||||
/// <param name="selectedConnectionIndex">The index of the currently selected connection.</param>
|
||||
public void DrawSelectedConnections(int selectedConnectionIndex)
|
||||
{
|
||||
if (_isSelected)
|
||||
{
|
||||
bool hasBoxesSelection = HasBoxesSelection;
|
||||
for (int j = 0; j < Elements.Count; j++)
|
||||
if (HasBoxesSelection)
|
||||
{
|
||||
if (Elements[j] is Box box && box.HasAnyConnection && (!hasBoxesSelection || box.IsSelected))
|
||||
for (int j = 0; j < Elements.Count; j++)
|
||||
{
|
||||
if (box is OutputBox ob)
|
||||
if (Elements[j] is Box box && box.IsSelected && selectedConnectionIndex < box.Connections.Count)
|
||||
{
|
||||
for (int i = 0; i < ob.Connections.Count; i++)
|
||||
if (box is OutputBox ob)
|
||||
{
|
||||
ob.DrawSelectedConnection(ob.Connections[i]);
|
||||
ob.DrawSelectedConnection(ob.Connections[selectedConnectionIndex]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < box.Connections.Count; i++)
|
||||
else
|
||||
{
|
||||
if (box.Connections[i] is OutputBox outputBox)
|
||||
if (box.Connections[selectedConnectionIndex] is OutputBox outputBox)
|
||||
{
|
||||
outputBox.DrawSelectedConnection(box);
|
||||
}
|
||||
@@ -784,6 +792,32 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < Elements.Count; j++)
|
||||
{
|
||||
if (Elements[j] is Box box)
|
||||
{
|
||||
if (box is OutputBox ob)
|
||||
{
|
||||
for (int i = 0; i < ob.Connections.Count; i++)
|
||||
{
|
||||
ob.DrawSelectedConnection(ob.Connections[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < box.Connections.Count; i++)
|
||||
{
|
||||
if (box.Connections[i] is OutputBox outputBox)
|
||||
{
|
||||
outputBox.DrawSelectedConnection(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -943,7 +977,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)
|
||||
@@ -1006,7 +1040,7 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
|
||||
// Secondary Context Menu
|
||||
if (button == MouseButton.Right && false)
|
||||
if (button == MouseButton.Right)
|
||||
{
|
||||
if (!IsSelected)
|
||||
Surface.Select(this);
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace FlaxEditor.Surface.Undo
|
||||
/// The helper structure for Surface node box handle.
|
||||
/// </summary>
|
||||
[HideInEditor]
|
||||
public struct BoxHandle
|
||||
public struct BoxHandle : IEquatable<BoxHandle>
|
||||
{
|
||||
private readonly uint _nodeId;
|
||||
private readonly int _boxId;
|
||||
@@ -51,5 +51,27 @@ namespace FlaxEditor.Surface.Undo
|
||||
throw new Exception("Missing box.");
|
||||
return box;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is BoxHandle handle && Equals(handle);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(BoxHandle other)
|
||||
{
|
||||
return _nodeId == other._nodeId &&
|
||||
_boxId == other._boxId;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (_nodeId.GetHashCode() * 397) ^ _boxId.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,9 +106,12 @@ namespace FlaxEditor.Surface.Undo
|
||||
}
|
||||
for (int i = 0; i < output.Length; i++)
|
||||
{
|
||||
var box = output[i].Get(context);
|
||||
oB.Connections.Add(box);
|
||||
box.Connections.Add(oB);
|
||||
if (!output[i].Equals(_input))
|
||||
{
|
||||
var box = output[i].Get(context);
|
||||
oB.Connections.Add(box);
|
||||
box.Connections.Add(oB);
|
||||
}
|
||||
}
|
||||
|
||||
toUpdate.AddRange(iB.Connections);
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace FlaxEditor.Surface
|
||||
{
|
||||
for (int j = 0; j < node.Elements.Count; j++)
|
||||
{
|
||||
if (node.Elements[j] is Box box)
|
||||
if (node.Elements[j] is Box box && box.Connections.Count > 0)
|
||||
{
|
||||
var dataModelBox = new DataModelBox
|
||||
{
|
||||
|
||||
@@ -103,6 +103,7 @@ namespace FlaxEditor.Surface
|
||||
for (int i = 0; i < Nodes.Count; i++)
|
||||
{
|
||||
Nodes[i].DrawConnections(ref mousePosition);
|
||||
Nodes[i].DrawSelectedConnections(_selectedConnectionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -274,12 +274,47 @@ 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 InputBox inputBox, out OutputBox outputBox))
|
||||
{
|
||||
if (Undo != null)
|
||||
{
|
||||
bool undoEnabled = Undo.Enabled;
|
||||
Undo.Enabled = false;
|
||||
var rerouteNode = Context.SpawnNode(7, 29, mousePos);
|
||||
Undo.Enabled = undoEnabled;
|
||||
|
||||
var spawnNodeAction = new AddRemoveNodeAction(rerouteNode, true);
|
||||
|
||||
var disconnectBoxesAction = new ConnectBoxesAction(inputBox, outputBox, false);
|
||||
inputBox.BreakConnection(outputBox);
|
||||
disconnectBoxesAction.End();
|
||||
|
||||
var addConnectionsAction = new EditNodeConnections(Context, rerouteNode);
|
||||
outputBox.CreateConnection(rerouteNode.GetBoxes().First(b => !b.IsOutput));
|
||||
rerouteNode.GetBoxes().First(b => b.IsOutput).CreateConnection(inputBox);
|
||||
addConnectionsAction.End();
|
||||
|
||||
|
||||
Undo.AddAction(new MultiUndoAction(spawnNodeAction, disconnectBoxesAction, addConnectionsAction));
|
||||
}
|
||||
else
|
||||
{
|
||||
var rerouteNode = Context.SpawnNode(7, 29, mousePos);
|
||||
inputBox.BreakConnection(outputBox);
|
||||
outputBox.CreateConnection(rerouteNode.GetBoxes().First(b => !b.IsOutput));
|
||||
rerouteNode.GetBoxes().First(b => b.IsOutput).CreateConnection(inputBox);
|
||||
}
|
||||
MarkAsEdited();
|
||||
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return handled;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -527,6 +562,81 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (key == KeyboardKeys.ArrowUp || key == KeyboardKeys.ArrowDown)
|
||||
{
|
||||
Box selectedBox = GetSelectedBox(SelectedNodes);
|
||||
if (selectedBox == null) return true;
|
||||
|
||||
Box toSelect = (key == KeyboardKeys.ArrowUp) ?
|
||||
selectedBox?.ParentNode.GetPreviousBox(selectedBox) :
|
||||
selectedBox?.ParentNode.GetNextBox(selectedBox);
|
||||
|
||||
if (toSelect != null && toSelect.IsOutput == selectedBox.IsOutput)
|
||||
{
|
||||
Select(toSelect.ParentNode);
|
||||
toSelect.ParentNode.SelectBox(toSelect);
|
||||
}
|
||||
}
|
||||
|
||||
if (key == KeyboardKeys.Tab)
|
||||
{
|
||||
Box selectedBox = GetSelectedBox(SelectedNodes);
|
||||
if (selectedBox == null) return true;
|
||||
|
||||
int connectionCount = selectedBox.Connections.Count;
|
||||
if (connectionCount == 0) return true;
|
||||
|
||||
if (Root.GetKey(KeyboardKeys.Shift))
|
||||
{
|
||||
_selectedConnectionIndex = ((_selectedConnectionIndex - 1) % connectionCount + connectionCount) % connectionCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedConnectionIndex = (_selectedConnectionIndex + 1) % connectionCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (key == KeyboardKeys.ArrowRight || key == KeyboardKeys.ArrowLeft)
|
||||
{
|
||||
Box selectedBox = GetSelectedBox(SelectedNodes);
|
||||
if (selectedBox == null) return true;
|
||||
|
||||
Box toSelect = null;
|
||||
|
||||
if ((key == KeyboardKeys.ArrowRight && selectedBox.IsOutput) || (key == KeyboardKeys.ArrowLeft && !selectedBox.IsOutput))
|
||||
{
|
||||
if (_selectedConnectionIndex < 0 || _selectedConnectionIndex >= selectedBox.Connections.Count)
|
||||
{
|
||||
_selectedConnectionIndex = 0;
|
||||
}
|
||||
toSelect = selectedBox.Connections[_selectedConnectionIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the node with the closest Y-level
|
||||
// Since there are cases like 3 nodes on one side and only 1 node on the other side
|
||||
|
||||
var elements = selectedBox.ParentNode.Elements;
|
||||
float minDistance = float.PositiveInfinity;
|
||||
for (int i = 0; i < elements.Count; i++)
|
||||
{
|
||||
if (elements[i] is Box box && box.IsOutput != selectedBox.IsOutput && Mathf.Abs(box.Y - selectedBox.Y) < minDistance)
|
||||
{
|
||||
toSelect = box;
|
||||
minDistance = Mathf.Abs(box.Y - selectedBox.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toSelect != null)
|
||||
{
|
||||
Select(toSelect.ParentNode);
|
||||
toSelect.ParentNode.SelectBox(toSelect);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -720,5 +830,31 @@ namespace FlaxEditor.Surface
|
||||
yLocation
|
||||
);
|
||||
}
|
||||
|
||||
private bool IntersectsConnection(Vector2 mousePosition, out InputBox inputBox, out OutputBox outputBox)
|
||||
{
|
||||
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;
|
||||
inputBox = ob.Connections[k] as InputBox;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outputBox = null;
|
||||
inputBox = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace FlaxEditor.Surface
|
||||
private GroupArchetype _customNodesGroup;
|
||||
private List<NodeArchetype> _customNodes;
|
||||
private Action _onSave;
|
||||
private int _selectedConnectionIndex;
|
||||
|
||||
internal int _isUpdatingBoxTypes;
|
||||
|
||||
@@ -362,6 +363,8 @@ namespace FlaxEditor.Surface
|
||||
Context.ControlSpawned += OnSurfaceControlSpawned;
|
||||
Context.ControlDeleted += OnSurfaceControlDeleted;
|
||||
|
||||
SelectionChanged += () => { _selectedConnectionIndex = 0; };
|
||||
|
||||
// Init drag handlers
|
||||
DragHandlers.Add(_dragAssets = new DragAssets<DragDropEventArgs>(ValidateDragItem));
|
||||
DragHandlers.Add(_dragParameters = new DragNames<DragDropEventArgs>(SurfaceParameter.DragPrefix, ValidateDragParameter));
|
||||
|
||||
@@ -121,8 +121,11 @@ public:
|
||||
API_FIELD() static float PhysicsFPS;
|
||||
|
||||
/// <summary>
|
||||
/// The target amount of the frames rendered per second (actual game FPS).
|
||||
/// The target amount of the frames rendered per second (target game FPS).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To get the actual game FPS use <see cref="Engine.FramesPerSecond"/>
|
||||
/// </remarks>
|
||||
API_FIELD() static float DrawFPS;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -770,6 +770,11 @@ void ShaderGenerator::ProcessGroupTools(Box* box, Node* node, Value& value)
|
||||
#undef PLATFORM_CASE
|
||||
break;
|
||||
}
|
||||
case 29:
|
||||
{
|
||||
value = tryGetValue(node->GetBox(0), Value::Zero);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -738,6 +738,12 @@ void VisjectExecutor::ProcessGroupTools(Box* box, Node* node, Value& value)
|
||||
value = Scripting::FindObject<Actor>((Guid)node->Values[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
case 29:
|
||||
{
|
||||
value = tryGetValue(node->GetBox(0), Value::Zero);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user