From 4ed6d10f38a8749a7d3bb5e8b3debf884a15de65 Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 25 Aug 2022 20:34:00 +0200 Subject: [PATCH] Nodes - Added IList support Nodes - Added simple List operator node --- src/Artemis.Core/VisualScripting/Pin.cs | 8 ++-- .../Screens/VisualScripting/CableView.axaml | 4 ++ .../Nodes/List/ListOperatorNode.cs | 46 +++++++++++++++++++ .../Screens/ListOperatorNodeCustomView.axaml | 11 +++++ .../ListOperatorNodeCustomView.axaml.cs | 19 ++++++++ .../ListOperatorNodeCustomViewModel.cs | 27 +++++++++++ .../Screens/DisplayValueNodeCustomView.axaml | 4 ++ .../Nodes/Static/StaticStringValueNode.cs | 4 +- .../Nodes/Text/StringFormatNode.cs | 2 +- 9 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs create mode 100644 src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml create mode 100644 src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml.cs create mode 100644 src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomViewModel.cs diff --git a/src/Artemis.Core/VisualScripting/Pin.cs b/src/Artemis.Core/VisualScripting/Pin.cs index 89fc2ce2a..a562f7961 100644 --- a/src/Artemis.Core/VisualScripting/Pin.cs +++ b/src/Artemis.Core/VisualScripting/Pin.cs @@ -130,10 +130,10 @@ public abstract class Pin : CorePropertyChanged, IPin public bool IsTypeCompatible(Type type, bool forgivingEnumMatching = true) { return Type == type + || (Direction == PinDirection.Input && type.IsAssignableTo(Type)) + || (Direction == PinDirection.Output && type.IsAssignableFrom(Type)) || (Direction == PinDirection.Input && Type == typeof(Enum) && type.IsEnum && forgivingEnumMatching) - || (Direction == PinDirection.Output && type == typeof(Enum) && Type.IsEnum && forgivingEnumMatching) - || (Direction == PinDirection.Input && Type == typeof(object)) - || (Direction == PinDirection.Output && type == typeof(object)); + || (Direction == PinDirection.Output && type == typeof(Enum) && Type.IsEnum && forgivingEnumMatching); } /// @@ -168,6 +168,6 @@ public abstract class Pin : CorePropertyChanged, IPin IsNumeric = type == typeof(Numeric); } } - + #endregion } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/VisualScripting/CableView.axaml b/src/Artemis.UI/Screens/VisualScripting/CableView.axaml index 2c4dc4ee5..c882bda2c 100644 --- a/src/Artemis.UI/Screens/VisualScripting/CableView.axaml +++ b/src/Artemis.UI/Screens/VisualScripting/CableView.axaml @@ -7,6 +7,7 @@ xmlns:skiaSharp="clr-namespace:SkiaSharp;assembly=SkiaSharp" xmlns:shared="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared" xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core" + xmlns:collections="clr-namespace:System.Collections;assembly=System.Runtime" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Screens.VisualScripting.CableView" x:DataType="visualScripting:CableViewModel" @@ -79,6 +80,9 @@ + + + diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs new file mode 100644 index 000000000..78614819d --- /dev/null +++ b/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs @@ -0,0 +1,46 @@ +using System.Collections; +using Artemis.Core; +using Artemis.VisualScripting.Nodes.List.Screens; + +namespace Artemis.VisualScripting.Nodes.List; + +[Node("List Operator", "Checks if any/all/no value in the input list matches the input value", "List", InputType = typeof(IEnumerable), OutputType = typeof(bool))] +public class ListOperatorNode : Node +{ + public ListOperatorNode() : base("List Operator", "Checks if any/all/no value in the input list matches the input value") + { + InputList = CreateInputPin(); + InputValue = CreateInputPin(); + + Ouput = CreateOutputPin(); + } + + public InputPin InputList { get; } + public InputPin InputValue { get; } + public OutputPin Ouput { get; } + + /// + public override void Evaluate() + { + if (InputList.Value == null) + { + Ouput.Value = Storage == ListOperator.None; + return; + } + + object? input = InputValue.Value; + if (Storage == ListOperator.Any) + Ouput.Value = InputList.Value.Cast().Any(v => v.Equals(input)); + else if (Storage == ListOperator.All) + Ouput.Value = InputList.Value.Cast().All(v => v.Equals(input)); + else if (Storage == ListOperator.All) + Ouput.Value = InputList.Value.Cast().All(v => !v.Equals(input)); + } +} + +public enum ListOperator +{ + Any, + All, + None +} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml new file mode 100644 index 000000000..faa4e5543 --- /dev/null +++ b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml @@ -0,0 +1,11 @@ + + + diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml.cs new file mode 100644 index 000000000..000d729e8 --- /dev/null +++ b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; + +namespace Artemis.VisualScripting.Nodes.List.Screens; + +public partial class ListOperatorNodeCustomView : ReactiveUserControl +{ + public ListOperatorNodeCustomView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } +} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomViewModel.cs new file mode 100644 index 000000000..134e6e1f1 --- /dev/null +++ b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomViewModel.cs @@ -0,0 +1,27 @@ +using Artemis.Core; +using Artemis.UI.Shared.Services.NodeEditor; +using Artemis.UI.Shared.Services.NodeEditor.Commands; +using Artemis.UI.Shared.VisualScripting; +using ReactiveUI; + +namespace Artemis.VisualScripting.Nodes.List.Screens; + +public class ListOperatorNodeCustomViewModel : CustomNodeViewModel +{ + private readonly ListOperatorNode _node; + private readonly INodeEditorService _nodeEditorService; + + public ListOperatorNodeCustomViewModel(ListOperatorNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) + { + _node = node; + _nodeEditorService = nodeEditorService; + + NodeModified += (_, _) => this.RaisePropertyChanged(nameof(CurrentValue)); + } + + public ListOperator CurrentValue + { + get => _node.Storage; + set => _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, value)); + } +} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml index ca473031e..100dd461b 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml +++ b/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml @@ -6,6 +6,7 @@ xmlns:skiaSharp="clr-namespace:SkiaSharp;assembly=SkiaSharp" xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core" xmlns:converters1="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared" + xmlns:collections="clr-namespace:System.Collections;assembly=System.Runtime" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.VisualScripting.Nodes.Static.Screens.DisplayValueNodeCustomView" x:DataType="screens:DisplayValueNodeCustomViewModel"> @@ -43,6 +44,9 @@ + + + diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs index bb886af23..a18093d8e 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs @@ -3,13 +3,13 @@ using Artemis.VisualScripting.Nodes.Static.Screens; namespace Artemis.VisualScripting.Nodes.Static; -[Node("String-Value", "Outputs a configurable static string value.", "Static", OutputType = typeof(string))] +[Node("Text-Value", "Outputs a configurable static text value.", "Static", OutputType = typeof(string))] public class StaticStringValueNode : Node { #region Constructors public StaticStringValueNode() - : base("String", "Outputs a configurable string value.") + : base("Text", "Outputs a configurable text value.") { Output = CreateOutputPin(); } diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs index ef498bd59..915bb10d5 100644 --- a/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs @@ -2,7 +2,7 @@ namespace Artemis.VisualScripting.Nodes.Text; -[Node("Format", "Formats the input string.", "Text", InputType = typeof(object), OutputType = typeof(string))] +[Node("Format", "Formats the input text.", "Text", InputType = typeof(object), OutputType = typeof(string))] public class StringFormatNode : Node { #region Constructors