Meta - Replace WPF projects with Avalonia projects

This commit is contained in:
Robert committed 2022-03-27 11:55:26 +02:00
1 parent fcf0376a9a
commit d7f3ee1190
1110 files changed
+10872 -52240

No files matched your search

@@ -1,75 +1,105 @@
using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Reactive.Disposables;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Artemis.VisualScripting.Nodes.CustomViewModels;
using Stylet;
using Artemis.Storage.Entities.Profile;
using Artemis.UI.Shared.Services.NodeEditor;
using Artemis.UI.Shared.Services.NodeEditor.Commands;
using Artemis.UI.Shared.VisualScripting;
using ReactiveUI;
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViewModels
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
public class DataModelEventNodeCustomViewModel : CustomNodeViewModel
{
public class DataModelEventNodeCustomViewModel : CustomNodeViewModel
private readonly DataModelEventNode _node;
private readonly INodeEditorService _nodeEditorService;
private bool _updating;
private DataModelPath? _dataModelPath;
private ObservableCollection<Module>? _modules;
public DataModelEventNodeCustomViewModel(DataModelEventNode node, INodeScript script, ISettingsService settingsService, INodeEditorService nodeEditorService) : base(node, script)
{
private readonly DataModelEventNode _node;
private BindableCollection<Module> _modules;
_node = node;
_nodeEditorService = nodeEditorService;
public DataModelEventNodeCustomViewModel(DataModelEventNode node, ISettingsService settingsService) : base(node)
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
Modules = new ObservableCollection<Module>();
this.WhenActivated(d =>
{
_node = node;
// Set up extra modules
if (_node.Script?.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
Modules = new ObservableCollection<Module> {scriptProfile.Configuration.Module};
else if (_node.Script?.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
Modules = new ObservableCollection<Module> {profileConfiguration.Module};
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
}
// Subscribe to node changes
_node.WhenAnyValue(n => n.Storage).Subscribe(UpdateDataModelPath).DisposeWith(d);
this.WhenAnyValue(vm => vm.DataModelPath).Subscribe(ApplyDataModelPath).DisposeWith(d);
public PluginSetting<bool> ShowFullPaths { get; }
public PluginSetting<bool> ShowDataModelValues { get; }
public BindableCollection<Type> FilterTypes { get; } = new() { typeof(IDataModelEvent) };
public BindableCollection<Module> Modules
{
get => _modules;
set => SetAndNotify(ref _modules, value);
}
public DataModelPath DataModelPath
{
get => _node.DataModelPath;
set
Disposable.Create(() =>
{
if (ReferenceEquals(_node.DataModelPath, value))
return;
_dataModelPath?.Dispose();
_dataModelPath = null;
}).DisposeWith(d);
});
}
_node.DataModelPath?.Dispose();
_node.DataModelPath = value;
_node.DataModelPath.Save();
public PluginSetting<bool> ShowFullPaths { get; }
public PluginSetting<bool> ShowDataModelValues { get; }
public ObservableCollection<Type> FilterTypes { get; } = new() {typeof(IDataModelEvent)};
_node.Storage = _node.DataModelPath.Entity;
}
}
public ObservableCollection<Module>? Modules
{
get => _modules;
set => RaiseAndSetIfChanged(ref _modules, value);
}
public override void OnActivate()
public DataModelPath? DataModelPath
{
get => _dataModelPath;
set => RaiseAndSetIfChanged(ref _dataModelPath, value);
}
private void UpdateDataModelPath(DataModelPathEntity? entity)
{
try
{
if (Modules != null)
if (_updating)
return;
Modules = new BindableCollection<Module>();
if (_node.Script.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
Modules.Add(scriptProfile.Configuration.Module);
else if (_node.Script.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
Modules.Add(profileConfiguration.Module);
_updating = true;
_node.PropertyChanged += NodeOnPropertyChanged;
DataModelPath? old = DataModelPath;
DataModelPath = entity != null ? new DataModelPath(entity) : null;
old?.Dispose();
}
public override void OnDeactivate()
finally
{
_node.PropertyChanged -= NodeOnPropertyChanged;
_updating = false;
}
}
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
private void ApplyDataModelPath(DataModelPath? path)
{
try
{
if (e.PropertyName == nameof(DataModelNode.DataModelPath))
OnPropertyChanged(nameof(DataModelPath));
if (_updating)
return;
if (path?.Path == _node.Storage?.Path)
return;
_updating = true;
path?.Save();
_nodeEditorService.ExecuteCommand(Script, new UpdateStorage<DataModelPathEntity>(_node, path?.Entity, "event"));
}
finally
{
_updating = false;
}
}
}
@@ -1,74 +1,104 @@
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reactive.Disposables;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Artemis.VisualScripting.Nodes.CustomViewModels;
using Stylet;
using Artemis.Storage.Entities.Profile;
using Artemis.UI.Shared.Services.NodeEditor;
using Artemis.UI.Shared.Services.NodeEditor.Commands;
using Artemis.UI.Shared.VisualScripting;
using ReactiveUI;
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViewModels
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
public class DataModelNodeCustomViewModel : CustomNodeViewModel
{
public class DataModelNodeCustomViewModel : CustomNodeViewModel
private readonly DataModelNode _node;
private readonly INodeEditorService _nodeEditorService;
private ObservableCollection<Module>? _modules;
private DataModelPath? _dataModelPath;
private bool _updating;
public DataModelNodeCustomViewModel(DataModelNode node, INodeScript script, ISettingsService settingsService, INodeEditorService nodeEditorService) : base(node, script)
{
private readonly DataModelNode _node;
private BindableCollection<Module> _modules;
_node = node;
_nodeEditorService = nodeEditorService;
public DataModelNodeCustomViewModel(DataModelNode node, ISettingsService settingsService) : base(node)
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
this.WhenActivated(d =>
{
_node = node;
// Set up extra modules
if (_node.Script?.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
Modules = new ObservableCollection<Module> {scriptProfile.Configuration.Module};
else if (_node.Script?.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
Modules = new ObservableCollection<Module> {profileConfiguration.Module};
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
}
// Subscribe to node changes
_node.WhenAnyValue(n => n.Storage).Subscribe(UpdateDataModelPath).DisposeWith(d);
this.WhenAnyValue(vm => vm.DataModelPath).Subscribe(ApplyDataModelPath).DisposeWith(d);
public PluginSetting<bool> ShowFullPaths { get; }
public PluginSetting<bool> ShowDataModelValues { get; }
public BindableCollection<Module> Modules
{
get => _modules;
set => SetAndNotify(ref _modules, value);
}
public DataModelPath DataModelPath
{
get => _node.DataModelPath;
set
Disposable.Create(() =>
{
if (ReferenceEquals(_node.DataModelPath, value))
return;
_dataModelPath?.Dispose();
_dataModelPath = null;
}).DisposeWith(d);
});
}
_node.DataModelPath?.Dispose();
_node.DataModelPath = value;
_node.DataModelPath.Save();
public PluginSetting<bool> ShowFullPaths { get; }
public PluginSetting<bool> ShowDataModelValues { get; }
_node.Storage = _node.DataModelPath.Entity;
_node.UpdateOutputPin(false);
}
}
public ObservableCollection<Module>? Modules
{
get => _modules;
set => RaiseAndSetIfChanged(ref _modules, value);
}
public override void OnActivate()
public DataModelPath? DataModelPath
{
get => _dataModelPath;
set => RaiseAndSetIfChanged(ref _dataModelPath, value);
}
private void UpdateDataModelPath(DataModelPathEntity? entity)
{
try
{
if (Modules != null)
if (_updating)
return;
Modules = new BindableCollection<Module>();
if (_node.Script.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
Modules.Add(scriptProfile.Configuration.Module);
else if (_node.Script.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
Modules.Add(profileConfiguration.Module);
_updating = true;
_node.PropertyChanged += NodeOnPropertyChanged;
DataModelPath? old = DataModelPath;
DataModelPath = entity != null ? new DataModelPath(entity) : null;
old?.Dispose();
}
public override void OnDeactivate()
finally
{
_node.PropertyChanged -= NodeOnPropertyChanged;
_updating = false;
}
}
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
private void ApplyDataModelPath(DataModelPath? path)
{
try
{
if (e.PropertyName == nameof(DataModelNode.DataModelPath))
OnPropertyChanged(nameof(DataModelPath));
if (_updating)
return;
if (path?.Path == _node.Storage?.Path)
return;
_updating = true;
path?.Save();
_nodeEditorService.ExecuteCommand(Script, new UpdateStorage<DataModelPathEntity>(_node, path?.Entity, "path"));
}
finally
{
_updating = false;
}
}
}
@@ -0,0 +1,16 @@
<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:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
xmlns:customViewModels="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.CustomViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelEventNodeCustomView"
x:DataType="customViewModels:DataModelEventNodeCustomViewModel">
<dataModelPicker:DataModelPickerButton Classes="condensed"
DataModelPath="{CompiledBinding DataModelPath}"
Modules="{CompiledBinding Modules}"
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
FilterTypes="{CompiledBinding FilterTypes}"
VerticalAlignment="Top"/>
</UserControl>
@@ -0,0 +1,21 @@
using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViews
{
public partial class DataModelEventNodeCustomView : ReactiveUserControl<DataModelEventNodeCustomViewModel>
{
public DataModelEventNodeCustomView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}
@@ -1,21 +0,0 @@
<UserControl x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelEventNodeCustomView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.VisualScripting.Nodes.CustomViews"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:editor="clr-namespace:Artemis.VisualScripting.Editor.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Orientation="Vertical">
<controls:DataModelPicker DataModelPath="{Binding DataModelPath}"
Modules="{Binding Modules}"
ShowFullPath="{Binding ShowFullPaths.Value}"
ShowDataModelValues="{Binding ShowDataModelValues.Value}"
FilterTypes="{Binding FilterTypes}"
ButtonBrush="DarkGoldenrod"/>
</StackPanel>
</UserControl>
@@ -0,0 +1,14 @@
<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:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
xmlns:customViewModels="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.CustomViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelNodeCustomView"
x:DataType="customViewModels:DataModelNodeCustomViewModel">
<dataModelPicker:DataModelPickerButton Classes="condensed"
DataModelPath="{CompiledBinding DataModelPath}"
Modules="{CompiledBinding Modules}"
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}" />
</UserControl>
@@ -0,0 +1,21 @@
using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViews
{
public partial class DataModelNodeCustomView : ReactiveUserControl<DataModelNodeCustomViewModel>
{
public DataModelNodeCustomView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}
@@ -1,16 +0,0 @@
<UserControl x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelNodeCustomView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.VisualScripting.Nodes.CustomViews"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<controls:DataModelPicker DataModelPath="{Binding DataModelPath}"
Modules="{Binding Modules}"
ShowFullPath="{Binding ShowFullPaths.Value}"
ShowDataModelValues="{Binding ShowDataModelValues.Value}"
ButtonBrush="#434343"/>
</UserControl>
@@ -1,191 +1,151 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using Artemis.Core;
using Artemis.Core.Events;
using Artemis.Storage.Entities.Profile;
using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
namespace Artemis.VisualScripting.Nodes.DataModel
namespace Artemis.VisualScripting.Nodes.DataModel;
[Node("Data Model-Event", "Responds to a data model event trigger", "Data Model", OutputType = typeof(bool))]
public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCustomViewModel>, IDisposable
{
[Node("Data Model-Event", "Responds to a data model event trigger", "Data Model", OutputType = typeof(bool))]
public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCustomViewModel>, IDisposable
private int _currentIndex;
private Type _currentType;
private DataModelPath? _dataModelPath;
private DateTime _lastTrigger;
private bool _updating;
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
{
private DataModelPath _dataModelPath;
private DateTime _lastTrigger;
private int _currentIndex;
private Type _currentType;
private bool _updating;
_currentType = typeof(object);
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
{
_currentType = typeof(object);
CreateCycleValues(typeof(object), 1);
Output = CreateOutputPin(typeof(object));
}
CycleValues = CreateInputPinCollection(typeof(object), "", 0);
Output = CreateOutputPin(typeof(object));
private void CreateCycleValues(Type type, int initialCount)
CycleValues.PinAdded += CycleValuesOnPinAdded;
CycleValues.PinRemoved += CycleValuesOnPinRemoved;
CycleValues.Add(CycleValues.CreatePin());
// Monitor storage for changes
StorageModified += (_, _) => UpdateDataModelPath();
}
public INodeScript? Script { get; set; }
public InputPinCollection CycleValues { get; }
public OutputPin Output { get; }
public override void Initialize(INodeScript script)
{
Script = script;
if (Storage == null)
return;
UpdateDataModelPath();
}
public override void Evaluate()
{
object? outputValue = null;
if (_dataModelPath?.GetValue() is IDataModelEvent dataModelEvent)
{
if (CycleValues != null)
if (dataModelEvent.LastTrigger > _lastTrigger)
{
CycleValues.PinAdded -= CycleValuesOnPinAdded;
CycleValues.PinRemoved -= CycleValuesOnPinRemoved;
foreach (IPin pin in CycleValues)
{
pin.PinConnected -= OnPinConnected;
pin.PinDisconnected -= OnPinDisconnected;
}
_lastTrigger = dataModelEvent.LastTrigger;
_currentIndex++;
RemovePinCollection(CycleValues);
if (_currentIndex >= CycleValues.Count())
_currentIndex = 0;
}
CycleValues = CreateInputPinCollection(type, "", initialCount);
CycleValues.PinAdded += CycleValuesOnPinAdded;
CycleValues.PinRemoved += CycleValuesOnPinRemoved;
foreach (IPin pin in CycleValues)
{
pin.PinConnected += OnPinConnected;
pin.PinDisconnected += OnPinDisconnected;
}
outputValue = CycleValues.ElementAt(_currentIndex).PinValue;
}
private void CycleValuesOnPinAdded(object sender, SingleValueEventArgs<IPin> e)
if (Output.Type.IsInstanceOfType(outputValue))
Output.Value = outputValue;
else if (Output.Type.IsValueType)
Output.Value = Output.Type.GetDefault()!;
}
private void CycleValuesOnPinAdded(object? sender, SingleValueEventArgs<IPin> e)
{
e.Value.PinConnected += OnPinConnected;
e.Value.PinDisconnected += OnPinDisconnected;
}
private void CycleValuesOnPinRemoved(object? sender, SingleValueEventArgs<IPin> e)
{
e.Value.PinConnected -= OnPinConnected;
e.Value.PinDisconnected -= OnPinDisconnected;
}
private void OnPinDisconnected(object? sender, SingleValueEventArgs<IPin> e)
{
ProcessPinDisconnected();
}
private void OnPinConnected(object? sender, SingleValueEventArgs<IPin> e)
{
ProcessPinConnected(e.Value);
}
private void ProcessPinConnected(IPin source)
{
if (_updating)
return;
try
{
e.Value.PinConnected += OnPinConnected;
e.Value.PinDisconnected += OnPinDisconnected;
}
_updating = true;
private void CycleValuesOnPinRemoved(object sender, SingleValueEventArgs<IPin> e)
{
e.Value.PinConnected -= OnPinConnected;
e.Value.PinDisconnected -= OnPinDisconnected;
}
private void OnPinDisconnected(object sender, SingleValueEventArgs<IPin> e)
{
ProcessPinDisconnected();
}
private void OnPinConnected(object sender, SingleValueEventArgs<IPin> e)
{
IPin source = e.Value;
IPin target = (IPin) sender;
ProcessPinConnected(source, target);
}
public InputPinCollection CycleValues { get; set; }
public OutputPin Output { get; set; }
public INodeScript Script { get; set; }
public DataModelPath DataModelPath
{
get => _dataModelPath;
set => SetAndNotify(ref _dataModelPath, value);
}
public override void Initialize(INodeScript script)
{
Script = script;
if (Storage == null)
return;
DataModelPath = new DataModelPath(Storage);
}
public override void Evaluate()
{
object outputValue = null;
if (DataModelPath?.GetValue() is IDataModelEvent dataModelEvent)
{
if (dataModelEvent.LastTrigger > _lastTrigger)
{
_lastTrigger = dataModelEvent.LastTrigger;
_currentIndex++;
if (_currentIndex >= CycleValues.Count())
_currentIndex = 0;
}
outputValue = CycleValues.ElementAt(_currentIndex).PinValue;
}
if (Output.Type.IsInstanceOfType(outputValue))
Output.Value = outputValue;
else if (Output.Type.IsValueType)
Output.Value = Output.Type.GetDefault()!;
}
private void ProcessPinConnected(IPin source, IPin target)
{
if (_updating)
return;
try
{
_updating = true;
// No need to change anything if the types haven't changed
if (_currentType == source.Type)
return;
int reconnectIndex = CycleValues.ToList().IndexOf(target);
// No need to change anything if the types haven't changed
if (_currentType != source.Type)
ChangeCurrentType(source.Type);
if (reconnectIndex != -1)
{
CycleValues.ToList()[reconnectIndex].ConnectTo(source);
source.ConnectTo(CycleValues.ToList()[reconnectIndex]);
}
}
finally
{
_updating = false;
}
}
private void ChangeCurrentType(Type type)
{
CreateCycleValues(type, CycleValues.Count());
List<IPin> oldOutputConnections = Output.ConnectedTo.ToList();
RemovePin(Output);
Output = CreateOutputPin(type);
foreach (IPin oldOutputConnection in oldOutputConnections.Where(o => o.Type.IsAssignableFrom(Output.Type)))
{
oldOutputConnection.DisconnectAll();
oldOutputConnection.ConnectTo(Output);
Output.ConnectTo(oldOutputConnection);
}
_currentType = type;
}
private void ProcessPinDisconnected()
{
if (_updating)
return;
try
{
// If there's still a connected pin, stick to the current type
if (CycleValues.Any(v => v.ConnectedTo.Any()))
return;
ChangeCurrentType(typeof(object));
}
finally
{
_updating = false;
}
}
private void UpdatePinsType(IPin source)
{
}
/// <inheritdoc />
public void Dispose()
finally
{
_updating = false;
}
}
private void UpdateDataModelPath()
{
DataModelPath? old = _dataModelPath;
_dataModelPath = Storage != null ? new DataModelPath(Storage) : null;
old?.Dispose();
}
private void ChangeCurrentType(Type type)
{
CycleValues.ChangeType(type);
Output.ChangeType(type);
_currentType = type;
}
private void ProcessPinDisconnected()
{
if (_updating)
return;
try
{
// If there's still a connected pin, stick to the current type
if (CycleValues.Any(v => v.ConnectedTo.Any()))
return;
ChangeCurrentType(typeof(object));
}
finally
{
_updating = false;
}
}
/// <inheritdoc />
public void Dispose()
{
_dataModelPath?.Dispose();
}
}
@@ -1,97 +1,82 @@
using System;
using System.ComponentModel;
using Artemis.Core;
using Artemis.Storage.Entities.Profile;
using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
using Stylet;
using Avalonia.Threading;
namespace Artemis.VisualScripting.Nodes.DataModel
namespace Artemis.VisualScripting.Nodes.DataModel;
[Node("Data Model-Value", "Outputs a selectable data model value.", "Data Model")]
public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewModel>, IDisposable
{
[Node("Data Model-Value", "Outputs a selectable data model value.", "Data Model")]
public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewModel>, IDisposable
private DataModelPath? _dataModelPath;
public DataModelNode() : base("Data Model", "Outputs a selectable data model value")
{
private DataModelPath _dataModelPath;
Output = CreateOutputPin(typeof(object));
StorageModified += (_, _) => UpdateDataModelPath();
}
public DataModelNode() : base("Data Model", "Outputs a selectable data model value")
public INodeScript? Script { get; private set; }
public OutputPin Output { get; }
public override void Initialize(INodeScript script)
{
Script = script;
if (Storage == null)
return;
UpdateDataModelPath();
}
private void UpdateDataModelPath()
{
DataModelPath? old = _dataModelPath;
old?.Dispose();
_dataModelPath = Storage != null ? new DataModelPath(Storage) : null;
if (_dataModelPath != null)
_dataModelPath.PathValidated += DataModelPathOnPathValidated;
UpdateOutputPin();
}
public override void Evaluate()
{
if (_dataModelPath == null || !_dataModelPath.IsValid)
return;
object? pathValue = _dataModelPath.GetValue();
if (pathValue == null)
{
if (!Output.Type.IsValueType)
Output.Value = null;
}
public INodeScript Script { get; private set; }
public OutputPin Output { get; private set; }
public DataModelPath DataModelPath
else
{
get => _dataModelPath;
set => SetAndNotify(ref _dataModelPath, value);
}
public override void Initialize(INodeScript script)
{
Script = script;
if (Storage == null)
return;
DataModelPath = new DataModelPath(Storage);
DataModelPath.PathValidated += DataModelPathOnPathValidated;
UpdateOutputPin(false);
}
public override void Evaluate()
{
if (DataModelPath.IsValid)
{
if (Output == null)
UpdateOutputPin(false);
object pathValue = DataModelPath.GetValue();
if (pathValue == null)
{
if (!Output.Type.IsValueType)
Output.Value = null;
}
else
{
if (Output.Type == typeof(Numeric))
Output.Value = new Numeric(pathValue);
else
Output.Value = pathValue;
}
}
}
public void UpdateOutputPin(bool loadConnections)
{
Type type = DataModelPath?.GetPropertyType();
if (Numeric.IsTypeCompatible(type))
type = typeof(Numeric);
if (Output != null && Output.Type == type)
return;
if (Output != null)
{
RemovePin(Output);
Output = null;
}
if (type != null)
Output = CreateOutputPin(type);
if (loadConnections && Script is NodeScript nodeScript)
nodeScript.LoadConnections();
}
private void DataModelPathOnPathValidated(object sender, EventArgs e)
{
Execute.OnUIThread(() => UpdateOutputPin(true));
}
/// <inheritdoc />
public void Dispose()
{
DataModelPath?.Dispose();
Output.Value = Output.Type == typeof(Numeric) ? new Numeric(pathValue) : pathValue;
}
}
public void UpdateOutputPin()
{
Type? type = _dataModelPath?.GetPropertyType();
if (Numeric.IsTypeCompatible(type))
type = typeof(Numeric);
type ??= typeof(object);
if (Output.Type != type)
Output.ChangeType(type);
}
private void DataModelPathOnPathValidated(object? sender, EventArgs e)
{
Dispatcher.UIThread.InvokeAsync(UpdateOutputPin);
}
/// <inheritdoc />
public void Dispose()
{
_dataModelPath?.Dispose();
}
}