1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Nodes - Added categories

Nodes - Added quick node creation
Nodes - Added input and output types to NodeAttribute
This commit is contained in:
Robert 2021-08-26 22:09:04 +02:00
parent 73794591bc
commit c4340c3c97
29 changed files with 389 additions and 82 deletions

View File

@ -54,7 +54,7 @@ namespace Artemis.Core.Services
string description = nodeAttribute?.Description ?? string.Empty;
string category = nodeAttribute?.Category ?? string.Empty;
NodeData nodeData = new(plugin, nodeType, name, description, category, (s, e) => CreateNode(s, e, nodeType));
NodeData nodeData = new(plugin, nodeType, name, description, category, nodeAttribute?.InputType, nodeAttribute?.OutputType, (s, e) => CreateNode(s, e, nodeType));
return NodeTypeStore.Add(nodeData);
}

View File

@ -9,6 +9,8 @@ namespace Artemis.Core
public string Name { get; }
public string Description { get; set; }
public string Category { get; set; }
public Type InputType { get; set; }
public Type OutputType { get; set; }
#endregion

View File

@ -13,6 +13,8 @@ namespace Artemis.Core
public string Name { get; }
public string Description { get; }
public string Category { get; }
public Type? InputType { get; }
public Type? OutputType { get; }
private Func<INodeScript, NodeEntity?, INode> _create;
@ -20,13 +22,15 @@ namespace Artemis.Core
#region Constructors
internal NodeData(Plugin plugin, Type type, string name, string description, string category, Func<INodeScript, NodeEntity?, INode>? create)
internal NodeData(Plugin plugin, Type type, string name, string description, string category, Type? inputType, Type? outputType, Func<INodeScript, NodeEntity?, INode>? create)
{
this.Plugin = plugin;
this.Type = type;
this.Name = name;
this.Description = description;
this.Category = category;
this.InputType = inputType;
this.OutputType = outputType;
this._create = create;
}

View File

