mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-01-02 02:33:32 +00:00
Nodes - Made types mutable for non-generic pins/collections
This commit is contained in:
parent
30ec28a9a9
commit
f824f16658
@ -257,7 +257,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a boolean indicating whether the provided type can be used as a <see cref="Numeric" />.
|
/// Returns a boolean indicating whether the provided type can be used as a <see cref="Numeric" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool IsTypeCompatible(Type type)
|
public static bool IsTypeCompatible(Type? type)
|
||||||
{
|
{
|
||||||
return type == typeof(Numeric) ||
|
return type == typeof(Numeric) ||
|
||||||
type == typeof(float) ||
|
type == typeof(float) ||
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -76,7 +78,7 @@ namespace Artemis.Core
|
|||||||
internal InputPin(INode node, Type type, string name)
|
internal InputPin(INode node, Type type, string name)
|
||||||
: base(node, name)
|
: base(node, name)
|
||||||
{
|
{
|
||||||
Type = type;
|
_type = type;
|
||||||
_value = type.GetDefault();
|
_value = type.GetDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +86,25 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the type of this pin, disconnecting any pins that are incompatible with the new type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The new type of the pin.</param>
|
||||||
|
public void ChangeType(Type type)
|
||||||
|
{
|
||||||
|
if (_type == type)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Disconnect pins incompatible with the new type
|
||||||
|
List<IPin> toDisconnect = ConnectedTo.Where(p => !p.IsTypeCompatible(type)).ToList();
|
||||||
|
foreach (IPin pin in toDisconnect)
|
||||||
|
DisconnectFrom(pin);
|
||||||
|
|
||||||
|
// Change the type
|
||||||
|
SetAndNotify(ref _type, type, nameof(Type));
|
||||||
|
Value = type.GetDefault();
|
||||||
|
}
|
||||||
|
|
||||||
private void Evaluate()
|
private void Evaluate()
|
||||||
{
|
{
|
||||||
if (Type.IsValueType)
|
if (Type.IsValueType)
|
||||||
@ -104,7 +125,7 @@ namespace Artemis.Core
|
|||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Type Type { get; }
|
public override Type Type => _type;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object? PinValue => Value;
|
public override object? PinValue => Value;
|
||||||
@ -113,6 +134,7 @@ namespace Artemis.Core
|
|||||||
public override PinDirection Direction => PinDirection.Input;
|
public override PinDirection Direction => PinDirection.Input;
|
||||||
|
|
||||||
private object? _value;
|
private object? _value;
|
||||||
|
private Type _type;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the value of the input pin
|
/// Gets or sets the value of the input pin
|
||||||
|
|||||||
@ -59,12 +59,14 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class InputPinCollection : PinCollection
|
public sealed class InputPinCollection : PinCollection
|
||||||
{
|
{
|
||||||
|
private Type _type;
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
internal InputPinCollection(INode node, Type type, string name, int initialCount)
|
internal InputPinCollection(INode node, Type type, string name, int initialCount)
|
||||||
: base(node, name)
|
: base(node, name)
|
||||||
{
|
{
|
||||||
Type = type;
|
_type = type;
|
||||||
|
|
||||||
// Can't do this in the base constructor because the type won't be set yet
|
// Can't do this in the base constructor because the type won't be set yet
|
||||||
for (int i = 0; i < initialCount; i++)
|
for (int i = 0; i < initialCount; i++)
|
||||||
@ -75,6 +77,20 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the type of this pin, disconnecting any pins that are incompatible with the new type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The new type of the pin.</param>
|
||||||
|
public void ChangeType(Type type)
|
||||||
|
{
|
||||||
|
if (_type == type)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (IPin pin in Pins)
|
||||||
|
(pin as InputPin)?.ChangeType(type);
|
||||||
|
SetAndNotify(ref _type, type, nameof(Type));
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override IPin CreatePin()
|
public override IPin CreatePin()
|
||||||
{
|
{
|
||||||
@ -89,17 +105,12 @@ namespace Artemis.Core
|
|||||||
public override PinDirection Direction => PinDirection.Input;
|
public override PinDirection Direction => PinDirection.Input;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Type Type { get; }
|
public override Type Type => _type;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an enumerable of the pins in this collection
|
|
||||||
/// </summary>
|
|
||||||
public new IEnumerable<InputPin> Pins => base.Pins.Cast<InputPin>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an enumerable of the values of the pins in this collection
|
/// Gets an enumerable of the values of the pins in this collection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable Values => Pins.Where(p => p.Value != null).Select(p => p.Value);
|
public IEnumerable Values => Pins.Where(p => p.PinValue != null).Select(p => p.PinValue);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,5 +75,12 @@ namespace Artemis.Core
|
|||||||
/// Disconnects all pins this pin is connected to
|
/// Disconnects all pins this pin is connected to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void DisconnectAll();
|
void DisconnectAll();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether this pin is compatible with the given type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type to check for compatibility</param>
|
||||||
|
/// <returns><see langword="true"/> if the type is compatible, otherwise <see langword="false"/>.</returns>
|
||||||
|
public bool IsTypeCompatible(Type type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -66,16 +68,36 @@ namespace Artemis.Core
|
|||||||
internal OutputPin(INode node, Type type, string name)
|
internal OutputPin(INode node, Type type, string name)
|
||||||
: base(node, name)
|
: base(node, name)
|
||||||
{
|
{
|
||||||
Type = type;
|
_type = type;
|
||||||
_value = type.GetDefault();
|
_value = type.GetDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the type of this pin, disconnecting any pins that are incompatible with the new type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The new type of the pin.</param>
|
||||||
|
public void ChangeType(Type type)
|
||||||
|
{
|
||||||
|
// Disconnect pins incompatible with the new type
|
||||||
|
List<IPin> toDisconnect = ConnectedTo.Where(p => !p.IsTypeCompatible(type)).ToList();
|
||||||
|
foreach (IPin pin in toDisconnect)
|
||||||
|
DisconnectFrom(pin);
|
||||||
|
|
||||||
|
// Change the type
|
||||||
|
SetAndNotify(ref _type, type, nameof(Type));
|
||||||
|
Value = type.GetDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Type Type { get; }
|
public override Type Type => _type;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object? PinValue => Value;
|
public override object? PinValue => Value;
|
||||||
@ -84,6 +106,7 @@ namespace Artemis.Core
|
|||||||
public override PinDirection Direction => PinDirection.Output;
|
public override PinDirection Direction => PinDirection.Output;
|
||||||
|
|
||||||
private object? _value;
|
private object? _value;
|
||||||
|
private Type _type;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the value of the output pin
|
/// Gets or sets the value of the output pin
|
||||||
|
|||||||
@ -101,6 +101,9 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void DisconnectAll()
|
public void DisconnectAll()
|
||||||
{
|
{
|
||||||
|
if (!_connectedTo.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
List<IPin> connectedPins = new(_connectedTo);
|
List<IPin> connectedPins = new(_connectedTo);
|
||||||
_connectedTo.Clear();
|
_connectedTo.Clear();
|
||||||
|
|
||||||
@ -114,6 +117,12 @@ namespace Artemis.Core
|
|||||||
OnPropertyChanged(nameof(ConnectedTo));
|
OnPropertyChanged(nameof(ConnectedTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsTypeCompatible(Type type) => Type == type
|
||||||
|
|| Type == typeof(Enum) && type.IsEnum
|
||||||
|
|| Direction == PinDirection.Input && Type == typeof(object)
|
||||||
|
|| Direction == PinDirection.Output && type == typeof(object);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,7 +7,7 @@ using Artemis.Core.Events;
|
|||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="IPinCollection"/>
|
/// <inheritdoc cref="IPinCollection"/>
|
||||||
public abstract class PinCollection : IPinCollection
|
public abstract class PinCollection : CorePropertyChanged, IPinCollection
|
||||||
{
|
{
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ using Artemis.Core;
|
|||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.DataModelVisualization.Shared;
|
using Artemis.UI.Shared.DataModelVisualization.Shared;
|
||||||
using Artemis.UI.Shared.Events;
|
using Artemis.UI.Shared.Events;
|
||||||
|
using Artemis.UI.Shared.Extensions;
|
||||||
using Artemis.UI.Shared.Services.Interfaces;
|
using Artemis.UI.Shared.Services.Interfaces;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
@ -267,8 +268,10 @@ public class DataModelPicker : TemplatedControl
|
|||||||
|
|
||||||
if (selected is DataModelPropertyViewModel property && property.DataModelPath != null)
|
if (selected is DataModelPropertyViewModel property && property.DataModelPath != null)
|
||||||
DataModelPath = new DataModelPath(property.DataModelPath);
|
DataModelPath = new DataModelPath(property.DataModelPath);
|
||||||
if (selected is DataModelListViewModel list && list.DataModelPath != null)
|
else if (selected is DataModelListViewModel list && list.DataModelPath != null)
|
||||||
DataModelPath = new DataModelPath(list.DataModelPath);
|
DataModelPath = new DataModelPath(list.DataModelPath);
|
||||||
|
else if (selected is DataModelEventViewModel dataModelEvent && dataModelEvent.DataModelPath != null)
|
||||||
|
DataModelPath = new DataModelPath(dataModelEvent.DataModelPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCurrentPath(bool selectCurrentPath)
|
private void UpdateCurrentPath(bool selectCurrentPath)
|
||||||
@ -292,24 +295,8 @@ public class DataModelPicker : TemplatedControl
|
|||||||
_currentPathDisplay.Text = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
_currentPathDisplay.Text = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
||||||
if (_currentPathDescription != null)
|
if (_currentPathDescription != null)
|
||||||
_currentPathDescription.Text = DataModelPath.GetPropertyDescription()?.Description;
|
_currentPathDescription.Text = DataModelPath.GetPropertyDescription()?.Description;
|
||||||
|
|
||||||
if (_currentPathIcon != null)
|
if (_currentPathIcon != null)
|
||||||
{
|
_currentPathIcon.Kind = DataModelPath.GetPropertyType().GetTypeIcon();
|
||||||
Type? type = DataModelPath.GetPropertyType();
|
|
||||||
if (type == null)
|
|
||||||
_currentPathIcon.Kind = MaterialIconKind.QuestionMarkCircle;
|
|
||||||
else if (type.TypeIsNumber())
|
|
||||||
_currentPathIcon.Kind = MaterialIconKind.CalculatorVariantOutline;
|
|
||||||
else if (type.IsEnum)
|
|
||||||
_currentPathIcon.Kind = MaterialIconKind.FormatListBulletedSquare;
|
|
||||||
else if (type == typeof(bool))
|
|
||||||
_currentPathIcon.Kind = MaterialIconKind.CircleHalfFull;
|
|
||||||
else if (type == typeof(string))
|
|
||||||
_currentPathIcon.Kind = MaterialIconKind.Text;
|
|
||||||
else if (type == typeof(SKColor))
|
|
||||||
_currentPathIcon.Kind = MaterialIconKind.Palette;
|
|
||||||
else
|
|
||||||
_currentPathIcon.Kind = MaterialIconKind.Matrix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,6 +32,12 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
public static readonly StyledProperty<bool> ShowFullPathProperty =
|
public static readonly StyledProperty<bool> ShowFullPathProperty =
|
||||||
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowFullPath));
|
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowFullPath));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether the button should show the icon of the first provided filter type.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> ShowTypeIconProperty =
|
||||||
|
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowTypeIcon));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether the data model picker has a value.
|
/// Gets a boolean indicating whether the data model picker has a value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -77,6 +83,7 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
private bool _attached;
|
private bool _attached;
|
||||||
private bool _flyoutActive;
|
private bool _flyoutActive;
|
||||||
private Button? _button;
|
private Button? _button;
|
||||||
|
private TextBlock? _label;
|
||||||
private DataModelPickerFlyout? _flyout;
|
private DataModelPickerFlyout? _flyout;
|
||||||
|
|
||||||
static DataModelPickerButton()
|
static DataModelPickerButton()
|
||||||
@ -103,6 +110,16 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
set => SetValue(ShowFullPathProperty, value);
|
set => SetValue(ShowFullPathProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether the button should show the icon of the first provided filter type.
|
||||||
|
/// </summary>
|
||||||
|
public bool ShowTypeIcon
|
||||||
|
{
|
||||||
|
get => GetValue(ShowTypeIconProperty);
|
||||||
|
set => SetValue(ShowTypeIconProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether the data model picker has a value.
|
/// Gets a boolean indicating whether the data model picker has a value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -212,13 +229,13 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
{
|
{
|
||||||
HasValue = DataModelPath != null && DataModelPath.IsValid;
|
HasValue = DataModelPath != null && DataModelPath.IsValid;
|
||||||
|
|
||||||
if (_button == null)
|
if (_button == null || _label == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!HasValue)
|
if (!HasValue)
|
||||||
{
|
{
|
||||||
ToolTip.SetTip(_button, null);
|
ToolTip.SetTip(_button, null);
|
||||||
_button.Content = Placeholder;
|
_label.Text = Placeholder;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -227,7 +244,7 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
formattedPath = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
formattedPath = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
||||||
|
|
||||||
ToolTip.SetTip(_button, formattedPath);
|
ToolTip.SetTip(_button, formattedPath);
|
||||||
_button.Content = ShowFullPath
|
_label.Text = ShowFullPath
|
||||||
? formattedPath
|
? formattedPath
|
||||||
: DataModelPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier;
|
: DataModelPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier;
|
||||||
}
|
}
|
||||||
@ -261,6 +278,7 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
_button.Click -= OnButtonClick;
|
_button.Click -= OnButtonClick;
|
||||||
base.OnApplyTemplate(e);
|
base.OnApplyTemplate(e);
|
||||||
_button = e.NameScope.Find<Button>("MainButton");
|
_button = e.NameScope.Find<Button>("MainButton");
|
||||||
|
_label = e.NameScope.Find<TextBlock>("MainButtonLabel");
|
||||||
if (_button != null)
|
if (_button != null)
|
||||||
_button.Click += OnButtonClick;
|
_button.Click += OnButtonClick;
|
||||||
UpdateValueDisplay();
|
UpdateValueDisplay();
|
||||||
|
|||||||
37
src/Avalonia/Artemis.UI.Shared/Extensions/TypeExtensions.cs
Normal file
37
src/Avalonia/Artemis.UI.Shared/Extensions/TypeExtensions.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Artemis.Core;
|
||||||
|
using Material.Icons;
|
||||||
|
using SkiaSharp;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Shared.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides utilities when working with types in UI elements.
|
||||||
|
/// </summary>
|
||||||
|
public static class TypeExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Finds an appropriate Material Design icon for the given <paramref name="type"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type to retrieve an icon for.</param>
|
||||||
|
/// <returns>An appropriate Material Design icon for the given <paramref name="type"/>.</returns>
|
||||||
|
public static MaterialIconKind GetTypeIcon(this Type? type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
return MaterialIconKind.QuestionMarkCircle;
|
||||||
|
if (type.TypeIsNumber())
|
||||||
|
return MaterialIconKind.CalculatorVariantOutline;
|
||||||
|
if (type.IsEnum)
|
||||||
|
return MaterialIconKind.FormatListBulletedSquare;
|
||||||
|
if (type == typeof(bool))
|
||||||
|
return MaterialIconKind.CircleHalfFull;
|
||||||
|
if (type == typeof(string))
|
||||||
|
return MaterialIconKind.Text;
|
||||||
|
if (type == typeof(SKColor))
|
||||||
|
return MaterialIconKind.Palette;
|
||||||
|
if (type.IsAssignableTo(typeof(IDataModelEvent)))
|
||||||
|
return MaterialIconKind.LightningBolt;
|
||||||
|
return MaterialIconKind.Matrix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:controls1="clr-namespace:Artemis.UI.Shared.Controls"
|
xmlns:controls1="clr-namespace:Artemis.UI.Shared.Controls"
|
||||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker">
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker"
|
||||||
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<Border Padding="50">
|
<Border Padding="50">
|
||||||
<StackPanel Spacing="5">
|
<StackPanel Spacing="5">
|
||||||
@ -32,6 +33,9 @@
|
|||||||
|
|
||||||
<gradientPicker:GradientPickerButton></gradientPicker:GradientPickerButton>
|
<gradientPicker:GradientPickerButton></gradientPicker:GradientPickerButton>
|
||||||
<gradientPicker:GradientPickerButton Classes="condensed"></gradientPicker:GradientPickerButton>
|
<gradientPicker:GradientPickerButton Classes="condensed"></gradientPicker:GradientPickerButton>
|
||||||
|
|
||||||
|
<dataModelPicker:DataModelPickerButton></dataModelPicker:DataModelPickerButton>
|
||||||
|
<dataModelPicker:DataModelPickerButton Classes="condensed"></dataModelPicker:DataModelPickerButton>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Design.PreviewWith>
|
</Design.PreviewWith>
|
||||||
@ -79,4 +83,15 @@
|
|||||||
<Setter Property="Margin" Value="4" />
|
<Setter Property="Margin" Value="4" />
|
||||||
<Setter Property="CornerRadius" Value="2" />
|
<Setter Property="CornerRadius" Value="2" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="dataModelPicker|DataModelPickerButton.condensed">
|
||||||
|
<Setter Property="Padding" Value="4 2" />
|
||||||
|
<Setter Property="FontSize" Value="13" />
|
||||||
|
<Setter Property="MinHeight" Value="24" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="dataModelPicker|DataModelPickerButton.condensed /template/ controls|Button">
|
||||||
|
<Setter Property="Padding" Value="6 3 11 3" />
|
||||||
|
<Setter Property="Height" Value="24" />
|
||||||
|
</Style>
|
||||||
</Styles>
|
</Styles>
|
||||||
@ -1,17 +1,18 @@
|
|||||||
<Styles xmlns="https://github.com/avaloniaui"
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker"
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<Border Padding="20" Width="200">
|
<Border Padding="20" Width="200">
|
||||||
<StackPanel Spacing="5">
|
<StackPanel Spacing="5">
|
||||||
<dataModelPicker:DataModelPickerButton />
|
<dataModelPicker:DataModelPickerButton />
|
||||||
|
<gradientPicker:GradientPickerButton />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Design.PreviewWith>
|
</Design.PreviewWith>
|
||||||
|
|
||||||
<Style Selector="FlyoutPresenter.data-model-picker-presenter">
|
<Style Selector="FlyoutPresenter.data-model-picker-presenter">
|
||||||
<!-- <Setter Property="Padding" Value="0" /> -->
|
|
||||||
<Setter Property="MaxWidth" Value="1200" />
|
<Setter Property="MaxWidth" Value="1200" />
|
||||||
<Setter Property="MaxHeight" Value="1200" />
|
<Setter Property="MaxHeight" Value="1200" />
|
||||||
<Setter Property="Background" Value="{DynamicResource SolidBackgroundFillColorBaseBrush}" />
|
<Setter Property="Background" Value="{DynamicResource SolidBackgroundFillColorBaseBrush}" />
|
||||||
@ -28,7 +29,25 @@
|
|||||||
<ControlTemplate>
|
<ControlTemplate>
|
||||||
<controls:Button Name="MainButton"
|
<controls:Button Name="MainButton"
|
||||||
CornerRadius="{TemplateBinding CornerRadius}"
|
CornerRadius="{TemplateBinding CornerRadius}"
|
||||||
BorderBrush="{TemplateBinding BorderBrush}">
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||||
|
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||||
|
HorizontalContentAlignment="Stretch">
|
||||||
|
<Grid ColumnDefinitions="*,Auto" HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Name="MainButtonLabel"
|
||||||
|
Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
TextAlignment="Left" />
|
||||||
|
<TextBlock Name="ChevronTextBlock"
|
||||||
|
Grid.Column="1"
|
||||||
|
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||||
|
FontSize="13"
|
||||||
|
Text=""
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
TextAlignment="Right"
|
||||||
|
Padding="2 2 2 0"
|
||||||
|
Margin="5 0" />
|
||||||
|
</Grid>
|
||||||
</controls:Button>
|
</controls:Button>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
|||||||
@ -99,11 +99,7 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
DragCableViewModel DragCableViewModel(PinViewModel pinViewModel);
|
DragCableViewModel DragCableViewModel(PinViewModel pinViewModel);
|
||||||
InputPinViewModel InputPinViewModel(IPin inputPin);
|
InputPinViewModel InputPinViewModel(IPin inputPin);
|
||||||
OutputPinViewModel OutputPinViewModel(IPin outputPin);
|
OutputPinViewModel OutputPinViewModel(IPin outputPin);
|
||||||
}
|
InputPinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
||||||
|
OutputPinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
||||||
public interface INodePinVmFactory
|
|
||||||
{
|
|
||||||
PinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
|
||||||
PinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,28 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Screens.VisualScripting.Pins;
|
|
||||||
using Ninject.Extensions.Factory;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Ninject.InstanceProviders;
|
|
||||||
|
|
||||||
public class NodePinViewModelInstanceProvider : StandardInstanceProvider
|
|
||||||
{
|
|
||||||
protected override Type GetType(MethodInfo methodInfo, object[] arguments)
|
|
||||||
{
|
|
||||||
if (methodInfo.ReturnType != typeof(PinCollectionViewModel))
|
|
||||||
return base.GetType(methodInfo, arguments);
|
|
||||||
|
|
||||||
if (arguments[0] is IPinCollection pinCollection)
|
|
||||||
return CreatePinCollectionViewModelType(pinCollection);
|
|
||||||
|
|
||||||
return base.GetType(methodInfo, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Type CreatePinCollectionViewModelType(IPinCollection pinCollection)
|
|
||||||
{
|
|
||||||
if (pinCollection.Direction == PinDirection.Input)
|
|
||||||
return typeof(InputPinCollectionViewModel<>).MakeGenericType(pinCollection.Type);
|
|
||||||
return typeof(OutputPinCollectionViewModel<>).MakeGenericType(pinCollection.Type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -59,7 +59,6 @@ namespace Artemis.UI.Ninject
|
|||||||
});
|
});
|
||||||
|
|
||||||
Kernel.Bind<IPropertyVmFactory>().ToFactory(() => new LayerPropertyViewModelInstanceProvider());
|
Kernel.Bind<IPropertyVmFactory>().ToFactory(() => new LayerPropertyViewModelInstanceProvider());
|
||||||
Kernel.Bind<INodePinVmFactory>().ToFactory(() => new NodePinViewModelInstanceProvider());
|
|
||||||
|
|
||||||
// Bind all UI services as singletons
|
// Bind all UI services as singletons
|
||||||
Kernel.Bind(x =>
|
Kernel.Bind(x =>
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:skiaSharp="clr-namespace:SkiaSharp;assembly=SkiaSharp"
|
xmlns:skiaSharp="clr-namespace:SkiaSharp;assembly=SkiaSharp"
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
xmlns:shared="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
||||||
|
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.VisualScripting.CableView"
|
x:Class="Artemis.UI.Screens.VisualScripting.CableView"
|
||||||
x:DataType="visualScripting:CableViewModel"
|
x:DataType="visualScripting:CableViewModel"
|
||||||
@ -45,7 +46,8 @@
|
|||||||
CornerRadius="3"
|
CornerRadius="3"
|
||||||
Padding="4"
|
Padding="4"
|
||||||
Canvas.Left="{CompiledBinding ValuePoint.X}"
|
Canvas.Left="{CompiledBinding ValuePoint.X}"
|
||||||
Canvas.Top="{CompiledBinding ValuePoint.Y}">
|
Canvas.Top="{CompiledBinding ValuePoint.Y}"
|
||||||
|
IsVisible="{CompiledBinding FromViewModel.Pin.PinValue, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
<ContentControl Content="{CompiledBinding FromViewModel.Pin.PinValue}">
|
<ContentControl Content="{CompiledBinding FromViewModel.Pin.PinValue}">
|
||||||
<ContentControl.DataTemplates>
|
<ContentControl.DataTemplates>
|
||||||
<DataTemplate DataType="skiaSharp:SKColor">
|
<DataTemplate DataType="skiaSharp:SKColor">
|
||||||
|
|||||||
@ -16,10 +16,10 @@ namespace Artemis.UI.Screens.VisualScripting;
|
|||||||
public class CableViewModel : ActivatableViewModelBase
|
public class CableViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private readonly ObservableAsPropertyHelper<bool> _connected;
|
private readonly ObservableAsPropertyHelper<bool> _connected;
|
||||||
private readonly ObservableAsPropertyHelper<Color> _cableColor;
|
|
||||||
private readonly ObservableAsPropertyHelper<Point> _fromPoint;
|
private readonly ObservableAsPropertyHelper<Point> _fromPoint;
|
||||||
private readonly ObservableAsPropertyHelper<Point> _toPoint;
|
private readonly ObservableAsPropertyHelper<Point> _toPoint;
|
||||||
private readonly ObservableAsPropertyHelper<Point> _valuePoint;
|
private readonly ObservableAsPropertyHelper<Point> _valuePoint;
|
||||||
|
private ObservableAsPropertyHelper<Color>? _cableColor;
|
||||||
|
|
||||||
private PinViewModel? _fromViewModel;
|
private PinViewModel? _fromViewModel;
|
||||||
private PinViewModel? _toViewModel;
|
private PinViewModel? _toViewModel;
|
||||||
@ -36,6 +36,12 @@ public class CableViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
nodeScriptViewModel.PinViewModels.ToObservableChangeSet().Filter(p => ReferenceEquals(p.Pin, from)).Transform(model => FromViewModel = model).Subscribe().DisposeWith(d);
|
nodeScriptViewModel.PinViewModels.ToObservableChangeSet().Filter(p => ReferenceEquals(p.Pin, from)).Transform(model => FromViewModel = model).Subscribe().DisposeWith(d);
|
||||||
nodeScriptViewModel.PinViewModels.ToObservableChangeSet().Filter(p => ReferenceEquals(p.Pin, to)).Transform(model => ToViewModel = model).Subscribe().DisposeWith(d);
|
nodeScriptViewModel.PinViewModels.ToObservableChangeSet().Filter(p => ReferenceEquals(p.Pin, to)).Transform(model => ToViewModel = model).Subscribe().DisposeWith(d);
|
||||||
|
|
||||||
|
_cableColor = this.WhenAnyValue(vm => vm.FromViewModel, vm => vm.ToViewModel)
|
||||||
|
.Select(tuple => tuple.Item1?.WhenAnyValue(p => p.PinColor) ?? tuple.Item2?.WhenAnyValue(p => p.PinColor) ?? Observable.Never<Color>())
|
||||||
|
.Switch()
|
||||||
|
.ToProperty(this, vm => vm.CableColor)
|
||||||
|
.DisposeWith(d);
|
||||||
});
|
});
|
||||||
|
|
||||||
_fromPoint = this.WhenAnyValue(vm => vm.FromViewModel)
|
_fromPoint = this.WhenAnyValue(vm => vm.FromViewModel)
|
||||||
@ -51,10 +57,6 @@ public class CableViewModel : ActivatableViewModelBase
|
|||||||
tuple.Item1.Y + (tuple.Item2.Y - tuple.Item1.Y) / 2
|
tuple.Item1.Y + (tuple.Item2.Y - tuple.Item1.Y) / 2
|
||||||
)).ToProperty(this, vm => vm.ValuePoint);
|
)).ToProperty(this, vm => vm.ValuePoint);
|
||||||
|
|
||||||
_cableColor = this.WhenAnyValue(vm => vm.FromViewModel, vm => vm.ToViewModel)
|
|
||||||
.Select(tuple => tuple.Item1?.PinColor ?? tuple.Item2?.PinColor ?? new Color(255, 255, 255, 255))
|
|
||||||
.ToProperty(this, vm => vm.CableColor);
|
|
||||||
|
|
||||||
// Not a perfect solution but this makes sure the cable never renders at 0,0 (can happen when the cable spawns before the pin ever rendered)
|
// Not a perfect solution but this makes sure the cable never renders at 0,0 (can happen when the cable spawns before the pin ever rendered)
|
||||||
_connected = this.WhenAnyValue(vm => vm.FromPoint, vm => vm.ToPoint)
|
_connected = this.WhenAnyValue(vm => vm.FromPoint, vm => vm.ToPoint)
|
||||||
.Select(tuple => tuple.Item1 != new Point(0, 0) && tuple.Item2 != new Point(0, 0))
|
.Select(tuple => tuple.Item1 != new Point(0, 0) && tuple.Item2 != new Point(0, 0))
|
||||||
@ -78,5 +80,5 @@ public class CableViewModel : ActivatableViewModelBase
|
|||||||
public Point FromPoint => _fromPoint.Value;
|
public Point FromPoint => _fromPoint.Value;
|
||||||
public Point ToPoint => _toPoint.Value;
|
public Point ToPoint => _toPoint.Value;
|
||||||
public Point ValuePoint => _valuePoint.Value;
|
public Point ValuePoint => _valuePoint.Value;
|
||||||
public Color CableColor => _cableColor.Value;
|
public Color CableColor => _cableColor?.Value ?? new Color(255, 255, 255, 255);
|
||||||
}
|
}
|
||||||
@ -64,6 +64,7 @@ public class NodeScriptViewModel : ActivatableViewModelBase
|
|||||||
PinViewModels.ToObservableChangeSet()
|
PinViewModels.ToObservableChangeSet()
|
||||||
.Filter(p => p.Pin.Direction == PinDirection.Output)
|
.Filter(p => p.Pin.Direction == PinDirection.Output)
|
||||||
.TransformMany(p => p.Connections)
|
.TransformMany(p => p.Connections)
|
||||||
|
.Filter(p => p.ConnectedTo.Any())
|
||||||
.Transform(pin => _nodeVmFactory.CableViewModel(this, pin.ConnectedTo.First(), pin))
|
.Transform(pin => _nodeVmFactory.CableViewModel(this, pin.ConnectedTo.First(), pin))
|
||||||
.Bind(out ReadOnlyObservableCollection<CableViewModel> cableViewModels)
|
.Bind(out ReadOnlyObservableCollection<CableViewModel> cableViewModels)
|
||||||
.Subscribe();
|
.Subscribe();
|
||||||
|
|||||||
@ -33,7 +33,7 @@ public class NodeViewModel : ActivatableViewModelBase
|
|||||||
private ObservableAsPropertyHelper<bool>? _hasInputPins;
|
private ObservableAsPropertyHelper<bool>? _hasInputPins;
|
||||||
private ObservableAsPropertyHelper<bool>? _hasOutputPins;
|
private ObservableAsPropertyHelper<bool>? _hasOutputPins;
|
||||||
|
|
||||||
public NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node, INodeVmFactory nodeVmFactory, INodePinVmFactory nodePinVmFactory, INodeEditorService nodeEditorService)
|
public NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
|
||||||
{
|
{
|
||||||
NodeScriptViewModel = nodeScriptViewModel;
|
NodeScriptViewModel = nodeScriptViewModel;
|
||||||
_nodeEditorService = nodeEditorService;
|
_nodeEditorService = nodeEditorService;
|
||||||
@ -61,12 +61,12 @@ public class NodeViewModel : ActivatableViewModelBase
|
|||||||
// Same again but for pin collections
|
// Same again but for pin collections
|
||||||
nodePinCollections.Connect()
|
nodePinCollections.Connect()
|
||||||
.Filter(n => n.Direction == PinDirection.Input)
|
.Filter(n => n.Direction == PinDirection.Input)
|
||||||
.Transform(c => nodePinVmFactory.InputPinCollectionViewModel(c, nodeScriptViewModel))
|
.Transform(c => (PinCollectionViewModel) nodeVmFactory.InputPinCollectionViewModel(c, nodeScriptViewModel))
|
||||||
.Bind(out ReadOnlyObservableCollection<PinCollectionViewModel> inputPinCollections)
|
.Bind(out ReadOnlyObservableCollection<PinCollectionViewModel> inputPinCollections)
|
||||||
.Subscribe();
|
.Subscribe();
|
||||||
nodePinCollections.Connect()
|
nodePinCollections.Connect()
|
||||||
.Filter(n => n.Direction == PinDirection.Output)
|
.Filter(n => n.Direction == PinDirection.Output)
|
||||||
.Transform(c => nodePinVmFactory.OutputPinCollectionViewModel(c, nodeScriptViewModel))
|
.Transform(c => (PinCollectionViewModel) nodeVmFactory.OutputPinCollectionViewModel(c, nodeScriptViewModel))
|
||||||
.Bind(out ReadOnlyObservableCollection<PinCollectionViewModel> outputPinCollections)
|
.Bind(out ReadOnlyObservableCollection<PinCollectionViewModel> outputPinCollections)
|
||||||
.Subscribe();
|
.Subscribe();
|
||||||
InputPinCollectionViewModels = inputPinCollections;
|
InputPinCollectionViewModels = inputPinCollections;
|
||||||
|
|||||||
@ -4,12 +4,12 @@ using Artemis.UI.Shared.Services.NodeEditor;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||||
|
|
||||||
public class InputPinCollectionViewModel<T> : PinCollectionViewModel
|
public class InputPinCollectionViewModel : PinCollectionViewModel
|
||||||
{
|
{
|
||||||
private readonly INodeVmFactory _nodeVmFactory;
|
private readonly INodeVmFactory _nodeVmFactory;
|
||||||
public InputPinCollection<T> InputPinCollection { get; }
|
public IPinCollection InputPinCollection { get; }
|
||||||
|
|
||||||
public InputPinCollectionViewModel(InputPinCollection<T> inputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
|
public InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
|
||||||
: base(inputPinCollection, nodeScriptViewModel, nodeEditorService)
|
: base(inputPinCollection, nodeScriptViewModel, nodeEditorService)
|
||||||
{
|
{
|
||||||
_nodeVmFactory = nodeVmFactory;
|
_nodeVmFactory = nodeVmFactory;
|
||||||
|
|||||||
@ -4,12 +4,12 @@ using Artemis.UI.Shared.Services.NodeEditor;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||||
|
|
||||||
public class OutputPinCollectionViewModel<T> : PinCollectionViewModel
|
public class OutputPinCollectionViewModel : PinCollectionViewModel
|
||||||
{
|
{
|
||||||
private readonly INodeVmFactory _nodeVmFactory;
|
private readonly INodeVmFactory _nodeVmFactory;
|
||||||
public OutputPinCollection<T> OutputPinCollection { get; }
|
public IPinCollection OutputPinCollection { get; }
|
||||||
|
|
||||||
public OutputPinCollectionViewModel(OutputPinCollection<T> outputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
|
public OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
|
||||||
: base(outputPinCollection, nodeScriptViewModel, nodeEditorService)
|
: base(outputPinCollection, nodeScriptViewModel, nodeEditorService)
|
||||||
{
|
{
|
||||||
_nodeVmFactory = nodeVmFactory;
|
_nodeVmFactory = nodeVmFactory;
|
||||||
|
|||||||
@ -16,17 +16,17 @@ namespace Artemis.UI.Screens.VisualScripting.Pins;
|
|||||||
|
|
||||||
public abstract class PinViewModel : ActivatableViewModelBase
|
public abstract class PinViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private Point _position;
|
private readonly INodeService _nodeService;
|
||||||
private ReactiveCommand<IPin, Unit>? _removePin;
|
private ReactiveCommand<IPin, Unit>? _removePin;
|
||||||
|
private Point _position;
|
||||||
|
private Color _pinColor;
|
||||||
|
private Color _darkenedPinColor;
|
||||||
|
|
||||||
protected PinViewModel(IPin pin, INodeService nodeService)
|
protected PinViewModel(IPin pin, INodeService nodeService)
|
||||||
{
|
{
|
||||||
|
_nodeService = nodeService;
|
||||||
|
|
||||||
Pin = pin;
|
Pin = pin;
|
||||||
|
|
||||||
TypeColorRegistration registration = nodeService.GetTypeColorRegistration(Pin.Type);
|
|
||||||
PinColor = registration.Color.ToColor();
|
|
||||||
DarkenedPinColor = registration.DarkenedColor.ToColor();
|
|
||||||
|
|
||||||
SourceList<IPin> connectedPins = new();
|
SourceList<IPin> connectedPins = new();
|
||||||
this.WhenActivated(d =>
|
this.WhenActivated(d =>
|
||||||
{
|
{
|
||||||
@ -36,17 +36,35 @@ public abstract class PinViewModel : ActivatableViewModelBase
|
|||||||
Observable.FromEventPattern<SingleValueEventArgs<IPin>>(x => Pin.PinDisconnected += x, x => Pin.PinDisconnected -= x)
|
Observable.FromEventPattern<SingleValueEventArgs<IPin>>(x => Pin.PinDisconnected += x, x => Pin.PinDisconnected -= x)
|
||||||
.Subscribe(e => connectedPins.Remove(e.EventArgs.Value))
|
.Subscribe(e => connectedPins.Remove(e.EventArgs.Value))
|
||||||
.DisposeWith(d);
|
.DisposeWith(d);
|
||||||
|
Pin.WhenAnyValue(p => p.Type).Subscribe(_ => UpdatePinColor()).DisposeWith(d);
|
||||||
});
|
});
|
||||||
|
|
||||||
Connections = connectedPins.Connect().AsObservableList();
|
Connections = connectedPins.Connect().AsObservableList();
|
||||||
connectedPins.AddRange(Pin.ConnectedTo);
|
connectedPins.AddRange(Pin.ConnectedTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdatePinColor()
|
||||||
|
{
|
||||||
|
TypeColorRegistration registration = _nodeService.GetTypeColorRegistration(Pin.Type);
|
||||||
|
PinColor = registration.Color.ToColor();
|
||||||
|
DarkenedPinColor = registration.DarkenedColor.ToColor();
|
||||||
|
}
|
||||||
|
|
||||||
public IObservableList<IPin> Connections { get; }
|
public IObservableList<IPin> Connections { get; }
|
||||||
|
|
||||||
public IPin Pin { get; }
|
public IPin Pin { get; }
|
||||||
public Color PinColor { get; }
|
|
||||||
public Color DarkenedPinColor { get; }
|
public Color PinColor
|
||||||
|
{
|
||||||
|
get => _pinColor;
|
||||||
|
set => RaiseAndSetIfChanged(ref _pinColor, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color DarkenedPinColor
|
||||||
|
{
|
||||||
|
get => _darkenedPinColor;
|
||||||
|
set => RaiseAndSetIfChanged(ref _darkenedPinColor, value);
|
||||||
|
}
|
||||||
|
|
||||||
public Point Position
|
public Point Position
|
||||||
{
|
{
|
||||||
@ -62,14 +80,9 @@ public abstract class PinViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
public bool IsCompatibleWith(PinViewModel pinViewModel)
|
public bool IsCompatibleWith(PinViewModel pinViewModel)
|
||||||
{
|
{
|
||||||
if (pinViewModel.Pin.Direction == Pin.Direction)
|
if (pinViewModel.Pin.Direction == Pin.Direction || pinViewModel.Pin.Node == Pin.Node)
|
||||||
return false;
|
|
||||||
if (pinViewModel.Pin.Node == Pin.Node)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return Pin.Type == pinViewModel.Pin.Type
|
return Pin.IsTypeCompatible(pinViewModel.Pin.Type);
|
||||||
|| Pin.Type == typeof(Enum) && pinViewModel.Pin.Type.IsEnum
|
|
||||||
|| Pin.Direction == PinDirection.Input && Pin.Type == typeof(object)
|
|
||||||
|| Pin.Direction == PinDirection.Output && pinViewModel.Pin.Type == typeof(object);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,9 +27,9 @@ public class DataModelNodeCustomViewModel : CustomNodeViewModel
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Modules = new ObservableCollection<Module>();
|
Modules = new ObservableCollection<Module>();
|
||||||
if (_node.Script.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
|
if (_node.Script?.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
|
||||||
Modules.Add(scriptProfile.Configuration.Module);
|
Modules.Add(scriptProfile.Configuration.Module);
|
||||||
else if (_node.Script.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
|
else if (_node.Script?.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
|
||||||
Modules.Add(profileConfiguration.Module);
|
Modules.Add(profileConfiguration.Module);
|
||||||
|
|
||||||
_node.PropertyChanged += NodeOnPropertyChanged;
|
_node.PropertyChanged += NodeOnPropertyChanged;
|
||||||
@ -46,7 +46,7 @@ public class DataModelNodeCustomViewModel : CustomNodeViewModel
|
|||||||
set => RaiseAndSetIfChanged(ref _modules, value);
|
set => RaiseAndSetIfChanged(ref _modules, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataModelPath DataModelPath
|
public DataModelPath? DataModelPath
|
||||||
{
|
{
|
||||||
get => _node.DataModelPath;
|
get => _node.DataModelPath;
|
||||||
set
|
set
|
||||||
@ -56,10 +56,10 @@ public class DataModelNodeCustomViewModel : CustomNodeViewModel
|
|||||||
|
|
||||||
_node.DataModelPath?.Dispose();
|
_node.DataModelPath?.Dispose();
|
||||||
_node.DataModelPath = value;
|
_node.DataModelPath = value;
|
||||||
_node.DataModelPath.Save();
|
_node.DataModelPath?.Save();
|
||||||
|
|
||||||
_node.Storage = _node.DataModelPath.Entity;
|
_node.Storage = _node.DataModelPath?.Entity;
|
||||||
_node.UpdateOutputPin(false);
|
_node.UpdateOutputPin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,10 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelEventNodeCustomView"
|
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelEventNodeCustomView"
|
||||||
x:DataType="customViewModels:DataModelEventNodeCustomViewModel">
|
x:DataType="customViewModels:DataModelEventNodeCustomViewModel">
|
||||||
<dataModelPicker:DataModelPickerButton DataModelPath="{CompiledBinding DataModelPath}"
|
<dataModelPicker:DataModelPickerButton Classes="condensed"
|
||||||
|
DataModelPath="{CompiledBinding DataModelPath}"
|
||||||
Modules="{CompiledBinding Modules}"
|
Modules="{CompiledBinding Modules}"
|
||||||
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
|
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
|
||||||
FilterTypes="{CompiledBinding FilterTypes}" />
|
FilterTypes="{CompiledBinding FilterTypes}"
|
||||||
|
VerticalAlignment="Top"/>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,18 +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:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
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>
|
|
||||||
@ -7,7 +7,8 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelNodeCustomView"
|
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelNodeCustomView"
|
||||||
x:DataType="customViewModels:DataModelNodeCustomViewModel">
|
x:DataType="customViewModels:DataModelNodeCustomViewModel">
|
||||||
<dataModelPicker:DataModelPickerButton DataModelPath="{CompiledBinding DataModelPath}"
|
<dataModelPicker:DataModelPickerButton Classes="condensed"
|
||||||
|
DataModelPath="{CompiledBinding DataModelPath}"
|
||||||
Modules="{CompiledBinding Modules}"
|
Modules="{CompiledBinding Modules}"
|
||||||
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}" />
|
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,14 +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: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>
|
|
||||||
@ -10,22 +10,28 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
{
|
{
|
||||||
private int _currentIndex;
|
private int _currentIndex;
|
||||||
private Type _currentType;
|
private Type _currentType;
|
||||||
private DataModelPath _dataModelPath;
|
private DataModelPath? _dataModelPath;
|
||||||
private DateTime _lastTrigger;
|
private DateTime _lastTrigger;
|
||||||
private bool _updating;
|
private bool _updating;
|
||||||
|
|
||||||
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
|
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
|
||||||
{
|
{
|
||||||
_currentType = typeof(object);
|
_currentType = typeof(object);
|
||||||
CreateCycleValues(typeof(object), 1);
|
|
||||||
|
CycleValues = CreateInputPinCollection(typeof(object), "", 0);
|
||||||
Output = CreateOutputPin(typeof(object));
|
Output = CreateOutputPin(typeof(object));
|
||||||
|
|
||||||
|
CycleValues.PinAdded += CycleValuesOnPinAdded;
|
||||||
|
CycleValues.PinRemoved += CycleValuesOnPinRemoved;
|
||||||
|
CycleValues.Add(CycleValues.CreatePin());
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputPinCollection CycleValues { get; set; }
|
public INodeScript? Script { get; set; }
|
||||||
public OutputPin Output { get; set; }
|
|
||||||
public INodeScript Script { get; set; }
|
|
||||||
|
|
||||||
public DataModelPath DataModelPath
|
public InputPinCollection CycleValues { get; }
|
||||||
|
public OutputPin Output { get; }
|
||||||
|
|
||||||
|
public DataModelPath? DataModelPath
|
||||||
{
|
{
|
||||||
get => _dataModelPath;
|
get => _dataModelPath;
|
||||||
set => SetAndNotify(ref _dataModelPath, value);
|
set => SetAndNotify(ref _dataModelPath, value);
|
||||||
@ -43,7 +49,7 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
object outputValue = null;
|
object? outputValue = null;
|
||||||
if (DataModelPath?.GetValue() is IDataModelEvent dataModelEvent)
|
if (DataModelPath?.GetValue() is IDataModelEvent dataModelEvent)
|
||||||
{
|
{
|
||||||
if (dataModelEvent.LastTrigger > _lastTrigger)
|
if (dataModelEvent.LastTrigger > _lastTrigger)
|
||||||
@ -64,56 +70,29 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
Output.Value = Output.Type.GetDefault()!;
|
Output.Value = Output.Type.GetDefault()!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateCycleValues(Type type, int initialCount)
|
private void CycleValuesOnPinAdded(object? sender, SingleValueEventArgs<IPin> e)
|
||||||
{
|
|
||||||
if (CycleValues != null)
|
|
||||||
{
|
|
||||||
CycleValues.PinAdded -= CycleValuesOnPinAdded;
|
|
||||||
CycleValues.PinRemoved -= CycleValuesOnPinRemoved;
|
|
||||||
foreach (IPin pin in CycleValues)
|
|
||||||
{
|
|
||||||
pin.PinConnected -= OnPinConnected;
|
|
||||||
pin.PinDisconnected -= OnPinDisconnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemovePinCollection(CycleValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
CycleValues = CreateInputPinCollection(type, "", initialCount);
|
|
||||||
CycleValues.PinAdded += CycleValuesOnPinAdded;
|
|
||||||
CycleValues.PinRemoved += CycleValuesOnPinRemoved;
|
|
||||||
foreach (IPin pin in CycleValues)
|
|
||||||
{
|
|
||||||
pin.PinConnected += OnPinConnected;
|
|
||||||
pin.PinDisconnected += OnPinDisconnected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CycleValuesOnPinAdded(object sender, SingleValueEventArgs<IPin> e)
|
|
||||||
{
|
{
|
||||||
e.Value.PinConnected += OnPinConnected;
|
e.Value.PinConnected += OnPinConnected;
|
||||||
e.Value.PinDisconnected += OnPinDisconnected;
|
e.Value.PinDisconnected += OnPinDisconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CycleValuesOnPinRemoved(object sender, SingleValueEventArgs<IPin> e)
|
private void CycleValuesOnPinRemoved(object? sender, SingleValueEventArgs<IPin> e)
|
||||||
{
|
{
|
||||||
e.Value.PinConnected -= OnPinConnected;
|
e.Value.PinConnected -= OnPinConnected;
|
||||||
e.Value.PinDisconnected -= OnPinDisconnected;
|
e.Value.PinDisconnected -= OnPinDisconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPinDisconnected(object sender, SingleValueEventArgs<IPin> e)
|
private void OnPinDisconnected(object? sender, SingleValueEventArgs<IPin> e)
|
||||||
{
|
{
|
||||||
ProcessPinDisconnected();
|
ProcessPinDisconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPinConnected(object sender, SingleValueEventArgs<IPin> e)
|
private void OnPinConnected(object? sender, SingleValueEventArgs<IPin> e)
|
||||||
{
|
{
|
||||||
IPin source = e.Value;
|
ProcessPinConnected(e.Value);
|
||||||
IPin target = (IPin) sender;
|
|
||||||
ProcessPinConnected(source, target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessPinConnected(IPin source, IPin target)
|
private void ProcessPinConnected(IPin source)
|
||||||
{
|
{
|
||||||
if (_updating)
|
if (_updating)
|
||||||
return;
|
return;
|
||||||
@ -123,17 +102,8 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
_updating = true;
|
_updating = true;
|
||||||
|
|
||||||
// No need to change anything if the types haven't changed
|
// No need to change anything if the types haven't changed
|
||||||
if (_currentType == source.Type)
|
if (_currentType != source.Type)
|
||||||
return;
|
|
||||||
|
|
||||||
int reconnectIndex = CycleValues.ToList().IndexOf(target);
|
|
||||||
ChangeCurrentType(source.Type);
|
ChangeCurrentType(source.Type);
|
||||||
|
|
||||||
if (reconnectIndex != -1)
|
|
||||||
{
|
|
||||||
CycleValues.ToList()[reconnectIndex].ConnectTo(source);
|
|
||||||
source.ConnectTo(CycleValues.ToList()[reconnectIndex]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -143,17 +113,8 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
|
|
||||||
private void ChangeCurrentType(Type type)
|
private void ChangeCurrentType(Type type)
|
||||||
{
|
{
|
||||||
CreateCycleValues(type, CycleValues.Count());
|
CycleValues.ChangeType(type);
|
||||||
|
Output.ChangeType(type);
|
||||||
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;
|
_currentType = type;
|
||||||
}
|
}
|
||||||
@ -176,10 +137,6 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePinsType(IPin source)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,16 +8,17 @@ namespace Artemis.VisualScripting.Nodes.DataModel;
|
|||||||
[Node("Data Model-Value", "Outputs a selectable data model value.", "Data Model")]
|
[Node("Data Model-Value", "Outputs a selectable data model value.", "Data Model")]
|
||||||
public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewModel>, IDisposable
|
public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewModel>, IDisposable
|
||||||
{
|
{
|
||||||
private DataModelPath _dataModelPath;
|
private DataModelPath? _dataModelPath;
|
||||||
|
|
||||||
public DataModelNode() : base("Data Model", "Outputs a selectable data model value")
|
public DataModelNode() : base("Data Model", "Outputs a selectable data model value")
|
||||||
{
|
{
|
||||||
|
Output = CreateOutputPin(typeof(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
public INodeScript Script { get; private set; }
|
public INodeScript? Script { get; private set; }
|
||||||
public OutputPin Output { get; private set; }
|
public OutputPin Output { get; }
|
||||||
|
|
||||||
public DataModelPath DataModelPath
|
public DataModelPath? DataModelPath
|
||||||
{
|
{
|
||||||
get => _dataModelPath;
|
get => _dataModelPath;
|
||||||
set => SetAndNotify(ref _dataModelPath, value);
|
set => SetAndNotify(ref _dataModelPath, value);
|
||||||
@ -33,18 +34,15 @@ public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewMo
|
|||||||
DataModelPath = new DataModelPath(Storage);
|
DataModelPath = new DataModelPath(Storage);
|
||||||
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
||||||
|
|
||||||
UpdateOutputPin(false);
|
UpdateOutputPin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
if (DataModelPath.IsValid)
|
if (DataModelPath == null || !DataModelPath.IsValid)
|
||||||
{
|
return;
|
||||||
if (Output == null)
|
|
||||||
UpdateOutputPin(false);
|
|
||||||
|
|
||||||
object pathValue = DataModelPath.GetValue();
|
|
||||||
|
|
||||||
|
object? pathValue = DataModelPath.GetValue();
|
||||||
if (pathValue == null)
|
if (pathValue == null)
|
||||||
{
|
{
|
||||||
if (!Output.Type.IsValueType)
|
if (!Output.Type.IsValueType)
|
||||||
@ -52,39 +50,24 @@ public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewMo
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Output.Type == typeof(Numeric))
|
Output.Value = Output.Type == typeof(Numeric) ? new Numeric(pathValue) : pathValue;
|
||||||
Output.Value = new Numeric(pathValue);
|
|
||||||
else
|
|
||||||
Output.Value = pathValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateOutputPin(bool loadConnections)
|
public void UpdateOutputPin()
|
||||||
{
|
{
|
||||||
Type type = DataModelPath?.GetPropertyType();
|
Type? type = DataModelPath?.GetPropertyType();
|
||||||
if (Numeric.IsTypeCompatible(type))
|
if (Numeric.IsTypeCompatible(type))
|
||||||
type = typeof(Numeric);
|
type = typeof(Numeric);
|
||||||
|
type ??= typeof(object);
|
||||||
|
|
||||||
if (Output != null && Output.Type == type)
|
if (Output.Type != type)
|
||||||
return;
|
Output.ChangeType(type);
|
||||||
|
|
||||||
if (Output != null)
|
|
||||||
{
|
|
||||||
RemovePin(Output);
|
|
||||||
Output = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != null)
|
private void DataModelPathOnPathValidated(object? sender, EventArgs e)
|
||||||
Output = CreateOutputPin(type);
|
|
||||||
|
|
||||||
if (loadConnections && Script is NodeScript nodeScript)
|
|
||||||
nodeScript.LoadConnections();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DataModelPathOnPathValidated(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.InvokeAsync(() => UpdateOutputPin(true));
|
Dispatcher.UIThread.InvokeAsync(UpdateOutputPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user