From 3758275b712d63998c1ab9342073b7fd32e36b72 Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Fri, 30 Sep 2022 21:47:32 +0100 Subject: [PATCH 01/10] Core - Changed version format --- .github/workflows/nuget.yml | 12 ++++++------ src/Artemis.Core/Artemis.Core.csproj | 3 +-- src/Artemis.Core/Constants.cs | 2 +- src/Artemis.Core/Plugins/PluginInfo.cs | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 0522d3f3a..2ee196d62 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -10,7 +10,7 @@ jobs: version: runs-on: ubuntu-latest outputs: - version-suffix: ${{ steps.get-version.outputs.version-suffix }} + version-number: ${{ steps.get-version.outputs.version-number }} steps: - name: Checkout uses: actions/checkout@v3 @@ -21,10 +21,10 @@ jobs: shell: pwsh run: | $MidnightUtc = [DateTime]::UtcNow.Date - $BranchName = "${{ github.ref_name }}".replace('/','-').replace('.','-') + $ApiVersion = (Select-Xml -Path 'src/Artemis.Core/Artemis.Core.csproj' -XPath '//PluginApiVersion').Node.InnerText $NumberOfCommitsToday = (git log --after=$($MidnightUtc.ToString("o")) --oneline | Measure-Object -Line).Lines - $VersionSuffix = "$BranchName.$($MidnightUtc.ToString("yyyyMMdd")).$NumberOfCommitsToday" - Write-Output "::set-output name=version-suffix::$VersionSuffix" + $VersionNumber = "$ApiVersion.$($MidnightUtc.ToString("yyyy.MMdd")).$NumberOfCommitsToday" + Write-Output "::set-output name=version-number::$VersionNumber" nuget: name: Publish Nuget Packages @@ -38,8 +38,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 - name: Pack Artemis.Core - run: dotnet pack -c Release -p:VersionSuffix=${{ needs.version.outputs.version-suffix }} -p:BuildingNuget=True src/Artemis.Core/Artemis.Core.csproj + run: dotnet pack -c Release -p:Version=${{ needs.version.outputs.version-number }} -p:BuildingNuget=True src/Artemis.Core/Artemis.Core.csproj - name: Pack Artemis.UI.Shared - run: dotnet pack -c Release -p:VersionSuffix=${{ needs.version.outputs.version-suffix }} src/Artemis.UI.Shared/Artemis.UI.Shared.csproj + run: dotnet pack -c Release -p:Version=${{ needs.version.outputs.version-number }} src/Artemis.UI.Shared/Artemis.UI.Shared.csproj - name: Push Nugets run: dotnet nuget push **/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate \ No newline at end of file diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 801bebb44..a7ec57544 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -10,8 +10,7 @@ x64 true ArtemisRGB.Core - - 1.0.0.0 + 1 diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs index e745c8cc3..e57b947e4 100644 --- a/src/Artemis.Core/Constants.cs +++ b/src/Artemis.Core/Constants.cs @@ -61,7 +61,7 @@ public static class Constants /// /// The current API version for plugins /// - public static readonly Version PluginApi = CoreAssembly.GetName().Version!; + public static readonly int PluginApiVersion = CoreAssembly.GetName().Version.Major; /// /// The plugin info used by core components of Artemis diff --git a/src/Artemis.Core/Plugins/PluginInfo.cs b/src/Artemis.Core/Plugins/PluginInfo.cs index bcc988891..43b8319c0 100644 --- a/src/Artemis.Core/Plugins/PluginInfo.cs +++ b/src/Artemis.Core/Plugins/PluginInfo.cs @@ -191,7 +191,7 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject /// /// Gets a boolean indicating whether this plugin is compatible with the current operating system and API version /// - public bool IsCompatible => Platforms.MatchesCurrentOperatingSystem() && Api != null && Api >= Constants.PluginApi; + public bool IsCompatible => Platforms.MatchesCurrentOperatingSystem() && Api != null && Api.Major >= Constants.PluginApiVersion; internal string PreferredPluginDirectory => $"{Main.Split(".dll")[0].Replace("/", "").Replace("\\", "")}-{Guid.ToString().Substring(0, 8)}"; From 22268fc94592b86f7e004cf30979b7a1177e6e2c Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Fri, 30 Sep 2022 21:57:28 +0100 Subject: [PATCH 02/10] CI - Allow for non-master nugets, manually. --- .github/workflows/nuget.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 2ee196d62..b6fe9fb50 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -21,9 +21,12 @@ jobs: shell: pwsh run: | $MidnightUtc = [DateTime]::UtcNow.Date + $BranchName = "${{ github.ref_name }}".replace('/','-').replace('.','-') $ApiVersion = (Select-Xml -Path 'src/Artemis.Core/Artemis.Core.csproj' -XPath '//PluginApiVersion').Node.InnerText $NumberOfCommitsToday = (git log --after=$($MidnightUtc.ToString("o")) --oneline | Measure-Object -Line).Lines $VersionNumber = "$ApiVersion.$($MidnightUtc.ToString("yyyy.MMdd")).$NumberOfCommitsToday" + # If we're not in master, add the branch name to the version so it counts as prerelease + if ($BranchName -ne "master") { $VersionNumber += "-$BranchName" } Write-Output "::set-output name=version-number::$VersionNumber" nuget: From 3f1eaeda295f1d416d1064c0fef96e02a2ea550b Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Fri, 30 Sep 2022 22:16:02 +0100 Subject: [PATCH 03/10] Core - Embed PluginApiVersion into the assembly metadata --- src/Artemis.Core/Artemis.Core.csproj | 5 +++++ src/Artemis.Core/Constants.cs | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index a7ec57544..0499f1427 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -13,6 +13,11 @@ 1 + + + + + diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs index e57b947e4..f465f118e 100644 --- a/src/Artemis.Core/Constants.cs +++ b/src/Artemis.Core/Constants.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; +using System.Linq; using System.Reflection; using Artemis.Core.JsonConverters; using Artemis.Core.Services; @@ -61,7 +62,8 @@ public static class Constants /// /// The current API version for plugins /// - public static readonly int PluginApiVersion = CoreAssembly.GetName().Version.Major; + public static readonly int PluginApiVersion = int.Parse(CoreAssembly.GetCustomAttributes() + .First(a => a.Key == "PluginApiVersion").Value); /// /// The plugin info used by core components of Artemis From b83f1f01024afe6c3c5e08c86c2e87d24cbe681f Mon Sep 17 00:00:00 2001 From: RobertBeekman Date: Sat, 1 Oct 2022 11:40:09 +0200 Subject: [PATCH 04/10] Profiles - Fixed LEDs of devices that are missing being removed from layers (#733) --- src/Artemis.Core/Artemis.Core.csproj | 5 +-- src/Artemis.Core/Models/Profile/Layer.cs | 35 ++++++++----------- .../Entities/Profile/LedEntity.cs | 32 ++++++++++++++++- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 0499f1427..4a3d0f3b1 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -11,6 +11,7 @@ true ArtemisRGB.Core 1 + enable @@ -19,8 +20,8 @@ - - + + diff --git a/src/Artemis.UI.Shared/Styles/TextBox.axaml b/src/Artemis.UI.Shared/Styles/TextBox.axaml index 7497f7019..c6b950b6d 100644 --- a/src/Artemis.UI.Shared/Styles/TextBox.axaml +++ b/src/Artemis.UI.Shared/Styles/TextBox.axaml @@ -8,9 +8,10 @@ - + attached:TextBoxAssist.SuffixText="%"> + @@ -30,80 +31,95 @@ - From 7ada77f5e3bdbff09c9cbccc5e04d2281c563887 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 4 Oct 2022 23:31:20 +0200 Subject: [PATCH 07/10] Nodes - Added help URL and help button --- src/Artemis.Core/Services/NodeService.cs | 5 +++-- .../VisualScripting/Interfaces/INode.cs | 9 +++++++-- .../VisualScripting/NodeAttribute.cs | 16 ++++++++++++++++ src/Artemis.Core/VisualScripting/NodeData.cs | 19 +++++++++++++++++-- .../VisualScripting/Nodes/Node.cs | 14 ++++++++++++-- .../Screens/VisualScripting/NodeView.axaml | 15 +++++++++++++-- 6 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/Artemis.Core/Services/NodeService.cs b/src/Artemis.Core/Services/NodeService.cs index 5ebe8cc80..f09b20d04 100644 --- a/src/Artemis.Core/Services/NodeService.cs +++ b/src/Artemis.Core/Services/NodeService.cs @@ -75,8 +75,9 @@ internal class NodeService : INodeService string name = nodeAttribute?.Name ?? nodeType.Name; string description = nodeAttribute?.Description ?? string.Empty; string category = nodeAttribute?.Category ?? string.Empty; - - NodeData nodeData = new(plugin, nodeType, name, description, category, nodeAttribute?.InputType, nodeAttribute?.OutputType, (s, e) => CreateNode(s, e, nodeType)); + string helpUrl = nodeAttribute?.HelpUrl ?? string.Empty; + + NodeData nodeData = new(plugin, nodeType, name, description, category, helpUrl, nodeAttribute?.InputType, nodeAttribute?.OutputType, (s, e) => CreateNode(s, e, nodeType)); return NodeTypeStore.Add(nodeData); } diff --git a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs index 022cddfaa..dce2df631 100644 --- a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs +++ b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs @@ -18,12 +18,12 @@ public interface INode : INotifyPropertyChanged, IBreakableModel /// /// Gets the name of the node /// - string Name { get; } + string Name { get; set; } /// /// Gets the description of the node /// - string Description { get; } + string Description { get; set; } /// /// Gets a boolean indicating whether the node is the exit node of the script @@ -44,6 +44,11 @@ public interface INode : INotifyPropertyChanged, IBreakableModel /// Gets or sets the Y-position of the node /// public double Y { get; set; } + + /// + /// Gets or sets the help URL of the node + /// + string HelpUrl { get; set; } /// /// Gets a read-only collection of the pins on this node diff --git a/src/Artemis.Core/VisualScripting/NodeAttribute.cs b/src/Artemis.Core/VisualScripting/NodeAttribute.cs index 4bd174502..c21574c03 100644 --- a/src/Artemis.Core/VisualScripting/NodeAttribute.cs +++ b/src/Artemis.Core/VisualScripting/NodeAttribute.cs @@ -24,6 +24,11 @@ public class NodeAttribute : Attribute /// public string Category { get; } = string.Empty; + /// + /// Gets the help URL of the node + /// + public string HelpUrl { get; init; } = string.Empty; + /// /// Gets the primary input type of the node /// @@ -65,5 +70,16 @@ public class NodeAttribute : Attribute Category = category; } + /// + /// Creates a new instance of the class + /// + public NodeAttribute(string name, string description, string category, string helpUrl) + { + Name = name; + Description = description; + Category = category; + HelpUrl = helpUrl; + } + #endregion } \ No newline at end of file diff --git a/src/Artemis.Core/VisualScripting/NodeData.cs b/src/Artemis.Core/VisualScripting/NodeData.cs index 6259f6ca6..d01dd9ab4 100644 --- a/src/Artemis.Core/VisualScripting/NodeData.cs +++ b/src/Artemis.Core/VisualScripting/NodeData.cs @@ -1,5 +1,6 @@ using System; using Artemis.Storage.Entities.Profile.Nodes; +using Castle.Core.Internal; namespace Artemis.Core; @@ -10,13 +11,14 @@ public class NodeData { #region Constructors - internal NodeData(Plugin plugin, Type type, string name, string description, string category, Type? inputType, Type? outputType, Func create) + internal NodeData(Plugin plugin, Type type, string name, string description, string category, string helpUrl, Type? inputType, Type? outputType, Func create) { Plugin = plugin; Type = type; Name = name; Description = description; Category = category; + HelpUrl = helpUrl; InputType = inputType; OutputType = outputType; _create = create; @@ -34,7 +36,15 @@ public class NodeData /// The returning node of type public INode CreateNode(INodeScript script, NodeEntity? entity) { - return _create(script, entity); + INode node = _create(script, entity); + if (string.IsNullOrWhiteSpace(node.Name)) + node.Name = Name; + if (string.IsNullOrWhiteSpace(node.Description)) + node.Description = Description; + if (string.IsNullOrWhiteSpace(node.HelpUrl)) + node.HelpUrl = HelpUrl; + + return node; } #endregion @@ -101,6 +111,11 @@ public class NodeData /// public string Category { get; } + /// + /// Gets the help URL of the node this data represents + /// + public string HelpUrl { get; } + /// /// Gets the primary input type of the node this data represents /// diff --git a/src/Artemis.Core/VisualScripting/Nodes/Node.cs b/src/Artemis.Core/VisualScripting/Nodes/Node.cs index e451f05aa..a6906ab57 100644 --- a/src/Artemis.Core/VisualScripting/Nodes/Node.cs +++ b/src/Artemis.Core/VisualScripting/Nodes/Node.cs @@ -46,7 +46,7 @@ public abstract class Node : BreakableModel, INode public string Name { get => _name; - protected set => SetAndNotify(ref _name, value); + set => SetAndNotify(ref _name, value); } private string _description; @@ -55,7 +55,7 @@ public abstract class Node : BreakableModel, INode public string Description { get => _description; - protected set => SetAndNotify(ref _description, value); + set => SetAndNotify(ref _description, value); } private double _x; @@ -76,6 +76,13 @@ public abstract class Node : BreakableModel, INode set => SetAndNotify(ref _y, value); } + /// + public string HelpUrl + { + get => _helpUrl; + set => SetAndNotify(ref _helpUrl, value); + } + /// public virtual bool IsExitNode => false; @@ -88,6 +95,7 @@ public abstract class Node : BreakableModel, INode public IReadOnlyCollection Pins => new ReadOnlyCollection(_pins); private readonly List _pinCollections = new(); + private string _helpUrl; /// public IReadOnlyCollection PinCollections => new ReadOnlyCollection(_pinCollections); @@ -106,6 +114,7 @@ public abstract class Node : BreakableModel, INode { _name = string.Empty; _description = string.Empty; + _helpUrl = string.Empty; _id = Guid.NewGuid(); } @@ -116,6 +125,7 @@ public abstract class Node : BreakableModel, INode { _name = name; _description = description; + _helpUrl = string.Empty; _id = Guid.NewGuid(); } diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeView.axaml b/src/Artemis.UI/Screens/VisualScripting/NodeView.axaml index 7a26616ef..7adfdbbdf 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeView.axaml +++ b/src/Artemis.UI/Screens/VisualScripting/NodeView.axaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" xmlns:visualScripting="clr-namespace:Artemis.UI.Screens.VisualScripting" + xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" mc:Ignorable="d" d:DesignWidth="250" d:DesignHeight="150" x:Class="Artemis.UI.Screens.VisualScripting.NodeView" x:DataType="visualScripting:NodeViewModel"> @@ -37,7 +38,7 @@ ClipToBounds="True" Background="{DynamicResource ContentDialogBackground}"> - + From a59183c3faa386826d328fa9034fb31c11447445 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 4 Oct 2022 23:32:34 +0200 Subject: [PATCH 08/10] Nodes - Removed constructor base calls where unnecessary --- .../Nodes/Branching/BooleanBranchNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Branching/EnumSwitchNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs | 2 +- .../Nodes/Color/ColorGradientFromPinsNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs | 3 ++- src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs | 2 +- .../Nodes/Color/DesaturateSKColorNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Color/InvertSKColorNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Color/LerpSKColorNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Color/RampSKColorNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Color/RgbSKColorNode.cs | 1 - .../Nodes/Color/RotateHueSkColorNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Color/SumSKColorsNode.cs | 2 +- .../Nodes/Conversion/ConvertToNumericNode.cs | 1 - .../Nodes/Conversion/ConvertToStringNode.cs | 3 +-- .../Nodes/DataModel/DataModelEventCycleNode.cs | 2 +- .../Nodes/DataModel/DataModelEventNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/DataModel/DataModelNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Easing/NumericEasingNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs | 3 ++- .../Nodes/List/ListOperatorPredicateNode.cs | 3 ++- src/Artemis.VisualScripting/Nodes/Mathematics/Clamp.cs | 1 - src/Artemis.VisualScripting/Nodes/Mathematics/CounterNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Mathematics/LerpNode.cs | 1 - .../Nodes/Mathematics/MathExpressionNode.cs | 3 +-- src/Artemis.VisualScripting/Nodes/Mathematics/MaxNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Mathematics/RangeNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Mathematics/RoundNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Mathematics/Saturate.cs | 1 - src/Artemis.VisualScripting/Nodes/Mathematics/SumNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Static/DisplayValueNode.cs | 2 +- .../Nodes/Static/RandomNumericValueNode.cs | 1 - .../Nodes/Static/StaticBooleanValueNode.cs | 2 +- .../Nodes/Static/StaticNumericValueNode.cs | 2 +- .../Nodes/Static/StaticSKColorValueNode.cs | 2 +- .../Nodes/Static/StaticStringValueNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Text/StringContainsNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Text/StringLengthNode.cs | 1 - .../Nodes/Text/StringNullOrEmptyNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Text/StringRegexMatchNode.cs | 2 +- src/Artemis.VisualScripting/Nodes/Timing/DelayNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Timing/EdgeNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Timing/FlipFlopNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Timing/LatchNode.cs | 1 - src/Artemis.VisualScripting/Nodes/Timing/SequencerNode.cs | 1 - 59 files changed, 34 insertions(+), 61 deletions(-) diff --git a/src/Artemis.VisualScripting/Nodes/Branching/BooleanBranchNode.cs b/src/Artemis.VisualScripting/Nodes/Branching/BooleanBranchNode.cs index eda02463e..fdd7c5bcc 100644 --- a/src/Artemis.VisualScripting/Nodes/Branching/BooleanBranchNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Branching/BooleanBranchNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Branching; [Node("Branch", "Forwards one of two values depending on an input boolean", "Branching", InputType = typeof(object), OutputType = typeof(object))] public class BooleanBranchNode : Node { - public BooleanBranchNode() : base("Branch", "Forwards one of two values depending on an input boolean") + public BooleanBranchNode() { BooleanInput = CreateInputPin(); TrueInput = CreateInputPin(typeof(object), "True"); diff --git a/src/Artemis.VisualScripting/Nodes/Branching/EnumSwitchNode.cs b/src/Artemis.VisualScripting/Nodes/Branching/EnumSwitchNode.cs index f94911661..e380c3446 100644 --- a/src/Artemis.VisualScripting/Nodes/Branching/EnumSwitchNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Branching/EnumSwitchNode.cs @@ -9,7 +9,7 @@ public class EnumSwitchNode : Node { private readonly Dictionary _inputPins; - public EnumSwitchNode() : base("Enum Branch", "desc") + public EnumSwitchNode() { _inputPins = new Dictionary(); diff --git a/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs index 384d09d88..e5adaad4e 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Color; [Node("Brighten Color", "Brightens a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] public class BrightenSKColorNode : Node { - public BrightenSKColorNode() : base("Brighten Color", "Brightens a color by a specified amount in percent") + public BrightenSKColorNode() { Input = CreateInputPin("Color"); Percentage = CreateInputPin("%"); diff --git a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientFromPinsNode.cs b/src/Artemis.VisualScripting/Nodes/Color/ColorGradientFromPinsNode.cs index 6c43f510c..5467aecb7 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientFromPinsNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/ColorGradientFromPinsNode.cs @@ -11,7 +11,7 @@ public class ColorGradientFromPinsNode : Node public InputPinCollection Colors { get; set; } public InputPinCollection Positions { get; set; } - public ColorGradientFromPinsNode() : base("Color Gradient", "Outputs a Color Gradient from colors and positions") + public ColorGradientFromPinsNode() { Colors = CreateInputPinCollection("Colors", 0); Positions = CreateInputPinCollection("Positions", 0); diff --git a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs b/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs index 8c4676818..92ef3183e 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs @@ -10,8 +10,9 @@ public class ColorGradientNode : Node _inputPins; - public ColorGradientNode() : base("Color Gradient", "Outputs a color gradient with the given colors") + public ColorGradientNode() { + Name = "Color Gradient"; _inputPins = new List(); Gradient = ColorGradient.GetUnicornBarf(); diff --git a/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs index 8ba31d1d6..5b4983e40 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Color; [Node("Darken Color", "Darkens a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] public class DarkenSKColorNode : Node { - public DarkenSKColorNode() : base("Darken Color", "Darkens a color by a specified amount in percent") + public DarkenSKColorNode() { Input = CreateInputPin("Color"); Percentage = CreateInputPin("%"); diff --git a/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs index 818b77bb4..f02e9b6f6 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Color; [Node("Desaturate Color", "Desaturates a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] public class DesaturateSKColorNode : Node { - public DesaturateSKColorNode() : base("Desaturate Color", "Desaturates a color by a specified amount in percent") + public DesaturateSKColorNode() { Input = CreateInputPin("Color"); Percentage = CreateInputPin("%"); diff --git a/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs index 558041355..cba686c38 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Color; [Node("HSL Color", "Creates a color from hue, saturation and lightness values", "Color", InputType = typeof(Numeric), OutputType = typeof(SKColor))] public class HslSKColorNode : Node { - public HslSKColorNode() : base("HSL Color", "Creates a color from hue, saturation and lightness values") + public HslSKColorNode() { H = CreateInputPin("H"); S = CreateInputPin("S"); diff --git a/src/Artemis.VisualScripting/Nodes/Color/InvertSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/InvertSKColorNode.cs index 5abf00994..b194b8a01 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/InvertSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/InvertSKColorNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Color; [Node("Invert Color", "Inverts a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] public class InvertSKColorNode : Node { - public InvertSKColorNode() : base("Invert Color", "Inverts a color") + public InvertSKColorNode() { Input = CreateInputPin(); Output = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Color/LerpSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/LerpSKColorNode.cs index 0ca5125e0..7bf45e08d 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/LerpSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/LerpSKColorNode.cs @@ -20,8 +20,8 @@ public class LerpSKColorNode : Node #region Constructors public LerpSKColorNode() - : base("Lerp", "Interpolates linear between the two values A and B") { + Name = "Lerp"; A = CreateInputPin("A"); B = CreateInputPin("B"); T = CreateInputPin("T"); diff --git a/src/Artemis.VisualScripting/Nodes/Color/RampSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/RampSKColorNode.cs index c0ff87d6f..b1cc9b183 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/RampSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/RampSKColorNode.cs @@ -10,7 +10,6 @@ public class RampSKColorNode : Node(); Output = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Color/RgbSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/RgbSKColorNode.cs index 338ab17da..7d3bd63b7 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/RgbSKColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/RgbSKColorNode.cs @@ -18,7 +18,6 @@ public class RgbSKColorNode : Node #region Constructors public RgbSKColorNode() - : base("RGB Color", "Creates a color from red, green and blue values") { R = CreateInputPin("R"); G = CreateInputPin("G"); diff --git a/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs index 22d16ef53..4325724b0 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Color; [Node("Rotate Color Hue", "Rotates the hue of a color by a specified amount in degrees", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] public class RotateHueSKColorNode : Node { - public RotateHueSKColorNode() : base("Rotate Color Hue", "Rotates the hue of a color by a specified amount in degrees") + public RotateHueSKColorNode() { Input = CreateInputPin("Color"); Amount = CreateInputPin("Amount"); diff --git a/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs index 252db28dc..1c8922262 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Color; [Node("Saturate Color", "Saturates a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] public class SaturateSKColorNode : Node { - public SaturateSKColorNode() : base("Saturate Color", "Saturates a color by a specified amount in percent") + public SaturateSKColorNode() { Input = CreateInputPin("Color"); Percentage = CreateInputPin("%"); diff --git a/src/Artemis.VisualScripting/Nodes/Color/SumSKColorsNode.cs b/src/Artemis.VisualScripting/Nodes/Color/SumSKColorsNode.cs index a67a5238f..49b86ed14 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/SumSKColorsNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/SumSKColorsNode.cs @@ -9,8 +9,8 @@ public class SumSKColorsNode : Node #region Constructors public SumSKColorsNode() - : base("Sum", "Sums the connected color values.") { + Name = "Sum"; Values = CreateInputPinCollection("Values", 2); Sum = CreateOutputPin("Sum"); } diff --git a/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToNumericNode.cs b/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToNumericNode.cs index b82a85f1f..8a4190098 100644 --- a/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToNumericNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToNumericNode.cs @@ -8,7 +8,6 @@ public class ConvertToNumericNode : Node #region Constructors public ConvertToNumericNode() - : base("To Numeric", "Converts the input to a numeric.") { Input = CreateInputPin(); Output = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToStringNode.cs b/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToStringNode.cs index e03ecffc7..d54d5ab7a 100644 --- a/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToStringNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToStringNode.cs @@ -2,13 +2,12 @@ namespace Artemis.VisualScripting.Nodes.Conversion; -[Node("To String", "Converts the input to a string.", "Conversion", InputType = typeof(object), OutputType = typeof(string))] +[Node("To Text", "Converts the input to text.", "Conversion", InputType = typeof(object), OutputType = typeof(string))] public class ConvertToStringNode : Node { #region Constructors public ConvertToStringNode() - : base("To String", "Converts the input to a string.") { Input = CreateInputPin(); String = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventCycleNode.cs b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventCycleNode.cs index a5de87de0..c9c3a7be2 100644 --- a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventCycleNode.cs +++ b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventCycleNode.cs @@ -15,7 +15,7 @@ public class DataModelEventCycleNode : Node UpdateDataModelPath(); diff --git a/src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs b/src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs index c43d46474..8b120cd8f 100644 --- a/src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Easing; [Node("Easing Type", "Outputs a selectable easing type.", "Easing", OutputType = typeof(Easings.Functions))] public class EasingTypeNode : Node { - public EasingTypeNode() : base("Easing Type", "Outputs a selectable easing type.") + public EasingTypeNode() { Output = CreateOutputPin(); } diff --git a/src/Artemis.VisualScripting/Nodes/Easing/NumericEasingNode.cs b/src/Artemis.VisualScripting/Nodes/Easing/NumericEasingNode.cs index 3aee1d5c4..426398869 100644 --- a/src/Artemis.VisualScripting/Nodes/Easing/NumericEasingNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Easing/NumericEasingNode.cs @@ -11,7 +11,7 @@ public class NumericEasingNode : Node private float _sourceValue; private float _targetValue; - public NumericEasingNode() : base("Numeric Easing", "Outputs an eased numeric value") + public NumericEasingNode() { Input = CreateInputPin(); EasingTime = CreateInputPin("delay"); diff --git a/src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs b/src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs index e4f65536d..c3e41db37 100644 --- a/src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Easing/SKColorEasingNode.cs @@ -12,7 +12,7 @@ public class SKColorEasingNode : Node private SKColor _sourceValue; private SKColor _targetValue; - public SKColorEasingNode() : base("Color Easing", "Outputs an eased color value") + public SKColorEasingNode() { Input = CreateInputPin(); EasingTime = CreateInputPin("delay"); diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs index 29ee2391a..aa7bd98ed 100644 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs @@ -7,8 +7,9 @@ namespace Artemis.VisualScripting.Nodes.List; [Node("List Operator (Simple)", "Checks if any/all/no values in the input list match the input value", "List", InputType = typeof(IEnumerable), OutputType = typeof(bool))] public class ListOperatorNode : Node { - public ListOperatorNode() : base("List Operator (Simple)", "Checks if any/all/no values in the input list match the input value") + public ListOperatorNode() { + Name = "List Operator"; InputList = CreateInputPin(); InputValue = CreateInputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs index e6d811e88..b8857a6d3 100644 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs +++ b/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs @@ -11,8 +11,9 @@ public class ListOperatorPredicateNode : Node(); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/Clamp.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/Clamp.cs index 2fcb944f1..4cd839ecb 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/Clamp.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/Clamp.cs @@ -19,7 +19,6 @@ public class ClampNode : Node #region Constructors public ClampNode() - : base("Clamp", "Clamps the value to be in between min and max") { Value = CreateInputPin("Value"); Min = CreateInputPin("Min"); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/CounterNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/CounterNode.cs index f45d73abe..b8e08d641 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/CounterNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/CounterNode.cs @@ -9,7 +9,6 @@ public class CounterNode : Node private float _progress; public CounterNode() - : base("Counter", "Counts from 0.0 to 1.0 at a configurable rate.") { Time = CreateInputPin("Time (ms)"); Output = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/LerpNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/LerpNode.cs index 23273208c..5ae96af1c 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/LerpNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/LerpNode.cs @@ -19,7 +19,6 @@ public class LerpNode : Node #region Constructors public LerpNode() - : base("Lerp", "Interpolates linear between the two values A and B") { A = CreateInputPin("A"); B = CreateInputPin("B"); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/MathExpressionNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/MathExpressionNode.cs index 25ec87bf8..305373b97 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/MathExpressionNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/MathExpressionNode.cs @@ -5,7 +5,7 @@ using NoStringEvaluating.Models.FormulaChecker; namespace Artemis.VisualScripting.Nodes.Mathematics; -[Node("Math Expression", "Outputs the result of a math expression.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] +[Node("Math Expression", "Outputs the result of a math expression.", "Mathematics", "https://wiki.artemis-rgb.com/en/guides/user/profiles/nodes/mathematics/math-expression", InputType = typeof(Numeric), OutputType = typeof(Numeric))] public class MathExpressionNode : Node { private readonly IFormulaChecker _checker; @@ -15,7 +15,6 @@ public class MathExpressionNode : Node("Values", 2); Max = CreateOutputPin("Max"); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs index a10ff8c3a..84a5dee37 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs @@ -8,7 +8,6 @@ public class MinNumericsNode : Node #region Constructors public MinNumericsNode() - : base("Min", "Outputs the smallest of the connected numeric values.") { Values = CreateInputPinCollection("Values", 2); Min = CreateOutputPin("Min"); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/RangeNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/RangeNode.cs index 74e6cc50d..2f8dbef51 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/RangeNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/RangeNode.cs @@ -19,7 +19,6 @@ public class RangeNode : Node #region Constructors public RangeNode() - : base("Range", "Selects the best integer value in the given range by the given percentage") { Min = CreateInputPin("Min"); Max = CreateInputPin("Max"); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/RoundNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/RoundNode.cs index f526f6b55..c445f5316 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/RoundNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/RoundNode.cs @@ -5,7 +5,7 @@ namespace Artemis.VisualScripting.Nodes.Mathematics; [Node("Round", "Outputs a rounded numeric value.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] public class RoundNode : Node { - public RoundNode() : base("Round", "Outputs a rounded numeric value.") + public RoundNode() { Input = CreateInputPin(); Output = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/Saturate.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/Saturate.cs index ebc81a03d..3cd22c958 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/Saturate.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/Saturate.cs @@ -17,7 +17,6 @@ public class SaturateNode : Node #region Constructors public SaturateNode() - : base("Saturate", "Clamps the value to be in between 0 and 1") { Value = CreateInputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/SumNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/SumNode.cs index e026fa32d..8fc6913c2 100644 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/SumNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Mathematics/SumNode.cs @@ -8,7 +8,6 @@ public class SumNumericsNode : Node #region Constructors public SumNumericsNode() - : base("Sum", "Sums the connected numeric values.") { Values = CreateInputPinCollection("Values", 2); Sum = CreateOutputPin("Sum"); diff --git a/src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs index 889eede47..efbecdfc1 100644 --- a/src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs @@ -8,7 +8,6 @@ public class AndNode : Node #region Constructors public AndNode() - : base("And", "Checks if all inputs are true.") { Input = CreateInputPinCollection(); Result = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs index 6d409602d..e4e2bdf2f 100644 --- a/src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Operators; [Node("Enum Equals", "Determines the equality between an input and a selected enum value", "Operators", InputType = typeof(Enum), OutputType = typeof(bool))] public class EnumEqualsNode : Node { - public EnumEqualsNode() : base("Enum Equals", "Determines the equality between an input and a selected enum value") + public EnumEqualsNode() { InputPin = CreateInputPin(); OutputPin = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs index 812eaec1c..7c022f1d7 100644 --- a/src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs @@ -8,7 +8,6 @@ public class EqualsNode : Node #region Constructors public EqualsNode() - : base("Equals", "Checks if the two inputs are equals.") { Input1 = CreateInputPin(); Input2 = CreateInputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs index 36dca3360..adae0971a 100644 --- a/src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs @@ -9,7 +9,6 @@ public class GreaterThanNode : Node #region Constructors public GreaterThanNode() - : base("Greater than", "Checks if the first input is greater than the second.") { Input1 = CreateInputPin(); Input2 = CreateInputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs index 8a8c93dfa..4eb100a7f 100644 --- a/src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs @@ -9,7 +9,6 @@ public class LessThanNode : Node #region Constructors public LessThanNode() - : base("Less than", "Checks if the first input is less than the second.") { Input1 = CreateInputPin(); Input2 = CreateInputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs index ca8c68368..a911c2e81 100644 --- a/src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs @@ -8,7 +8,6 @@ public class NegateNode : Node #region Constructors public NegateNode() - : base("Negate", "Negates the boolean.") { Input = CreateInputPin(); Output = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs index 286f0130f..b78d24d3d 100644 --- a/src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs @@ -8,7 +8,6 @@ public class OrNode : Node #region Constructors public OrNode() - : base("Or", "Checks if any inputs are true.") { Input = CreateInputPinCollection(); Result = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs index 18553f81c..42197ed25 100644 --- a/src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs @@ -8,7 +8,6 @@ public class XorNode : Node #region Constructors public XorNode() - : base("Exclusive Or", "Checks if one of the inputs is true.") { Input = CreateInputPinCollection(); Result = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Static/DisplayValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/DisplayValueNode.cs index ae5f457b7..d4206cbec 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/DisplayValueNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Static/DisplayValueNode.cs @@ -6,7 +6,7 @@ namespace Artemis.VisualScripting.Nodes.Static; [Node("Display Value", "Displays an input value for testing purposes.", "Static", InputType = typeof(object))] public class DisplayValueNode : Node { - public DisplayValueNode() : base("Display Value", "Displays an input value for testing purposes.") + public DisplayValueNode() { Input = CreateInputPin(); } diff --git a/src/Artemis.VisualScripting/Nodes/Static/RandomNumericValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/RandomNumericValueNode.cs index a883d0dcb..b00d2f419 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/RandomNumericValueNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Static/RandomNumericValueNode.cs @@ -16,7 +16,6 @@ public class RandomNumericValueNode : Node #region Constructors public RandomNumericValueNode() - : base("Random", "Generates a random value between 0 and 1") { Output = CreateOutputPin(); } diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticBooleanValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticBooleanValueNode.cs index 76000d70b..9db639db9 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticBooleanValueNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Static/StaticBooleanValueNode.cs @@ -9,8 +9,8 @@ public class StaticBooleanValueNode : Node(); } diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticNumericValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticNumericValueNode.cs index 5dd0384b7..8b11709cb 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticNumericValueNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Static/StaticNumericValueNode.cs @@ -9,8 +9,8 @@ public class StaticNumericValueNode : Node(); } diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticSKColorValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticSKColorValueNode.cs index 5ae466bc2..84879d3a3 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticSKColorValueNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Static/StaticSKColorValueNode.cs @@ -10,8 +10,8 @@ public class StaticSKColorValueNode : Node(); Storage = new SKColor(255, 0, 0); } diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs index a18093d8e..2c1c7079a 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs @@ -9,8 +9,8 @@ public class StaticStringValueNode : Node(); } diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringContainsNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringContainsNode.cs index 71ea85f68..547a85fbe 100644 --- a/src/Artemis.VisualScripting/Nodes/Text/StringContainsNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Text/StringContainsNode.cs @@ -6,7 +6,6 @@ namespace Artemis.VisualScripting.Nodes.Text; public class StringContainsNode : Node { public StringContainsNode() - : base("Contains", "Checks whether the first input is contained in the second input.") { Input1 = CreateInputPin(); Input2 = CreateInputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs index 915bb10d5..4985555c1 100644 --- a/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs @@ -8,7 +8,6 @@ public class StringFormatNode : Node #region Constructors public StringFormatNode() - : base("Format", "Formats the input string.") { Format = CreateInputPin("Format"); Values = CreateInputPinCollection("Values"); diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringLengthNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringLengthNode.cs index 421ad4dec..006f84c5f 100644 --- a/src/Artemis.VisualScripting/Nodes/Text/StringLengthNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Text/StringLengthNode.cs @@ -7,7 +7,6 @@ namespace Artemis.VisualScripting.Nodes.Text; public class StringLengthNode : Node { public StringLengthNode() - : base("Text Length", "Outputs text length.") { Input1 = CreateInputPin(); Result = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringNullOrEmptyNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringNullOrEmptyNode.cs index 6c80e372f..50e703c96 100644 --- a/src/Artemis.VisualScripting/Nodes/Text/StringNullOrEmptyNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Text/StringNullOrEmptyNode.cs @@ -7,7 +7,6 @@ namespace Artemis.VisualScripting.Nodes.Text; public class StringNullOrEmptyNode : Node { public StringNullOrEmptyNode() - : base("Text is empty", "Outputs true if empty") { Input1 = CreateInputPin(); Output1 = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringRegexMatchNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringRegexMatchNode.cs index 810080877..b33a0aaa3 100644 --- a/src/Artemis.VisualScripting/Nodes/Text/StringRegexMatchNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Text/StringRegexMatchNode.cs @@ -10,7 +10,7 @@ public class StringRegexMatchNode : Node private Regex? _regex; private Exception? _exception; - public StringRegexMatchNode() : base("Regex Match", "Checks provided regex pattern matches the input.") + public StringRegexMatchNode() { Pattern = CreateInputPin("Pattern"); Input = CreateInputPin("Input"); diff --git a/src/Artemis.VisualScripting/Nodes/Timing/DelayNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/DelayNode.cs index 2dee0a8e1..d1a1f59b7 100644 --- a/src/Artemis.VisualScripting/Nodes/Timing/DelayNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Timing/DelayNode.cs @@ -25,7 +25,6 @@ public class DelayNode : Node #region Constructors public DelayNode() - : base("Delay", "Delays the resolution of the input pin(s) for the given time after each update") { Delay = CreateInputPin("Delay"); Input = CreateInputPinCollection(typeof(object), initialCount: 0); diff --git a/src/Artemis.VisualScripting/Nodes/Timing/EdgeNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/EdgeNode.cs index cf019289e..10f341668 100644 --- a/src/Artemis.VisualScripting/Nodes/Timing/EdgeNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Timing/EdgeNode.cs @@ -17,7 +17,6 @@ public class EdgeNode : Node #region Constructors public EdgeNode() - : base("Edge", "Outputs true on each edge when the input changes") { Input = CreateInputPin(); Output = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Timing/FlipFlopNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/FlipFlopNode.cs index 62b6c8f21..a3807e93d 100644 --- a/src/Artemis.VisualScripting/Nodes/Timing/FlipFlopNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Timing/FlipFlopNode.cs @@ -18,7 +18,6 @@ public class FlipFlopNode : Node #region Constructors public FlipFlopNode() - : base("FlipFlop", "Inverts the output when the input changes from false to true") { Input = CreateInputPin(); Output = CreateOutputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/Timing/LatchNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/LatchNode.cs index a509741b2..53c2e71c5 100644 --- a/src/Artemis.VisualScripting/Nodes/Timing/LatchNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Timing/LatchNode.cs @@ -25,7 +25,6 @@ public class LatchNode : Node #region Constructors public LatchNode() - : base("Latch", "Only passes the input to the output as long as the control-pin is true. If the control pin is false the last passed value is provided.") { Control = CreateInputPin("Control"); Input = CreateInputPinCollection(typeof(object), initialCount: 0); diff --git a/src/Artemis.VisualScripting/Nodes/Timing/SequencerNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/SequencerNode.cs index 6fd2c0ec5..e72c8d5e1 100644 --- a/src/Artemis.VisualScripting/Nodes/Timing/SequencerNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Timing/SequencerNode.cs @@ -25,7 +25,6 @@ public class SequencerNode : Node #region Constructors public SequencerNode() - : base("Sequencer", "Advances on input every time the control has a rising edge (change to true)") { _currentType = typeof(object); From 2c32abaee5267621c9c9387ca271456a99f1bd03 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 4 Oct 2022 23:37:15 +0200 Subject: [PATCH 09/10] Nodes - Show simple/advanced in list node name --- src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs | 1 - src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs | 1 - .../Nodes/List/ListOperatorPredicateNode.cs | 1 - 3 files changed, 3 deletions(-) diff --git a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs b/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs index 92ef3183e..18dc15f54 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs @@ -12,7 +12,6 @@ public class ColorGradientNode : Node(); Gradient = ColorGradient.GetUnicornBarf(); diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs index aa7bd98ed..5a2cadd5b 100644 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs +++ b/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs @@ -9,7 +9,6 @@ public class ListOperatorNode : Node(); InputValue = CreateInputPin(); diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs index b8857a6d3..90f4f83eb 100644 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs +++ b/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs @@ -13,7 +13,6 @@ public class ListOperatorPredicateNode : Node(); From 35b593a31de54b5a8941ea7f1461473d78989ff3 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 4 Oct 2022 21:33:11 +0200 Subject: [PATCH 10/10] Node editor - Added copy/pasting --- .../Profile/Nodes/NodeConnectionEntity.cs | 16 +++++ .../Entities/Profile/Nodes/NodeEntity.cs | 17 +++++ .../Profile/Nodes/NodePinCollectionEntity.cs | 11 +++ .../Services/NodeEditor/Commands/AddNode.cs | 4 +- src/Artemis.UI/Models/NodesClipboardModel.cs | 72 +++++++++++++++++++ .../Screens/VisualScripting/CableView.axaml | 7 -- .../VisualScripting/CableView.axaml.cs | 18 +++-- .../Screens/VisualScripting/CableViewModel.cs | 12 +--- .../VisualScripting/NodeScriptView.axaml | 2 + .../VisualScripting/NodeScriptView.axaml.cs | 9 +++ .../VisualScripting/NodeScriptViewModel.cs | 49 +++++++++++-- 11 files changed, 191 insertions(+), 26 deletions(-) create mode 100644 src/Artemis.UI/Models/NodesClipboardModel.cs diff --git a/src/Artemis.Storage/Entities/Profile/Nodes/NodeConnectionEntity.cs b/src/Artemis.Storage/Entities/Profile/Nodes/NodeConnectionEntity.cs index 028d9c638..b85678d53 100644 --- a/src/Artemis.Storage/Entities/Profile/Nodes/NodeConnectionEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/Nodes/NodeConnectionEntity.cs @@ -4,6 +4,22 @@ namespace Artemis.Storage.Entities.Profile.Nodes; public class NodeConnectionEntity { + public NodeConnectionEntity() + { + } + + public NodeConnectionEntity(NodeConnectionEntity nodeConnectionEntity) + { + SourceType = nodeConnectionEntity.SourceType; + SourceNode = nodeConnectionEntity.SourceNode; + TargetNode = nodeConnectionEntity.TargetNode; + SourcePinCollectionId = nodeConnectionEntity.SourcePinCollectionId; + SourcePinId = nodeConnectionEntity.SourcePinId; + TargetType = nodeConnectionEntity.TargetType; + TargetPinCollectionId = nodeConnectionEntity.TargetPinCollectionId; + TargetPinId = nodeConnectionEntity.TargetPinId; + } + public string SourceType { get; set; } public Guid SourceNode { get; set; } public Guid TargetNode { get; set; } diff --git a/src/Artemis.Storage/Entities/Profile/Nodes/NodeEntity.cs b/src/Artemis.Storage/Entities/Profile/Nodes/NodeEntity.cs index 85647e59c..5683e5c0f 100644 --- a/src/Artemis.Storage/Entities/Profile/Nodes/NodeEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/Nodes/NodeEntity.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Artemis.Storage.Entities.Profile.Nodes; @@ -10,6 +11,22 @@ public class NodeEntity PinCollections = new List(); } + public NodeEntity(NodeEntity nodeEntity) + { + Id = nodeEntity.Id; + Type = nodeEntity.Type; + PluginId = nodeEntity.PluginId; + + Name = nodeEntity.Name; + Description = nodeEntity.Description; + IsExitNode = nodeEntity.IsExitNode; + X = nodeEntity.X; + Y = nodeEntity.Y; + Storage = nodeEntity.Storage; + + PinCollections = nodeEntity.PinCollections.Select(p => new NodePinCollectionEntity(p)).ToList(); + } + public Guid Id { get; set; } public string Type { get; set; } public Guid PluginId { get; set; } diff --git a/src/Artemis.Storage/Entities/Profile/Nodes/NodePinCollectionEntity.cs b/src/Artemis.Storage/Entities/Profile/Nodes/NodePinCollectionEntity.cs index 9076ead6e..e74a22780 100644 --- a/src/Artemis.Storage/Entities/Profile/Nodes/NodePinCollectionEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/Nodes/NodePinCollectionEntity.cs @@ -2,6 +2,17 @@ public class NodePinCollectionEntity { + public NodePinCollectionEntity() + { + } + + public NodePinCollectionEntity(NodePinCollectionEntity nodePinCollectionEntity) + { + Id = nodePinCollectionEntity.Id; + Direction = nodePinCollectionEntity.Direction; + Amount = nodePinCollectionEntity.Amount; + } + public int Id { get; set; } public int Direction { set; get; } public int Amount { get; set; } diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs index c1f92dcc0..3d6033784 100644 --- a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs +++ b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Artemis.Core; namespace Artemis.UI.Shared.Services.NodeEditor.Commands; @@ -36,7 +37,8 @@ public class AddNode : INodeEditorCommand, IDisposable /// public void Execute() { - _nodeScript.AddNode(_node); + if (!_nodeScript.Nodes.Contains(_node)) + _nodeScript.AddNode(_node); _isRemoved = false; } diff --git a/src/Artemis.UI/Models/NodesClipboardModel.cs b/src/Artemis.UI/Models/NodesClipboardModel.cs new file mode 100644 index 000000000..842d5348d --- /dev/null +++ b/src/Artemis.UI/Models/NodesClipboardModel.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Artemis.Core; +using Artemis.Storage.Entities.Profile.Nodes; +using FluentAvalonia.Core; + +namespace Artemis.UI.Models; + +public class NodesClipboardModel +{ + public NodesClipboardModel(NodeScript nodeScript, List nodes) + { + nodeScript.Save(); + + // Grab all entities belonging to provided nodes + Nodes = nodeScript.Entity.Nodes.Where(e => nodes.Any(n => n.Id == e.Id)).ToList(); + // Grab all connections between provided nodes + Connections = nodeScript.Entity.Connections.Where(e => nodes.Any(n => n.Id == e.SourceNode) && nodes.Any(n => n.Id == e.TargetNode)).ToList(); + } + + public NodesClipboardModel() + { + Nodes = new List(); + Connections = new List(); + } + + public List Nodes { get; set; } + public List Connections { get; set; } + + public List Paste(NodeScript nodeScript, double x, double y) + { + if (!Nodes.Any()) + return new List(); + + nodeScript.Save(); + + // Copy the entities, not messing with the originals + List nodes = Nodes.Select(n => new NodeEntity(n)).ToList(); + List connections = Connections.Select(c => new NodeConnectionEntity(c)).ToList(); + + double xOffset = x - nodes.Min(n => n.X); + double yOffset = y - nodes.Min(n => n.Y); + + foreach (NodeEntity node in nodes) + { + // Give each node a new GUID, updating any connections to it + Guid newGuid = Guid.NewGuid(); + foreach (NodeConnectionEntity connection in connections) + { + if (connection.SourceNode == node.Id) + connection.SourceNode = newGuid; + else if (connection.TargetNode == node.Id) + connection.TargetNode = newGuid; + + // Only add the connection if this is the first time we hit it + if (!nodeScript.Entity.Connections.Contains(connection)) + nodeScript.Entity.Connections.Add(connection); + } + + node.Id = newGuid; + node.X += xOffset; + node.Y += yOffset; + nodeScript.Entity.Nodes.Add(node); + } + + nodeScript.Load(); + + // Return the newly created nodes + return nodeScript.Nodes.Where(n => nodes.Any(e => e.Id == n.Id)).ToList(); + } +} \ 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 c1c7610d9..e18230f6f 100644 --- a/src/Artemis.UI/Screens/VisualScripting/CableView.axaml +++ b/src/Artemis.UI/Screens/VisualScripting/CableView.axaml @@ -24,11 +24,6 @@ Stroke="{CompiledBinding CableColor, Converter={StaticResource ColorToSolidColorBrushConverter}}" StrokeThickness="4" StrokeLineCap="Round"> - - - - - @@ -47,8 +42,6 @@ BorderThickness="2" CornerRadius="3" Padding="4" - Canvas.Left="{CompiledBinding ValuePoint.X}" - Canvas.Top="{CompiledBinding ValuePoint.Y}" IsVisible="{CompiledBinding DisplayValue}"> diff --git a/src/Artemis.UI/Screens/VisualScripting/CableView.axaml.cs b/src/Artemis.UI/Screens/VisualScripting/CableView.axaml.cs index c4d032f88..1cd822bf3 100644 --- a/src/Artemis.UI/Screens/VisualScripting/CableView.axaml.cs +++ b/src/Artemis.UI/Screens/VisualScripting/CableView.axaml.cs @@ -8,6 +8,7 @@ using Avalonia.Input; using Avalonia.Markup.Xaml; using Avalonia.Media; using Avalonia.ReactiveUI; +using Avalonia.Rendering; using ReactiveUI; namespace Artemis.UI.Screens.VisualScripting; @@ -29,9 +30,9 @@ public class CableView : ReactiveUserControl { _valueBorder.GetObservable(BoundsProperty).Subscribe(rect => _valueBorder.RenderTransform = new TranslateTransform(rect.Width / 2 * -1, rect.Height / 2 * -1)).DisposeWith(d); - ViewModel.WhenAnyValue(vm => vm.FromPoint).Subscribe(_ => Update()).DisposeWith(d); - ViewModel.WhenAnyValue(vm => vm.ToPoint).Subscribe(_ => Update()).DisposeWith(d); - Update(); + ViewModel.WhenAnyValue(vm => vm.FromPoint).Subscribe(_ => Update(true)).DisposeWith(d); + ViewModel.WhenAnyValue(vm => vm.ToPoint).Subscribe(_ => Update(false)).DisposeWith(d); + Update(true); }); } @@ -40,10 +41,12 @@ public class CableView : ReactiveUserControl AvaloniaXamlLoader.Load(this); } - private void Update() + private void Update(bool from) { // Workaround for https://github.com/AvaloniaUI/Avalonia/issues/4748 - _cablePath.Margin = _cablePath.Margin != new Thickness(0, 0, 0, 0) ? new Thickness(0, 0, 0, 0) : new Thickness(1, 1, 0, 0); + _cablePath.Margin = new Thickness(_cablePath.Margin.Left + 1, _cablePath.Margin.Top + 1, 0, 0); + if (_cablePath.Margin.Left > 2) + _cablePath.Margin = new Thickness(0, 0, 0, 0); PathFigure pathFigure = ((PathGeometry) _cablePath.Data).Figures.First(); BezierSegment segment = (BezierSegment) pathFigure.Segments!.First(); @@ -51,6 +54,11 @@ public class CableView : ReactiveUserControl segment.Point1 = new Point(ViewModel.FromPoint.X + CABLE_OFFSET, ViewModel.FromPoint.Y); segment.Point2 = new Point(ViewModel.ToPoint.X - CABLE_OFFSET, ViewModel.ToPoint.Y); segment.Point3 = new Point(ViewModel.ToPoint.X, ViewModel.ToPoint.Y); + + Canvas.SetLeft(_valueBorder, ViewModel.FromPoint.X + (ViewModel.ToPoint.X - ViewModel.FromPoint.X) / 2); + Canvas.SetTop(_valueBorder, ViewModel.FromPoint.Y + (ViewModel.ToPoint.Y - ViewModel.FromPoint.Y) / 2); + + _cablePath.InvalidateVisual(); } private void OnPointerEnter(object? sender, PointerEventArgs e) diff --git a/src/Artemis.UI/Screens/VisualScripting/CableViewModel.cs b/src/Artemis.UI/Screens/VisualScripting/CableViewModel.cs index 6d5db773c..1d44adecc 100644 --- a/src/Artemis.UI/Screens/VisualScripting/CableViewModel.cs +++ b/src/Artemis.UI/Screens/VisualScripting/CableViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; using Artemis.Core; @@ -27,7 +28,6 @@ public class CableViewModel : ActivatableViewModelBase private PinViewModel? _fromViewModel; private ObservableAsPropertyHelper? _toPoint; private PinViewModel? _toViewModel; - private ObservableAsPropertyHelper? _valuePoint; public CableViewModel(NodeScriptViewModel nodeScriptViewModel, IPin from, IPin to, ISettingsService settingsService) { @@ -63,12 +63,7 @@ public class CableViewModel : ActivatableViewModelBase .Switch() .ToProperty(this, vm => vm.ToPoint) .DisposeWith(d); - _valuePoint = this.WhenAnyValue(vm => vm.FromPoint, vm => vm.ToPoint).Select(tuple => new Point( - tuple.Item1.X + (tuple.Item2.X - tuple.Item1.X) / 2, - tuple.Item1.Y + (tuple.Item2.Y - tuple.Item1.Y) / 2 - )).ToProperty(this, vm => vm.ValuePoint) - .DisposeWith(d); - + // 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) .Select(tuple => tuple.Item1 != new Point(0, 0) && tuple.Item2 != new Point(0, 0)) @@ -104,11 +99,10 @@ public class CableViewModel : ActivatableViewModelBase } public bool Connected => _connected?.Value ?? false; - public bool IsFirst => _from.ConnectedTo[0] == _to; + public bool IsFirst => _from.ConnectedTo.FirstOrDefault() == _to; public Point FromPoint => _fromPoint?.Value ?? new Point(); public Point ToPoint => _toPoint?.Value ?? new Point(); - public Point ValuePoint => _valuePoint?.Value ?? new Point(); public Color CableColor => _cableColor?.Value ?? new Color(255, 255, 255, 255); public void UpdateDisplayValue(bool hoveringOver) diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeScriptView.axaml b/src/Artemis.UI/Screens/VisualScripting/NodeScriptView.axaml index b442e5e6f..3a8c99638 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeScriptView.axaml +++ b/src/Artemis.UI/Screens/VisualScripting/NodeScriptView.axaml @@ -30,6 +30,8 @@ + + diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeScriptView.axaml.cs b/src/Artemis.UI/Screens/VisualScripting/NodeScriptView.axaml.cs index 682f61bc0..92728f4d3 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeScriptView.axaml.cs +++ b/src/Artemis.UI/Screens/VisualScripting/NodeScriptView.axaml.cs @@ -14,6 +14,7 @@ using Avalonia.Markup.Xaml; using Avalonia.Media; using Avalonia.ReactiveUI; using Avalonia.Threading; +using Avalonia.VisualTree; using DynamicData.Binding; using ReactiveUI; @@ -39,6 +40,8 @@ public class NodeScriptView : ReactiveUserControl _zoomBorder.AddHandler(PointerReleasedEvent, CanvasOnPointerReleased, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true); _zoomBorder.AddHandler(PointerWheelChangedEvent, ZoomOnPointerWheelChanged, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true); + _zoomBorder.AddHandler(PointerMovedEvent, ZoomOnPointerMoved, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true); + this.WhenActivated(d => { ViewModel!.AutoFitRequested += ViewModelOnAutoFitRequested; @@ -67,6 +70,12 @@ public class NodeScriptView : ReactiveUserControl e.Handled = true; } + private void ZoomOnPointerMoved(object? sender, PointerEventArgs e) + { + if (ViewModel != null) + ViewModel.PastePosition = e.GetPosition(_grid); + } + private void ShowPickerAt(Point point) { if (ViewModel == null) diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeScriptViewModel.cs b/src/Artemis.UI/Screens/VisualScripting/NodeScriptViewModel.cs index 8c0adc5b9..00ab99900 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeScriptViewModel.cs +++ b/src/Artemis.UI/Screens/VisualScripting/NodeScriptViewModel.cs @@ -6,9 +6,12 @@ using System.Linq; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; +using System.Text; +using System.Threading.Tasks; using Artemis.Core; using Artemis.Core.Events; using Artemis.Core.Services; +using Artemis.UI.Models; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.VisualScripting.Pins; using Artemis.UI.Shared; @@ -16,6 +19,7 @@ using Artemis.UI.Shared.Services.NodeEditor; using Artemis.UI.Shared.Services.NodeEditor.Commands; using Avalonia; using Avalonia.Controls.Mixins; +using Avalonia.Input; using DynamicData; using DynamicData.Binding; using ReactiveUI; @@ -24,6 +28,8 @@ namespace Artemis.UI.Screens.VisualScripting; public class NodeScriptViewModel : ActivatableViewModelBase { + public const string CLIPBOARD_DATA_FORMAT = "Artemis.Nodes"; + private readonly INodeEditorService _nodeEditorService; private readonly INodeService _nodeService; private readonly SourceList _nodeViewModels; @@ -33,6 +39,7 @@ public class NodeScriptViewModel : ActivatableViewModelBase private DragCableViewModel? _dragViewModel; private List? _initialNodeSelection; private Matrix _panMatrix; + private Point _pastePosition; public NodeScriptViewModel(NodeScript nodeScript, bool isPreview, INodeVmFactory nodeVmFactory, INodeService nodeService, INodeEditorService nodeEditorService) { @@ -86,8 +93,8 @@ public class NodeScriptViewModel : ActivatableViewModelBase ClearSelection = ReactiveCommand.Create(ExecuteClearSelection); DeleteSelected = ReactiveCommand.Create(ExecuteDeleteSelected); DuplicateSelected = ReactiveCommand.Create(ExecuteDuplicateSelected); - CopySelected = ReactiveCommand.Create(ExecuteCopySelected); - PasteSelected = ReactiveCommand.Create(ExecutePasteSelected); + CopySelected = ReactiveCommand.CreateFromTask(ExecuteCopySelected); + PasteSelected = ReactiveCommand.CreateFromTask(ExecutePasteSelected); } public NodeScript NodeScript { get; } @@ -118,6 +125,12 @@ public class NodeScriptViewModel : ActivatableViewModelBase set => RaiseAndSetIfChanged(ref _panMatrix, value); } + public Point PastePosition + { + get => _pastePosition; + set => RaiseAndSetIfChanged(ref _pastePosition, value); + } + public void DeleteSelectedNodes() { List toRemove = NodeViewModels.Where(vm => vm.IsSelected && !vm.Node.IsDefaultNode && !vm.Node.IsExitNode).ToList(); @@ -279,11 +292,39 @@ public class NodeScriptViewModel : ActivatableViewModelBase } } - private void ExecuteCopySelected() + private async Task ExecuteCopySelected() { + if (Application.Current?.Clipboard == null) + return; + + List nodes = NodeViewModels.Where(vm => vm.IsSelected).Select(vm => vm.Node).Where(n => !n.IsDefaultNode && !n.IsExitNode).ToList(); + DataObject dataObject = new(); + string copy = CoreJson.SerializeObject(new NodesClipboardModel(NodeScript, nodes), true); + dataObject.Set(CLIPBOARD_DATA_FORMAT, copy); + await Application.Current.Clipboard.SetDataObjectAsync(dataObject); } - private void ExecutePasteSelected() + private async Task ExecutePasteSelected() { + if (Application.Current?.Clipboard == null) + return; + + byte[]? bytes = (byte[]?) await Application.Current.Clipboard.GetDataAsync(CLIPBOARD_DATA_FORMAT); + if (bytes == null!) + return; + + NodesClipboardModel? nodesClipboardModel = CoreJson.DeserializeObject(Encoding.Unicode.GetString(bytes), true); + if (nodesClipboardModel == null) + return; + + List nodes = nodesClipboardModel.Paste(NodeScript, PastePosition.X, PastePosition.Y); + + using NodeEditorCommandScope scope = _nodeEditorService.CreateCommandScope(NodeScript, "Paste nodes"); + foreach (INode node in nodes) + _nodeEditorService.ExecuteCommand(NodeScript, new AddNode(NodeScript, node)); + + // Select only the new nodes + foreach (NodeViewModel nodeViewModel in NodeViewModels) + nodeViewModel.IsSelected = nodes.Contains(nodeViewModel.Node); } } \ No newline at end of file