@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
namespace Artemis.VisualScripting.Behaviors
{
// Source: https://stackoverflow.com/a/60474831/5015269
// Made some changes to add a foreground and background property
public static class HighlightTermBehavior
{
public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
"Text",
typeof(string),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata("", OnTextChanged));
public static readonly DependencyProperty TermToBeHighlightedProperty = DependencyProperty.RegisterAttached(
"TermToBeHighlighted",
typeof(string),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata("", OnTextChanged));
public static readonly DependencyProperty HighlightForegroundProperty = DependencyProperty.RegisterAttached(
"HighlightForeground",
typeof(Color?),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata(null, OnTextChanged));
public static readonly DependencyProperty HighlightBackgroundProperty = DependencyProperty.RegisterAttached(
"HighlightBackground",
typeof(Color?),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata(null, OnTextChanged));
public static string GetText(FrameworkElement frameworkElement)
{
return (string) frameworkElement.GetValue(TextProperty);
}
public static void SetText(FrameworkElement frameworkElement, string value)
{
frameworkElement.SetValue(TextProperty, value);
}
public static string GetTermToBeHighlighted(FrameworkElement frameworkElement)
{
return (string) frameworkElement.GetValue(TermToBeHighlightedProperty);
}
public static void SetTermToBeHighlighted(FrameworkElement frameworkElement, string value)
{
frameworkElement.SetValue(TermToBeHighlightedProperty, value);
}
public static void SetHighlightForeground(FrameworkElement frameworkElement, Color? value)
{
frameworkElement.SetValue(HighlightForegroundProperty, value);
}
public static Color? GetHighlightForeground(FrameworkElement frameworkElement)
{
return (Color?) frameworkElement.GetValue(HighlightForegroundProperty);
}
public static void SetHighlightBackground(FrameworkElement frameworkElement, Color? value)
{
frameworkElement.SetValue(HighlightBackgroundProperty, value);
}
public static Color? GetHighlightBackground(FrameworkElement frameworkElement)
{
return (Color?) frameworkElement.GetValue(HighlightBackgroundProperty);
}
public static List<string> SplitTextIntoTermAndNotTermParts(string text, string term)
{
if (string.IsNullOrEmpty(text))
return new List<string> {string.Empty};
return Regex.Split(text, $@"({Regex.Escape(term)})", RegexOptions.IgnoreCase)
.Where(p => p != string.Empty)
.ToList();
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBlock textBlock)
SetTextBlockTextAndHighlightTerm(textBlock, GetText(textBlock), GetTermToBeHighlighted(textBlock));
}
private static void SetTextBlockTextAndHighlightTerm(TextBlock textBlock, string text, string termToBeHighlighted)
{
textBlock.Text = string.Empty;
if (TextIsEmpty(text))
return;
if (TextIsNotContainingTermToBeHighlighted(text, termToBeHighlighted))
{
AddPartToTextBlock(textBlock, text);
return;
}
List<string> textParts = SplitTextIntoTermAndNotTermParts(text, termToBeHighlighted);
foreach (string textPart in textParts)
AddPartToTextBlockAndHighlightIfNecessary(textBlock, termToBeHighlighted, textPart);
}
private static bool TextIsEmpty(string text)
{
return string.IsNullOrEmpty(text);
}
private static bool TextIsNotContainingTermToBeHighlighted(string text, string termToBeHighlighted)
{
if (text == null || termToBeHighlighted == null)
return true;
return text.Contains(termToBeHighlighted, StringComparison.OrdinalIgnoreCase) == false;
}
private static void AddPartToTextBlockAndHighlightIfNecessary(TextBlock textBlock, string termToBeHighlighted, string textPart)
{
if (textPart.Equals(termToBeHighlighted, StringComparison.OrdinalIgnoreCase))
AddHighlightedPartToTextBlock(textBlock, textPart);
else
AddPartToTextBlock(textBlock, textPart);
}
private static void AddPartToTextBlock(TextBlock textBlock, string part)
{
textBlock.Inlines.Add(new Run {Text = part});
}
private static void AddHighlightedPartToTextBlock(TextBlock textBlock, string part)
{
Color? foreground = GetHighlightForeground(textBlock);
Color? background = GetHighlightBackground(textBlock);
if (background == null)
{
Run run = new() {Text = part, FontWeight = FontWeights.ExtraBold};
if (foreground != null)
run.Foreground = new SolidColorBrush(foreground.Value);
textBlock.Inlines.Add(run);
return;
}
Border border = new()
{
Background = new SolidColorBrush(background.Value),
BorderThickness = new Thickness(0),
CornerRadius = new CornerRadius(2),
Child = new TextBlock {Text = part, FontWeight = FontWeights.Bold},
Padding = new Thickness(1),
Margin = new Thickness(-1, -5, -1, -5)
};
if (foreground != null)
((TextBlock) border.Child).Foreground = new SolidColorBrush(foreground.Value);
textBlock.Inlines.Add(border);
}
}
}

View File

