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

Nodes - Added color nodes

This commit is contained in:
Robert 2021-08-22 22:31:47 +02:00
parent 0bb93f2ebd
commit 9d6a61f1e5
20 changed files with 420 additions and 34 deletions

View File

@ -22,6 +22,11 @@ namespace Artemis.Core
/// </summary>
LayerPropertyGroup LayerPropertyGroup { get; }
/// <summary>
/// Gets or sets whether the property is hidden in the UI
/// </summary>
public bool IsHidden { get; set; }
/// <summary>
/// Gets the data binding of this property
/// </summary>

View File

@ -105,9 +105,7 @@ namespace Artemis.Core
private bool _isHidden;
/// <summary>
/// Gets or sets whether the property is hidden in the UI
/// </summary>
/// <inheritdoc />
public bool IsHidden
{
get => _isHidden;

View File

@ -178,9 +178,13 @@ namespace Artemis.Core
Entity.Description = Description;
Entity.Nodes.Clear();
// No need to save the exit node if that's all there is
if (Nodes.Count() == 1)
return;
int id = 0;
Dictionary<INode, int> nodes = new();
foreach (INode node in Nodes)
{
NodeEntity nodeEntity = new()
@ -208,7 +212,6 @@ namespace Artemis.Core
}
Entity.Nodes.Add(nodeEntity);
nodes.Add(node, id);
id++;
}
@ -216,20 +219,21 @@ namespace Artemis.Core
Entity.Connections.Clear();
foreach (INode node in Nodes)
{
SavePins(nodes, node, -1, node.Pins);
SavePins(node, -1, node.Pins);
int pinCollectionId = 0;
foreach (IPinCollection pinCollection in node.PinCollections)
{
SavePins(nodes, node, pinCollectionId, pinCollection);
SavePins(node, pinCollectionId, pinCollection);
pinCollectionId++;
}
}
}
private void SavePins(Dictionary<INode, int> nodes, INode node, int collectionId, IEnumerable<IPin> pins)
private void SavePins(INode node, int collectionId, IEnumerable<IPin> pins)
{
int sourcePinId = 0;
List<INode> nodes = Nodes.ToList();
foreach (IPin sourcePin in pins.Where(p => p.Direction == PinDirection.Input))
{
foreach (IPin targetPin in sourcePin.ConnectedTo)
@ -249,11 +253,11 @@ namespace Artemis.Core
Entity.Connections.Add(new NodeConnectionEntity()
{
SourceType = sourcePin.Type.Name,
SourceNode = nodes[node],
SourceNode = nodes.IndexOf(node),
SourcePinCollectionId = collectionId,
SourcePinId = sourcePinId,
TargetType = targetPin.Type.Name,
TargetNode = nodes[targetPin.Node],
TargetNode = nodes.IndexOf(targetPin.Node),
TargetPinCollectionId = targetPinCollectionId,
TargetPinId = targetPinId,
});

View File

@ -126,6 +126,7 @@ namespace Artemis.UI.Services
_nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(int), new SKColor(0xFF32CD32));
_nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(double), new SKColor(0xFF1E90FF));
_nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(float), new SKColor(0xFFFF7C00));
_nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(SKColor), new SKColor(0xFF7630C7));
_nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(IList), new SKColor(0xFFC842FF));
foreach (Type nodeType in typeof(SumIntegersNode).Assembly.GetTypes().Where(t => typeof(INode).IsAssignableFrom(t) && t.IsPublic && !t.IsAbstract && !t.IsInterface))

View File

@ -535,8 +535,8 @@
},
"SkiaSharp": {
"type": "Transitive",
"resolved": "2.80.2",
"contentHash": "D25rzdCwh+3L+XyXqpNa+H/yiLJbE3/R3K/XexwHyQjGdzZvSufFW3oqf3En7hhqSIsxsJ8f5NEZ0J5W5wlGBg==",
"resolved": "2.80.3",
"contentHash": "qX6tGNP3+MXNYe2pKm0PCRiJ/cx+LTeLaggwZifB7sUMXhECfKKKHJq45VqZKt37xQegnCCdf1jHXwmHeJQs5Q==",
"dependencies": {
"System.Memory": "4.5.3"
}
@ -1484,6 +1484,7 @@
"Artemis.Core": "1.0.0",
"Artemis.UI.Shared": "2.0.0",
"JetBrains.Annotations": "2021.1.0",
"SkiaSharp": "2.80.3",
"Stylet": "1.3.6"
}
}

