From 7c83d5345fe33ec2af9b508e84fd4207d82366fe Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 30 Mar 2022 20:10:43 +0200 Subject: [PATCH] Nodes - Reorganized code --- .../Profile/Colors/ColorGradientStop.cs | 2 +- .../Models/Profile/DataModel/DataModelPath.cs | 2 +- src/Artemis.Core/RGB.NET/SKTextureBrush.cs | 2 +- src/Artemis.Core/Utilities/MaxStack.cs | 4 +- .../VisualScripting/Internal/ExitNode.cs | 4 +- src/Artemis.Core/VisualScripting/Node.cs | 15 + .../Controls/EnumComboBox.axaml.cs | 6 +- .../Services/NodeEditor/Commands/AddNode.cs | 4 +- .../NodeEditor/Commands/DeleteNode.cs | 55 +--- .../NodeEditor/NodeConnectionStore.cs | 73 +++++ src/Artemis.UI.Shared/ViewModelBase.cs | 2 +- .../VisualScripting/NodePickerView.axaml | 10 +- .../Screens/Workshop/WorkshopViewModel.cs | 1 + .../Services/RegistrationService.cs | 1 + .../Artemis.VisualScripting.csproj | 7 +- .../Nodes/BoolOperations.cs | 299 ------------------ .../ConvertToNumericNode.cs} | 34 +- .../Nodes/Conversion/ConvertToStringNode.cs | 35 ++ .../EnumEqualsNodeCustomViewModel.cs | 49 --- .../LayerPropertyNodeCustomViewModel.cs | 73 ----- .../Nodes/DataModel/DataModelEventNode.cs | 2 +- .../Nodes/DataModel/DataModelNode.cs | 2 +- .../DataModelEventNodeCustomView.axaml | 6 +- .../DataModelEventNodeCustomView.axaml.cs | 5 +- .../DataModelEventNodeCustomViewModel.cs | 2 +- .../DataModelNodeCustomView.axaml | 6 +- .../DataModelNodeCustomView.axaml.cs | 5 +- .../DataModelNodeCustomViewModel.cs | 3 +- .../Nodes/Easing/EasingTypeNode.cs | 2 +- .../EasingTypeNodeCustomView.axaml | 6 +- .../EasingTypeNodeCustomView.axaml.cs | 5 +- .../EasingTypeNodeCustomViewModel.cs | 8 +- .../EasingTypeNodeEasingView.axaml} | 6 +- .../EasingTypeNodeEasingView.axaml.cs} | 7 +- .../EasingTypeNodeEasingViewModel.cs} | 6 +- ...eLayerPropertyNodeSelectedLayerProperty.cs | 45 +++ ...LayerPropertyNodeSelectedProfileElement.cs | 54 ++++ .../Nodes/{ => External}/LayerPropertyNode.cs | 60 +++- .../Screens/LayerPropertyNodeCustomView.axaml | 24 ++ .../LayerPropertyNodeCustomView.axaml.cs | 18 ++ .../LayerPropertyNodeCustomViewModel.cs | 93 ++++++ .../MathExpressionNode.cs} | 49 +-- .../Mathematics/PinsVariablesContainer.cs | 48 +++ .../Nodes/{Maths => Mathematics}/RoundNode.cs | 2 +- .../MathExpressionNodeCustomView.axaml | 6 +- .../MathExpressionNodeCustomView.axaml.cs | 3 +- .../MathExpressionNodeCustomViewModel.cs | 4 +- .../Nodes/{ => Mathematics}/SumNode.cs | 2 +- .../Nodes/Operators/AndNode.cs | 34 ++ .../Nodes/Operators/EnumEqualsNode.cs | 36 +++ .../Nodes/Operators/EqualsNode.cs | 44 +++ .../Nodes/Operators/GreaterThanNode.cs | 57 ++++ .../Nodes/Operators/LessThanNode.cs | 57 ++++ .../Nodes/Operators/NegateNode.cs | 34 ++ .../Nodes/Operators/OrNode.cs | 34 ++ .../Screens/EnumEqualsNodeCustomView.axaml | 15 + .../Screens/EnumEqualsNodeCustomView.axaml.cs | 18 ++ .../Screens/EnumEqualsNodeCustomViewModel.cs | 59 ++++ .../Nodes/Operators/XorNode.cs | 34 ++ .../StaticNumericValueNodeCustomView.axaml | 6 +- .../StaticNumericValueNodeCustomView.axaml.cs | 4 +- .../StaticNumericValueNodeCustomViewModel.cs} | 22 +- .../StaticSKColorValueNodeCustomView.axaml | 6 +- .../StaticSKColorValueNodeCustomView.axaml.cs | 3 +- .../StaticSKColorValueNodeCustomViewModel.cs | 2 +- .../StaticStringValueNodeCustomView.axaml | 6 +- .../StaticStringValueNodeCustomView.axaml.cs | 4 +- .../Screens/StaticValueNodeViewModels.cs | 27 ++ .../Nodes/Static/StaticNumericValueNode.cs | 33 ++ .../StaticSKColorValueNode.cs | 4 +- .../Nodes/Static/StaticStringValueNode.cs | 33 ++ .../Nodes/StaticValueNodes.cs | 62 ---- .../Nodes/{ => Text}/StringFormatNode.cs | 2 +- 73 files changed, 1055 insertions(+), 738 deletions(-) create mode 100644 src/Artemis.UI.Shared/Services/NodeEditor/NodeConnectionStore.cs delete mode 100644 src/Artemis.VisualScripting/Nodes/BoolOperations.cs rename src/Artemis.VisualScripting/Nodes/{ConvertNodes.cs => Conversion/ConvertToNumericNode.cs} (60%) create mode 100644 src/Artemis.VisualScripting/Nodes/Conversion/ConvertToStringNode.cs delete mode 100644 src/Artemis.VisualScripting/Nodes/CustomViewModels/EnumEqualsNodeCustomViewModel.cs delete mode 100644 src/Artemis.VisualScripting/Nodes/CustomViewModels/LayerPropertyNodeCustomViewModel.cs rename src/Artemis.VisualScripting/Nodes/DataModel/{CustomViews => Screens}/DataModelEventNodeCustomView.axaml (77%) rename src/Artemis.VisualScripting/Nodes/DataModel/{CustomViews => Screens}/DataModelEventNodeCustomView.axaml.cs (70%) rename src/Artemis.VisualScripting/Nodes/DataModel/{CustomViewModels => Screens}/DataModelEventNodeCustomViewModel.cs (98%) rename src/Artemis.VisualScripting/Nodes/DataModel/{CustomViews => Screens}/DataModelNodeCustomView.axaml (74%) rename src/Artemis.VisualScripting/Nodes/DataModel/{CustomViews => Screens}/DataModelNodeCustomView.axaml.cs (69%) rename src/Artemis.VisualScripting/Nodes/DataModel/{CustomViewModels => Screens}/DataModelNodeCustomViewModel.cs (97%) rename src/Artemis.VisualScripting/Nodes/Easing/{CustomViews => Screens}/EasingTypeNodeCustomView.axaml (64%) rename src/Artemis.VisualScripting/Nodes/Easing/{CustomViews => Screens}/EasingTypeNodeCustomView.axaml.cs (70%) rename src/Artemis.VisualScripting/Nodes/Easing/{CustomViewModels => Screens}/EasingTypeNodeCustomViewModel.cs (71%) rename src/Artemis.VisualScripting/Nodes/Easing/{CustomViews/NodeEasingView.axaml => Screens/EasingTypeNodeEasingView.axaml} (75%) rename src/Artemis.VisualScripting/Nodes/Easing/{CustomViews/NodeEasingView.axaml.cs => Screens/EasingTypeNodeEasingView.axaml.cs} (59%) rename src/Artemis.VisualScripting/Nodes/Easing/{CustomViewModels/NodeEasingViewModel.cs => Screens/EasingTypeNodeEasingViewModel.cs} (74%) create mode 100644 src/Artemis.VisualScripting/Nodes/External/Commands/UpdateLayerPropertyNodeSelectedLayerProperty.cs create mode 100644 src/Artemis.VisualScripting/Nodes/External/Commands/UpdateLayerPropertyNodeSelectedProfileElement.cs rename src/Artemis.VisualScripting/Nodes/{ => External}/LayerPropertyNode.cs (54%) create mode 100644 src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomView.axaml create mode 100644 src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomView.axaml.cs create mode 100644 src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomViewModel.cs rename src/Artemis.VisualScripting/Nodes/{Maths/ExpressionNode.cs => Mathematics/MathExpressionNode.cs} (70%) create mode 100644 src/Artemis.VisualScripting/Nodes/Mathematics/PinsVariablesContainer.cs rename src/Artemis.VisualScripting/Nodes/{Maths => Mathematics}/RoundNode.cs (92%) rename src/Artemis.VisualScripting/Nodes/{Maths/CustomViews => Mathematics/Screens}/MathExpressionNodeCustomView.axaml (66%) rename src/Artemis.VisualScripting/Nodes/{Maths/CustomViews => Mathematics/Screens}/MathExpressionNodeCustomView.axaml.cs (80%) rename src/Artemis.VisualScripting/Nodes/{Maths/CustomViewModels => Mathematics/Screens}/MathExpressionNodeCustomViewModel.cs (93%) rename src/Artemis.VisualScripting/Nodes/{ => Mathematics}/SumNode.cs (93%) create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomView.axaml create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomView.axaml.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomViewModel.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs rename src/Artemis.VisualScripting/Nodes/{CustomViews => Static/Screens}/StaticNumericValueNodeCustomView.axaml (79%) rename src/Artemis.VisualScripting/Nodes/{CustomViews => Static/Screens}/StaticNumericValueNodeCustomView.axaml.cs (75%) rename src/Artemis.VisualScripting/Nodes/{CustomViewModels/StaticValueNodeViewModels.cs => Static/Screens/StaticNumericValueNodeCustomViewModel.cs} (54%) rename src/Artemis.VisualScripting/Nodes/{Color/CustomViews => Static/Screens}/StaticSKColorValueNodeCustomView.axaml (85%) rename src/Artemis.VisualScripting/Nodes/{Color/CustomViews => Static/Screens}/StaticSKColorValueNodeCustomView.axaml.cs (84%) rename src/Artemis.VisualScripting/Nodes/{Color/CustomViewModels => Static/Screens}/StaticSKColorValueNodeCustomViewModel.cs (96%) rename src/Artemis.VisualScripting/Nodes/{CustomViews => Static/Screens}/StaticStringValueNodeCustomView.axaml (71%) rename src/Artemis.VisualScripting/Nodes/{CustomViews => Static/Screens}/StaticStringValueNodeCustomView.axaml.cs (75%) create mode 100644 src/Artemis.VisualScripting/Nodes/Static/Screens/StaticValueNodeViewModels.cs create mode 100644 src/Artemis.VisualScripting/Nodes/Static/StaticNumericValueNode.cs rename src/Artemis.VisualScripting/Nodes/{Color => Static}/StaticSKColorValueNode.cs (87%) create mode 100644 src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs delete mode 100644 src/Artemis.VisualScripting/Nodes/StaticValueNodes.cs rename src/Artemis.VisualScripting/Nodes/{ => Text}/StringFormatNode.cs (94%) diff --git a/src/Artemis.Core/Models/Profile/Colors/ColorGradientStop.cs b/src/Artemis.Core/Models/Profile/Colors/ColorGradientStop.cs index 8f19b2b95..205c772ff 100644 --- a/src/Artemis.Core/Models/Profile/Colors/ColorGradientStop.cs +++ b/src/Artemis.Core/Models/Profile/Colors/ColorGradientStop.cs @@ -23,7 +23,7 @@ namespace Artemis.Core return false; if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) + if (obj.GetType() != GetType()) return false; return Equals((ColorGradientStop) obj); } diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs index c6ee7ce90..6aaaf0ee9 100644 --- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs @@ -376,7 +376,7 @@ namespace Artemis.Core { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (obj.GetType() != GetType()) return false; return Equals((DataModelPath) obj); } diff --git a/src/Artemis.Core/RGB.NET/SKTextureBrush.cs b/src/Artemis.Core/RGB.NET/SKTextureBrush.cs index be238d83f..c3d5705a9 100644 --- a/src/Artemis.Core/RGB.NET/SKTextureBrush.cs +++ b/src/Artemis.Core/RGB.NET/SKTextureBrush.cs @@ -26,7 +26,7 @@ namespace Artemis.Core /// The texture drawn by this brush. public SKTextureBrush(SKTexture? texture) { - this.Texture = texture; + Texture = texture; } #endregion diff --git a/src/Artemis.Core/Utilities/MaxStack.cs b/src/Artemis.Core/Utilities/MaxStack.cs index 8af6f9a2b..7b80c060c 100644 --- a/src/Artemis.Core/Utilities/MaxStack.cs +++ b/src/Artemis.Core/Utilities/MaxStack.cs @@ -90,7 +90,7 @@ namespace Artemis.Core public bool IsTop(T value) { bool result = false; - if (this.Count > 0) + if (Count > 0) { result = Peek()!.Equals(value); } @@ -100,7 +100,7 @@ namespace Artemis.Core public bool Contains(T value) { bool result = false; - if (this.Count > 0) + if (Count > 0) { result = _list.Contains(value); } diff --git a/src/Artemis.Core/VisualScripting/Internal/ExitNode.cs b/src/Artemis.Core/VisualScripting/Internal/ExitNode.cs index a3808cc62..978aa3f76 100644 --- a/src/Artemis.Core/VisualScripting/Internal/ExitNode.cs +++ b/src/Artemis.Core/VisualScripting/Internal/ExitNode.cs @@ -19,8 +19,8 @@ public ExitNode(string name, string description = "") { - this.Name = name; - this.Description = description; + Name = name; + Description = description; Input = CreateInputPin(); } diff --git a/src/Artemis.Core/VisualScripting/Node.cs b/src/Artemis.Core/VisualScripting/Node.cs index 5e8f003f1..c81d54ade 100644 --- a/src/Artemis.Core/VisualScripting/Node.cs +++ b/src/Artemis.Core/VisualScripting/Node.cs @@ -167,6 +167,21 @@ public abstract class Node : CorePropertyChanged, INode return isRemoved; } + /// + /// Adds an existing to the collection. + /// + /// The pin to add + protected void AddPin(Pin pin) + { + if (pin.Node != this) + throw new ArtemisCoreException("Can't add a pin to a node that belongs to a different node than the one it's being added to."); + if (_pins.Contains(pin)) + return; + + _pins.Add(pin); + OnPropertyChanged(nameof(Pins)); + } + /// /// Creates a new input pin collection and adds it to the collection /// diff --git a/src/Artemis.UI.Shared/Controls/EnumComboBox.axaml.cs b/src/Artemis.UI.Shared/Controls/EnumComboBox.axaml.cs index f04f5572d..c172e11af 100644 --- a/src/Artemis.UI.Shared/Controls/EnumComboBox.axaml.cs +++ b/src/Artemis.UI.Shared/Controls/EnumComboBox.axaml.cs @@ -24,6 +24,7 @@ namespace Artemis.UI.Shared.Controls private readonly ObservableCollection<(Enum, string)> _currentValues = new(); private ComboBox? _enumComboBox; + private Type _currentType; /// /// Creates a new instance of the class. @@ -69,11 +70,14 @@ namespace Artemis.UI.Shared.Controls private void UpdateValues() { Type? newType = Value?.GetType(); - if (_enumComboBox == null || _currentValues.Any() || newType is not {IsEnum: true}) + if (_enumComboBox == null || newType == null || _currentType == newType) return; + _currentValues.Clear(); foreach ((Enum, string) valueDesc in EnumUtilities.GetAllValuesAndDescriptions(newType)) _currentValues.Add(valueDesc); + + _currentType = newType; } private void UpdateSelection() diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs index 45b4a9b59..6229fd4e8 100644 --- a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs +++ b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs @@ -45,8 +45,8 @@ public class AddNode : INodeEditorCommand, IDisposable /// public void Dispose() { - if (_isRemoved) - _nodeScript.Dispose(); + if (_isRemoved && _node is IDisposable disposableNode) + disposableNode.Dispose(); } #endregion diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DeleteNode.cs b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DeleteNode.cs index 5886c5993..e216c295a 100644 --- a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DeleteNode.cs +++ b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DeleteNode.cs @@ -11,7 +11,7 @@ public class DeleteNode : INodeEditorCommand, IDisposable { private readonly INode _node; private readonly INodeScript _nodeScript; - private readonly Dictionary> _pinConnections = new(); + private readonly NodeConnectionStore _connections; private bool _isRemoved; /// @@ -23,58 +23,15 @@ public class DeleteNode : INodeEditorCommand, IDisposable { _nodeScript = nodeScript; _node = node; - } - private void StoreConnections() - { - _pinConnections.Clear(); - foreach (IPin nodePin in _node.Pins) - { - _pinConnections.Add(nodePin, new List(nodePin.ConnectedTo)); - nodePin.DisconnectAll(); - } - - foreach (IPinCollection nodePinCollection in _node.PinCollections) - { - foreach (IPin nodePin in nodePinCollection) - { - _pinConnections.Add(nodePin, new List(nodePin.ConnectedTo)); - nodePin.DisconnectAll(); - } - } - } - - private void RestoreConnections() - { - foreach (IPin nodePin in _node.Pins) - { - if (_pinConnections.TryGetValue(nodePin, out List? connections)) - { - foreach (IPin connection in connections) - nodePin.ConnectTo(connection); - } - } - - foreach (IPinCollection nodePinCollection in _node.PinCollections) - { - foreach (IPin nodePin in nodePinCollection) - { - if (_pinConnections.TryGetValue(nodePin, out List? connections)) - { - foreach (IPin connection in connections) - nodePin.ConnectTo(connection); - } - } - } - - _pinConnections.Clear(); + _connections = new NodeConnectionStore(_node); } /// public void Dispose() { - if (_isRemoved) - _nodeScript.Dispose(); + if (_isRemoved && _node is IDisposable disposableNode) + disposableNode.Dispose(); } /// @@ -83,7 +40,7 @@ public class DeleteNode : INodeEditorCommand, IDisposable /// public void Execute() { - StoreConnections(); + _connections.Store(); _nodeScript.RemoveNode(_node); _isRemoved = true; @@ -93,7 +50,7 @@ public class DeleteNode : INodeEditorCommand, IDisposable public void Undo() { _nodeScript.AddNode(_node); - RestoreConnections(); + _connections.Restore(); _isRemoved = false; } diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/NodeConnectionStore.cs b/src/Artemis.UI.Shared/Services/NodeEditor/NodeConnectionStore.cs new file mode 100644 index 000000000..1d8582a11 --- /dev/null +++ b/src/Artemis.UI.Shared/Services/NodeEditor/NodeConnectionStore.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using Artemis.Core; + +namespace Artemis.UI.Shared.Services.NodeEditor; + +/// +/// Represents a class that can store and restore a node's connections +/// +public class NodeConnectionStore +{ + private readonly Dictionary> _pinConnections = new(); + + /// + /// Creates a new instance of the class. + /// + /// The node whose connections to store + public NodeConnectionStore(INode node) + { + Node = node; + } + + /// + /// Gets the node this instance will store connections for. + /// + public INode Node { get; } + + /// + /// Stores and clears the current connections of the node + /// + public void Store() + { + _pinConnections.Clear(); + foreach (IPin nodePin in Node.Pins) + { + _pinConnections.Add(nodePin, new List(nodePin.ConnectedTo)); + nodePin.DisconnectAll(); + } + + foreach (IPinCollection nodePinCollection in Node.PinCollections) + { + foreach (IPin nodePin in nodePinCollection) + { + _pinConnections.Add(nodePin, new List(nodePin.ConnectedTo)); + nodePin.DisconnectAll(); + } + } + } + + /// + /// Restores the connections of the node as they were during the last call. + /// + public void Restore() + { + foreach (IPin nodePin in Node.Pins) + { + if (_pinConnections.TryGetValue(nodePin, out List? connections)) + foreach (IPin connection in connections) + nodePin.ConnectTo(connection); + } + + foreach (IPinCollection nodePinCollection in Node.PinCollections) + { + foreach (IPin nodePin in nodePinCollection) + { + if (_pinConnections.TryGetValue(nodePin, out List? connections)) + foreach (IPin connection in connections) + nodePin.ConnectTo(connection); + } + } + + _pinConnections.Clear(); + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/ViewModelBase.cs b/src/Artemis.UI.Shared/ViewModelBase.cs index d28200871..6d68c4b9e 100644 --- a/src/Artemis.UI.Shared/ViewModelBase.cs +++ b/src/Artemis.UI.Shared/ViewModelBase.cs @@ -58,7 +58,7 @@ public abstract class ViewModelValidationBase : ReactiveValidationObject public string? DisplayName { get => _displayName; - set => this.RaiseAndSetIfChanged(ref _displayName, value); + set => RaiseAndSetIfChanged(ref _displayName, value); } /// diff --git a/src/Artemis.UI/Screens/VisualScripting/NodePickerView.axaml b/src/Artemis.UI/Screens/VisualScripting/NodePickerView.axaml index 9025e35c8..1d5f3d0c3 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodePickerView.axaml +++ b/src/Artemis.UI/Screens/VisualScripting/NodePickerView.axaml @@ -30,15 +30,15 @@ - - - +