mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Node editor - Added VM structure
Debugger - Run updates on UI thread
This commit is contained in:
parent
4c274a1749
commit
c99224ab2d
@ -6,7 +6,7 @@ namespace Artemis.UI.Shared
|
||||
/// <summary>
|
||||
/// Represents a view model for a plugin configuration window
|
||||
/// </summary>
|
||||
public abstract class PluginConfigurationViewModel : ViewModelBase, IPluginConfigurationViewModel
|
||||
public abstract class PluginConfigurationViewModel : ViewModelValidationBase, IPluginConfigurationViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="PluginConfigurationViewModel" /> class
|
||||
|
||||
@ -60,6 +60,33 @@ public abstract class ViewModelValidationBase : ReactiveValidationObject
|
||||
get => _displayName;
|
||||
set => this.RaiseAndSetIfChanged(ref _displayName, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RaiseAndSetIfChanged fully implements a Setter for a read-write property on a ReactiveObject, using
|
||||
/// CallerMemberName to raise the notification and the ref to the backing field to set the property.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRet">The type of the return value.</typeparam>
|
||||
/// <param name="backingField">A Reference to the backing field for this property.</param>
|
||||
/// <param name="newValue">The new value.</param>
|
||||
/// <param name="propertyName">
|
||||
/// The name of the property, usually automatically provided through the CallerMemberName
|
||||
/// attribute.
|
||||
/// </param>
|
||||
/// <returns>The newly set value, normally discarded.</returns>
|
||||
[NotifyPropertyChangedInvocator]
|
||||
public TRet RaiseAndSetIfChanged<TRet>(ref TRet backingField, TRet newValue, [CallerMemberName] string? propertyName = null)
|
||||
{
|
||||
if (propertyName is null)
|
||||
throw new ArgumentNullException(nameof(propertyName));
|
||||
|
||||
if (EqualityComparer<TRet>.Default.Equals(backingField, newValue))
|
||||
return newValue;
|
||||
|
||||
this.RaisePropertyChanging(propertyName);
|
||||
backingField = newValue;
|
||||
this.RaisePropertyChanged(propertyName);
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -90,6 +90,11 @@
|
||||
"Splat": "14.1.45"
|
||||
}
|
||||
},
|
||||
"ArtemisRGB.Plugins.BuildTask": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.0",
|
||||
"contentHash": "B8A5NkUEzTUgc5M/QACfyjIF5M23EUzSx8A8l/owJtB0bgmij6y/MQW1i/PcS3EDFQRothBOUuC3BCPY5UoRRQ=="
|
||||
},
|
||||
"Avalonia.Angle.Windows.Natives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.0.2020091801",
|
||||
@ -560,6 +565,11 @@
|
||||
"Ninject": "3.3.3"
|
||||
}
|
||||
},
|
||||
"OpenRGB.NET": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.7.0",
|
||||
"contentHash": "12pMEUaeoG8mN707QRO9hdT529+UnqUpwMW1H/gDTMsJrerhJve6Yt5Dnheu1isQB4PWP1wu3IDVbHCchznkiw=="
|
||||
},
|
||||
"ReactiveUI.Validation": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.1",
|
||||
@ -1762,6 +1772,21 @@
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"artemis.plugins.devices.openrgb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"ArtemisRGB.Plugins.BuildTask": "1.1.0",
|
||||
"Avalonia": "0.10.11",
|
||||
"Avalonia.Controls.DataGrid": "0.10.11",
|
||||
"Avalonia.ReactiveUI": "0.10.11",
|
||||
"Material.Icons.Avalonia": "1.0.2",
|
||||
"OpenRGB.NET": "1.7.0",
|
||||
"RGB.NET.Core": "1.0.0-prerelease7",
|
||||
"ReactiveUI": "16.3.10",
|
||||
"Serilog": "2.10.0",
|
||||
"SkiaSharp": "2.88.0-preview.178"
|
||||
}
|
||||
},
|
||||
"artemis.storage": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
|
||||
@ -14,6 +14,8 @@ using Artemis.UI.Screens.ProfileEditor.VisualEditor.Visualizers;
|
||||
using Artemis.UI.Screens.Settings;
|
||||
using Artemis.UI.Screens.Sidebar;
|
||||
using Artemis.UI.Screens.SurfaceEditor;
|
||||
using Artemis.UI.Screens.VisualScripting;
|
||||
using Artemis.UI.Screens.VisualScripting.Pins;
|
||||
using Artemis.UI.Services;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
@ -87,4 +89,15 @@ namespace Artemis.UI.Ninject.Factories
|
||||
ITreePropertyViewModel TreePropertyViewModel(ILayerProperty layerProperty, PropertyViewModel propertyViewModel);
|
||||
ITimelinePropertyViewModel TimelinePropertyViewModel(ILayerProperty layerProperty, PropertyViewModel propertyViewModel);
|
||||
}
|
||||
|
||||
public interface INodeVmFactory
|
||||
{
|
||||
NodeScriptViewModel NodeScriptViewModel(NodeScript nodeScript);
|
||||
NodePickerViewModel NodePickerViewModel(NodeScript nodeScript);
|
||||
NodeViewModel NodeViewModel(INode node);
|
||||
InputPinCollectionViewModel<T> InputPinCollectionViewModel<T>(InputPinCollection<T> inputPinCollection);
|
||||
InputPinViewModel<T> InputPinViewModel<T>(InputPin<T> inputPin);
|
||||
OutputPinCollectionViewModel<T> OutputPinCollectionViewModel<T>(OutputPinCollection<T> outputPinCollection);
|
||||
OutputPinViewModel<T> OutputPinViewModel<T>(OutputPin<T> outputPin);
|
||||
}
|
||||
}
|
||||
@ -4,23 +4,23 @@ using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Timers;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.DataModelVisualization.Shared;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
using Avalonia.Threading;
|
||||
using DynamicData;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
{
|
||||
namespace Artemis.UI.Screens.Debugger.DataModel;
|
||||
|
||||
public class DataModelDebugViewModel : ActivatableViewModelBase, IRoutableViewModel
|
||||
{
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly Timer _updateTimer;
|
||||
private readonly DispatcherTimer _updateTimer;
|
||||
|
||||
private bool _isModuleFilterEnabled;
|
||||
private DataModelPropertiesViewModel? _mainDataModel;
|
||||
@ -32,8 +32,7 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
{
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_updateTimer = new Timer(25);
|
||||
_updateTimer.Elapsed += UpdateTimerOnElapsed;
|
||||
_updateTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(25), DispatcherPriority.Normal, (_, _) => Update());
|
||||
|
||||
HostScreen = hostScreen;
|
||||
Modules = new ObservableCollection<Module>();
|
||||
@ -53,9 +52,6 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
});
|
||||
}
|
||||
|
||||
public string UrlPathSegment => "data-model";
|
||||
public IScreen HostScreen { get; }
|
||||
|
||||
public DataModelPropertiesViewModel? MainDataModel
|
||||
{
|
||||
get => _mainDataModel;
|
||||
@ -74,7 +70,7 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
set
|
||||
{
|
||||
RaiseAndSetIfChanged(ref _slowUpdates, value);
|
||||
_updateTimer.Interval = _slowUpdates ? 500 : 25;
|
||||
_updateTimer.Interval = TimeSpan.FromMilliseconds(_slowUpdates ? 500 : 25);
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +99,8 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
GetDataModel();
|
||||
}
|
||||
}
|
||||
private void UpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (MainDataModel == null)
|
||||
return;
|
||||
@ -123,7 +120,7 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
private void GetDataModel()
|
||||
{
|
||||
MainDataModel = SelectedModule != null
|
||||
? _dataModelUIService.GetPluginDataModelVisualization(new List<Module>() { SelectedModule }, false)
|
||||
? _dataModelUIService.GetPluginDataModelVisualization(new List<Module> {SelectedModule}, false)
|
||||
: _dataModelUIService.GetMainDataModelVisualization();
|
||||
}
|
||||
|
||||
@ -141,7 +138,11 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
_dataModelUIService.UpdateModules(MainDataModel);
|
||||
}
|
||||
else if (!SelectedModule.IsEnabled)
|
||||
{
|
||||
SelectedModule = null;
|
||||
}
|
||||
}
|
||||
|
||||
public string UrlPathSegment => "data-model";
|
||||
public IScreen HostScreen { get; }
|
||||
}
|
||||
@ -3,19 +3,20 @@ using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Timers;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using Avalonia.Threading;
|
||||
using ReactiveUI;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.UI.Screens.Debugger.Performance
|
||||
{
|
||||
namespace Artemis.UI.Screens.Debugger.Performance;
|
||||
|
||||
public class PerformanceDebugViewModel : ActivatableViewModelBase, IRoutableViewModel
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly DispatcherTimer _updateTimer;
|
||||
private double _currentFps;
|
||||
private string? _renderer;
|
||||
private int _renderHeight;
|
||||
@ -26,9 +27,7 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
HostScreen = hostScreen;
|
||||
_coreService = coreService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
|
||||
Timer updateTimer = new(500);
|
||||
updateTimer.Elapsed += UpdateTimerOnElapsed;
|
||||
_updateTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(500), DispatcherPriority.Normal, (_, _) => Update());
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
@ -47,20 +46,17 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
|
||||
HandleActivation();
|
||||
PopulateItems();
|
||||
updateTimer.Start();
|
||||
_updateTimer.Start();
|
||||
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
updateTimer.Stop();
|
||||
_updateTimer.Stop();
|
||||
Items.Clear();
|
||||
HandleDeactivation();
|
||||
}).DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public string UrlPathSegment => "performance";
|
||||
public IScreen HostScreen { get; }
|
||||
public ObservableCollection<PerformanceDebugPluginViewModel> Items { get; } = new();
|
||||
|
||||
public double CurrentFps
|
||||
@ -113,7 +109,7 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
PopulateItems();
|
||||
}
|
||||
|
||||
private void UpdateTimerOnElapsed(object? sender, ElapsedEventArgs e)
|
||||
private void Update()
|
||||
{
|
||||
foreach (PerformanceDebugPluginViewModel viewModel in Items)
|
||||
viewModel.Update();
|
||||
@ -127,5 +123,8 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
RenderHeight = bitmapInfo.Height;
|
||||
RenderWidth = bitmapInfo.Width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string UrlPathSegment => "performance";
|
||||
public IScreen HostScreen { get; }
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.CableView">
|
||||
Welcome to Avalonia!
|
||||
</UserControl>
|
||||
@ -0,0 +1,20 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting
|
||||
{
|
||||
public partial class CableView : ReactiveUserControl<CableViewModel>
|
||||
{
|
||||
public CableView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
using Artemis.UI.Screens.VisualScripting.Pins;
|
||||
using Artemis.UI.Shared;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting;
|
||||
|
||||
public class CableViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private PinViewModel _from;
|
||||
private PinViewModel _to;
|
||||
|
||||
public CableViewModel(PinViewModel from, PinViewModel to)
|
||||
{
|
||||
_from = from;
|
||||
_to = to;
|
||||
}
|
||||
|
||||
public PinViewModel From
|
||||
{
|
||||
get => _from;
|
||||
set => RaiseAndSetIfChanged(ref _from, value);
|
||||
}
|
||||
|
||||
public PinViewModel To
|
||||
{
|
||||
get => _to;
|
||||
set => RaiseAndSetIfChanged(ref _to, value);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:visualScripting="clr-namespace:Artemis.UI.Screens.VisualScripting"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.NodePickerView"
|
||||
x:DataType="visualScripting:NodePickerViewModel">
|
||||
<UserControl.Styles>
|
||||
<Style Selector="Border.picker-container">
|
||||
|
||||
</Style>
|
||||
<Style Selector="Border.picker-container-hidden">
|
||||
<Style.Animations>
|
||||
<Animation Duration="0:0:1">
|
||||
<KeyFrame Cue="0%">
|
||||
<Setter Property="Opacity" Value="1.0" />
|
||||
</KeyFrame>
|
||||
<KeyFrame Cue="100%">
|
||||
<Setter Property="Opacity" Value="0.0" />
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</KeyFrame>
|
||||
</Animation>
|
||||
</Style.Animations>
|
||||
</Style>
|
||||
<Style Selector="Border.picker-container-visible">
|
||||
<Style.Animations>
|
||||
<Animation Duration="0:0:1">
|
||||
<KeyFrame Cue="0%">
|
||||
<Setter Property="Opacity" Value="0.0" />
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</KeyFrame>
|
||||
<KeyFrame Cue="100%">
|
||||
<Setter Property="Opacity" Value="1.0" />
|
||||
</KeyFrame>
|
||||
</Animation>
|
||||
</Style.Animations>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<Border Classes="grid picker-container"
|
||||
Classes.picker-container-hidden="{CompiledBinding !IsVisible}"
|
||||
Classes.picker-container-visible="{CompiledBinding !IsVisible}">
|
||||
<TextBlock>Test</TextBlock>
|
||||
</Border>
|
||||
</UserControl>
|
||||
@ -0,0 +1,20 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting
|
||||
{
|
||||
public partial class NodePickerView : ReactiveUserControl<NodePickerViewModel>
|
||||
{
|
||||
public NodePickerView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using Avalonia;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting;
|
||||
|
||||
public class NodePickerViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly INodeService _nodeService;
|
||||
|
||||
private bool _isVisible;
|
||||
private Point _position;
|
||||
|
||||
public bool IsVisible
|
||||
{
|
||||
get => _isVisible;
|
||||
set => RaiseAndSetIfChanged(ref _isVisible, value);
|
||||
}
|
||||
|
||||
public Point Position
|
||||
{
|
||||
get => _position;
|
||||
set => RaiseAndSetIfChanged(ref _position, value);
|
||||
}
|
||||
|
||||
public NodePickerViewModel(INodeService nodeService)
|
||||
{
|
||||
_nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void Show(Point position)
|
||||
{
|
||||
IsVisible = true;
|
||||
Position = position;
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
IsVisible = false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:visualScripting="clr-namespace:Artemis.UI.Screens.VisualScripting"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.NodeScriptView"
|
||||
x:DataType="visualScripting:NodeScriptViewModel">
|
||||
<Canvas PointerReleased="InputElement_OnPointerReleased">
|
||||
<!-- Cables -->
|
||||
|
||||
<!-- Nodes -->
|
||||
|
||||
<!-- Flyout -->
|
||||
<ContentControl Content="{CompiledBinding NodePickerViewModel}"
|
||||
Canvas.Left="{CompiledBinding NodePickerViewModel.Position.X}"
|
||||
Canvas.Top="{CompiledBinding NodePickerViewModel.Position.Y}"/>
|
||||
</Canvas>
|
||||
</UserControl>
|
||||
@ -0,0 +1,29 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting
|
||||
{
|
||||
public partial class NodeScriptView : ReactiveUserControl<NodeScriptViewModel>
|
||||
{
|
||||
public NodeScriptView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (e.InitialPressMouseButton == MouseButton.Right)
|
||||
ViewModel?.ShowNodePicker(e.GetCurrentPoint(this).Position);
|
||||
if (e.InitialPressMouseButton == MouseButton.Left)
|
||||
ViewModel?.HideNodePicker();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Events;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting;
|
||||
|
||||
public class NodeScriptViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly INodeService _nodeService;
|
||||
private readonly INodeVmFactory _nodeVmFactory;
|
||||
|
||||
public NodeScriptViewModel(NodeScript nodeScript, INodeVmFactory nodeVmFactory, INodeService nodeService)
|
||||
{
|
||||
_nodeVmFactory = nodeVmFactory;
|
||||
_nodeService = nodeService;
|
||||
|
||||
NodeScript = nodeScript;
|
||||
NodePickerViewModel = _nodeVmFactory.NodePickerViewModel(nodeScript);
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
Observable.FromEventPattern<SingleValueEventArgs<INode>>(x => NodeScript.NodeAdded += x, x => NodeScript.NodeAdded -= x)
|
||||
.Subscribe(e => HandleNodeAdded(e.EventArgs))
|
||||
.DisposeWith(d);
|
||||
Observable.FromEventPattern<SingleValueEventArgs<INode>>(x => NodeScript.NodeRemoved += x, x => NodeScript.NodeRemoved -= x)
|
||||
.Subscribe(e => HandleNodeRemoved(e.EventArgs))
|
||||
.DisposeWith(d);
|
||||
});
|
||||
|
||||
NodeViewModels = new ObservableCollection<NodeViewModel>();
|
||||
foreach (INode nodeScriptNode in NodeScript.Nodes)
|
||||
NodeViewModels.Add(_nodeVmFactory.NodeViewModel(nodeScriptNode));
|
||||
}
|
||||
|
||||
public NodeScript NodeScript { get; }
|
||||
public ObservableCollection<NodeViewModel> NodeViewModels { get; }
|
||||
public NodePickerViewModel NodePickerViewModel { get; }
|
||||
|
||||
|
||||
private void HandleNodeAdded(SingleValueEventArgs<INode> eventArgs)
|
||||
{
|
||||
NodeViewModels.Add(_nodeVmFactory.NodeViewModel(eventArgs.Value));
|
||||
}
|
||||
|
||||
private void HandleNodeRemoved(SingleValueEventArgs<INode> eventArgs)
|
||||
{
|
||||
NodeViewModel? toRemove = NodeViewModels.FirstOrDefault(vm => vm.Node == eventArgs.Value);
|
||||
if (toRemove != null)
|
||||
NodeViewModels.Remove(toRemove);
|
||||
}
|
||||
|
||||
public void ShowNodePicker(Point position)
|
||||
{
|
||||
NodePickerViewModel.Show(position);
|
||||
}
|
||||
|
||||
public void HideNodePicker()
|
||||
{
|
||||
NodePickerViewModel.Hide();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.NodeView">
|
||||
Welcome to Avalonia!
|
||||
</UserControl>
|
||||
@ -0,0 +1,20 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting
|
||||
{
|
||||
public partial class NodeView : ReactiveUserControl<NodeViewModel>
|
||||
{
|
||||
public NodeView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared;
|
||||
using Avalonia;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting;
|
||||
|
||||
public class NodeViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private Point _position;
|
||||
|
||||
public NodeViewModel(INode node)
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
|
||||
public INode Node { get; }
|
||||
|
||||
public Point Position
|
||||
{
|
||||
get => _position;
|
||||
set => RaiseAndSetIfChanged(ref _position, value);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.Pins.InputPinCollectionView">
|
||||
Welcome to Avalonia!
|
||||
</UserControl>
|
||||
@ -0,0 +1,20 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins
|
||||
{
|
||||
public partial class InputPinCollectionView : ReactiveUserControl<PinCollectionViewModel>
|
||||
{
|
||||
public InputPinCollectionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||
|
||||
public class InputPinCollectionViewModel<T> : PinCollectionViewModel
|
||||
{
|
||||
public InputPinCollection<T> InputPinCollection { get; }
|
||||
|
||||
public InputPinCollectionViewModel(InputPinCollection<T> inputPinCollection) : base(inputPinCollection)
|
||||
{
|
||||
InputPinCollection = inputPinCollection;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.Pins.InputPinView">
|
||||
Welcome to Avalonia!
|
||||
</UserControl>
|
||||
@ -0,0 +1,20 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins
|
||||
{
|
||||
public partial class InputPinView : ReactiveUserControl<PinViewModel>
|
||||
{
|
||||
public InputPinView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||
|
||||
public class InputPinViewModel<T> : PinViewModel
|
||||
{
|
||||
public InputPin<T> InputPin { get; }
|
||||
|
||||
public InputPinViewModel(InputPin<T> inputPin) : base(inputPin)
|
||||
{
|
||||
InputPin = inputPin;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.Pins.OutputPinCollectionView">
|
||||
Welcome to Avalonia!
|
||||
</UserControl>
|
||||
@ -0,0 +1,20 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins
|
||||
{
|
||||
public partial class OutputPinCollectionView : ReactiveUserControl<PinCollectionViewModel>
|
||||
{
|
||||
public OutputPinCollectionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||
|
||||
public class OutputPinCollectionViewModel<T> : PinCollectionViewModel
|
||||
{
|
||||
public OutputPinCollection<T> OutputPinCollection { get; }
|
||||
|
||||
public OutputPinCollectionViewModel(OutputPinCollection<T> outputPinCollection) : base(outputPinCollection)
|
||||
{
|
||||
OutputPinCollection = outputPinCollection;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.VisualScripting.Pins.OutputPinView">
|
||||
Welcome to Avalonia!
|
||||
</UserControl>
|
||||
@ -0,0 +1,20 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins
|
||||
{
|
||||
public partial class OutputPinView : ReactiveUserControl<PinViewModel>
|
||||
{
|
||||
public OutputPinView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||
|
||||
public class OutputPinViewModel<T> : PinViewModel
|
||||
{
|
||||
public OutputPin<T> OutputPin { get; }
|
||||
|
||||
public OutputPinViewModel(OutputPin<T> outputPin) : base(outputPin)
|
||||
{
|
||||
OutputPin = outputPin;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||
|
||||
public abstract class PinCollectionViewModel : ActivatableViewModelBase
|
||||
{
|
||||
public PinCollection PinCollection { get; }
|
||||
|
||||
protected PinCollectionViewModel(PinCollection pinCollection)
|
||||
{
|
||||
PinCollection = pinCollection;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared;
|
||||
|
||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||
|
||||
public abstract class PinViewModel : ActivatableViewModelBase
|
||||
{
|
||||
protected PinViewModel(IPin pin)
|
||||
{
|
||||
Pin = pin;
|
||||
}
|
||||
|
||||
public IPin Pin { get; }
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user