View File

@ -37,6 +37,7 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2021.1.0" />
<PackageReference Include="SkiaSharp" Version="2.80.3" />
<PackageReference Include="Stylet" Version="1.3.6" />
</ItemGroup>

View File

@ -3,8 +3,10 @@
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:controls="clr-namespace:Artemis.VisualScripting.Editor.Controls"
xmlns:converters="clr-namespace:Artemis.VisualScripting.Converters"
xmlns:collections="clr-namespace:System.Collections;assembly=System.Runtime">
<converters:CenterTranslateConverter x:Key="CenterTranslateConverter"/>
xmlns:collections="clr-namespace:System.Collections;assembly=System.Runtime"
xmlns:skiaSharp="clr-namespace:SkiaSharp;assembly=SkiaSharp"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared">
<converters:CenterTranslateConverter x:Key="CenterTranslateConverter" />
<ControlTemplate x:Key="TemplateVisualScriptCablePresenter"
TargetType="{x:Type controls:VisualScriptCablePresenter}">
@ -45,7 +47,41 @@
<TranslateTransform X="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Border}, Converter={StaticResource CenterTranslateConverter}}"
Y="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=Border}, Converter={StaticResource CenterTranslateConverter}}" />
</Border.RenderTransform>
<TextBlock Text="{Binding Cable.From.Pin.PinValue, TargetNullValue=-, RelativeSource={RelativeSource TemplatedParent}}" />
<Border.Resources>
<DataTemplate DataType="{x:Type skiaSharp:SKColor}">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<StackPanel.Resources>
<shared:SKColorToStringConverter x:Key="SKColorToStringConverter" />
<shared:SKColorToColorConverter x:Key="SKColorToColorConverter" />
</StackPanel.Resources>
<TextBlock x:Name="HexDisplay"
Text="{Binding Converter={StaticResource SKColorToStringConverter}}"
VerticalAlignment="Center"
HorizontalAlignment="Stretch" />
<Border Width="{Binding ActualHeight, ElementName=HexDisplay}"
Height="{Binding ActualHeight, ElementName=HexDisplay}"
CornerRadius="{Binding ActualHeight, ElementName=HexDisplay}"
Margin="5 0 0 0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Background="{StaticResource Checkerboard}">
<Ellipse Stroke="{DynamicResource NormalBorderBrush}">
<Ellipse.Fill>
<SolidColorBrush Color="{Binding Converter={StaticResource SKColorToColorConverter}}" />
</Ellipse.Fill>
</Ellipse>
</Border>
</StackPanel>
</DataTemplate>
<!-- <DataTemplate DataType=""> -->
<!-- <TextBlock></TextBlock> -->
<!-- </DataTemplate> -->
</Border.Resources>
<ContentControl Content="{Binding Cable.From.Pin.PinValue, RelativeSource={RelativeSource TemplatedParent}}" />
<!-- <TextBlock Text="{Binding Cable.From.Pin.PinValue, TargetNullValue=-, RelativeSource={RelativeSource TemplatedParent}}" /> -->
</Border>
</Canvas>

View File

@ -0,0 +1,27 @@
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Brighten Color", "Brightens a color by a specified amount in percent")]
public class BrightenSKColorNode : Node
{
public BrightenSKColorNode() : base("Brighten Color", "Brightens a color by a specified amount in percent")
{
Input = CreateInputPin<SKColor>("Color");
Percentage = CreateInputPin<float>("%");
Output = CreateOutputPin<SKColor>();
}
public InputPin<SKColor> Input { get; }
public InputPin<float> Percentage { get; }
public OutputPin<SKColor> Output { get; set; }
public override void Evaluate()
{
Input.Value.ToHsl(out float h, out float s, out float l);
l *= (Percentage.Value + 100f) / 100f;
Output.Value = SKColor.FromHsl(h, s, l);
}
}
}

View File