@ -6,6 +6,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using Artemis.Core;
using Artemis.VisualScripting.Editor.Controls.Wrapper;
namespace Artemis.VisualScripting.Editor.Controls
{
@ -37,16 +38,26 @@ namespace Artemis.VisualScripting.Editor.Controls
public IEnumerable AvailableNodes
{
get => (IEnumerable)GetValue(AvailableNodesProperty);
get => (IEnumerable) GetValue(AvailableNodesProperty);
set => SetValue(AvailableNodesProperty, value);
}
public static readonly DependencyProperty SourcePinProperty = DependencyProperty.Register(
"SourcePin", typeof(VisualScriptPin), typeof(VisualScriptNodeCreationBox), new PropertyMetadata(default(VisualScriptPin), OnSourcePinChanged));
public VisualScriptPin SourcePin
{
get => (VisualScriptPin) GetValue(SourcePinProperty);
set => SetValue(SourcePinProperty, value);
}
public static readonly DependencyProperty CreateNodeCommandProperty = DependencyProperty.Register(
"CreateNodeCommand", typeof(ICommand), typeof(VisualScriptNodeCreationBox), new PropertyMetadata(default(ICommand)));
public ICommand CreateNodeCommand
{
get => (ICommand)GetValue(CreateNodeCommandProperty);
get => (ICommand) GetValue(CreateNodeCommandProperty);
set => SetValue(CreateNodeCommandProperty, value);
}
@ -63,12 +74,23 @@ namespace Artemis.VisualScripting.Editor.Controls
_contentList.IsSynchronizedWithCurrentItem = false;
_contentList.SelectionChanged += OnContentListSelectionChanged;
_contentList.SelectionMode = SelectionMode.Single;
IsVisibleChanged += OnIsVisibleChanged;
_searchBox.Focus();
_contentView?.Refresh();
ItemsSourceChanged();
}
private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is not true)
return;
_searchBox.Focus();
_searchBox.SelectionStart = 0;
_searchBox.SelectionLength = _searchBox.Text.Length;
}
private void OnSearchBoxTextChanged(object sender, TextChangedEventArgs args)
{
_contentView?.Refresh();
@ -86,7 +108,14 @@ namespace Artemis.VisualScripting.Editor.Controls
if (_searchBox == null) return false;
if (o is not NodeData nodeData) return false;
return nodeData.Name.Contains(_searchBox.Text, StringComparison.OrdinalIgnoreCase);
bool nameContains = nodeData.Name.Contains(_searchBox.Text, StringComparison.OrdinalIgnoreCase);
if (SourcePin == null || SourcePin.Pin.Type == typeof(object))
return nameContains;
if (SourcePin.Pin.Direction == PinDirection.Input)
return nameContains && (nodeData.OutputType == typeof(object) || nodeData.OutputType == SourcePin.Pin.Type);
return nameContains && (nodeData.InputType == typeof(object) || nodeData.InputType == SourcePin.Pin.Type);
}
private void ItemsSourceChanged()
@ -100,7 +129,16 @@ namespace Artemis.VisualScripting.Editor.Controls
}
else
{
_collectionViewSource = new CollectionViewSource { Source = AvailableNodes, SortDescriptions = { new SortDescription("Name", ListSortDirection.Ascending)}};
_collectionViewSource = new CollectionViewSource
{
Source = AvailableNodes,
SortDescriptions =
{
new SortDescription(nameof(NodeData.Category), ListSortDirection.Ascending),
new SortDescription(nameof(NodeData.Name), ListSortDirection.Ascending)
},
GroupDescriptions = {new PropertyGroupDescription(nameof(NodeData.Category))}
};
_contentView = _collectionViewSource.View;
_contentView.Filter += Filter;
}
@ -110,6 +148,8 @@ namespace Artemis.VisualScripting.Editor.Controls
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) => (d as VisualScriptNodeCreationBox)?.ItemsSourceChanged();
private static void OnSourcePinChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as VisualScriptNodeCreationBox)?._contentView.Refresh();
#endregion
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
@ -65,7 +66,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public INodeScript Script
{
get => (INodeScript)GetValue(ScriptProperty);
get => (INodeScript) GetValue(ScriptProperty);
set => SetValue(ScriptProperty, value);
}
@ -74,7 +75,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public double Scale
{
get => (double)GetValue(ScaleProperty);
get => (double) GetValue(ScaleProperty);
set => SetValue(ScaleProperty, value);
}
@ -83,7 +84,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public double MinScale
{
get => (double)GetValue(MinScaleProperty);
get => (double) GetValue(MinScaleProperty);
set => SetValue(MinScaleProperty, value);
}
@ -92,7 +93,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public double MaxScale
{
get => (double)GetValue(MaxScaleProperty);
get => (double) GetValue(MaxScaleProperty);
set => SetValue(MaxScaleProperty, value);
}
@ -101,7 +102,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public double ScaleFactor
{
get => (double)GetValue(ScaleFactorProperty);
get => (double) GetValue(ScaleFactorProperty);
set => SetValue(ScaleFactorProperty, value);
}
@ -110,7 +111,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public IEnumerable<NodeData> AvailableNodes
{
get => (IEnumerable<NodeData>)GetValue(AvailableNodesProperty);
get => (IEnumerable<NodeData>) GetValue(AvailableNodesProperty);
set => SetValue(AvailableNodesProperty, value);
}
@ -119,16 +120,25 @@ namespace Artemis.VisualScripting.Editor.Controls
public bool AlwaysShowValues
{
get => (bool)GetValue(AlwaysShowValuesProperty);
get => (bool) GetValue(AlwaysShowValuesProperty);
set => SetValue(AlwaysShowValuesProperty, value);
}
public static readonly DependencyProperty SourcePinProperty = DependencyProperty.Register(
"SourcePin", typeof(VisualScriptPin), typeof(VisualScriptPresenter), new PropertyMetadata(default(VisualScriptPin)));
public VisualScriptPin SourcePin
{
get => (VisualScriptPin) GetValue(SourcePinProperty);
set => SetValue(SourcePinProperty, value);
}
public static readonly DependencyProperty CreateNodeCommandProperty = DependencyProperty.Register(
"CreateNodeCommand", typeof(ICommand), typeof(VisualScriptPresenter), new PropertyMetadata(default(ICommand)));
public ICommand CreateNodeCommand
{
get => (ICommand)GetValue(CreateNodeCommandProperty);
get => (ICommand) GetValue(CreateNodeCommandProperty);
private set => SetValue(CreateNodeCommandProperty, value);
}
@ -137,7 +147,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public int GridSize
{
get => (int)GetValue(GridSizeProperty);
get => (int) GetValue(GridSizeProperty);
set => SetValue(GridSizeProperty, value);
}
@ -146,7 +156,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public int SurfaceSize
{
get => (int)GetValue(SurfaceSizeProperty);
get => (int) GetValue(SurfaceSizeProperty);
set => SetValue(SurfaceSizeProperty, value);
}
@ -155,7 +165,7 @@ namespace Artemis.VisualScripting.Editor.Controls
public bool AutoFitScript
{
get => (bool)GetValue(AutoFitScriptProperty);
get => (bool) GetValue(AutoFitScriptProperty);
set => SetValue(AutoFitScriptProperty, value);
}
@ -194,7 +204,7 @@ namespace Artemis.VisualScripting.Editor.Controls
_canvas.MouseMove += OnCanvasMouseMove;
_canvas.MouseWheel += OnCanvasMouseWheel;
_canvas.DragOver += OnCanvasDragOver;
_canvas.Drop += OnCanvasDrop;
_nodeList.ItemsSource = VisualScript?.Nodes;
_cableList.ItemsSource = VisualScript?.Cables;
}
@ -387,6 +397,34 @@ namespace Artemis.VisualScripting.Editor.Controls
VisualScript.OnDragOver(args.GetPosition(_canvas));
}
private void OnCanvasDrop(object sender, DragEventArgs args)
{
if (!args.Data.GetDataPresent(typeof(VisualScriptPin))) return;
VisualScriptPin sourcePin = (VisualScriptPin) args.Data.GetData(typeof(VisualScriptPin));
if (sourcePin == null) return;
if (_creationBoxParent.ContextMenu != null)
{
SourcePin = sourcePin;
_lastRightClickLocation = args.GetPosition(_canvas);
_creationBoxParent.ContextMenu.IsOpen = true;
_creationBoxParent.ContextMenu.DataContext = this;
void ContextMenuOnClosed(object s, RoutedEventArgs e)
{
SourcePin = null;
if (_creationBoxParent.ContextMenu != null)
_creationBoxParent.ContextMenu.Closed -= ContextMenuOnClosed;
}
_creationBoxParent.ContextMenu.Closed += ContextMenuOnClosed;
}
args.Handled = true;
}
private void OnCanvasMouseWheel(object sender, MouseWheelEventArgs args)
{
if (AutoFitScript)
@ -415,8 +453,8 @@ namespace Artemis.VisualScripting.Editor.Controls
for (int i = 0; i < _nodeList.Items.Count; i++)
{
ContentPresenter nodeControl = (ContentPresenter)_nodeList.ItemContainerGenerator.ContainerFromIndex(i);
VisualScriptNode node = (VisualScriptNode)nodeControl.Content;
ContentPresenter nodeControl = (ContentPresenter) _nodeList.ItemContainerGenerator.ContainerFromIndex(i);
VisualScriptNode node = (VisualScriptNode) nodeControl.Content;
double nodeWidth = nodeControl.ActualWidth;
double nodeHeight = nodeControl.ActualHeight;
@ -492,14 +530,32 @@ namespace Artemis.VisualScripting.Editor.Controls
{
if (nodeData == null) return;
if (_creationBoxParent.ContextMenu != null)
_creationBoxParent.ContextMenu.IsOpen = false;
INode node = nodeData.CreateNode(Script, null);
node.Initialize(Script);
node.X = _lastRightClickLocation.X - VisualScript.LocationOffset;
node.Y = _lastRightClickLocation.Y - VisualScript.LocationOffset;
if (SourcePin != null)
{
// Connect to the first matching input or output pin
List<IPin> pins = node.Pins.ToList();
pins.AddRange(node.PinCollections.SelectMany(c => c));
pins = pins.Where(p => p.Type == typeof(object) || p.Type == SourcePin.Pin.Type).OrderBy(p => p.Type != typeof(object)).ToList();
IPin preferredPin = SourcePin.Pin.Direction == PinDirection.Input
? pins.FirstOrDefault(p => p.Direction == PinDirection.Output)
: pins.FirstOrDefault(p => p.Direction == PinDirection.Input);
if (preferredPin != null)
{
preferredPin.ConnectTo(SourcePin.Pin);
SourcePin.Pin.ConnectTo(preferredPin);
}
}
if (_creationBoxParent.ContextMenu != null)
_creationBoxParent.ContextMenu.IsOpen = false;
Script.AddNode(node);
}
@ -549,6 +605,7 @@ namespace Artemis.VisualScripting.Editor.Controls
T result = (child as T) ?? GetChildOfType<T>(child);
if (result != null) return result;
}
return null;
}

