1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Visual scripting - Added pin disconnect with MMB

Visual scripting - Added min and max node
This commit is contained in:
Robert 2022-08-01 22:26:11 +02:00
parent b6e0c0fb66
commit dc17253518
15 changed files with 164 additions and 21 deletions

View File

@ -0,0 +1,43 @@
using System.Collections.Generic;
using Artemis.Core;
namespace Artemis.UI.Shared.Services.NodeEditor.Commands;
/// <summary>
/// Represents a node editor command that can be used to connect two pins.
/// </summary>
public class DisconnectPins : INodeEditorCommand
{
private readonly IPin _pin;
private readonly List<IPin> _originalConnections;
/// <summary>
/// Creates a new instance of the <see cref="DisconnectPins" /> class.
/// </summary>
/// <param name="pin">The pin to disconnect.</param>
public DisconnectPins(IPin pin)
{
_pin = pin;
_originalConnections = new List<IPin>(_pin.ConnectedTo);
}
#region Implementation of INodeEditorCommand
/// <inheritdoc />
public string DisplayName => "Disconnect pins";
/// <inheritdoc />
public void Execute()
{
_pin.DisconnectAll();
}
/// <inheritdoc />
public void Undo()
{
foreach (IPin pin in _originalConnections)
_pin.ConnectTo(pin);
}
#endregion
}

View File

@ -106,8 +106,8 @@ public interface INodeVmFactory : IVmFactory
NodeViewModel NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node);
CableViewModel CableViewModel(NodeScriptViewModel nodeScriptViewModel, IPin from, IPin to);
DragCableViewModel DragCableViewModel(PinViewModel pinViewModel);
InputPinViewModel InputPinViewModel(IPin inputPin);
OutputPinViewModel OutputPinViewModel(IPin outputPin);
InputPinViewModel InputPinViewModel(IPin inputPin, NodeScriptViewModel nodeScriptViewModel);
OutputPinViewModel OutputPinViewModel(IPin outputPin, NodeScriptViewModel nodeScriptViewModel);
InputPinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel);
OutputPinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel);
}

View File

@ -47,12 +47,12 @@ public class NodeViewModel : ActivatableViewModelBase
// Create observable collections split up by direction
nodePins.Connect()
.Filter(n => n.Direction == PinDirection.Input)
.Transform(p => (PinViewModel) nodeVmFactory.InputPinViewModel(p))
.Transform(p => (PinViewModel) nodeVmFactory.InputPinViewModel(p, nodeScriptViewModel))
.Bind(out ReadOnlyObservableCollection<PinViewModel> inputPins)
.Subscribe();
nodePins.Connect()
.Filter(n => n.Direction == PinDirection.Output)
.Transform(p => (PinViewModel) nodeVmFactory.OutputPinViewModel(p))
.Transform(p => (PinViewModel) nodeVmFactory.OutputPinViewModel(p, nodeScriptViewModel))
.Bind(out ReadOnlyObservableCollection<PinViewModel> outputPins)
.Subscribe();
InputPinViewModels = inputPins;

View File

@ -6,19 +6,21 @@ namespace Artemis.UI.Screens.VisualScripting.Pins;
public class InputPinCollectionViewModel : PinCollectionViewModel
{
private readonly NodeScriptViewModel _nodeScriptViewModel;
private readonly INodeVmFactory _nodeVmFactory;
public IPinCollection InputPinCollection { get; }
public InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
: base(inputPinCollection, nodeScriptViewModel, nodeEditorService)
{
_nodeScriptViewModel = nodeScriptViewModel;
_nodeVmFactory = nodeVmFactory;
InputPinCollection = inputPinCollection;
}
protected override PinViewModel CreatePinViewModel(IPin pin)
{
PinViewModel vm = _nodeVmFactory.InputPinViewModel(pin);
PinViewModel vm = _nodeVmFactory.InputPinViewModel(pin, _nodeScriptViewModel);
vm.RemovePin = RemovePin;
return vm;
}

View File

@ -14,7 +14,7 @@
<UserControl.Styles>
<StyleInclude Source="/Screens/VisualScripting/VisualScripting.axaml" />
</UserControl.Styles>
<StackPanel Name="PinContainer" Orientation="Horizontal" Spacing="6">
<StackPanel Name="PinContainer" Orientation="Horizontal" Spacing="6" PointerReleased="PinContainer_OnPointerReleased">
<Border Name="PinPoint">
<Border Name="VisualPinPoint"
BorderBrush="{CompiledBinding PinColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"

View File

@ -1,4 +1,6 @@
using System;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.VisualScripting.Pins;
@ -15,4 +17,10 @@ public class InputPinView : PinView
{
AvaloniaXamlLoader.Load(this);
}
private void PinContainer_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
if (e.InitialPressMouseButton == MouseButton.Middle)
ViewModel?.DisconnectPin.Execute().Subscribe();
}
}

View File

@ -1,11 +1,13 @@
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared.Services.NodeEditor;
namespace Artemis.UI.Screens.VisualScripting.Pins;
public class InputPinViewModel : PinViewModel
{
public InputPinViewModel(IPin inputPin, INodeService nodeService) : base(inputPin, nodeService)
public InputPinViewModel(IPin inputPin, NodeScriptViewModel nodeScriptViewModel, INodeService nodeService, INodeEditorService nodeEditorService)
: base(inputPin, nodeScriptViewModel, nodeService, nodeEditorService)
{
}
}

View File

