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:
parent
b6e0c0fb66
commit
dc17253518
@ -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
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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}}"
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
|
||||
@ -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>
|
||||
|
||||
35
src/Artemis.VisualScripting/Nodes/Mathematics/MaxNode.cs
Normal file
35
src/Artemis.VisualScripting/Nodes/Mathematics/MaxNode.cs
Normal 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
|
||||
}
|
||||
35
src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs
Normal file
35
src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs
Normal 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
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user