View File

@ -1,11 +1,18 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Artemis.VisualScripting.Editor.Controls"
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core">
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
xmlns:behaviors="clr-namespace:Artemis.VisualScripting.Behaviors">
<DataTemplate x:Key="TemplateNodeItem"
DataType="{x:Type core:NodeData}">
<TextBlock Text="{Binding Name}" />
<TextBlock Margin="8 0 0 0"
Text="{Binding Name}"
ToolTip="{Binding Description}"
behaviors:HighlightTermBehavior.TermToBeHighlighted="{Binding Text, ElementName=PART_SearchBox}"
behaviors:HighlightTermBehavior.Text="{Binding Name}"
behaviors:HighlightTermBehavior.HighlightForeground="{StaticResource Primary600Foreground}"
behaviors:HighlightTermBehavior.HighlightBackground="{StaticResource Primary600}"/>
</DataTemplate>
<ControlTemplate x:Key="TemplateVisualScriptNodeCreationBox"
@ -15,7 +22,7 @@
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
@ -34,7 +41,37 @@
Background="Transparent"
Foreground="#FFFFFFFF"
BorderThickness="0"
ItemTemplate="{StaticResource TemplateNodeItem}" />
ItemTemplate="{StaticResource TemplateNodeItem}">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander Header="{Binding Name}" IsExpanded="True">
<Expander.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" FontWeight="Bold" FontSize="16" Margin="0 8 8 8" />
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="Foreground" Value="AliceBlue"></Setter>
</Style>
</Expander.Style>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
</ListBox>
</Grid>
</Border>
</ControlTemplate>