@ -6,19 +6,21 @@ namespace Artemis.UI.Screens.VisualScripting.Pins;
public class OutputPinCollectionViewModel : PinCollectionViewModel
{
private readonly NodeScriptViewModel _nodeScriptViewModel;
private readonly INodeVmFactory _nodeVmFactory;
public IPinCollection OutputPinCollection { get; }
public OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
: base(outputPinCollection, nodeScriptViewModel, nodeEditorService)
{
_nodeScriptViewModel = nodeScriptViewModel;
_nodeVmFactory = nodeVmFactory;
OutputPinCollection = outputPinCollection;
}
protected override PinViewModel CreatePinViewModel(IPin pin)
{
PinViewModel vm = _nodeVmFactory.OutputPinViewModel(pin);
PinViewModel vm = _nodeVmFactory.OutputPinViewModel(pin, _nodeScriptViewModel);
vm.RemovePin = RemovePin;
return vm;
}

View File

@ -14,7 +14,7 @@
<UserControl.Styles>
<StyleInclude Source="/Screens/VisualScripting/VisualScripting.axaml" />
</UserControl.Styles>
<StackPanel Name="PinContainer" Orientation="Horizontal" Spacing="6">
<StackPanel Name="PinContainer" Orientation="Horizontal" Spacing="6" PointerReleased="PinContainer_OnPointerReleased">
<TextBlock Name="PinName" VerticalAlignment="Center" Text="{CompiledBinding Pin.Name}" />
<Border Name="PinPoint">
<Border Name="VisualPinPoint"

View File

@ -1,4 +1,6 @@
using System;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.VisualScripting.Pins;
@ -15,4 +17,10 @@ public class OutputPinView : PinView
{
AvaloniaXamlLoader.Load(this);
}
private void PinContainer_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
if (e.InitialPressMouseButton == MouseButton.Middle)
ViewModel?.DisconnectPin.Execute().Subscribe();
}
}

View File

@ -1,11 +1,13 @@
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared.Services.NodeEditor;
namespace Artemis.UI.Screens.VisualScripting.Pins;
public class OutputPinViewModel : PinViewModel
{
public OutputPinViewModel(IPin outputPin, INodeService nodeService) : base(outputPin, nodeService)
public OutputPinViewModel(IPin outputPin, NodeScriptViewModel nodeScriptViewModel, INodeService nodeService, INodeEditorService nodeEditorService)
: base(outputPin, nodeScriptViewModel, nodeService, nodeEditorService)
{
}
}

View File

@ -6,6 +6,8 @@ using Artemis.Core.Events;
using Artemis.Core.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Extensions;
using Artemis.UI.Shared.Services.NodeEditor;
using Artemis.UI.Shared.Services.NodeEditor.Commands;
using Avalonia;
using Avalonia.Controls.Mixins;
using Avalonia.Media;
@ -22,11 +24,13 @@ public abstract class PinViewModel : ActivatableViewModelBase
private Color _pinColor;
private Color _darkenedPinColor;
protected PinViewModel(IPin pin, INodeService nodeService)
protected PinViewModel(IPin pin, NodeScriptViewModel nodeScriptViewModel, INodeService nodeService, INodeEditorService nodeEditorService)
{
_nodeService = nodeService;
Pin = pin;
DisconnectPin = ReactiveCommand.Create(() => nodeEditorService.ExecuteCommand(nodeScriptViewModel.NodeScript, new DisconnectPins(Pin)));
SourceList<IPin> connectedPins = new();
this.WhenActivated(d =>
{
@ -78,6 +82,8 @@ public abstract class PinViewModel : ActivatableViewModelBase
set => RaiseAndSetIfChanged(ref _removePin, value);
}
public ReactiveCommand<Unit, Unit> DisconnectPin { get; }
public bool IsCompatibleWith(PinViewModel pinViewModel)
{
if (pinViewModel.Pin.Direction == Pin.Direction || pinViewModel.Pin.Node == Pin.Node)

View File

@ -8,19 +8,19 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.15"/>
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.15"/>
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.14"/>
<PackageReference Include="Ninject" Version="3.3.4"/>
<PackageReference Include="NoStringEvaluating" Version="2.2.2"/>
<PackageReference Include="ReactiveUI" Version="17.1.50"/>
<PackageReference Include="ReactiveUI.Validation" Version="2.2.1"/>
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1"/>
<PackageReference Include="Avalonia" Version="0.10.15" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.15" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.14" />
<PackageReference Include="Ninject" Version="3.3.4" />
<PackageReference Include="NoStringEvaluating" Version="2.2.2" />
<PackageReference Include="ReactiveUI" Version="17.1.50" />
<PackageReference Include="ReactiveUI.Validation" Version="2.2.1" />
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj"/>
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj"/>
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1,35 @@
using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Mathematics;
[Node("Max", "Outputs the largest of the connected numeric values.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
public class MaxNumericsNode : Node
{
#region Constructors
public MaxNumericsNode()
: base("Max", "Outputs the largest of the connected numeric values.")
{
Values = CreateInputPinCollection<Numeric>("Values", 2);
Max = CreateOutputPin<Numeric>("Max");
}
#endregion
#region Methods
public override void Evaluate()
{
Max.Value = Values.Values.Max();
}
#endregion
#region Properties & Fields
public InputPinCollection<Numeric> Values { get; }
public OutputPin<Numeric> Max { get; }
#endregion
}

View File

@ -0,0 +1,35 @@
using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Mathematics;
[Node("Min", "Outputs the smallest of the connected numeric values.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
public class MinNumericsNode : Node
{
#region Constructors
public MinNumericsNode()
: base("Min", "Outputs the smallest of the connected numeric values.")
{
Values = CreateInputPinCollection<Numeric>("Values", 2);
Min = CreateOutputPin<Numeric>("Min");
}
#endregion
#region Methods
public override void Evaluate()
{
Min.Value = Values.Values.Min();
}
#endregion
#region Properties & Fields
public InputPinCollection<Numeric> Values { get; }
public OutputPin<Numeric> Min { get; }
#endregion
}