diff --git a/src/Artemis.Core/VisualScripting/IPin.cs b/src/Artemis.Core/VisualScripting/IPin.cs index 9b2cb9245..69c11ed2c 100644 --- a/src/Artemis.Core/VisualScripting/IPin.cs +++ b/src/Artemis.Core/VisualScripting/IPin.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Artemis.VisualScripting.Model; namespace Artemis.Core.VisualScripting @@ -12,6 +13,8 @@ namespace Artemis.Core.VisualScripting Type Type { get; } object PinValue { get; } + IReadOnlyList ConnectedTo { get; } + bool IsEvaluated { get; set; } void ConnectTo(IPin pin); diff --git a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptPresenter.cs b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptPresenter.cs index 327c96be9..7da76fc75 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptPresenter.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptPresenter.cs @@ -213,13 +213,16 @@ namespace Artemis.VisualScripting.Editor.Controls InitializeNode(node); } + VisualScript?.RecreateCables(); + CenterAt(new Vector(0, 0)); } private void OnVisualScriptPropertyChanged(object sender, PropertyChangedEventArgs args) { if (args.PropertyName == nameof(VisualScript.Cables)) - _cableList.ItemsSource = VisualScript.Cables; + if (_cableList != null) + _cableList.ItemsSource = VisualScript.Cables; } private void OnCanvasPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs args) diff --git a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScript.cs b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScript.cs index 57fdaaa5b..3645e79b0 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScript.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScript.cs @@ -44,10 +44,10 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper public ObservableCollection Nodes { get; } = new(); - public IEnumerable Cables => Nodes.SelectMany(n => n.InputPins.SelectMany(p => p.Connections)) - .Concat(Nodes.SelectMany(n => n.OutputPins.SelectMany(p => p.Connections))) - .Concat(Nodes.SelectMany(n => n.InputPinCollections.SelectMany(p => p.Pins).SelectMany(p => p.Connections))) - .Concat(Nodes.SelectMany(n => n.OutputPinCollections.SelectMany(p => p.Pins).SelectMany(p => p.Connections))) + public IEnumerable Cables => Nodes.SelectMany(n => n.InputPins.SelectMany(p => p.InternalConnections)) + .Concat(Nodes.SelectMany(n => n.OutputPins.SelectMany(p => p.InternalConnections))) + .Concat(Nodes.SelectMany(n => n.InputPinCollections.SelectMany(p => p.Pins).SelectMany(p => p.InternalConnections))) + .Concat(Nodes.SelectMany(n => n.OutputPinCollections.SelectMany(p => p.Pins).SelectMany(p => p.InternalConnections))) .Distinct(); public bool IsConnecting => IsConnectingPin != null; @@ -184,6 +184,36 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper Script.RemoveNode(node.Node); } + internal void RecreateCables() + { + Dictionary pinMapping = Nodes.SelectMany(n => n.InputPins) + .Concat(Nodes.SelectMany(n => n.OutputPins)) + .Concat(Nodes.SelectMany(n => n.InputPinCollections.SelectMany(p => p.Pins))) + .Concat(Nodes.SelectMany(n => n.OutputPinCollections.SelectMany(p => p.Pins))) + .ToDictionary(p => p.Pin, p => p); + + foreach (VisualScriptPin pin in pinMapping.Values) + pin.InternalConnections.Clear(); + + HashSet connectedPins = new(); + foreach (IPin pin in pinMapping.Keys) + { + foreach (IPin connectedPin in pin.ConnectedTo) + if (!connectedPins.Contains(connectedPin)) + { + VisualScriptPin pin1 = pinMapping[pin]; + VisualScriptPin pin2 = pinMapping[connectedPin]; + VisualScriptCable cable = new(pin1, pin2, false); + pin1.InternalConnections.Add(cable); + pin2.InternalConnections.Add(cable); + } + + connectedPins.Add(pin); + } + + OnPropertyChanged(nameof(Cables)); + } + #endregion } } diff --git a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptCable.cs b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptCable.cs index 9fe3943ae..d3e939b32 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptCable.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptCable.cs @@ -28,6 +28,10 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper #region Constructors public VisualScriptCable(VisualScriptPin pin1, VisualScriptPin pin2) + : this(pin1, pin2, true) + { } + + internal VisualScriptCable(VisualScriptPin pin1, VisualScriptPin pin2, bool connect) { if ((pin1.Pin.Direction == PinDirection.Input) && (pin2.Pin.Direction == PinDirection.Input)) throw new ArgumentException("Can't connect two input pins."); @@ -38,8 +42,11 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper From = pin1.Pin.Direction == PinDirection.Output ? pin1 : pin2; To = pin1.Pin.Direction == PinDirection.Input ? pin1 : pin2; - From.ConnectTo(this); - To.ConnectTo(this); + if (connect) + { + From.ConnectTo(this); + To.ConnectTo(this); + } } #endregion diff --git a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPin.cs b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPin.cs index 00b6e5184..793b9a6ec 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPin.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/Wrapper/VisualScriptPin.cs @@ -26,7 +26,8 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper public VisualScriptNode Node { get; } public IPin Pin { get; } - public ObservableCollection Connections { get; } = new(); + public IReadOnlyCollection Connections => new ReadOnlyCollection(InternalConnections); + internal ObservableCollection InternalConnections { get; } = new(); private Point _absolutePosition; public Point AbsolutePosition @@ -39,7 +40,8 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper } } - public Point AbsoluteCableTargetPosition => Pin.Direction == PinDirection.Input ? new Point(AbsolutePosition.X - CABLE_OFFSET, AbsolutePosition.Y) : new Point(AbsolutePosition.X + CABLE_OFFSET, AbsolutePosition.Y); + public Point AbsoluteCableTargetPosition => Pin.Direction == PinDirection.Input ? new Point(AbsolutePosition.X - CABLE_OFFSET, AbsolutePosition.Y) + : new Point(AbsolutePosition.X + CABLE_OFFSET, AbsolutePosition.Y); #endregion @@ -62,7 +64,8 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper if (_isConnectingCable != null) SetConnecting(false); - _isConnectingPin = new VisualScriptPin(null, new IsConnectingPin(Pin.Direction == PinDirection.Input ? PinDirection.Output : PinDirection.Input)) { AbsolutePosition = AbsolutePosition }; + _isConnectingPin = new VisualScriptPin(null, new IsConnectingPin(Pin.Direction == PinDirection.Input ? PinDirection.Output : PinDirection.Input, Pin.Type)) + { AbsolutePosition = AbsolutePosition }; _isConnectingCable = new VisualScriptCable(this, _isConnectingPin); Node.OnIsConnectingPinChanged(_isConnectingPin); } @@ -77,16 +80,16 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper internal void ConnectTo(VisualScriptCable cable) { - if (Connections.Contains(cable)) return; + if (InternalConnections.Contains(cable)) return; if (Pin.Direction == PinDirection.Input) { - List cables = Connections.ToList(); + List cables = InternalConnections.ToList(); foreach (VisualScriptCable c in cables) c.Disconnect(); } - Connections.Add(cable); + InternalConnections.Add(cable); Pin.ConnectTo(cable.GetConnectedPin(Pin)); Node?.OnPinConnected(new PinConnectedEventArgs(this, cable)); @@ -94,14 +97,14 @@ namespace Artemis.VisualScripting.Editor.Controls.Wrapper public void DisconnectAll() { - List cables = Connections.ToList(); + List cables = InternalConnections.ToList(); foreach (VisualScriptCable cable in cables) cable.Disconnect(); } internal void Disconnect(VisualScriptCable cable) { - Connections.Remove(cable); + InternalConnections.Remove(cable); Pin.DisconnectFrom(cable.GetConnectedPin(Pin)); Node?.OnPinDisconnected(new PinDisconnectedEventArgs(this, cable));