View File

@ -15,6 +15,7 @@
<ControlTemplate>
<Border Width="700" Height="300">
<controls:VisualScriptNodeCreationBox AvailableNodes="{Binding AvailableNodes}"
SourcePin="{Binding SourcePin}"
CreateNodeCommand="{Binding CreateNodeCommand}" />
</Border>
</ControlTemplate>

View File

@ -3,7 +3,7 @@ using Artemis.Core;
namespace Artemis.VisualScripting.Nodes
{
[Node("Greater than", "Checks if the first input is greater than the second.")]
[Node("Greater than", "Checks if the first input is greater than the second.", "Operators", InputType = typeof(object), OutputType = typeof(bool))]
public class GreaterThanNode : Node
{
#region Properties & Fields
@ -44,7 +44,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("Less than", "Checks if the first input is less than the second.")]
[Node("Less than", "Checks if the first input is less than the second.", "Operators", InputType = typeof(object), OutputType = typeof(bool))]
public class LessThanNode : Node
{
#region Properties & Fields
@ -85,7 +85,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("Equals", "Checks if the two inputs are equals.")]
[Node("Equals", "Checks if the two inputs are equals.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
public class EqualsNode : Node
{
#region Properties & Fields
@ -126,7 +126,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("Negate", "Negates the boolean.")]
[Node("Negate", "Negates the boolean.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
public class NegateNode : Node
{
#region Properties & Fields

View File

@ -3,7 +3,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Brighten Color", "Brightens a color by a specified amount in percent")]
[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")
@ -20,7 +20,7 @@ namespace Artemis.VisualScripting.Nodes.Color
public override void Evaluate()
{
Input.Value.ToHsl(out float h, out float s, out float l);
l *= (Percentage.Value + 100f) / 100f;
l += l * (Percentage.Value / 100f);
Output.Value = SKColor.FromHsl(h, s, l);
}
}

View File

@ -3,7 +3,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Darken Color", "Darkens a color by a specified amount in percent")]
[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")
@ -20,7 +20,7 @@ namespace Artemis.VisualScripting.Nodes.Color
public override void Evaluate()
{
Input.Value.ToHsl(out float h, out float s, out float l);
l *= (Percentage.Value * -1 + 100f) / 100f;
l -= l * (Percentage.Value / 100f);
Output.Value = SKColor.FromHsl(h, s, l);
}
}

View File

@ -4,7 +4,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Desaturate Color", "Desaturates a color by a specified amount in percent")]
[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")
@ -21,9 +21,8 @@ namespace Artemis.VisualScripting.Nodes.Color
public override void Evaluate()
{
Input.Value.ToHsl(out float h, out float s, out float l);
s -= Percentage.Value;
s = Math.Clamp(s, 0, 100);
Output.Value = SKColor.FromHsl(h, s, l);
s -= s * (Percentage.Value / 100f);
Output.Value = SKColor.FromHsl(h, Math.Clamp(s, 0f, 100f), l);
}
}
}

View File

@ -3,7 +3,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("HSL Color", "Creates a color from hue, saturation and lightness values")]
[Node("HSL Color", "Creates a color from hue, saturation and lightness values", "Color", InputType = typeof(float), OutputType = typeof(SKColor))]
public class HslSKColorNode : Node
{
public HslSKColorNode() : base("HSL Color", "Creates a color from hue, saturation and lightness values")

View File

@ -3,7 +3,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Invert Color", "Inverts a color by a specified amount in percent")]
[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")
@ -17,9 +17,12 @@ namespace Artemis.VisualScripting.Nodes.Color
public override void Evaluate()
{
Input.Value.ToHsl(out float h, out float s, out float l);
h += 180;
Output.Value = SKColor.FromHsl(h % 360, s, l);
Output.Value = new SKColor(
(byte) (255 - Input.Value.Red),
(byte) (255 - Input.Value.Green),
(byte) (255 - Input.Value.Blue),
Input.Value.Alpha
);
}
}
}

View File

@ -3,7 +3,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Rotate Color Hue", "Rotates the hue of a color by a specified amount in degrees")]
[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")

View File

@ -4,7 +4,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Saturate Color", "Saturates a color by a specified amount in percent")]
[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")
@ -21,9 +21,8 @@ namespace Artemis.VisualScripting.Nodes.Color
public override void Evaluate()
{
Input.Value.ToHsl(out float h, out float s, out float l);
s += Percentage.Value;
s = Math.Clamp(s, 0, 100);
Output.Value = SKColor.FromHsl(h, s, l);
s += s * (Percentage.Value / 100f);
Output.Value = SKColor.FromHsl(h, Math.Clamp(s, 0f, 100f), l);
}
}
}

View File

@ -4,7 +4,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Color-Value", "Outputs a configurable color value.")]
[Node("Color-Value", "Outputs a configurable color value.", "Static", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
public class StaticSKColorValueNode : Node<StaticSKColorValueNodeCustomViewModel>
{
#region Constructors

View File

@ -3,7 +3,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Sum (Color)", "Sums the connected color values.")]
[Node("Sum (Color)", "Sums the connected color values.", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
public class SumSKColorsNode : Node
{
#region Properties & Fields

View File

@ -2,7 +2,7 @@
namespace Artemis.VisualScripting.Nodes
{
[Node("To String", "Converts the input to a string.")]
[Node("To String", "Converts the input to a string.", "Conversion", InputType = typeof(object), OutputType = typeof(string))]
public class ConvertToStringNode : Node
{
#region Properties & Fields
@ -34,7 +34,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("To Integer", "Converts the input to an integer.")]
[Node("To Integer", "Converts the input to an integer.", "Conversion", InputType = typeof(object), OutputType = typeof(int))]
public class ConvertToIntegerNode : Node
{
#region Properties & Fields
@ -80,7 +80,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("To Double", "Converts the input to a double.")]
[Node("To Double", "Converts the input to a double.", "Conversion", InputType = typeof(object), OutputType = typeof(double))]
public class ConvertToDoubleNode : Node
{
#region Properties & Fields
@ -126,7 +126,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("To Float", "Converts the input to a float.")]
[Node("To Float", "Converts the input to a float.", "Conversion", InputType = typeof(object), OutputType = typeof(float))]
public class ConvertToFloatNode : Node
{
#region Properties & Fields

View File

@ -7,7 +7,7 @@ using Stylet;
namespace Artemis.VisualScripting.Nodes
{
[Node("Data Model-Value", "Outputs a selectable data model value.")]
[Node("Data Model-Value", "Outputs a selectable data model value.", "External")]
public class DataModelNode : Node<DataModelNodeCustomViewModel>, IDisposable
{
private DataModelPath _dataModelPath;

View File

@ -3,7 +3,7 @@ using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Double Easing", "Outputs an eased double value")]
[Node("Double Easing", "Outputs an eased double value", "Easing", InputType = typeof(double), OutputType = typeof(double))]
public class DoubleEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;

View File

@ -3,7 +3,7 @@ using Artemis.VisualScripting.Nodes.Easing.CustomViewModels;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Easing Type", "Outputs a selectable easing type.")]
[Node("Easing Type", "Outputs a selectable easing type.", "Easing", OutputType = typeof(Easings.Functions))]
public class EasingTypeNode : Node<EasingTypeNodeCustomViewModel>
{
public EasingTypeNode() : base("Easing Type", "Outputs a selectable easing type.")

View File

@ -3,7 +3,7 @@ using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Float Easing", "Outputs an eased float value")]
[Node("Float Easing", "Outputs an eased float value", "Easing", InputType = typeof(float), OutputType = typeof(float))]
public class FloatEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;

View File

@ -3,7 +3,7 @@ using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Integer Easing", "Outputs an eased integer value")]
[Node("Integer Easing", "Outputs an eased integer value", "Easing", InputType = typeof(int), OutputType = typeof(int))]
public class IntEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;

View File

@ -4,7 +4,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Color Easing", "Outputs an eased color value")]
[Node("Color Easing", "Outputs an eased color value", "Easing", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
public class SKColorEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;

View File

@ -6,7 +6,7 @@ using Artemis.VisualScripting.Nodes.CustomViewModels;
namespace Artemis.VisualScripting.Nodes
{
[Node("Layer/Folder Property", "Outputs the property of a selected layer or folder")]
[Node("Layer/Folder Property", "Outputs the property of a selected layer or folder", "External")]
public class LayerPropertyNode : Node<LayerPropertyNodeCustomViewModel>
{
private readonly object _layerPropertyLock = new();

View File

@ -3,7 +3,7 @@ using Artemis.VisualScripting.Nodes.CustomViewModels;
namespace Artemis.VisualScripting.Nodes
{
[Node("Integer-Value", "Outputs an configurable integer value.")]
[Node("Integer-Value", "Outputs an configurable integer value.", "Static", OutputType = typeof(int))]
public class StaticIntegerValueNode : Node<StaticIntegerValueNodeCustomViewModel>
{
#region Properties & Fields
@ -34,7 +34,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("Double-Value", "Outputs a configurable double value.")]
[Node("Double-Value", "Outputs a configurable double value.", "Static", OutputType = typeof(double))]
public class StaticDoubleValueNode : Node<StaticDoubleValueNodeCustomViewModel>
{
#region Properties & Fields
@ -65,7 +65,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("Float-Value", "Outputs a configurable float value.")]
[Node("Float-Value", "Outputs a configurable float value.", "Static", OutputType = typeof(float))]
public class StaticFloatValueNode : Node<StaticFloatValueNodeCustomViewModel>
{
#region Properties & Fields
@ -99,7 +99,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("String-Value", "Outputs a configurable string value.")]
[Node("String-Value", "Outputs a configurable string value.", "Static", OutputType = typeof(string))]
public class StaticStringValueNode : Node<StaticStringValueNodeCustomViewModel>
{
#region Properties & Fields
@ -127,8 +127,4 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
#region CustomViewModels
#endregion
}

View File

@ -3,7 +3,7 @@ using Artemis.Core;
namespace Artemis.VisualScripting.Nodes
{
[Node("Format", "Formats the input string.")]
[Node("Format", "Formats the input string.", "Text", InputType = typeof(object), OutputType = typeof(string))]
public class StringFormatNode : Node
{
#region Properties & Fields

View File

@ -3,7 +3,7 @@ using Artemis.Core;
namespace Artemis.VisualScripting.Nodes
{
[Node("Sum (Integer)", "Sums the connected integer values.")]
[Node("Sum (Integer)", "Sums the connected integer values.", "Mathematics", InputType = typeof(int), OutputType = typeof(int))]
public class SumIntegersNode : Node
{
#region Properties & Fields
@ -35,7 +35,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("Sum (Float)", "Sums the connected float values.")]
[Node("Sum (Float)", "Sums the connected float values.", "Mathematics", InputType = typeof(float), OutputType = typeof(float))]
public class SumFloatsNode : Node
{
#region Properties & Fields
@ -67,7 +67,7 @@ namespace Artemis.VisualScripting.Nodes
#endregion
}
[Node("Sum (Double)", "Sums the connected double values.")]
[Node("Sum (Double)", "Sums the connected double values.", "Mathematics", InputType = typeof(double), OutputType = typeof(double))]
public class SumDoublesNode : Node
{
#region Properties & Fields