@ -0,0 +1,38 @@
using System.ComponentModel;
using Artemis.VisualScripting.Nodes.CustomViewModels;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color.CustomViewModels
{
public class StaticSKColorValueNodeCustomViewModel : CustomNodeViewModel
{
private readonly StaticSKColorValueNode _node;
public StaticSKColorValueNodeCustomViewModel(StaticSKColorValueNode node) : base(node)
{
_node = node;
}
public SKColor Input
{
get => (SKColor) (_node.Storage ?? SKColor.Empty);
set => _node.Storage = value;
}
public override void OnActivate()
{
_node.PropertyChanged += NodeOnPropertyChanged;
}
public override void OnDeactivate()
{
_node.PropertyChanged -= NodeOnPropertyChanged;
}
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Node.Storage))
OnPropertyChanged(nameof(Input));
}
}
}

View File

@ -0,0 +1,16 @@
<UserControl x:Class="Artemis.VisualScripting.Nodes.Color.CustomViews.StaticSKColorValueNodeCustomView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.VisualScripting.Nodes.Color.CustomViews"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<shared:SKColorToColorConverter x:Key="SKColorToColorConverter" />
</UserControl.Resources>
<shared:ColorPicker VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Color="{Binding Input, Converter={StaticResource SKColorToColorConverter}}" />
</UserControl>

View File

@ -0,0 +1,27 @@
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Darken Color", "Darkens a color by a specified amount in percent")]
public class DarkenSKColorNode : Node
{
public DarkenSKColorNode() : base("Darken Color", "Darkens a color by a specified amount in percent")
{
Input = CreateInputPin<SKColor>("Color");
Percentage = CreateInputPin<float>("%");
Output = CreateOutputPin<SKColor>();
}
public InputPin<SKColor> Input { get; }
public InputPin<float> Percentage { get; }
public OutputPin<SKColor> Output { get; set; }
public override void Evaluate()
{
Input.Value.ToHsl(out float h, out float s, out float l);
l *= (Percentage.Value * -1 + 100f) / 100f;
Output.Value = SKColor.FromHsl(h, s, l);
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Desaturate Color", "Desaturates a color by a specified amount in percent")]
public class DesaturateSKColorNode : Node
{
public DesaturateSKColorNode() : base("Desaturate Color", "Desaturates a color by a specified amount in percent")
{
Input = CreateInputPin<SKColor>("Color");
Percentage = CreateInputPin<float>("%");
Output = CreateOutputPin<SKColor>();
}
public InputPin<SKColor> Input { get; }
public InputPin<float> Percentage { get; }
public OutputPin<SKColor> Output { get; set; }
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);
}
}
}

View File

@ -0,0 +1,32 @@
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("HSL Color", "Creates a color from hue, saturation and lightness values")]
public class HslSKColorNode : Node
{
public HslSKColorNode() : base("HSL Color", "Creates a color from hue, saturation and lightness values")
{
H = CreateInputPin<float>("H");
S = CreateInputPin<float>("S");
L = CreateInputPin<float>("L");
Output = CreateOutputPin<SKColor>();
}
public InputPin<float> H { get; set; }
public InputPin<float> S { get; set; }
public InputPin<float> L { get; set; }
public OutputPin<SKColor> Output { get; }
#region Overrides of Node
/// <inheritdoc />
public override void Evaluate()
{
Output.Value = SKColor.FromHsl(H.Value, S.Value, L.Value);
}
#endregion
}
}

View File

@ -0,0 +1,25 @@
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Invert Color", "Inverts a color by a specified amount in percent")]
public class InvertSKColorNode : Node
{
public InvertSKColorNode() : base("Invert Color", "Inverts a color")
{
Input = CreateInputPin<SKColor>();
Output = CreateOutputPin<SKColor>();
}
public InputPin<SKColor> Input { get; }
public OutputPin<SKColor> Output { get; set; }
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);
}
}
}

View File

@ -0,0 +1,27 @@
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Rotate Color Hue", "Rotates the hue of a color by a specified amount in degrees")]
public class RotateHueSKColorNode : Node
{
public RotateHueSKColorNode() : base("Rotate Color Hue", "Rotates the hue of a color by a specified amount in degrees")
{
Input = CreateInputPin<SKColor>("Color");
Amount = CreateInputPin<float>("Amount");
Output = CreateOutputPin<SKColor>();
}
public InputPin<SKColor> Input { get; }
public InputPin<float> Amount { get; }
public OutputPin<SKColor> Output { get; set; }
public override void Evaluate()
{
Input.Value.ToHsl(out float h, out float s, out float l);
h += Amount.Value;
Output.Value = SKColor.FromHsl(h % 360, s, l);
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Saturate Color", "Saturates a color by a specified amount in percent")]
public class SaturateSKColorNode : Node
{
public SaturateSKColorNode() : base("Saturate Color", "Saturates a color by a specified amount in percent")
{
Input = CreateInputPin<SKColor>("Color");
Percentage = CreateInputPin<float>("%");
Output = CreateOutputPin<SKColor>();
}
public InputPin<SKColor> Input { get; }
public InputPin<float> Percentage { get; }
public OutputPin<SKColor> Output { get; set; }
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);
}
}
}

