diff --git a/ExampleCalculatorApp/ViewModels/Nodes/ConstantNodeViewModel.cs b/ExampleCalculatorApp/ViewModels/Nodes/ConstantNodeViewModel.cs index d7549af..4fb4973 100644 --- a/ExampleCalculatorApp/ViewModels/Nodes/ConstantNodeViewModel.cs +++ b/ExampleCalculatorApp/ViewModels/Nodes/ConstantNodeViewModel.cs @@ -27,7 +27,7 @@ public ConstantNodeViewModel() Editor = ValueEditor, Value = this.WhenAnyValue(vm => vm.ValueEditor.Value) }; - this.Outputs.Add(Output); + this.EditableOutputs().Add(Output); } } } diff --git a/ExampleCalculatorApp/ViewModels/Nodes/DivisionNodeViewModel.cs b/ExampleCalculatorApp/ViewModels/Nodes/DivisionNodeViewModel.cs index b25cd07..4c3f21a 100644 --- a/ExampleCalculatorApp/ViewModels/Nodes/DivisionNodeViewModel.cs +++ b/ExampleCalculatorApp/ViewModels/Nodes/DivisionNodeViewModel.cs @@ -28,14 +28,14 @@ public DivisionNodeViewModel() Name = "A", Editor = new IntegerValueEditorViewModel() }; - Inputs.Add(Input1); + EditableInputs().Add(Input1); Input2 = new ValueNodeInputViewModel { Name = "B", Editor = new IntegerValueEditorViewModel() }; - Inputs.Add(Input2); + EditableInputs().Add(Input2); var divide = this.WhenAnyValue(vm => vm.Input1.Value, vm => vm.Input2.Value) .Select(_ => Input1.Value != null && Input2.Value != null && Input2.Value != 0 ? Input1.Value / Input2.Value : null); @@ -45,7 +45,7 @@ public DivisionNodeViewModel() Name = "A / B", Value = divide }; - Outputs.Add(Output); + EditableOutputs().Add(Output); } } } diff --git a/ExampleCalculatorApp/ViewModels/Nodes/OutputNodeViewModel.cs b/ExampleCalculatorApp/ViewModels/Nodes/OutputNodeViewModel.cs index e36d91e..5ffddcd 100644 --- a/ExampleCalculatorApp/ViewModels/Nodes/OutputNodeViewModel.cs +++ b/ExampleCalculatorApp/ViewModels/Nodes/OutputNodeViewModel.cs @@ -26,7 +26,7 @@ public OutputNodeViewModel() Name = "Value", Editor = new IntegerValueEditorViewModel() }; - this.Inputs.Add(ResultInput); + this.EditableInputs().Add(ResultInput); } } } diff --git a/ExampleCalculatorApp/ViewModels/Nodes/ProductNodeViewModel.cs b/ExampleCalculatorApp/ViewModels/Nodes/ProductNodeViewModel.cs index 0662b36..323dc7a 100644 --- a/ExampleCalculatorApp/ViewModels/Nodes/ProductNodeViewModel.cs +++ b/ExampleCalculatorApp/ViewModels/Nodes/ProductNodeViewModel.cs @@ -27,14 +27,14 @@ public ProductNodeViewModel() Name = "A", Editor = new IntegerValueEditorViewModel() }; - Inputs.Add(Input1); + EditableInputs().Add(Input1); Input2 = new ValueNodeInputViewModel { Name = "B", Editor = new IntegerValueEditorViewModel() }; - Inputs.Add(Input2); + EditableInputs().Add(Input2); var product = this.WhenAnyValue(vm => vm.Input1.Value, vm => vm.Input2.Value) .Select(_ => Input1.Value != null && Input2.Value != null ? Input1.Value * Input2.Value : null); @@ -44,7 +44,7 @@ public ProductNodeViewModel() Name = "A * B", Value = product }; - Outputs.Add(Output); + EditableOutputs().Add(Output); } } } diff --git a/ExampleCalculatorApp/ViewModels/Nodes/SubtractionNodeViewModel.cs b/ExampleCalculatorApp/ViewModels/Nodes/SubtractionNodeViewModel.cs index b40f99a..b0ff640 100644 --- a/ExampleCalculatorApp/ViewModels/Nodes/SubtractionNodeViewModel.cs +++ b/ExampleCalculatorApp/ViewModels/Nodes/SubtractionNodeViewModel.cs @@ -27,14 +27,14 @@ public SubtractionNodeViewModel() Name = "A", Editor = new IntegerValueEditorViewModel() }; - Inputs.Add(Input1); + EditableInputs().Add(Input1); Input2 = new ValueNodeInputViewModel { Name = "B", Editor = new IntegerValueEditorViewModel() }; - Inputs.Add(Input2); + EditableInputs().Add(Input2); var subtract = this.WhenAnyValue(vm => vm.Input1.Value, vm => vm.Input2.Value) .Select(_ => Input1.Value != null && Input2.Value != null ? Input1.Value - Input2.Value : null); @@ -44,7 +44,7 @@ public SubtractionNodeViewModel() Name = "A - B", Value = subtract }; - Outputs.Add(Output); + EditableOutputs().Add(Output); } } } diff --git a/ExampleCalculatorApp/ViewModels/Nodes/SumNodeViewModel.cs b/ExampleCalculatorApp/ViewModels/Nodes/SumNodeViewModel.cs index b260f20..939565c 100644 --- a/ExampleCalculatorApp/ViewModels/Nodes/SumNodeViewModel.cs +++ b/ExampleCalculatorApp/ViewModels/Nodes/SumNodeViewModel.cs @@ -27,14 +27,14 @@ public SumNodeViewModel() Name = "A", Editor = new IntegerValueEditorViewModel() }; - Inputs.Add(Input1); + EditableInputs().Add(Input1); Input2 = new ValueNodeInputViewModel { Name = "B", Editor = new IntegerValueEditorViewModel() }; - Inputs.Add(Input2); + EditableInputs().Add(Input2); var sum = this.WhenAnyValue(vm => vm.Input1.Value, vm => vm.Input2.Value) .Select(_ => Input1.Value != null && Input2.Value != null ? Input1.Value + Input2.Value : null); @@ -44,7 +44,7 @@ public SumNodeViewModel() Name = "A + B", Value = sum }; - Outputs.Add(Output); + EditableOutputs().Add(Output); } } } diff --git a/ExampleCodeGenApp/ViewModels/Editors/GroupEndpointEditorViewModel.cs b/ExampleCodeGenApp/ViewModels/Editors/GroupEndpointEditorViewModel.cs index 71f22c4..b1a99a7 100644 --- a/ExampleCodeGenApp/ViewModels/Editors/GroupEndpointEditorViewModel.cs +++ b/ExampleCodeGenApp/ViewModels/Editors/GroupEndpointEditorViewModel.cs @@ -45,7 +45,7 @@ public GroupEndpointEditorViewModel(CodeNodeGroupIOBinding nodeGroupBinding) MoveUp = ReactiveCommand.Create(() => { bool isInput = Parent is NodeInputViewModel; - IEnumerable endpoints = isInput ? (IEnumerable)Parent.Parent.Inputs.Items : Parent.Parent.Outputs.Items; + IEnumerable endpoints = isInput ? (IEnumerable)Parent.Parent.InputItems : Parent.Parent.OutputItems; // Swap SortIndex of this endpoint with the SortIndex of the previous endpoint in the list, if any. var prevElement = endpoints @@ -62,7 +62,7 @@ public GroupEndpointEditorViewModel(CodeNodeGroupIOBinding nodeGroupBinding) MoveDown = ReactiveCommand.Create(() => { bool isInput = Parent is NodeInputViewModel; - IEnumerable endpoints = isInput ? (IEnumerable)Parent.Parent.Inputs.Items : Parent.Parent.Outputs.Items; + IEnumerable endpoints = isInput ? (IEnumerable)Parent.Parent.InputItems : Parent.Parent.OutputItems; var nextElement = endpoints .Where(e => e.SortIndex > Parent.SortIndex) diff --git a/ExampleCodeGenApp/ViewModels/Nodes/ButtonEventNode.cs b/ExampleCodeGenApp/ViewModels/Nodes/ButtonEventNode.cs index d781a7b..da04728 100644 --- a/ExampleCodeGenApp/ViewModels/Nodes/ButtonEventNode.cs +++ b/ExampleCodeGenApp/ViewModels/Nodes/ButtonEventNode.cs @@ -30,7 +30,7 @@ public ButtonEventNode() : base(NodeType.EventNode) Name = "On Click" }; - this.Inputs.Add(OnClickFlow); + this.EditableInputs().Add(OnClickFlow); } } } diff --git a/ExampleCodeGenApp/ViewModels/Nodes/ForLoopNode.cs b/ExampleCodeGenApp/ViewModels/Nodes/ForLoopNode.cs index 21bf68c..0a23e44 100644 --- a/ExampleCodeGenApp/ViewModels/Nodes/ForLoopNode.cs +++ b/ExampleCodeGenApp/ViewModels/Nodes/ForLoopNode.cs @@ -47,14 +47,14 @@ public ForLoopNode() : base(NodeType.FlowControl) Name = "Loop Body", Group = controlFlowInputsGroup }; - this.Inputs.Add(LoopBodyFlow); + this.EditableInputs().Add(LoopBodyFlow); LoopEndFlow = new CodeGenListInputViewModel(PortType.Execution) { Name = "Loop End", Group = controlFlowInputsGroup }; - this.Inputs.Add(LoopEndFlow); + this.EditableInputs().Add(LoopEndFlow); FirstIndex = new CodeGenInputViewModel>(PortType.Integer) @@ -62,7 +62,7 @@ public ForLoopNode() : base(NodeType.FlowControl) Name = "First Index", Group = boundsGroup }; - this.Inputs.Add(FirstIndex); + this.EditableInputs().Add(FirstIndex); LastIndex = new CodeGenInputViewModel>(PortType.Integer) { @@ -70,7 +70,7 @@ public ForLoopNode() : base(NodeType.FlowControl) Group = boundsGroup }; - this.Inputs.Add(LastIndex); + this.EditableInputs().Add(LastIndex); ForLoop value = new ForLoop(); @@ -90,14 +90,14 @@ public ForLoopNode() : base(NodeType.FlowControl) }), Group = controlFlowGroup }; - this.Outputs.Add(FlowIn); + this.EditableOutputs().Add(FlowIn); CurrentIndex = new CodeGenOutputViewModel>(PortType.Integer) { Name = "Current Index", Value = Observable.Return(new VariableReference{ LocalVariable = value.CurrentIndex }) }; - this.Outputs.Add(CurrentIndex); + this.EditableOutputs().Add(CurrentIndex); } } } diff --git a/ExampleCodeGenApp/ViewModels/Nodes/IntLiteralNode.cs b/ExampleCodeGenApp/ViewModels/Nodes/IntLiteralNode.cs index 9ae12e3..40ea3d3 100644 --- a/ExampleCodeGenApp/ViewModels/Nodes/IntLiteralNode.cs +++ b/ExampleCodeGenApp/ViewModels/Nodes/IntLiteralNode.cs @@ -35,7 +35,7 @@ public IntLiteralNode() : base(NodeType.Literal) Editor = ValueEditor, Value = ValueEditor.ValueChanged.Select(v => new IntLiteral{Value = v ?? 0}) }; - this.Outputs.Add(Output); + this.EditableOutputs().Add(Output); } } } diff --git a/ExampleCodeGenApp/ViewModels/Nodes/PrintNode.cs b/ExampleCodeGenApp/ViewModels/Nodes/PrintNode.cs index afa68b7..fcd8850 100644 --- a/ExampleCodeGenApp/ViewModels/Nodes/PrintNode.cs +++ b/ExampleCodeGenApp/ViewModels/Nodes/PrintNode.cs @@ -33,7 +33,7 @@ public PrintNode() : base(NodeType.Function) { Name = "Text" }; - this.Inputs.Add(Text); + this.EditableInputs().Add(Text); Flow = new CodeGenOutputViewModel(PortType.Execution) { @@ -47,7 +47,7 @@ public PrintNode() : base(NodeType.Function) } }) }; - this.Outputs.Add(Flow); + this.EditableOutputs().Add(Flow); } } } diff --git a/ExampleCodeGenApp/ViewModels/Nodes/TextLiteralNode.cs b/ExampleCodeGenApp/ViewModels/Nodes/TextLiteralNode.cs index 2991cac..04fe72e 100644 --- a/ExampleCodeGenApp/ViewModels/Nodes/TextLiteralNode.cs +++ b/ExampleCodeGenApp/ViewModels/Nodes/TextLiteralNode.cs @@ -35,7 +35,7 @@ public TextLiteralNode() : base(NodeType.Literal) Editor = ValueEditor, Value = ValueEditor.ValueChanged.Select(v => new StringLiteral{ Value = v }) }; - this.Outputs.Add(Output); + this.EditableOutputs().Add(Output); } } } diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/ColorNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/ColorNodeViewModel.cs index dc0778d..bb382ae 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/ColorNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/ColorNodeViewModel.cs @@ -44,7 +44,7 @@ public ColorNodeViewModel() ColorOutput.Editor = editor; ColorOutput.ReturnType = typeof(Vec3); ColorOutput.Value = editor.ValueChanged; - this.Outputs.Add(ColorOutput); + this.EditableOutputs().Add(ColorOutput); } } } diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/GeometryNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/GeometryNodeViewModel.cs index 940f1a4..195e654 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/GeometryNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/GeometryNodeViewModel.cs @@ -46,19 +46,19 @@ public GeometryNodeViewModel() VertexPositionOutput.ReturnType = typeof(Vec3); VertexPositionOutput.Value = Observable.Return(new ShaderFunc(() => "pos")); VertexPositionOutput.Editor = null; - this.Outputs.Add(VertexPositionOutput); + this.EditableOutputs().Add(VertexPositionOutput); NormalOutput.Name = "Normal"; NormalOutput.ReturnType = typeof(Vec3); NormalOutput.Value = Observable.Return(new ShaderFunc(() => "norm")); NormalOutput.Editor = null; - this.Outputs.Add(NormalOutput); + this.EditableOutputs().Add(NormalOutput); CameraOutput.Name = "Camera"; CameraOutput.ReturnType = typeof(Vec3); CameraOutput.Value = Observable.Return(new ShaderFunc(() => "cam")); CameraOutput.Editor = null; - this.Outputs.Add(CameraOutput); + this.EditableOutputs().Add(CameraOutput); } } } diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/Math2NodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/Math2NodeViewModel.cs index a8bd54f..cd32dba 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/Math2NodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/Math2NodeViewModel.cs @@ -48,15 +48,15 @@ public Math2NodeViewModel() OperationInput.Editor = new EnumEditorViewModel(typeof(MathOperation)); OperationInput.Port.IsVisible = false; - Inputs.Add(OperationInput); + EditableInputs().Add(OperationInput); InputA.Name = "A"; InputA.Editor = new FloatEditorViewModel(); - Inputs.Add(InputA); + EditableInputs().Add(InputA); InputB.Name = "B"; InputB.Editor = new FloatEditorViewModel(); - Inputs.Add(InputB); + EditableInputs().Add(InputB); Result.Name = "Result"; Result.ReturnType = typeof(float); @@ -69,7 +69,7 @@ public Math2NodeViewModel() } return BuildMathOperation(t.Item1, t.Item2, (MathOperation) t.Item3); }); - Outputs.Add(Result); + EditableOutputs().Add(Result); } private ShaderFunc BuildMathOperation(ShaderFunc a, ShaderFunc b, MathOperation operation) diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/MathNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/MathNodeViewModel.cs index 8b96e75..825894e 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/MathNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/MathNodeViewModel.cs @@ -50,17 +50,17 @@ public MathNodeViewModel() OperationInput.Editor = new EnumEditorViewModel(typeof(MathOperation)); OperationInput.Port.IsVisible = false; - Inputs.Add(OperationInput); + EditableInputs().Add(OperationInput); Input.Name = "A"; Input.Editor = new FloatEditorViewModel(); - Inputs.Add(Input); + EditableInputs().Add(Input); Result.Name = "Result"; Result.ReturnType = typeof(float); Result.Value = this.WhenAnyValue(vm => vm.Input.Value, vm => vm.OperationInput.Value) .Select(t => (t.Item1 == null || t.Item2 == null) ? null : BuildMathOperation(t.Item1, (MathOperation)t.Item2)); - Outputs.Add(Result); + EditableOutputs().Add(Result); } private ShaderFunc BuildMathOperation(ShaderFunc a, MathOperation operation) diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/ShaderOutputNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/ShaderOutputNodeViewModel.cs index eb2d704..3edf62f 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/ShaderOutputNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/ShaderOutputNodeViewModel.cs @@ -29,7 +29,7 @@ public ShaderOutputNodeViewModel() this.CanBeRemovedByUser = false; ColorInput.Name = "Color"; - this.Inputs.Add(ColorInput); + this.EditableInputs().Add(ColorInput); } } } diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/TimeNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/TimeNodeViewModel.cs index 51f0598..67fca60 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/TimeNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/TimeNodeViewModel.cs @@ -26,7 +26,7 @@ public TimeNodeViewModel() Result.Name = "Seconds"; Result.ReturnType = typeof(float); Result.Value = Observable.Return(new ShaderFunc(() => "seconds")); - Outputs.Add(Result); + EditableOutputs().Add(Result); } } } diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/Vec2PackNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/Vec2PackNodeViewModel.cs index 387ea80..e5b56ba 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/Vec2PackNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/Vec2PackNodeViewModel.cs @@ -32,11 +32,11 @@ public Vec2PackNodeViewModel() XInput.Name = "X"; XInput.Editor = new FloatEditorViewModel(); - Inputs.Add(XInput); + EditableInputs().Add(XInput); YInput.Name = "Y"; YInput.Editor = new FloatEditorViewModel(); - Inputs.Add(YInput); + EditableInputs().Add(YInput); Result.Name = "Vec2"; Result.ReturnType = typeof(Vec2); @@ -49,7 +49,7 @@ public Vec2PackNodeViewModel() } return new ShaderFunc(() => $"vec2(({t.Item1.Compile()}), ({t.Item2.Compile()}))"); }); - Outputs.Add(Result); + EditableOutputs().Add(Result); } } } diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/Vec2UnpackNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/Vec2UnpackNodeViewModel.cs index a7c8c03..a1a0abf 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/Vec2UnpackNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/Vec2UnpackNodeViewModel.cs @@ -32,17 +32,17 @@ public Vec2UnpackNodeViewModel() VectorInput.Name = "Vec2"; VectorInput.Editor = null; - Inputs.Add(VectorInput); + EditableInputs().Add(VectorInput); X.Name = "X"; X.ReturnType = typeof(float); X.Value = this.WhenAnyValue(vm => vm.VectorInput.Value).Select(v => v == null ? null : new ShaderFunc(() => $"({v.Compile()}).x")); - Outputs.Add(X); + EditableOutputs().Add(X); Y.Name = "Y"; Y.ReturnType = typeof(float); Y.Value = this.WhenAnyValue(vm => vm.VectorInput.Value).Select(v => v == null ? null : new ShaderFunc(() => $"({v.Compile()}).y")); - Outputs.Add(Y); + EditableOutputs().Add(Y); } } } diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/Vec3MathNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/Vec3MathNodeViewModel.cs index c9f66fc..fbb01be 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/Vec3MathNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/Vec3MathNodeViewModel.cs @@ -40,15 +40,15 @@ public Vec3MathNodeViewModel() OperationInput.Editor = new EnumEditorViewModel(typeof(MathOperation)); OperationInput.Port.IsVisible = false; - Inputs.Add(OperationInput); + EditableInputs().Add(OperationInput); InputA.Name = "A"; InputA.Editor = new Vec3EditorViewModel(); - Inputs.Add(InputA); + EditableInputs().Add(InputA); InputB.Name = "B"; InputB.Editor = new Vec3EditorViewModel(); - Inputs.Add(InputB); + EditableInputs().Add(InputB); ResultVector.Name = "Result Vector"; ResultVector.ReturnType = typeof(Vec3); @@ -61,7 +61,7 @@ public Vec3MathNodeViewModel() } return BuildMathVectorOperation(t.Item1, t.Item2, (MathOperation) t.Item3); }); - Outputs.Add(ResultVector); + EditableOutputs().Add(ResultVector); ResultFloat.Name = "Result Float"; ResultFloat.ReturnType = typeof(float); @@ -74,7 +74,7 @@ public Vec3MathNodeViewModel() } return BuildMathFloatOperation(t.Item1, t.Item2, (MathOperation)t.Item3); }); - Outputs.Add(ResultFloat); + EditableOutputs().Add(ResultFloat); } private ShaderFunc BuildMathVectorOperation(ShaderFunc a, ShaderFunc b, MathOperation operation) diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/Vec3PackNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/Vec3PackNodeViewModel.cs index 8dd1ee4..6579bdf 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/Vec3PackNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/Vec3PackNodeViewModel.cs @@ -33,15 +33,15 @@ public Vec3PackNodeViewModel() XInput.Name = "X"; XInput.Editor = new FloatEditorViewModel(); - Inputs.Add(XInput); + EditableInputs().Add(XInput); YInput.Name = "Y"; YInput.Editor = new FloatEditorViewModel(); - Inputs.Add(YInput); + EditableInputs().Add(YInput); ZInput.Name = "Z"; ZInput.Editor = new FloatEditorViewModel(); - Inputs.Add(ZInput); + EditableInputs().Add(ZInput); Result.Name = "Vec3"; Result.ReturnType = typeof(Vec3); @@ -55,7 +55,7 @@ public Vec3PackNodeViewModel() return new ShaderFunc(() => $"vec3(({t.Item1.Compile()}), ({t.Item2.Compile()}), ({t.Item3.Compile()}))"); }); - Outputs.Add(Result); + EditableOutputs().Add(Result); } } } diff --git a/ExampleShaderEditorApp/ViewModels/Nodes/Vec3UnpackNodeViewModel.cs b/ExampleShaderEditorApp/ViewModels/Nodes/Vec3UnpackNodeViewModel.cs index 8dd4de9..573e9ee 100644 --- a/ExampleShaderEditorApp/ViewModels/Nodes/Vec3UnpackNodeViewModel.cs +++ b/ExampleShaderEditorApp/ViewModels/Nodes/Vec3UnpackNodeViewModel.cs @@ -33,22 +33,22 @@ public Vec3UnpackNodeViewModel() VectorInput.Name = "Vec3"; VectorInput.Editor = null; - Inputs.Add(VectorInput); + EditableInputs().Add(VectorInput); X.Name = "X"; X.ReturnType = typeof(float); X.Value = this.WhenAnyValue(vm => vm.VectorInput.Value).Select(v => v == null ? null : new ShaderFunc(() => $"({v.Compile()}).x")); - Outputs.Add(X); + EditableOutputs().Add(X); Y.Name = "Y"; Y.ReturnType = typeof(float); Y.Value = this.WhenAnyValue(vm => vm.VectorInput.Value).Select(v => v == null ? null : new ShaderFunc(() => $"({v.Compile()}).y")); - Outputs.Add(Y); + EditableOutputs().Add(Y); Z.Name = "Z"; Z.ReturnType = typeof(float); Z.Value = this.WhenAnyValue(vm => vm.VectorInput.Value).Select(v => v == null ? null : new ShaderFunc(() => $"({v.Compile()}).z")); - Outputs.Add(Z); + EditableOutputs().Add(Z); } } } diff --git a/NodeNetwork/ViewModels/Endpoint.cs b/NodeNetwork/ViewModels/Endpoint.cs index a30cf9c..b4e782e 100644 --- a/NodeNetwork/ViewModels/Endpoint.cs +++ b/NodeNetwork/ViewModels/Endpoint.cs @@ -139,16 +139,20 @@ public PortPosition PortPosition /// List of connections between this endpoint and other endpoints in the network. /// To add a new connection, do not add it here but instead add it to the Connections property in the network. /// - public IObservableList Connections { get; } - #endregion + private readonly IObservableList connections; + public IEnumerable ConnectionsItems => connections.Items; + public IObservable> Connections { get; } + public IObservable ConnectionsCountChanged => connections.CountChanged; + public int ConnectionsCount => connections.Count; + #endregion - #region MaxConnections - /// - /// The maximum amount of connections this endpoint accepts. - /// When Connections.Count == MaxConnections, the user cannot add more connections to this endpoint - /// until a connection is removed. - /// - public int MaxConnections + #region MaxConnections + /// + /// The maximum amount of connections this endpoint accepts. + /// When Connections.Count == MaxConnections, the user cannot add more connections to this endpoint + /// until a connection is removed. + /// + public int MaxConnections { get => _maxConnections; set => this.RaiseAndSetIfChanged(ref _maxConnections, value); @@ -236,12 +240,14 @@ protected Endpoint() (x, y, z) => Parent?.Parent?.Connections ?? new SourceList()) .Switch(); - Connections = networkConnections + connections = networkConnections .AutoRefresh(c => c.Input) .AutoRefresh(c => c.Output) .Filter(c => c.Input == this || c.Output == this) .AsObservableList(); + Connections = connections.Connect().RefCount(); + // Setup bindings between port mouse events and connection creation. this.WhenAnyObservable(vm => vm.Port.ConnectionDragStarted).Subscribe(_ => CreatePendingConnection()); this.WhenAnyObservable(vm => vm.Port.ConnectionPreviewActive).Subscribe(SetConnectionPreview); diff --git a/NodeNetwork/ViewModels/NetworkViewModel.cs b/NodeNetwork/ViewModels/NetworkViewModel.cs index 46ac484..20d1069 100644 --- a/NodeNetwork/ViewModels/NetworkViewModel.cs +++ b/NodeNetwork/ViewModels/NetworkViewModel.cs @@ -30,13 +30,14 @@ static NetworkViewModel() #region Logger private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - #endregion - - #region Nodes - /// - /// The list of nodes in this network. - /// - public ISourceList Nodes { get; } = new SourceList(); + private readonly IObservable> connectedNodes; + #endregion + + #region Nodes + /// + /// The list of nodes in this network. + /// + public ISourceList Nodes { get; } = new SourceList(); #endregion #region SelectedNodes @@ -237,15 +238,18 @@ public Point DragOffset public NetworkViewModel() { - // Setup parent relationship in nodes. - Nodes.Connect().ActOnEveryObject( + // Create shared connected Nodes + connectedNodes = Nodes.Connect().RefCount(); + + // Setup parent relationship in nodes. + connectedNodes.ActOnEveryObject( addedNode => addedNode.Parent = this, removedNode => removedNode.Parent = null ); // SelectedNodes is a derived collection of all nodes with IsSelected = true. - SelectedNodes = Nodes.Connect() - .AutoRefresh(node => node.IsSelected) + SelectedNodes = connectedNodes + .AutoRefresh(node => node.IsSelected) .Filter(node => node.IsSelected) .AsObservableList(); @@ -256,10 +260,10 @@ public NetworkViewModel() }); // When a node is removed, delete any connections from/to that node. - Nodes.Preview().OnItemRemoved(removedNode => + connectedNodes.OnItemRemoved(removedNode => { - Connections.RemoveMany(removedNode.Inputs.Items.SelectMany(o => o.Connections.Items)); - Connections.RemoveMany(removedNode.Outputs.Items.SelectMany(o => o.Connections.Items)); + Connections.RemoveMany(removedNode.InputItems.SelectMany(o => o.ConnectionsItems)); + Connections.RemoveMany(removedNode.OutputItems.SelectMany(o => o.ConnectionsItems)); bool pendingConnectionInvalid = PendingConnection?.Input?.Parent == removedNode || PendingConnection?.Output?.Parent == removedNode; @@ -317,17 +321,17 @@ public NetworkViewModel() // When a connection or node changes, validate the network. // Zip is used because when a connection is removed, it will trigger a change in both the input and the output and we want to combine these. - var a = Nodes.Connect() - .AutoRefreshOnObservable(node => node.Inputs.Connect()) - .SelectMany(node => node.Inputs.Items) - .AutoRefreshOnObservable(input => input.Connections.Connect()) - .SelectMany(input => input.Connections.Items); + var a = connectedNodes + .AutoRefreshOnObservable(node => node.Inputs) + .SelectMany(node => node.InputItems) + .AutoRefreshOnObservable(input => input.Connections) + .SelectMany(input => input.ConnectionsItems); - var b = Nodes.Connect() - .AutoRefreshOnObservable(node => node.Outputs.Connect()) - .SelectMany(node => node.Outputs.Items) - .AutoRefreshOnObservable(output => output.Connections.Connect()) - .SelectMany(output => output.Connections.Items); + var b = connectedNodes + .AutoRefreshOnObservable(node => node.Outputs) + .SelectMany(node => node.OutputItems) + .AutoRefreshOnObservable(output => output.Connections) + .SelectMany(output => output.ConnectionsItems); ConnectionsUpdated = Observable.Zip( a, @@ -335,7 +339,7 @@ public NetworkViewModel() (x, y) => Unit.Default ).Publish().RefCount(); ConnectionsUpdated.InvokeCommand(UpdateValidation); - Nodes.Connect().Select((IChangeSet n) => Unit.Default).InvokeCommand(UpdateValidation); + connectedNodes.Select((IChangeSet n) => Unit.Default).InvokeCommand(UpdateValidation); // Push a network change notification when a functional network change occurs. // These include: @@ -344,9 +348,9 @@ public NetworkViewModel() // - Endpoint editors change // - Network validation changes NetworkChanged = Observable.Merge( - Observable.Select(Nodes.Connect(), _ => Unit.Default), - Observable.Select(Nodes.Connect().MergeMany(node => node.Inputs.Connect()), _ => Unit.Default), - Observable.Select(Nodes.Connect().MergeMany(node => node.Outputs.Connect()), _ => Unit.Default), + Observable.Select(connectedNodes, _ => Unit.Default), + Observable.Select(connectedNodes.MergeMany(node => node.Inputs), _ => Unit.Default), + Observable.Select(connectedNodes.MergeMany(node => node.Outputs), _ => Unit.Default), ConnectionsUpdated, OnEditorChanged(), Validation.Select(_ => Unit.Default) @@ -356,14 +360,14 @@ public NetworkViewModel() private IObservable OnEditorChanged() { return Observable.Merge( - Nodes.Connect().MergeMany(n => - n.Inputs.Connect().MergeMany(i => + connectedNodes.MergeMany(n => + n.Inputs.MergeMany(i => // Use WhenAnyObservable because Editor can change. i.WhenAnyObservable(vm => vm.Editor.Changed) ) ).Select(_ => Unit.Default), - Nodes.Connect().MergeMany(n => - n.Outputs.Connect().MergeMany(o => + connectedNodes.MergeMany(n => + n.Outputs.MergeMany(o => o.WhenAnyObservable(vm => vm.Editor.Changed) ) ).Select(_ => Unit.Default) diff --git a/NodeNetwork/ViewModels/NodeInputViewModel.cs b/NodeNetwork/ViewModels/NodeInputViewModel.cs index b6ed329..92de911 100644 --- a/NodeNetwork/ViewModels/NodeInputViewModel.cs +++ b/NodeNetwork/ViewModels/NodeInputViewModel.cs @@ -67,7 +67,7 @@ public NodeInputViewModel() { this.HideEditorIfConnected = true; - this.Connections.CountChanged.Select(c => c == 0).StartWith(true) + this.ConnectionsCountChanged.Select(c => c == 0).StartWith(true) .CombineLatest(this.WhenAnyValue(vm => vm.HideEditorIfConnected), (noConnections, hideEditorIfConnected) => !hideEditorIfConnected || noConnections) .ToProperty(this, vm => vm.IsEditorVisible, out _isEditorVisible); @@ -93,9 +93,9 @@ protected override void CreatePendingConnection() } PendingConnectionViewModel pendingConnection; - if (MaxConnections == 1 && Connections.Items.Any()) + if (MaxConnections == 1 && ConnectionsCount>0) { - var conn = Connections.Items.First(); + var conn = ConnectionsItems.First(); pendingConnection = new PendingConnectionViewModel(network) { Output = conn.Output, @@ -104,7 +104,7 @@ protected override void CreatePendingConnection() }; network.Connections.Remove(conn); } - else if(Connections.Count < MaxConnections) + else if(ConnectionsCount < MaxConnections) { pendingConnection = new PendingConnectionViewModel(network) { Input = this, InputIsLocked = true, LooseEndPoint = Port.CenterPoint }; } @@ -169,15 +169,15 @@ protected override void FinishPendingConnection() { //Don't allow a new connection if max amount of connections has been reached and we //can't automatically remove one. - if (Connections.Count < MaxConnections || MaxConnections == 1) + if (ConnectionsCount < MaxConnections || MaxConnections == 1) { //Connection is valid bool canCreateConnection = true; - if (MaxConnections == Connections.Count && MaxConnections == 1) + if (MaxConnections == ConnectionsCount && MaxConnections == 1) { //Remove the connection to this input - network.Connections.Remove(Connections.Items.First()); + network.Connections.Remove(ConnectionsItems.First()); } else if (MaxConnections > 2) { diff --git a/NodeNetwork/ViewModels/NodeOutputViewModel.cs b/NodeNetwork/ViewModels/NodeOutputViewModel.cs index f11847e..aa96887 100644 --- a/NodeNetwork/ViewModels/NodeOutputViewModel.cs +++ b/NodeNetwork/ViewModels/NodeOutputViewModel.cs @@ -46,7 +46,7 @@ protected override void CreatePendingConnection() return; } - if (Connections.Count >= MaxConnections) + if (ConnectionsCount >= MaxConnections) { return; } @@ -105,7 +105,7 @@ protected override void FinishPendingConnection() if (network.PendingConnection.Validation.IsValid) { //Connection is valid - if (MaxConnections > Connections.Count) + if (MaxConnections > ConnectionsCount) { //MaxConnections hasn't been reached yet. if (!network.Connections.Items.Any(con => con.Output == this && con.Input == network.PendingConnection.Input)) diff --git a/NodeNetwork/ViewModels/NodeViewModel.cs b/NodeNetwork/ViewModels/NodeViewModel.cs index 77b4af4..a4550ae 100644 --- a/NodeNetwork/ViewModels/NodeViewModel.cs +++ b/NodeNetwork/ViewModels/NodeViewModel.cs @@ -86,22 +86,38 @@ public IBitmap HeaderIcon /// /// The list of inputs on this node. /// - public ISourceList Inputs { get; } = new SourceList(); + private readonly ISourceList inputs = new SourceList(); + public IObservable> Inputs { get; } + public int InputsCount => inputs.Count; + public IEnumerable InputItems => inputs.Items; + public ISourceList EditableInputs() + { + return inputs; + } + #endregion #region Outputs /// /// The list of outputs on this node. /// - public ISourceList Outputs { get; } = new SourceList(); - #endregion + private readonly ISourceList outputs = new SourceList(); + public IObservable> Outputs { get; } + public int OutputsCount => outputs.Count; - #region VisibleInputs - /// - /// The list of inputs that is currently visible on this node. - /// Some inputs may be hidden if the node is collapsed. - /// - public IObservableList VisibleInputs { get; } + public IEnumerable OutputItems => outputs.Items; + public ISourceList EditableOutputs() + { + return outputs; + } + #endregion + + #region VisibleInputs + /// + /// The list of inputs that is currently visible on this node. + /// Some inputs may be hidden if the node is collapsed. + /// + public IObservableList VisibleInputs { get; } #endregion #region VisibleOutputs @@ -212,28 +228,31 @@ public NodeViewModel() // Setup a default EndpointGroupViewModelFactory that will be used to create endpoint groups. EndpointGroupViewModelFactory = (group, allInputs, allOutputs, children, factory) => new EndpointGroupViewModel(group, allInputs, allOutputs, children, factory); - this.Name = "Untitled"; + Inputs = inputs.Connect().RefCount(); + Outputs = outputs.Connect().RefCount(); + + this.Name = "Untitled"; this.CanBeRemovedByUser = true; this.Resizable = ResizeOrientation.Horizontal; // Setup parent relationship with inputs. - Inputs.Connect().ActOnEveryObject( + Inputs.ActOnEveryObject( addedInput => addedInput.Parent = this, removedInput => removedInput.Parent = null ); // Setup parent relationship with outputs. - Outputs.Connect().ActOnEveryObject( + Outputs.ActOnEveryObject( addedOutput => addedOutput.Parent = this, removedOutput => removedOutput.Parent = null ); // When an input is removed, delete any connection to/from that input - Inputs.Preview().OnItemRemoved(removedInput => + Inputs.OnItemRemoved(removedInput => { if (Parent != null) { - Parent.Connections.RemoveMany(removedInput.Connections.Items); + Parent.Connections.RemoveMany(removedInput.ConnectionsItems); bool pendingConnectionInvalid = Parent.PendingConnection?.Input == removedInput; if (pendingConnectionInvalid) @@ -244,11 +263,11 @@ public NodeViewModel() }).Subscribe(); // Same for outputs. - Outputs.Preview().OnItemRemoved(removedOutput => + Outputs.OnItemRemoved(removedOutput => { if (Parent != null) { - Parent.Connections.RemoveMany(removedOutput.Connections.Items); + Parent.Connections.RemoveMany(removedOutput.ConnectionsItems); bool pendingConnectionInvalid = Parent.PendingConnection?.Output == removedOutput; if (pendingConnectionInvalid) @@ -262,7 +281,7 @@ public NodeViewModel() var onCollapseChange = this.WhenAnyValue(vm => vm.IsCollapsed).Publish(); onCollapseChange.Connect(); - var visibilityFilteredInputs = Inputs.Connect() + var visibilityFilteredInputs = Inputs .AutoRefreshOnObservable(_ => onCollapseChange) .AutoRefresh(vm => vm.Visibility) .AutoRefresh(vm => vm.Group) @@ -270,7 +289,7 @@ public NodeViewModel() { if (IsCollapsed) { - return i.Visibility == EndpointVisibility.AlwaysVisible || (i.Visibility == EndpointVisibility.Auto && i.Connections.Items.Any()); + return i.Visibility == EndpointVisibility.AlwaysVisible || (i.Visibility == EndpointVisibility.Auto && i.ConnectionsItems.Any()); } return i.Visibility != EndpointVisibility.AlwaysHidden; @@ -278,11 +297,11 @@ public NodeViewModel() VisibleInputs = visibilityFilteredInputs .Filter(i => i.Group == null) .Sort(Comparer.Create((i1, i2) => i1.SortIndex.CompareTo(i2.SortIndex)), - resort: Inputs.Connect().WhenValueChanged(i => i.SortIndex).Select(_ => Unit.Default)) + resort: Inputs.WhenValueChanged(i => i.SortIndex).Select(_ => Unit.Default)) .AsObservableList(); // Same for outputs. - var visibilityFilteredOutputs = Outputs.Connect() + var visibilityFilteredOutputs = Outputs .AutoRefreshOnObservable(_ => onCollapseChange) .AutoRefresh(vm => vm.Visibility) .AutoRefresh(vm => vm.Group) @@ -290,7 +309,7 @@ public NodeViewModel() { if (IsCollapsed) { - return o.Visibility == EndpointVisibility.AlwaysVisible || (o.Visibility == EndpointVisibility.Auto && o.Connections.Items.Any()); + return o.Visibility == EndpointVisibility.AlwaysVisible || (o.Visibility == EndpointVisibility.Auto && o.ConnectionsItems.Any()); } return o.Visibility != EndpointVisibility.AlwaysHidden; @@ -298,7 +317,7 @@ public NodeViewModel() VisibleOutputs = visibilityFilteredOutputs .Filter(o => o.Group == null) .Sort(Comparer.Create((o1, o2) => o1.SortIndex.CompareTo(o2.SortIndex)), - resort: Outputs.Connect().WhenValueChanged(o => o.SortIndex).Select(_ => Unit.Default)) + resort: Outputs.WhenValueChanged(o => o.SortIndex).Select(_ => Unit.Default)) .AsObservableList(); // Get all the groups, also the empty ones. diff --git a/NodeNetwork/Views/PortView.cs b/NodeNetwork/Views/PortView.cs index bd4c619..77d8853 100644 --- a/NodeNetwork/Views/PortView.cs +++ b/NodeNetwork/Views/PortView.cs @@ -153,7 +153,7 @@ private void SetupVisualStateBindings() { this.WhenActivated(d => { - this.WhenAnyObservable(v => v.ViewModel.Parent.Connections.CountChanged).Select(c => c == 0).Subscribe(isDisconnected => + this.WhenAnyObservable(v => v.ViewModel.Parent.ConnectionsCountChanged).Select(c => c == 0).Subscribe(isDisconnected => { VisualStateManager.GoToState(this, isDisconnected ? DisconnectedState : ConnectedState, true); }).DisposeWith(d); diff --git a/NodeNetworkTests/EndpointGroupingTests.cs b/NodeNetworkTests/EndpointGroupingTests.cs index 602f4bc..b5e8e17 100644 --- a/NodeNetworkTests/EndpointGroupingTests.cs +++ b/NodeNetworkTests/EndpointGroupingTests.cs @@ -25,8 +25,8 @@ public void TestAddingUngroupedEndpoints() { NodeViewModel node = new NodeViewModel(); - node.Inputs.Add(new NodeInputViewModel()); - node.Outputs.Add(new NodeOutputViewModel()); + node.EditableInputs().Add(new NodeInputViewModel()); + node.EditableOutputs().Add(new NodeOutputViewModel()); Assert.IsFalse(node.VisibleEndpointGroups.Any()); } @@ -49,7 +49,7 @@ public void TestGroupedEndpoints() NodeOutputViewModel outputB1 = new NodeOutputViewModel { Group = groupB }; NodeOutputViewModel outputB2 = new NodeOutputViewModel { Group = groupB }; - node.Inputs.Add(inputB1); + node.EditableInputs().Add(inputB1); Assert.IsTrue(node.VisibleInputs.Count == 0); Assert.IsTrue(node.VisibleEndpointGroups.Count == 1); @@ -58,7 +58,7 @@ public void TestGroupedEndpoints() Assert.IsTrue(groupBViewModel.VisibleInputs.Count == 1); Assert.AreEqual(inputB1, groupBViewModel.VisibleInputs.Items.First()); - node.Outputs.Add(outputB2); + node.EditableOutputs().Add(outputB2); Assert.IsTrue(node.VisibleInputs.Count == 0); Assert.IsTrue(node.VisibleEndpointGroups.Count == 1); @@ -69,8 +69,8 @@ public void TestGroupedEndpoints() Assert.IsTrue(groupBViewModel.VisibleOutputs.Count == 1); Assert.AreEqual(outputB2, groupBViewModel.VisibleOutputs.Items.First()); - node.Inputs.AddRange(new []{ inputA1, inputB2, inputA2 }); - node.Outputs.AddRange(new []{ outputB1, outputA1, outputA2 }); + node.EditableInputs().AddRange(new []{ inputA1, inputB2, inputA2 }); + node.EditableOutputs().AddRange(new []{ outputB1, outputA1, outputA2 }); Assert.IsTrue(node.VisibleInputs.Count == 0); Assert.IsTrue(node.VisibleEndpointGroups.Count == 2); @@ -92,7 +92,7 @@ public void TestGroupedEndpoints() Assert.AreEqual(outputA1, groupAViewModel.VisibleOutputs.Items.First()); Assert.AreEqual(outputA2, groupAViewModel.VisibleOutputs.Items.ElementAt(1)); - node.Inputs.Remove(inputB1); + node.EditableInputs().Remove(inputB1); Assert.IsTrue(node.VisibleInputs.Count == 0); Assert.IsTrue(node.VisibleEndpointGroups.Count == 2); @@ -113,8 +113,8 @@ public void TestGroupedEndpoints() Assert.AreEqual(outputA1, groupAViewModel.VisibleOutputs.Items.First()); Assert.AreEqual(outputA2, groupAViewModel.VisibleOutputs.Items.ElementAt(1)); - node.Inputs.Remove(inputB2); - node.Outputs.RemoveMany(new []{outputB1, outputB2}); + node.EditableInputs().Remove(inputB2); + node.EditableOutputs().RemoveMany(new []{outputB1, outputB2}); Assert.IsTrue(node.VisibleInputs.Count == 0); Assert.IsTrue(node.VisibleEndpointGroups.Count == 1); @@ -145,10 +145,10 @@ public void TestNestedGroups() NodeInputViewModel inputD = new NodeInputViewModel { Group = groupD, Name = "Input D" }; NodeOutputViewModel outputD = new NodeOutputViewModel { Group = groupD, Name = "Output D" }; - node.Inputs.Add(inputC); - node.Inputs.Add(inputD); - node.Outputs.Add(outputC); - node.Outputs.Add(outputD); + node.EditableInputs().Add(inputC); + node.EditableInputs().Add(inputD); + node.EditableOutputs().Add(outputC); + node.EditableOutputs().Add(outputD); Assert.IsTrue(node.VisibleInputs.Count == 0); Assert.IsTrue(node.VisibleOutputs.Count == 0); @@ -178,8 +178,8 @@ public void TestNestedGroups() Assert.IsTrue(groupDViewModel.VisibleOutputs.Count == 1); Assert.AreEqual(outputD, groupDViewModel.VisibleOutputs.Items.First()); - node.Inputs.Remove(inputC); - node.Outputs.Remove(outputC); + node.EditableInputs().Remove(inputC); + node.EditableOutputs().Remove(outputC); Assert.IsTrue(node.VisibleInputs.Count == 0); Assert.IsTrue(node.VisibleOutputs.Count == 0); @@ -214,10 +214,10 @@ public void TestCollapseWithGroups() NodeInputViewModel inputD = new NodeInputViewModel { Group = groupD, Name = "Input D" }; NodeOutputViewModel outputD = new NodeOutputViewModel { Group = groupD, Name = "Output D" }; - node.Inputs.Add(inputC); - node.Inputs.Add(inputD); - node.Outputs.Add(outputC); - node.Outputs.Add(outputD); + node.EditableInputs().Add(inputC); + node.EditableInputs().Add(inputD); + node.EditableOutputs().Add(outputC); + node.EditableOutputs().Add(outputD); var network = new NetworkViewModel(); network.Nodes.Add(node); diff --git a/NodeNetworkTests/NetworkViewModelTests.cs b/NodeNetworkTests/NetworkViewModelTests.cs index 3f281b1..55b701a 100644 --- a/NodeNetworkTests/NetworkViewModelTests.cs +++ b/NodeNetworkTests/NetworkViewModelTests.cs @@ -45,7 +45,7 @@ public void TestDeleteSelectedNodes() { NodeOutputViewModel nodeAOutput = new NodeOutputViewModel(); NodeViewModel nodeA = new NodeViewModel(); - nodeA.Outputs.Add(nodeAOutput); + nodeA.EditableOutputs().Add(nodeAOutput); NodeInputViewModel nodeBInput = new NodeInputViewModel(); NodeOutputViewModel nodeBOutput = new NodeOutputViewModel(); @@ -54,15 +54,15 @@ public void TestDeleteSelectedNodes() CanBeRemovedByUser = false, IsSelected = true, }; - nodeB.Inputs.Add(nodeBInput); - nodeB.Outputs.Add(nodeBOutput); + nodeB.EditableInputs().Add(nodeBInput); + nodeB.EditableOutputs().Add(nodeBOutput); NodeInputViewModel nodeCInput = new NodeInputViewModel(); NodeViewModel nodeC = new NodeViewModel { IsSelected = true }; - nodeC.Inputs.Add(nodeCInput); + nodeC.EditableInputs().Add(nodeCInput); NodeViewModel nodeD = new NodeViewModel { @@ -113,7 +113,7 @@ public void TestCutLine() { NodeOutputViewModel nodeAOutput = new NodeOutputViewModel(); NodeViewModel nodeA = new NodeViewModel(); - nodeA.Outputs.Add(nodeAOutput); + nodeA.EditableOutputs().Add(nodeAOutput); NodeInputViewModel nodeBInput = new NodeInputViewModel(); NodeOutputViewModel nodeBOutput = new NodeOutputViewModel(); @@ -122,15 +122,15 @@ public void TestCutLine() CanBeRemovedByUser = false, IsSelected = true }; - nodeB.Inputs.Add(nodeBInput); - nodeB.Outputs.Add(nodeBOutput); + nodeB.EditableInputs().Add(nodeBInput); + nodeB.EditableOutputs().Add(nodeBOutput); NodeInputViewModel nodeCInput = new NodeInputViewModel(); NodeViewModel nodeC = new NodeViewModel { IsSelected = true }; - nodeC.Inputs.Add(nodeCInput); + nodeC.EditableInputs().Add(nodeCInput); NodeViewModel nodeD = new NodeViewModel { @@ -158,7 +158,7 @@ public void TestRectangleSelection() { NodeOutputViewModel nodeAOutput = new NodeOutputViewModel(); NodeViewModel nodeA = new NodeViewModel(); - nodeA.Outputs.Add(nodeAOutput); + nodeA.EditableOutputs().Add(nodeAOutput); NodeInputViewModel nodeBInput = new NodeInputViewModel(); NodeOutputViewModel nodeBOutput = new NodeOutputViewModel(); @@ -167,15 +167,15 @@ public void TestRectangleSelection() CanBeRemovedByUser = false, IsSelected = true }; - nodeB.Inputs.Add(nodeBInput); - nodeB.Outputs.Add(nodeBOutput); + nodeB.EditableInputs().Add(nodeBInput); + nodeB.EditableOutputs().Add(nodeBOutput); NodeInputViewModel nodeCInput = new NodeInputViewModel(); NodeViewModel nodeC = new NodeViewModel { IsSelected = true }; - nodeC.Inputs.Add(nodeCInput); + nodeC.EditableInputs().Add(nodeCInput); NodeViewModel nodeD = new NodeViewModel { @@ -198,11 +198,11 @@ public void TestAddConnectionShouldUpdateInputAndOutputConnLists() { NodeOutputViewModel output = new NodeOutputViewModel(); NodeViewModel node1 = new NodeViewModel(); - node1.Outputs.Add(output); + node1.EditableOutputs().Add(output); NodeInputViewModel input = new NodeInputViewModel(); NodeViewModel node2 = new NodeViewModel(); - node2.Inputs.Add(input); + node2.EditableInputs().Add(input); NetworkViewModel network = new NetworkViewModel(); network.Nodes.Add(node1); @@ -211,13 +211,13 @@ public void TestAddConnectionShouldUpdateInputAndOutputConnLists() var conn = network.ConnectionFactory(input, output); network.Connections.Add(conn); - CollectionAssert.AreEqual(new []{ conn }, input.Connections.Items.AsArray()); - CollectionAssert.AreEqual(new[] { conn }, output.Connections.Items.AsArray()); + CollectionAssert.AreEqual(new []{ conn }, input.ConnectionsItems.AsArray()); + CollectionAssert.AreEqual(new[] { conn }, output.ConnectionsItems.AsArray()); network.Connections.Clear(); - CollectionAssert.AreEqual(new ConnectionViewModel[0], input.Connections.Items.AsArray()); - CollectionAssert.AreEqual(new ConnectionViewModel[0], output.Connections.Items.AsArray()); + CollectionAssert.AreEqual(new ConnectionViewModel[0], input.ConnectionsItems.AsArray()); + CollectionAssert.AreEqual(new ConnectionViewModel[0], output.ConnectionsItems.AsArray()); } [TestMethod] @@ -225,11 +225,11 @@ public void TestDeleteOutputShouldRemoveConnections() { NodeOutputViewModel output = new NodeOutputViewModel(); NodeViewModel node1 = new NodeViewModel(); - node1.Outputs.Add(output); + node1.EditableOutputs().Add(output); NodeInputViewModel input = new NodeInputViewModel(); NodeViewModel node2 = new NodeViewModel(); - node2.Inputs.Add(input); + node2.EditableInputs().Add(input); NetworkViewModel network = new NetworkViewModel(); network.Nodes.Add(node1); @@ -239,14 +239,14 @@ public void TestDeleteOutputShouldRemoveConnections() network.Connections.Add(conn); Assert.IsTrue(network.Connections.Items.Contains(conn)); - node1.Outputs.Remove(output); + node1.EditableOutputs().Remove(output); Assert.IsFalse(network.Connections.Items.Contains(conn)); - node1.Outputs.Add(output); + node1.EditableOutputs().Add(output); network.Connections.Add(conn); Assert.IsTrue(network.Connections.Items.Contains(conn)); - node1.Outputs.Clear(); + node1.EditableOutputs().Clear(); Assert.IsFalse(network.Connections.Items.Contains(conn)); } @@ -255,11 +255,11 @@ public void TestDeleteInputShouldRemoveConnections() { NodeOutputViewModel output = new NodeOutputViewModel(); NodeViewModel node1 = new NodeViewModel(); - node1.Outputs.Add(output); + node1.EditableOutputs().Add(output); NodeInputViewModel input = new NodeInputViewModel(); NodeViewModel node2 = new NodeViewModel(); - node2.Inputs.Add(input); + node2.EditableInputs().Add(input); NetworkViewModel network = new NetworkViewModel(); network.Nodes.Add(node1); @@ -268,19 +268,19 @@ public void TestDeleteInputShouldRemoveConnections() var conn = network.ConnectionFactory(input, output); network.Connections.Add(conn); - Assert.IsTrue(input.Connections.Items.Contains(conn)); + Assert.IsTrue(input.ConnectionsItems.Contains(conn)); Assert.IsTrue(network.Connections.Items.Contains(conn)); - node2.Inputs.Remove(input); - Assert.IsFalse(input.Connections.Items.Contains(conn)); + node2.EditableInputs().Remove(input); + Assert.IsFalse(input.ConnectionsItems.Contains(conn)); Assert.IsFalse(network.Connections.Items.Contains(conn)); - node2.Inputs.Add(input); + node2.EditableInputs().Add(input); network.Connections.Add(conn); - Assert.IsTrue(input.Connections.Items.Contains(conn)); + Assert.IsTrue(input.ConnectionsItems.Contains(conn)); Assert.IsTrue(network.Connections.Items.Contains(conn)); - node2.Inputs.Clear(); - Assert.IsFalse(input.Connections.Items.Contains(conn)); + node2.EditableInputs().Clear(); + Assert.IsFalse(input.ConnectionsItems.Contains(conn)); Assert.IsFalse(network.Connections.Items.Contains(conn)); } @@ -290,14 +290,14 @@ public void TestDeleteNodeShouldRemoveConnections() NodeInputViewModel input1 = new NodeInputViewModel(); NodeOutputViewModel output1 = new NodeOutputViewModel(); NodeViewModel node1 = new NodeViewModel(); - node1.Inputs.Add(input1); - node1.Outputs.Add(output1); + node1.EditableInputs().Add(input1); + node1.EditableOutputs().Add(output1); NodeInputViewModel input2 = new NodeInputViewModel(); NodeOutputViewModel output2 = new NodeOutputViewModel(); NodeViewModel node2 = new NodeViewModel(); - node2.Inputs.Add(input2); - node2.Outputs.Add(output2); + node2.EditableInputs().Add(input2); + node2.EditableOutputs().Add(output2); NetworkViewModel network = new NetworkViewModel(); network.Nodes.Add(node1); @@ -330,14 +330,14 @@ public void TestValidateAfterConnectionsAllUpdated() NodeInputViewModel input1 = new NodeInputViewModel(); NodeOutputViewModel output1 = new NodeOutputViewModel(); NodeViewModel node1 = new NodeViewModel(); - node1.Inputs.Add(input1); - node1.Outputs.Add(output1); + node1.EditableInputs().Add(input1); + node1.EditableOutputs().Add(output1); NodeInputViewModel input2 = new NodeInputViewModel(); NodeOutputViewModel output2 = new NodeOutputViewModel(); NodeViewModel node2 = new NodeViewModel(); - node2.Inputs.Add(input2); - node2.Outputs.Add(output2); + node2.EditableInputs().Add(input2); + node2.EditableOutputs().Add(output2); NetworkViewModel network = new NetworkViewModel(); network.Validator = n => @@ -376,14 +376,14 @@ public void TestConnectionsUpdatedAfterPreexistingConnectionRemoved() NodeInputViewModel input1 = new NodeInputViewModel(); NodeOutputViewModel output1 = new NodeOutputViewModel(); NodeViewModel node1 = new NodeViewModel(); - node1.Inputs.Add(input1); - node1.Outputs.Add(output1); + node1.EditableInputs().Add(input1); + node1.EditableOutputs().Add(output1); NodeInputViewModel input2 = new NodeInputViewModel(); NodeOutputViewModel output2 = new NodeOutputViewModel(); NodeViewModel node2 = new NodeViewModel(); - node2.Inputs.Add(input2); - node2.Outputs.Add(output2); + node2.EditableInputs().Add(input2); + node2.EditableOutputs().Add(output2); NetworkViewModel network = new NetworkViewModel(); @@ -417,14 +417,14 @@ public void TestNestedObserving() NodeInputViewModel input1 = new NodeInputViewModel(); NodeOutputViewModel output1 = new NodeOutputViewModel(); NodeViewModel node1 = new NodeViewModel(); - node1.Inputs.Add(input1); - node1.Outputs.Add(output1); + node1.EditableInputs().Add(input1); + node1.EditableOutputs().Add(output1); NodeInputViewModel input2 = new NodeInputViewModel(); NodeOutputViewModel output2 = new NodeOutputViewModel(); NodeViewModel node2 = new NodeViewModel(); - node2.Inputs.Add(input2); - node2.Outputs.Add(output2); + node2.EditableInputs().Add(input2); + node2.EditableOutputs().Add(output2); NetworkViewModel network = new NetworkViewModel(); @@ -454,14 +454,14 @@ public void TestListInputDisconnect() { var input1 = new ValueListNodeInputViewModel(); NodeViewModel node1 = new NodeViewModel(); - node1.Inputs.Add(input1); + node1.EditableInputs().Add(input1); var output2 = new ValueNodeOutputViewModel { Value = Observable.Return("Test") }; NodeViewModel node2 = new NodeViewModel(); - node2.Outputs.Add(output2); + node2.EditableOutputs().Add(output2); NetworkViewModel network = new NetworkViewModel(); diff --git a/NodeNetworkTests/NodeInputViewModelTests.cs b/NodeNetworkTests/NodeInputViewModelTests.cs index e296b07..fd7c742 100644 --- a/NodeNetworkTests/NodeInputViewModelTests.cs +++ b/NodeNetworkTests/NodeInputViewModelTests.cs @@ -21,7 +21,7 @@ public void TestConnections() { NodeOutputViewModel nodeAOutput = new NodeOutputViewModel(); NodeViewModel nodeA = new NodeViewModel(); - nodeA.Outputs.Add(nodeAOutput); + nodeA.EditableOutputs().Add(nodeAOutput); NodeInputViewModel nodeBInput = new NodeInputViewModel(); NodeOutputViewModel nodeBOutput = new NodeOutputViewModel(); @@ -30,8 +30,8 @@ public void TestConnections() CanBeRemovedByUser = false, IsSelected = true }; - nodeB.Inputs.Add(nodeBInput); - nodeB.Outputs.Add(nodeBOutput); + nodeB.EditableInputs().Add(nodeBInput); + nodeB.EditableOutputs().Add(nodeBOutput); NodeInputViewModel nodeCInput = new NodeInputViewModel { @@ -41,7 +41,7 @@ public void TestConnections() { IsSelected = true }; - nodeC.Inputs.Add(nodeCInput); + nodeC.EditableInputs().Add(nodeCInput); NodeViewModel nodeD = new NodeViewModel { @@ -51,23 +51,23 @@ public void TestConnections() NetworkViewModel network = new NetworkViewModel(); network.Nodes.AddRange(new[]{ nodeA, nodeB, nodeC, nodeD }); - Assert.IsTrue(nodeBInput.Connections.Count == 0); + Assert.IsTrue(nodeBInput.ConnectionsCount == 0); var conAB = network.ConnectionFactory(nodeBInput, nodeAOutput); var conBC = network.ConnectionFactory(nodeCInput, nodeBOutput); network.Connections.Add(conAB); network.Connections.Add(conBC); - Assert.IsTrue(Enumerable.SequenceEqual(nodeBInput.Connections.Items, new[]{conAB})); + Assert.IsTrue(Enumerable.SequenceEqual(nodeBInput.ConnectionsItems, new[]{conAB})); network.Connections.Remove(conAB); - Assert.IsTrue(nodeBInput.Connections.Count == 0); + Assert.IsTrue(nodeBInput.ConnectionsCount == 0); var conAC = network.ConnectionFactory(nodeCInput, nodeAOutput); network.Connections.Add(conAC); - Assert.IsTrue(Enumerable.SequenceEqual(nodeCInput.Connections.Items, new[] { conBC, conAC })); + Assert.IsTrue(Enumerable.SequenceEqual(nodeCInput.ConnectionsItems, new[] { conBC, conAC })); } [TestMethod] @@ -77,10 +77,10 @@ public void TestHideEditorIfConnected() TestableInput input = new TestableInput(); var outputNode = new NodeViewModel(); - outputNode.Outputs.Add(output); + outputNode.EditableOutputs().Add(output); var inputNode = new NodeViewModel(); - inputNode.Inputs.Add(input); + inputNode.EditableInputs().Add(input); NetworkViewModel network = new NetworkViewModel(); network.Nodes.AddRange(new[] { outputNode, inputNode }); @@ -99,7 +99,7 @@ public void TestCreatePendingConnection() TestableInput input = new TestableInput(); var node = new NodeViewModel(); - node.Inputs.Add(input); + node.EditableInputs().Add(input); NetworkViewModel network = new NetworkViewModel(); network.Nodes.Add(node); @@ -119,10 +119,10 @@ public void TestPreviewAndFinishPendingConnection() TestableInput input = new TestableInput(); var outputNode = new NodeViewModel(); - outputNode.Outputs.Add(output); + outputNode.EditableOutputs().Add(output); var inputNode = new NodeViewModel(); - inputNode.Inputs.Add(input); + inputNode.EditableInputs().Add(input); NetworkViewModel network = new NetworkViewModel(); network.Nodes.AddRange(new[] { outputNode, inputNode }); diff --git a/NodeNetworkTests/NodeOutputViewModelTests.cs b/NodeNetworkTests/NodeOutputViewModelTests.cs index 3532c63..35aa462 100644 --- a/NodeNetworkTests/NodeOutputViewModelTests.cs +++ b/NodeNetworkTests/NodeOutputViewModelTests.cs @@ -21,25 +21,25 @@ public void TestConnections() { NodeOutputViewModel nodeAOutput = new NodeOutputViewModel(); NodeViewModel nodeA = new NodeViewModel(); - nodeA.Outputs.Add(nodeAOutput); + nodeA.EditableOutputs().Add(nodeAOutput); NodeInputViewModel nodeBInput = new NodeInputViewModel(); NodeViewModel nodeB = new NodeViewModel(); - nodeB.Inputs.Add(nodeBInput); + nodeB.EditableInputs().Add(nodeBInput); NodeInputViewModel nodeCInput = new NodeInputViewModel(); NodeViewModel nodeC = new NodeViewModel(); - nodeC.Inputs.Add(nodeCInput); + nodeC.EditableInputs().Add(nodeCInput); NetworkViewModel network = new NetworkViewModel(); network.Nodes.AddRange(new[]{ nodeA, nodeB, nodeC }); - Assert.AreEqual(0, nodeAOutput.Connections.Count); + Assert.AreEqual(0, nodeAOutput.ConnectionsCount); var conAB = network.ConnectionFactory(nodeBInput, nodeAOutput); network.Connections.Add(conAB); - Assert.IsTrue(nodeAOutput.Connections.Items.SequenceEqual(new[] + Assert.IsTrue(nodeAOutput.ConnectionsItems.SequenceEqual(new[] { conAB })); @@ -47,21 +47,21 @@ public void TestConnections() var conAC = network.ConnectionFactory(nodeCInput, nodeAOutput); network.Connections.Add(conAC); - Assert.IsTrue(nodeAOutput.Connections.Items.SequenceEqual(new [] + Assert.IsTrue(nodeAOutput.ConnectionsItems.SequenceEqual(new [] { conAB, conAC })); network.Connections.Remove(conAB); - Assert.IsTrue(nodeAOutput.Connections.Items.SequenceEqual(new[] + Assert.IsTrue(nodeAOutput.ConnectionsItems.SequenceEqual(new[] { conAC })); network.Connections.Remove(conAC); - Assert.AreEqual(0, nodeAOutput.Connections.Count); + Assert.AreEqual(0, nodeAOutput.ConnectionsCount); } [TestMethod] @@ -69,7 +69,7 @@ public void TestCreatePendingConnection() { TestableOutput output = new TestableOutput(); var node = new NodeViewModel(); - node.Outputs.Add(output); + node.EditableOutputs().Add(output); NetworkViewModel network = new NetworkViewModel(); network.Nodes.Add(node); @@ -87,11 +87,11 @@ public void TestPreviewAndFinishPendingConnection() { TestableOutput output = new TestableOutput(); var outputNode = new NodeViewModel(); - outputNode.Outputs.Add(output); + outputNode.EditableOutputs().Add(output); TestableInput input = new TestableInput(); var inputNode = new NodeViewModel(); - inputNode.Inputs.Add(input); + inputNode.EditableInputs().Add(input); NetworkViewModel network = new NetworkViewModel(); network.Nodes.AddRange(new[] { outputNode, inputNode }); diff --git a/NodeNetworkTests/NodeViewModelTests.cs b/NodeNetworkTests/NodeViewModelTests.cs index 157436a..3a56eef 100644 --- a/NodeNetworkTests/NodeViewModelTests.cs +++ b/NodeNetworkTests/NodeViewModelTests.cs @@ -22,15 +22,15 @@ public void TestInputParent() Assert.AreEqual(null, input.Parent); NodeViewModel node = new NodeViewModel(); - node.Inputs.Add(input); + node.EditableInputs().Add(input); Assert.AreEqual(node, input.Parent); - node.Inputs.Remove(input); + node.EditableInputs().Remove(input); Assert.AreEqual(null, input.Parent); - node.Inputs.Add(input); + node.EditableInputs().Add(input); Assert.AreEqual(node, input.Parent); - node.Inputs.Clear(); + node.EditableInputs().Clear(); Assert.AreEqual(null, input.Parent); } @@ -41,15 +41,15 @@ public void TestOutputParent() Assert.AreEqual(null, output.Parent); NodeViewModel node = new NodeViewModel(); - node.Outputs.Add(output); + node.EditableOutputs().Add(output); Assert.AreEqual(node, output.Parent); - node.Outputs.Remove(output); + node.EditableOutputs().Remove(output); Assert.AreEqual(null, output.Parent); - node.Outputs.Add(output); + node.EditableOutputs().Add(output); Assert.AreEqual(node, output.Parent); - node.Outputs.Clear(); + node.EditableOutputs().Clear(); Assert.AreEqual(null, output.Parent); } @@ -61,19 +61,19 @@ public void TestNodeCollapse(EndpointVisibility visibility, bool nonCollapsedNon { NodeOutputViewModel nodeAOutput = new NodeOutputViewModel(); NodeViewModel nodeA = new NodeViewModel(); - nodeA.Outputs.Add(nodeAOutput); + nodeA.EditableOutputs().Add(nodeAOutput); NodeInputViewModel nodeBInput = new NodeInputViewModel { Visibility = visibility }; NodeInputViewModel nodeBInput2 = new NodeInputViewModel { Visibility = visibility }; NodeOutputViewModel nodeBOutput = new NodeOutputViewModel { Visibility = visibility }; NodeOutputViewModel nodeBOutput2 = new NodeOutputViewModel { Visibility = visibility }; NodeViewModel nodeB = new NodeViewModel(); - nodeB.Inputs.AddRange(new []{ nodeBInput, nodeBInput2 }); - nodeB.Outputs.AddRange(new []{ nodeBOutput, nodeBOutput2 }); + nodeB.EditableInputs().AddRange(new []{ nodeBInput, nodeBInput2 }); + nodeB.EditableOutputs().AddRange(new []{ nodeBOutput, nodeBOutput2 }); NodeInputViewModel nodeCInput = new NodeInputViewModel(); NodeViewModel nodeC = new NodeViewModel(); - nodeC.Inputs.Add(nodeCInput); + nodeC.EditableInputs().Add(nodeCInput); NetworkViewModel network = new NetworkViewModel(); network.Nodes.AddRange(new[] { nodeA, nodeB, nodeC }); diff --git a/NodeNetworkTests/ValueListInputTests.cs b/NodeNetworkTests/ValueListInputTests.cs index 4795cc8..0fe5a2d 100644 --- a/NodeNetworkTests/ValueListInputTests.cs +++ b/NodeNetworkTests/ValueListInputTests.cs @@ -31,11 +31,11 @@ public void TestValuePropagation() { Value = sourceA }; - nodeA.Outputs.Add(outputA); + nodeA.EditableOutputs().Add(outputA); var nodeB = new NodeViewModel(); var inputB = new ValueListNodeInputViewModel(); - nodeB.Inputs.Add(inputB); + nodeB.EditableInputs().Add(inputB); NetworkViewModel network = new NetworkViewModel(); network.Nodes.AddRange(new []{nodeA, nodeB}); @@ -99,25 +99,25 @@ public void TestOutputListPassthrough() var valNode = new NodeViewModel(); var valOutput1 = new ValueNodeOutputViewModel { Value = Observable.Return(1) }; - valNode.Outputs.Add(valOutput1); + valNode.EditableOutputs().Add(valOutput1); var valOutput2 = new ValueNodeOutputViewModel { Value = Observable.Return(2) }; - valNode.Outputs.Add(valOutput2); + valNode.EditableOutputs().Add(valOutput2); var valOutput3 = new ValueNodeOutputViewModel { Value = Observable.Return(3) }; - valNode.Outputs.Add(valOutput3); + valNode.EditableOutputs().Add(valOutput3); // var nodeA = new NodeViewModel(); var inputA = new ValueListNodeInputViewModel(); - nodeA.Inputs.Add(inputA); + nodeA.EditableInputs().Add(inputA); var outputA = new ValueNodeOutputViewModel> { Value = Observable.Return(inputA.Values) }; - nodeA.Outputs.Add(outputA); + nodeA.EditableOutputs().Add(outputA); var nodeB = new NodeViewModel(); var inputB = new ValueListNodeInputViewModel(); - nodeB.Inputs.Add(inputB); + nodeB.EditableInputs().Add(inputB); NetworkViewModel network = new NetworkViewModel(); network.Nodes.AddRange(new[] { nodeA, nodeB }); diff --git a/NodeNetworkToolkit/ContextMenu/AddNodeContextMenuViewModel.cs b/NodeNetworkToolkit/ContextMenu/AddNodeContextMenuViewModel.cs index f4f7d93..3787216 100644 --- a/NodeNetworkToolkit/ContextMenu/AddNodeContextMenuViewModel.cs +++ b/NodeNetworkToolkit/ContextMenu/AddNodeContextMenuViewModel.cs @@ -219,7 +219,7 @@ public static IEnumerable GetConnectableNodes(IEnumerable GetConnectableOutputs(NodeViewModel node, PendingConnectionViewModel testCon) { var validator = testCon.Input.ConnectionValidator; - foreach (var curOutput in node.Outputs.Items) + foreach (var curOutput in node.OutputItems) { testCon.Output = curOutput; if (curOutput.MaxConnections > 0 && validator(testCon).IsValid) @@ -235,7 +235,7 @@ public static IEnumerable GetConnectableOutputs(NodeViewMod /// public static IEnumerable GetConnectableInputs(NodeViewModel node, PendingConnectionViewModel testCon) { - foreach (var curInput in node.Inputs.Items) + foreach (var curInput in node.InputItems) { var validator = curInput.ConnectionValidator; testCon.Input = curInput; diff --git a/NodeNetworkToolkit/GraphAlgorithms.cs b/NodeNetworkToolkit/GraphAlgorithms.cs index 7b3a08f..044a420 100644 --- a/NodeNetworkToolkit/GraphAlgorithms.cs +++ b/NodeNetworkToolkit/GraphAlgorithms.cs @@ -81,9 +81,9 @@ private static ConnectionViewModel FindLoops(Dictionary nodesToCheck = new List(); - foreach (NodeInputViewModel input in node.Inputs.Items) + foreach (NodeInputViewModel input in node.InputItems) { - foreach (ConnectionViewModel con in input.Connections.Items) + foreach (ConnectionViewModel con in input.ConnectionsItems) { NodeViewModel connectedNode = con.Output.Parent; if (!nodeStates.TryGetValue(connectedNode, out var connectedNodeState)) @@ -147,7 +147,7 @@ public static IEnumerable GetConnectedNodesTunneling(NodeViewMode if (includeInputs) { - IEnumerable inputNodes = startingNode.Inputs.Items.SelectMany(i => i.Connections.Items).Select(c => c.Output.Parent); + IEnumerable inputNodes = startingNode.InputItems.SelectMany(i => i.ConnectionsItems).Select(c => c.Output.Parent); foreach (NodeViewModel nodeVM in inputNodes) { foreach (NodeViewModel subNodeVM in GetConnectedNodesTunneling(nodeVM, includeInputs, includeOutputs, true)) @@ -162,7 +162,7 @@ public static IEnumerable GetConnectedNodesTunneling(NodeViewMode if (includeOutputs) { - IEnumerable outputNodes = startingNode.Outputs.Items.SelectMany(i => i.Connections.Items).Select(c => c.Input.Parent); + IEnumerable outputNodes = startingNode.OutputItems.SelectMany(i => i.ConnectionsItems).Select(c => c.Input.Parent); foreach (NodeViewModel nodeVM in outputNodes) { foreach (NodeViewModel subNodeVM in GetConnectedNodesTunneling(nodeVM, includeInputs, includeOutputs, true)) @@ -211,9 +211,9 @@ public static IEnumerable FindStartingNodes(IEnumerable nodes.Contains(c.Output.Parent))) + if (input.ConnectionsItems.Any(c => nodes.Contains(c.Output.Parent))) { hasInputConnection = true; break; @@ -259,9 +259,9 @@ public static IEnumerable FindConnectedNodes(NodeViewModel source } } - foreach (NodeInputViewModel input in node.Inputs.Items) + foreach (NodeInputViewModel input in node.InputItems) { - foreach (NodeViewModel connectedNode in input.Connections.Items.Select(c => c.Output.Parent)) + foreach (NodeViewModel connectedNode in input.ConnectionsItems.Select(c => c.Output.Parent)) { if (visitedNodes.Add(connectedNode)) { @@ -269,9 +269,9 @@ public static IEnumerable FindConnectedNodes(NodeViewModel source } } } - foreach (NodeOutputViewModel output in node.Outputs.Items) + foreach (NodeOutputViewModel output in node.OutputItems) { - foreach (NodeViewModel connectedNode in output.Connections.Items.Select(c => c.Input.Parent)) + foreach (NodeViewModel connectedNode in output.ConnectionsItems.Select(c => c.Input.Parent)) { if (visitedNodes.Add(connectedNode)) { @@ -330,9 +330,9 @@ private static bool IsContinuousSubGroup(HashSet groupNodesSet, I { NodeViewModel cur = queue.Dequeue(); - foreach (NodeOutputViewModel output in cur.Outputs.Items) + foreach (NodeOutputViewModel output in cur.OutputItems) { - foreach (ConnectionViewModel con in output.Connections.Items) + foreach (ConnectionViewModel con in output.ConnectionsItems) { NodeViewModel connectedNode = con.Input.Parent; diff --git a/NodeNetworkToolkit/Group/NodeGrouper.cs b/NodeNetworkToolkit/Group/NodeGrouper.cs index c1668d8..dbc6038 100644 --- a/NodeNetworkToolkit/Group/NodeGrouper.cs +++ b/NodeNetworkToolkit/Group/NodeGrouper.cs @@ -203,7 +203,7 @@ public void Ungroup(NodeGroupIOBinding nodeGroupInfo) { if (conn.Input.Parent == nodeGroupInfo.EntranceNode || conn.Input.Parent == nodeGroupInfo.ExitNode) { - var inputs = nodeGroupInfo.GetGroupNodeOutput(conn.Input).Connections.Items.Select(c => c.Input).ToArray(); + var inputs = nodeGroupInfo.GetGroupNodeOutput(conn.Input).ConnectionsItems.Select(c => c.Input).ToArray(); if (inputs.Length > 0) { borderInputConnections.Add(Tuple.Create(conn.Output, inputs)); @@ -211,7 +211,7 @@ public void Ungroup(NodeGroupIOBinding nodeGroupInfo) } else if (conn.Output.Parent == nodeGroupInfo.EntranceNode || conn.Output.Parent == nodeGroupInfo.ExitNode) { - var outputs = nodeGroupInfo.GetGroupNodeInput(conn.Output).Connections.Items.Select(c => c.Output).ToArray(); + var outputs = nodeGroupInfo.GetGroupNodeInput(conn.Output).ConnectionsItems.Select(c => c.Output).ToArray(); if (outputs.Length > 0) { borderOutputConnections.Add(Tuple.Create(conn.Input, outputs)); diff --git a/NodeNetworkToolkit/Group/ValueNodeGroupIOBinding.cs b/NodeNetworkToolkit/Group/ValueNodeGroupIOBinding.cs index 8aacbe0..3bc5309 100644 --- a/NodeNetworkToolkit/Group/ValueNodeGroupIOBinding.cs +++ b/NodeNetworkToolkit/Group/ValueNodeGroupIOBinding.cs @@ -19,7 +19,7 @@ public ValueNodeGroupIOBinding(NodeViewModel groupNode, NodeViewModel entranceNo : base(groupNode, entranceNode, exitNode) { // For each input on the group node, create an output in the subnet - groupNode.Inputs.Connect() + groupNode.Inputs .Filter(input => input.PortPosition == PortPosition.Left) .Transform(i => { @@ -28,39 +28,39 @@ public ValueNodeGroupIOBinding(NodeViewModel groupNode, NodeViewModel entranceNo NodeOutputViewModel result = CreateCompatibleOutput((dynamic)i); BindOutputToInput((dynamic)result, (dynamic)i); return result; - }).PopulateInto(entranceNode.Outputs); - groupNode.Inputs.Connect() + }).PopulateInto(entranceNode.EditableOutputs()); + groupNode.Inputs .Filter(input => input.PortPosition == PortPosition.Right) .Transform(i => { NodeOutputViewModel result = CreateCompatibleOutput((dynamic) i); BindOutputToInput((dynamic) result, (dynamic) i); return result; - }).PopulateInto(exitNode.Outputs); - groupNode.Inputs.Connect().OnItemRemoved(input => + }).PopulateInto(exitNode.EditableOutputs()); + groupNode.Inputs.OnItemRemoved(input => _outputInputMapping.Remove( _outputInputMapping.First(kvp => kvp.Value == input) ) ); // For each output on the group node, create an input in the subnet - groupNode.Outputs.Connect() + groupNode.Outputs .Filter(input => input.PortPosition == PortPosition.Right) .Transform(o => { NodeInputViewModel result = CreateCompatibleInput((dynamic)o); BindOutputToInput((dynamic)o, (dynamic)result); return result; - }).PopulateInto(exitNode.Inputs); - groupNode.Outputs.Connect() + }).PopulateInto(exitNode.EditableInputs()); + groupNode.Outputs .Filter(input => input.PortPosition == PortPosition.Left) .Transform(o => { NodeInputViewModel result = CreateCompatibleInput((dynamic)o); BindOutputToInput((dynamic)o, (dynamic)result); return result; - }).PopulateInto(entranceNode.Inputs); - groupNode.Outputs.Connect().OnItemRemoved(output => _outputInputMapping.Remove(output)); + }).PopulateInto(entranceNode.EditableInputs()); + groupNode.Outputs.OnItemRemoved(output => _outputInputMapping.Remove(output)); } protected virtual void BindEndpointProperties(NodeOutputViewModel output, NodeInputViewModel input) @@ -125,9 +125,9 @@ public virtual ValueListNodeInputViewModel CreateCompatibleInput(ValueNode public override NodeInputViewModel AddNewGroupNodeInput(NodeOutputViewModel candidateOutput) { NodeInputViewModel input = CreateCompatibleInput((dynamic)candidateOutput); - GroupNode.Inputs.Add(input); + GroupNode.EditableInputs().Add(input); // Append to bottom of list - input.SortIndex = GroupNode.Inputs.Items.Select(i => i.SortIndex).DefaultIfEmpty(-1).Max() + 1; + input.SortIndex = GroupNode.InputItems.Select(i => i.SortIndex).DefaultIfEmpty(-1).Max() + 1; return input; } @@ -146,9 +146,9 @@ public override NodeInputViewModel AddNewSubnetOutlet(NodeOutputViewModel candid public override NodeOutputViewModel AddNewGroupNodeOutput(NodeInputViewModel candidateInput) { NodeOutputViewModel output = CreateCompatibleOutput((dynamic)candidateInput); - GroupNode.Outputs.Add(output); + GroupNode.EditableOutputs().Add(output); // Append to bottom of list - output.SortIndex = GroupNode.Outputs.Items.Select(o => o.SortIndex).DefaultIfEmpty(-1).Max() + 1; + output.SortIndex = GroupNode.OutputItems.Select(o => o.SortIndex).DefaultIfEmpty(-1).Max() + 1; return output; } #endregion @@ -191,24 +191,24 @@ public virtual void DeleteEndpoint(Endpoint endpoint) { if (isOnGroupNode) { - GroupNode.Inputs.Remove(input); + GroupNode.EditableInputs().Remove(input); } else { var groupOutput = GetGroupNodeOutput(input); - GroupNode.Outputs.Remove(groupOutput); + GroupNode.EditableOutputs().Remove(groupOutput); } } else if(endpoint is NodeOutputViewModel output) { if (isOnGroupNode) { - GroupNode.Outputs.Remove(output); + GroupNode.EditableOutputs().Remove(output); } else { var groupInput = GetGroupNodeInput(output); - GroupNode.Inputs.Remove(groupInput); + GroupNode.EditableInputs().Remove(groupInput); } } } diff --git a/NodeNetworkToolkit/Layout/ForceDirected/Engine.cs b/NodeNetworkToolkit/Layout/ForceDirected/Engine.cs index 8f48952..2b1e550 100644 --- a/NodeNetworkToolkit/Layout/ForceDirected/Engine.cs +++ b/NodeNetworkToolkit/Layout/ForceDirected/Engine.cs @@ -49,9 +49,9 @@ private Vector CalculateNodeForce(NodeViewModel node, IState state, Configuratio Vector force = new Vector(); // Calculate total force on node from endpoints - if (node.Inputs.Count > 0 || node.Outputs.Count > 0) + if (node.InputsCount > 0 || node.OutputsCount > 0) { - force += node.Inputs.Items.Cast().Concat(node.Outputs.Items) + force += node.InputItems.Cast().Concat(node.OutputItems) .Select(e => CalculateEndpointForce(e, state, config)) .Aggregate((v1, v2) => v1 + v2); } @@ -98,7 +98,7 @@ private Vector CalculateEndpointForce(Endpoint endpoint, IState state, Configura Vector force = new Vector(); - foreach (var conn in endpoint.Connections.Items) + foreach (var conn in endpoint.ConnectionsItems) { var otherSide = conn.Input == endpoint ? (Endpoint)conn.Output : conn.Input; var otherSidePos = state.GetEndpointPosition(otherSide); diff --git a/NodeNetworkToolkit/ValueNode/ValueListNodeInputViewModel.cs b/NodeNetworkToolkit/ValueNode/ValueListNodeInputViewModel.cs index 7d81ba1..a63b3e2 100644 --- a/NodeNetworkToolkit/ValueNode/ValueListNodeInputViewModel.cs +++ b/NodeNetworkToolkit/ValueNode/ValueListNodeInputViewModel.cs @@ -41,7 +41,7 @@ pending.Output is ValueNodeOutputViewModel || null ); - var valuesFromSingles = Connections.Connect(c => c.Output is ValueNodeOutputViewModel) + var valuesFromSingles = Connections.Filter(c => c.Output is ValueNodeOutputViewModel) .Transform(c => (ValueNodeOutputViewModel)c.Output) //Note: this line used to be //.AutoRefresh(output => output.CurrentValue) @@ -89,7 +89,7 @@ pending.Output is ValueNodeOutputViewModel || return changes; }); - var valuesFromLists = Connections.Connect(c => c.Output is ValueNodeOutputViewModel>) + var valuesFromLists = Connections.Filter(c => c.Output is ValueNodeOutputViewModel>) // Grab list of values from output, using switch to handle when the list object is replaced .Transform(c => ((ValueNodeOutputViewModel>) c.Output).Value.Switch()) // Materialize this changeset stream into a list (needed to make sure the next step is done dynamically) diff --git a/NodeNetworkToolkit/ValueNode/ValueNodeInputViewModel.cs b/NodeNetworkToolkit/ValueNode/ValueNodeInputViewModel.cs index f73fb6d..86ee948 100644 --- a/NodeNetworkToolkit/ValueNode/ValueNodeInputViewModel.cs +++ b/NodeNetworkToolkit/ValueNode/ValueNodeInputViewModel.cs @@ -80,7 +80,7 @@ public ValueNodeInputViewModel( .Switch(); var valueChanged = Observable.CombineLatest(connectedValues, localValues, - (connectedValue, localValue) => Connections.Count == 0 ? localValue : connectedValue + (connectedValue, localValue) => ConnectionsCount == 0 ? localValue : connectedValue ).Publish(); valueChanged.Connect(); valueChanged.ToProperty(this, vm => vm.Value, out _value); @@ -92,8 +92,8 @@ public ValueNodeInputViewModel( private IObservable GenerateConnectedValuesBinding(ValidationAction connectionChangedValidationAction, ValidationAction connectedValueChangedValidationAction) { - var onConnectionChanged = this.Connections.Connect().Select(_ => Unit.Default).StartWith(Unit.Default) - .Select(_ => Connections.Count == 0 ? null : Connections.Items.First()); + var onConnectionChanged = this.Connections.Select(_ => Unit.Default).StartWith(Unit.Default) + .Select(_ => ConnectionsCount == 0 ? null : ConnectionsItems.First()); //On connection change IObservable> connectionObservables; @@ -117,17 +117,17 @@ private IObservable GenerateConnectedValuesBinding(ValidationAction connectio //Or push a single default(T) if the validation fails connectionObservables = postValidation.Select(validation => { - if (Connections.Count == 0) + if (ConnectionsCount == 0) { return Observable.Return(default(T)); } else if(validation.NetworkIsTraversable) { IObservable connectedObservable = - ((ValueNodeOutputViewModel) Connections.Items.First().Output).Value; + ((ValueNodeOutputViewModel) ConnectionsItems.First().Output).Value; if (connectedObservable == null) { - throw new Exception($"The value observable for output '{Connections.Items.First().Output.Name}' is null."); + throw new Exception($"The value observable for output '{ConnectionsItems.First().Output.Name}' is null."); } return connectedObservable; } @@ -143,17 +143,17 @@ private IObservable GenerateConnectedValuesBinding(ValidationAction connectio connectionObservables = postValidation .Select(_ => { - if (Connections.Count == 0) + if (ConnectionsCount == 0) { return Observable.Return(default(T)); } else { IObservable connectedObservable = - ((ValueNodeOutputViewModel)Connections.Items.First().Output).Value; + ((ValueNodeOutputViewModel)ConnectionsItems.First().Output).Value; if (connectedObservable == null) { - throw new Exception($"The value observable for output '{Connections.Items.First().Output.Name}' is null."); + throw new Exception($"The value observable for output '{ConnectionsItems.First().Output.Name}' is null."); } return connectedObservable; } @@ -175,7 +175,7 @@ private IObservable GenerateConnectedValuesBinding(ValidationAction connectio ((ValueNodeOutputViewModel)con.Output).Value; if (connectedObservable == null) { - throw new Exception($"The value observable for output '{Connections.Items.First().Output.Name}' is null."); + throw new Exception($"The value observable for output '{ConnectionsItems.First().Output.Name}' is null."); } return connectedObservable; } @@ -200,7 +200,7 @@ private IObservable GenerateConnectedValuesBinding(ValidationAction connectio connectedValues = postValidation.Select(validation => { - if (Connections.Count == 0 + if (ConnectionsCount == 0 || connectionChangedValidationAction == ValidationAction.PushDefaultValue && !validation.NetworkIsTraversable || connectedValueChangedValidationAction == ValidationAction.PushDefaultValue && !validation.IsValid) { @@ -209,7 +209,7 @@ private IObservable GenerateConnectedValuesBinding(ValidationAction connectio } //Or just ignore the validation and push the value as is - return ((ValueNodeOutputViewModel) this.Connections.Items.First().Output).CurrentValue; + return ((ValueNodeOutputViewModel) this.ConnectionsItems.First().Output).CurrentValue; }); } diff --git a/StressTest/MainWindow.xaml.cs b/StressTest/MainWindow.xaml.cs index f73500e..fd6802d 100644 --- a/StressTest/MainWindow.xaml.cs +++ b/StressTest/MainWindow.xaml.cs @@ -52,7 +52,7 @@ public MainWindow() NetworkView.ViewModel = _network; this.WhenAnyValue(v => v.ShowOutputChecky.IsChecked).Subscribe(isChecked => { - _network.Nodes.Items.First().Outputs.Items.ElementAt(0).Visibility = + _network.Nodes.Items.First().OutputItems.ElementAt(0).Visibility = isChecked.Value ? EndpointVisibility.AlwaysVisible : EndpointVisibility.AlwaysHidden; }); } @@ -71,8 +71,8 @@ public NodeViewModel CreateNode() }; NodeViewModel node = new NodeViewModel(); - node.Inputs.Add(input); - node.Outputs.Add(output); + node.EditableInputs().Add(input); + node.EditableOutputs().Add(output); output.Value.Subscribe(v => node.Name = v.ToString()); return node; @@ -99,7 +99,7 @@ private void GenerateNodes(object sender, RoutedEventArgs e) private void GenerateConnections(object sender, RoutedEventArgs e) { var connections = _network.Nodes.Items.Zip(_network.Nodes.Items.Skip(1), - (node1, node2) => _network.ConnectionFactory(node2.Inputs.Items.ElementAt(0), node1.Outputs.Items.ElementAt(0))); + (node1, node2) => _network.ConnectionFactory(node2.InputItems.ElementAt(0), node1.OutputItems.ElementAt(0))); _network.Connections.AddRange(connections); }