mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 11:26:27 +00:00
Node script editor - Prevent creating loops
Node script popout editor - Added auto-layout hotkey (Ctrl+F)
This commit is contained in:
1 parent
65b8b377ec
commit
8e3b6c3459
4 files changed
+101
-19
No files matched your search
@@ -1,26 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Artemis.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for nodes.
|
||||
/// </summary>
|
||||
public static class NodeExtension
|
||||
{
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Estimates a height of a node in the editor.
|
||||
/// </summary>
|
||||
/// <param name="node">The node whose height to estimate.</param>
|
||||
/// <returns>The estimated height in pixels.</returns>
|
||||
public static double EstimateHeight(this INode node)
|
||||
{
|
||||
const double PIN_HEIGHT = 26;
|
||||
const double TITLE_HEIGHT = 46;
|
||||
|
||||
int inputPinCount = node.Pins.Count(x => x.Direction == PinDirection.Input)
|
||||
+ node.PinCollections.Where(x => x.Direction == PinDirection.Input).Sum(x => x.Count() + 1);
|
||||
+ node.PinCollections.Where(x => x.Direction == PinDirection.Input).Sum(x => x.Count() + 1);
|
||||
int outputPinCount = node.Pins.Count(x => x.Direction == PinDirection.Output)
|
||||
+ node.PinCollections.Where(x => x.Direction == PinDirection.Output).Sum(x => x.Count() + 1);
|
||||
+ node.PinCollections.Where(x => x.Direction == PinDirection.Output).Sum(x => x.Count() + 1);
|
||||
|
||||
return TITLE_HEIGHT + (Math.Max(inputPinCount, outputPinCount) * PIN_HEIGHT);
|
||||
return TITLE_HEIGHT + Math.Max(inputPinCount, outputPinCount) * PIN_HEIGHT;
|
||||
}
|
||||
|
||||
public static double EstimateWidth(this INode node) => 120; // DarthAffe 13.09.2022: For now just assume they are all the same size
|
||||
/// <summary>
|
||||
/// Estimates a width a node in the editor.
|
||||
/// </summary>
|
||||
/// <param name="node">The node whose width to estimate.</param>
|
||||
/// <returns>The estimated width in pixels.</returns>
|
||||
public static double EstimateWidth(this INode node)
|
||||
{
|
||||
// DarthAffe 13.09.2022: For now just assume they are all the same size
|
||||
return 120;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the node is part of a loop when the provided pending connecting would be connected.
|
||||
/// </summary>
|
||||
/// <param name="node">The node to check</param>
|
||||
/// <param name="pendingConnection">The node to which a connection is pending</param>
|
||||
/// <returns><see langword="true" /> if there would be a loop; otherwise <see langword="false" />.</returns>
|
||||
public static bool IsInLoop(this INode node, INode pendingConnection)
|
||||
{
|
||||
HashSet<INode> checkedNodes = new();
|
||||
|
||||
bool CheckNode(INode checkNode, INode? pending)
|
||||
{
|
||||
if (checkedNodes.Contains(checkNode)) return false;
|
||||
|
||||
checkedNodes.Add(checkNode);
|
||||
|
||||
List<INode> connectedNodes = checkNode.Pins
|
||||
.Where(x => x.Direction == PinDirection.Input)
|
||||
.SelectMany(x => x.ConnectedTo)
|
||||
.Select(x => x.Node)
|
||||
.Concat(checkNode.PinCollections
|
||||
.Where(x => x.Direction == PinDirection.Input)
|
||||
.SelectMany(x => x)
|
||||
.SelectMany(x => x.ConnectedTo)
|
||||
.Select(x => x.Node))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
if (pending != null)
|
||||
connectedNodes.Add(pending);
|
||||
|
||||
foreach (INode connectedNode in connectedNodes)
|
||||
{
|
||||
if (connectedNode == node)
|
||||
return true;
|
||||
else if (CheckNode(connectedNode, null))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return CheckNode(node, pendingConnection);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -3,10 +3,17 @@ using System.Linq;
|
||||
|
||||
namespace Artemis.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for node scripts.
|
||||
/// </summary>
|
||||
public static class NodeScriptExtension
|
||||
{
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Organize a node script, attempting to lay out nodes in a logical manner.
|
||||
/// </summary>
|
||||
/// <param name="nodeScript">The node script to organize.</param>
|
||||
public static void Organize(this NodeScript nodeScript)
|
||||
{
|
||||
const double SPACING_HORIZONTAL = 160;
|
||||
@@ -22,20 +29,22 @@ public static class NodeScriptExtension
|
||||
while (currentLevelNodes.Count > 0 && currentLevel < 1000)
|
||||
{
|
||||
List<INode> nextLevelNodes = currentLevelNodes.SelectMany(node => node.Pins
|
||||
.Where(x => x.Direction == PinDirection.Input)
|
||||
.SelectMany(x => x.ConnectedTo)
|
||||
.Select(x => x.Node)
|
||||
.Concat(node.PinCollections
|
||||
.Where(x => x.Direction == PinDirection.Input)
|
||||
.SelectMany(x => x)
|
||||
.SelectMany(x => x.ConnectedTo)
|
||||
.Select(x => x.Node)))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
.Where(x => x.Direction == PinDirection.Input)
|
||||
.SelectMany(x => x.ConnectedTo)
|
||||
.Select(x => x.Node)
|
||||
.Concat(node.PinCollections
|
||||
.Where(x => x.Direction == PinDirection.Input)
|
||||
.SelectMany(x => x)
|
||||
.SelectMany(x => x.ConnectedTo)
|
||||
.Select(x => x.Node)))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
foreach (INode nextLevelNode in nextLevelNodes)
|
||||
{
|
||||
if (currentLevel > levels[nextLevelNode])
|
||||
levels[nextLevelNode] = currentLevel;
|
||||
}
|
||||
|
||||
currentLevelNodes = nextLevelNodes;
|
||||
currentLevel++;
|
||||
@@ -60,7 +69,7 @@ public static class NodeScriptExtension
|
||||
foreach (IGrouping<int, INode> levelGroup in levels.GroupBy(x => x.Value, x => x.Key).OrderBy(x => x.Key))
|
||||
{
|
||||
List<INode> nodes = levelGroup.ToList();
|
||||
double levelHeight = nodes.Sum(x => x.EstimateHeight()) + ((nodes.Count - 1) * SPACING_VERTICAL);
|
||||
double levelHeight = nodes.Sum(x => x.EstimateHeight()) + (nodes.Count - 1) * SPACING_VERTICAL;
|
||||
double levelWidth = nodes.Max(x => x.EstimateWidth());
|
||||
double positionY = -(levelHeight / 2.0);
|
||||
|
||||
@@ -81,7 +90,7 @@ public static class NodeScriptExtension
|
||||
}
|
||||
|
||||
if (unusedNodes != null)
|
||||
LayoutLevel(unusedNodes, level0Width + (SPACING_HORIZONTAL / 2.0), unusedPosY);
|
||||
LayoutLevel(unusedNodes, level0Width + SPACING_HORIZONTAL / 2.0, unusedPosY);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in new issue
Block a user