add visject node formatting option to straighten node connections
Also fixes a bunch of missing trailing "." in doc comments and changes "Node editors" category in the input options to "Node Editors" to match the case of all other categories.
This commit is contained in:
@@ -652,42 +652,46 @@ namespace FlaxEditor.Options
|
||||
|
||||
#endregion
|
||||
|
||||
#region Node editors
|
||||
#region Node Editors
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+W")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4500)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4500)]
|
||||
public InputBinding NodesAlignTop = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+A")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4510)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4510)]
|
||||
public InputBinding NodesAlignLeft = new InputBinding(KeyboardKeys.A, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+S")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4520)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4520)]
|
||||
public InputBinding NodesAlignBottom = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+D")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4530)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4530)]
|
||||
public InputBinding NodesAlignRight = new InputBinding(KeyboardKeys.D, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Alt+Shift+W")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4540)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4540)]
|
||||
public InputBinding NodesAlignMiddle = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift, KeyboardKeys.Alt);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Alt+Shift+S")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4550)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4550)]
|
||||
public InputBinding NodesAlignCenter = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift, KeyboardKeys.Alt);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Q")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4560)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4560)]
|
||||
public InputBinding NodesAutoFormat = new InputBinding(KeyboardKeys.Q);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+Q")]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4560)]
|
||||
public InputBinding NodesStraightenConnections = new InputBinding(KeyboardKeys.Q, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "None")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4570)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4570)]
|
||||
public InputBinding NodesDistributeHorizontal = new InputBinding(KeyboardKeys.None);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "None")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4580)]
|
||||
[EditorDisplay("Node Editors"), EditorOrder(4580)]
|
||||
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.None);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -5,39 +5,39 @@ using FlaxEngine;
|
||||
namespace FlaxEditor.Surface
|
||||
{
|
||||
/// <summary>
|
||||
/// Node Alignment type
|
||||
/// Node Alignment type.
|
||||
/// </summary>
|
||||
[HideInEditor]
|
||||
public enum NodeAlignmentType
|
||||
{
|
||||
/// <summary>
|
||||
/// Align nodes vertically to top, matching top-most node
|
||||
/// Align nodes vertically to top, matching top-most node.
|
||||
/// </summary>
|
||||
Top,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes vertically to middle, using average of all nodes
|
||||
/// Align nodes vertically to middle, using average of all nodes.
|
||||
/// </summary>
|
||||
Middle,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes vertically to bottom, matching bottom-most node
|
||||
/// Align nodes vertically to bottom, matching bottom-most node.
|
||||
/// </summary>
|
||||
Bottom,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes horizontally to left, matching left-most node
|
||||
/// Align nodes horizontally to left, matching left-most node.
|
||||
/// </summary>
|
||||
Left,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes horizontally to center, using average of all nodes
|
||||
/// Align nodes horizontally to center, using average of all nodes.
|
||||
/// </summary>
|
||||
Center,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes horizontally to right, matching right-most node
|
||||
/// Align nodes horizontally to right, matching right-most node.
|
||||
/// </summary>
|
||||
Right,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace FlaxEditor.Surface
|
||||
/// </summary>
|
||||
/// <param name="scriptType">The input type to process.</param>
|
||||
/// <param name="cache">Node groups cache that can be used for reusing groups for different nodes.</param>
|
||||
/// <param name="version">The cache version number. Can be used to reject any cached data after <see cref="NodesCache"/> rebuilt.</param>
|
||||
/// <param name="version">The cache version number. Can be used to reject any cached data after.<see cref="NodesCache"/> rebuilt.</param>
|
||||
public delegate void IterateType(ScriptType scriptType, Dictionary<KeyValuePair<string, ushort>, GroupArchetype> cache, int version);
|
||||
|
||||
internal static readonly List<NodesCache> Caches = new List<NodesCache>(8);
|
||||
@@ -412,6 +412,7 @@ namespace FlaxEditor.Surface
|
||||
_cmFormatNodesMenu.Enabled = CanEdit && HasNodesSelection;
|
||||
|
||||
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Auto format", Editor.Instance.Options.Options.Input.NodesAutoFormat, () => { FormatGraph(SelectedNodes); });
|
||||
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Straighten connections", Editor.Instance.Options.Options.Input.NodesStraightenConnections, () => { StraightenGraphConnections(SelectedNodes); });
|
||||
|
||||
_cmFormatNodesMenu.ContextMenu.AddSeparator();
|
||||
_cmAlignNodesTopButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align top", Editor.Instance.Options.Options.Input.NodesAlignTop, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Top); });
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using FlaxEditor.Surface.Elements;
|
||||
using FlaxEditor.Surface.Undo;
|
||||
using FlaxEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FlaxEngine;
|
||||
using FlaxEditor.Surface.Elements;
|
||||
using FlaxEditor.Surface.Undo;
|
||||
|
||||
namespace FlaxEditor.Surface
|
||||
{
|
||||
@@ -14,26 +14,26 @@ namespace FlaxEditor.Surface
|
||||
private class NodeFormattingData
|
||||
{
|
||||
/// <summary>
|
||||
/// Starting from 0 at the main nodes
|
||||
/// Starting from 0 at the main nodes.
|
||||
/// </summary>
|
||||
public int Layer;
|
||||
|
||||
/// <summary>
|
||||
/// Position in the layer
|
||||
/// Position in the layer.
|
||||
/// </summary>
|
||||
public int Offset;
|
||||
|
||||
/// <summary>
|
||||
/// How far the subtree needs to be moved additionally
|
||||
/// How far the subtree needs to be moved additionally.
|
||||
/// </summary>
|
||||
public int SubtreeOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a graph where the nodes can be disjointed.
|
||||
/// Uses the Sugiyama method
|
||||
/// Uses the Sugiyama method.
|
||||
/// </summary>
|
||||
/// <param name="nodes">List of nodes</param>
|
||||
/// <param name="nodes">List of nodes.</param>
|
||||
public void FormatGraph(List<SurfaceNode> nodes)
|
||||
{
|
||||
if (nodes.Count <= 1)
|
||||
@@ -78,9 +78,9 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a graph where all nodes are connected
|
||||
/// Formats a graph where all nodes are connected.
|
||||
/// </summary>
|
||||
/// <param name="nodes">List of connected nodes</param>
|
||||
/// <param name="nodes">List of connected nodes.</param>
|
||||
protected void FormatConnectedGraph(List<SurfaceNode> nodes)
|
||||
{
|
||||
if (nodes.Count <= 1)
|
||||
@@ -160,11 +160,69 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a layer to every node
|
||||
/// Straightens every connection between nodes in <paramref name="nodes"/>.
|
||||
/// </summary>
|
||||
/// <param name="nodeData">The exta node data</param>
|
||||
/// <param name="endNodes">The end nodes</param>
|
||||
/// <returns>The number of the maximum layer</returns>
|
||||
/// <param name="nodes">List of nodes.</param>
|
||||
public void StraightenGraphConnections(List<SurfaceNode> nodes)
|
||||
{
|
||||
if (nodes.Count <= 1)
|
||||
return;
|
||||
|
||||
List<MoveNodesAction> undoActions = new List<MoveNodesAction>();
|
||||
|
||||
// Only process nodes that have any connection
|
||||
List<SurfaceNode> connectedNodes = nodes.Where(n => n.GetBoxes().Any(b => b.HasAnyConnection)).ToList();
|
||||
|
||||
if (connectedNodes.Count == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < connectedNodes.Count - 1; i++)
|
||||
{
|
||||
SurfaceNode nodeA = connectedNodes[i];
|
||||
List<Box> connectedOutputBoxes = nodeA.GetBoxes().Where(b => b.IsOutput && b.HasAnyConnection).ToList();
|
||||
|
||||
for (int j = 0; j < connectedOutputBoxes.Count; j++)
|
||||
{
|
||||
Box boxA = connectedOutputBoxes[j];
|
||||
|
||||
for (int b = 0; b < boxA.Connections.Count; b++)
|
||||
{
|
||||
Box boxB = boxA.Connections[b];
|
||||
|
||||
// Ensure the other node is selected
|
||||
if (!connectedNodes.Contains(boxB.ParentNode))
|
||||
continue;
|
||||
|
||||
// Node with no outgoing connections reached. Advance to next node in list
|
||||
if (boxA == null || boxB == null)
|
||||
continue;
|
||||
|
||||
SurfaceNode nodeB = boxB.ParentNode;
|
||||
|
||||
// Calculate the Y offset needed for nodeB to align boxB's Y to boxA's Y
|
||||
float boxASurfaceY = boxA.PointToParent(this, Float2.Zero).Y;
|
||||
float boxBSurfaceY = boxB.PointToParent(this, Float2.Zero).Y;
|
||||
float deltaY = (boxASurfaceY - boxBSurfaceY) / ViewScale;
|
||||
Float2 delta = new Float2(0f, deltaY);
|
||||
|
||||
nodeB.Location += delta;
|
||||
|
||||
if (Undo != null)
|
||||
undoActions.Add(new MoveNodesAction(Context, new[] { nodeB.ID }, delta));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Undo?.AddAction(new MultiUndoAction(undoActions, "Straightned "));
|
||||
MarkAsEdited(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a layer to every node.
|
||||
/// </summary>
|
||||
/// <param name="nodeData">The exta node data.</param>
|
||||
/// <param name="endNodes">The end nodes.</param>
|
||||
/// <returns>The number of the maximum layer.</returns>
|
||||
private int SetLayers(Dictionary<SurfaceNode, NodeFormattingData> nodeData, List<SurfaceNode> endNodes)
|
||||
{
|
||||
// Longest path layering
|
||||
@@ -201,12 +259,12 @@ namespace FlaxEditor.Surface
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the node offsets
|
||||
/// Sets the node offsets.
|
||||
/// </summary>
|
||||
/// <param name="nodeData">The exta node data</param>
|
||||
/// <param name="endNodes">The end nodes</param>
|
||||
/// <param name="maxLayer">The number of the maximum layer</param>
|
||||
/// <returns>The number of the maximum offset</returns>
|
||||
/// <param name="nodeData">The exta node data.</param>
|
||||
/// <param name="endNodes">The end nodes.</param>
|
||||
/// <param name="maxLayer">The number of the maximum layer.</param>
|
||||
/// <returns>The number of the maximum offset.</returns>
|
||||
private int SetOffsets(Dictionary<SurfaceNode, NodeFormattingData> nodeData, List<SurfaceNode> endNodes, int maxLayer)
|
||||
{
|
||||
int maxOffset = 0;
|
||||
@@ -287,10 +345,10 @@ namespace FlaxEditor.Surface
|
||||
/// Align given nodes on a graph using the given alignment type.
|
||||
/// Ignores any potential overlap.
|
||||
/// </summary>
|
||||
/// <param name="nodes">List of nodes</param>
|
||||
/// <param name="alignmentType">Alignemnt type</param>
|
||||
/// <param name="nodes">List of nodes.</param>
|
||||
/// <param name="alignmentType">Alignemnt type.</param>
|
||||
public void AlignNodes(List<SurfaceNode> nodes, NodeAlignmentType alignmentType)
|
||||
{
|
||||
{
|
||||
if(nodes.Count <= 1)
|
||||
return;
|
||||
|
||||
@@ -328,8 +386,8 @@ namespace FlaxEditor.Surface
|
||||
/// <summary>
|
||||
/// Distribute the given nodes as equally as possible inside the bounding box, if no fit can be done it will use a default pad of 10 pixels between nodes.
|
||||
/// </summary>
|
||||
/// <param name="nodes">List of nodes</param>
|
||||
/// <param name="vertically">If false will be done horizontally, if true will be done vertically</param>
|
||||
/// <param name="nodes">List of nodes.</param>
|
||||
/// <param name="vertically">If false will be done horizontally, if true will be done vertically.</param>
|
||||
public void DistributeNodes(List<SurfaceNode> nodes, bool vertically)
|
||||
{
|
||||
if(nodes.Count <= 1)
|
||||
|
||||
@@ -416,6 +416,7 @@ namespace FlaxEditor.Surface
|
||||
new InputActionsContainer.Binding(options => options.Cut, Cut),
|
||||
new InputActionsContainer.Binding(options => options.Duplicate, Duplicate),
|
||||
new InputActionsContainer.Binding(options => options.NodesAutoFormat, () => { FormatGraph(SelectedNodes); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesStraightenConnections, () => { StraightenGraphConnections(SelectedNodes); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignTop, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Top); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignMiddle, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Middle); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignBottom, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Bottom); }),
|
||||
|
||||
Reference in New Issue
Block a user