View File

@ -0,0 +1,43 @@
using Artemis.Core;
using Artemis.VisualScripting.Nodes.Color.CustomViewModels;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Color-Value", "Outputs a configurable color value.")]
public class StaticSKColorValueNode : Node<StaticSKColorValueNodeCustomViewModel>
{
#region Constructors
public StaticSKColorValueNode()
: base("Color", "Outputs a configurable color value.")
{
Output = CreateOutputPin<SKColor>();
}
#endregion
#region Properties & Fields
public OutputPin<SKColor> Output { get; }
#endregion
#region Methods
public override void Evaluate()
{
Output.Value = Storage as SKColor? ?? SKColor.Empty;
}
public override void Initialize(INodeScript script)
{
if (Storage is string && SKColor.TryParse(Storage.ToString(), out SKColor parsed))
Storage = parsed;
else
Storage = SKColor.Empty;
}
#endregion
}
}

View File

@ -0,0 +1,46 @@
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color
{
[Node("Sum (Color)", "Sums the connected color values.")]
public class SumSKColorsNode : Node
{
#region Properties & Fields
public InputPinCollection<SKColor> Values { get; }
public OutputPin<SKColor> Sum { get; }
#endregion
#region Constructors
public SumSKColorsNode()
: base("Sum", "Sums the connected color values.")
{
Values = CreateInputPinCollection<SKColor>("Values", 2);
Sum = CreateOutputPin<SKColor>("Sum");
}
#endregion
#region Methods
public override void Evaluate()
{
SKColor result = SKColor.Empty;
bool first = true;
foreach (SKColor current in Values.Values)
{
result = first ? current : result.Sum(current);
first = false;
}
Sum.Value = result;
}
#endregion
}
}

View File

@ -61,7 +61,7 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels
if (_node.ProfileElement == null)
return;
LayerProperties.AddRange(_node.ProfileElement.GetAllLayerProperties().Where(l => l.DataBindingsSupported));
LayerProperties.AddRange(_node.ProfileElement.GetAllLayerProperties().Where(l => !l.IsHidden && l.DataBindingsSupported));
_selectedLayerProperty = _node.LayerProperty;
NotifyOfPropertyChange(nameof(SelectedLayerProperty));
}

View File

@ -8,6 +8,15 @@
"resolved": "2021.1.0",
"contentHash": "n9JSw5Z+F+6gp9vSv4aLH6p/bx3GAYA6FZVq1wJq/TJySv/kPgFKLGFeS7A8Xa5X4/GWorh5gd43yjamUgnBNA=="
},
"SkiaSharp": {
"type": "Direct",
"requested": "[2.80.3, )",
"resolved": "2.80.3",
"contentHash": "qX6tGNP3+MXNYe2pKm0PCRiJ/cx+LTeLaggwZifB7sUMXhECfKKKHJq45VqZKt37xQegnCCdf1jHXwmHeJQs5Q==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"Stylet": {
"type": "Direct",
"requested": "[1.3.6, )",
@ -368,14 +377,6 @@
"resolved": "1.7.5",
"contentHash": "v9U5sSMGFE2zCMbh42BYHkaRYkmwwhsKMGcNRdHAKqD1ryOf4mhqnJR0o07hwg5KIEmCI9bDdrgYSmiZWlL+eA=="
},
"SkiaSharp": {
"type": "Transitive",
"resolved": "2.80.2",
"contentHash": "D25rzdCwh+3L+XyXqpNa+H/yiLJbE3/R3K/XexwHyQjGdzZvSufFW3oqf3En7hhqSIsxsJ8f5NEZ0J5W5wlGBg==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SkiaSharp.Views.Desktop.Common": {
"type": "Transitive",
"resolved": "2.80.2",