mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 11:56:30 +00:00
Meta - Replace WPF projects with Avalonia projects
This commit is contained in:
1 parent
fcf0376a9a
commit
d7f3ee1190
1110 files changed
+10872
-52240
No files matched your search
@@ -1,302 +1,299 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using Artemis.Core;
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes
|
||||
namespace Artemis.VisualScripting.Nodes;
|
||||
|
||||
[Node("Greater than", "Checks if the first input is greater than the second.", "Operators", InputType = typeof(object), OutputType = typeof(bool))]
|
||||
public class GreaterThanNode : Node
|
||||
{
|
||||
[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 Constructors
|
||||
|
||||
public GreaterThanNode()
|
||||
: base("Greater than", "Checks if the first input is greater than the second.")
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input1 { get; }
|
||||
public InputPin<object> Input2 { get; }
|
||||
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public GreaterThanNode()
|
||||
: base("Greater than", "Checks if the first input is greater than the second.")
|
||||
{
|
||||
Input1 = CreateInputPin<object>();
|
||||
Input2 = CreateInputPin<object>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
if (Input1.Value is Numeric numeric1 && Input2.Value is Numeric numeric2)
|
||||
{
|
||||
Result.Value = numeric1 > numeric2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Input2.Value != null && Input1.Value != null && Input1.Value.IsNumber() && Input2.Value.IsNumber())
|
||||
{
|
||||
Result.Value = Convert.ToSingle(Input1.Value) > Convert.ToSingle(Input2.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Result.Value = Comparer.DefaultInvariant.Compare(Input1.Value, Input2.Value) == 1;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Result.Value = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
Input1 = CreateInputPin<object>();
|
||||
Input2 = CreateInputPin<object>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
[Node("Less than", "Checks if the first input is less than the second.", "Operators", InputType = typeof(object), OutputType = typeof(bool))]
|
||||
public class LessThanNode : Node
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input1 { get; }
|
||||
public InputPin<object> Input2 { get; }
|
||||
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public LessThanNode()
|
||||
: base("Less than", "Checks if the first input is less than the second.")
|
||||
if (Input1.Value is Numeric numeric1 && Input2.Value is Numeric numeric2)
|
||||
{
|
||||
Input1 = CreateInputPin<object>();
|
||||
Input2 = CreateInputPin<object>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
Result.Value = numeric1 > numeric2;
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
if (Input2.Value != null && Input1.Value != null && Input1.Value.IsNumber() && Input2.Value.IsNumber())
|
||||
{
|
||||
if (Input1.Value is Numeric numeric1 && Input2.Value is Numeric numeric2)
|
||||
{
|
||||
Result.Value = numeric1 < numeric2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Input2.Value != null && Input1.Value != null && Input1.Value.IsNumber() && Input2.Value.IsNumber())
|
||||
{
|
||||
Result.Value = Convert.ToSingle(Input1.Value) < Convert.ToSingle(Input2.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Result.Value = Comparer.DefaultInvariant.Compare(Input1.Value, Input2.Value) == -1;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Result.Value = false;
|
||||
}
|
||||
Result.Value = Convert.ToSingle(Input1.Value) > Convert.ToSingle(Input2.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion
|
||||
try
|
||||
{
|
||||
Result.Value = Comparer.DefaultInvariant.Compare(Input1.Value, Input2.Value) == 1;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Result.Value = false;
|
||||
}
|
||||
}
|
||||
|
||||
[Node("Equals", "Checks if the two inputs are equals.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class EqualsNode : Node
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input1 { get; }
|
||||
public InputPin<object> Input2 { get; }
|
||||
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[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 Constructors
|
||||
|
||||
public LessThanNode()
|
||||
: base("Less than", "Checks if the first input is less than the second.")
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input1 { get; }
|
||||
public InputPin<object> Input2 { get; }
|
||||
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public EqualsNode()
|
||||
: base("Equals", "Checks if the two inputs are equals.")
|
||||
{
|
||||
Input1 = CreateInputPin<object>();
|
||||
Input2 = CreateInputPin<object>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
try
|
||||
{
|
||||
Result.Value = Equals(Input1.Value, Input2.Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Result.Value = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
Input1 = CreateInputPin<object>();
|
||||
Input2 = CreateInputPin<object>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
[Node("Negate", "Negates the boolean.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class NegateNode : Node
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<bool> Input { get; }
|
||||
public OutputPin<bool> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public NegateNode()
|
||||
: base("Negate", "Negates the boolean.")
|
||||
if (Input1.Value is Numeric numeric1 && Input2.Value is Numeric numeric2)
|
||||
{
|
||||
Input = CreateInputPin<bool>();
|
||||
Output = CreateOutputPin<bool>();
|
||||
Result.Value = numeric1 < numeric2;
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
if (Input2.Value != null && Input1.Value != null && Input1.Value.IsNumber() && Input2.Value.IsNumber())
|
||||
{
|
||||
Output.Value = !Input.Value;
|
||||
Result.Value = Convert.ToSingle(Input1.Value) < Convert.ToSingle(Input2.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion
|
||||
try
|
||||
{
|
||||
Result.Value = Comparer.DefaultInvariant.Compare(Input1.Value, Input2.Value) == -1;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Result.Value = false;
|
||||
}
|
||||
}
|
||||
|
||||
[Node("And", "Checks if all inputs are true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class AndNode : Node
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input1 { get; }
|
||||
public InputPin<object> Input2 { get; }
|
||||
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Node("Equals", "Checks if the two inputs are equals.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class EqualsNode : Node
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public EqualsNode()
|
||||
: base("Equals", "Checks if the two inputs are equals.")
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<bool> Input { get; set; }
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public AndNode()
|
||||
: base("And", "Checks if all inputs are true.")
|
||||
{
|
||||
Input = CreateInputPinCollection<bool>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Result.Value = Input.Values.All(v => v);
|
||||
}
|
||||
|
||||
#endregion
|
||||
Input1 = CreateInputPin<object>();
|
||||
Input2 = CreateInputPin<object>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
[Node("Or", "Checks if any inputs are true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class OrNode : Node
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<bool> Input { get; set; }
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public OrNode()
|
||||
: base("Or", "Checks if any inputs are true.")
|
||||
try
|
||||
{
|
||||
Input = CreateInputPinCollection<bool>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
Result.Value = Equals(Input1.Value, Input2.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
catch
|
||||
{
|
||||
Result.Value = Input.Values.Any(v => v);
|
||||
Result.Value = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Node("Exclusive Or", "Checks if one of the inputs is true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class XorNode : Node
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input1 { get; }
|
||||
public InputPin<object> Input2 { get; }
|
||||
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Node("Negate", "Negates the boolean.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class NegateNode : Node
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public NegateNode()
|
||||
: base("Negate", "Negates the boolean.")
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<bool> Input { get; set; }
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public XorNode()
|
||||
: base("Exclusive Or", "Checks if one of the inputs is true.")
|
||||
{
|
||||
Input = CreateInputPinCollection<bool>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Result.Value = Input.Values.Count(v => v) == 1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
Input = CreateInputPin<bool>();
|
||||
Output = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
[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<Enum, EnumEqualsNodeCustomViewModel>
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
public EnumEqualsNode() : base("Enum Equals", "Determines the equality between an input and a selected enum value")
|
||||
{
|
||||
InputPin = CreateInputPin<Enum>();
|
||||
OutputPin = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
public InputPin<Enum> InputPin { get; }
|
||||
public OutputPin<bool> OutputPin { get; }
|
||||
|
||||
#region Overrides of Node
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Evaluate()
|
||||
{
|
||||
OutputPin.Value = InputPin.Value != null && InputPin.Value.Equals(Storage);
|
||||
}
|
||||
|
||||
#endregion
|
||||
Output.Value = !Input.Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<bool> Input { get; }
|
||||
public OutputPin<bool> Output { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Node("And", "Checks if all inputs are true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class AndNode : Node
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public AndNode()
|
||||
: base("And", "Checks if all inputs are true.")
|
||||
{
|
||||
Input = CreateInputPinCollection<bool>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Result.Value = Input.Values.All(v => v);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<bool> Input { get; set; }
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Node("Or", "Checks if any inputs are true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class OrNode : Node
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public OrNode()
|
||||
: base("Or", "Checks if any inputs are true.")
|
||||
{
|
||||
Input = CreateInputPinCollection<bool>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Result.Value = Input.Values.Any(v => v);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<bool> Input { get; set; }
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Node("Exclusive Or", "Checks if one of the inputs is true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))]
|
||||
public class XorNode : Node
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public XorNode()
|
||||
: base("Exclusive Or", "Checks if one of the inputs is true.")
|
||||
{
|
||||
Input = CreateInputPinCollection<bool>();
|
||||
Result = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Result.Value = Input.Values.Count(v => v) == 1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<bool> Input { get; set; }
|
||||
public OutputPin<bool> Result { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[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<Enum, EnumEqualsNodeCustomViewModel>
|
||||
{
|
||||
public EnumEqualsNode() : base("Enum Equals", "Determines the equality between an input and a selected enum value")
|
||||
{
|
||||
InputPin = CreateInputPin<Enum>();
|
||||
OutputPin = CreateOutputPin<bool>();
|
||||
}
|
||||
|
||||
public InputPin<Enum> InputPin { get; }
|
||||
public OutputPin<bool> OutputPin { get; }
|
||||
|
||||
#region Overrides of Node
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Evaluate()
|
||||
{
|
||||
OutputPin.Value = InputPin.Value != null && InputPin.Value.Equals(Storage);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,27 +1,26 @@
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
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
|
||||
{
|
||||
[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() : base("Brighten Color", "Brightens a color by a specified amount in percent")
|
||||
{
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Percentage = CreateInputPin<Numeric>("%");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Percentage = CreateInputPin<Numeric>("%");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> Percentage { get; }
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> 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 += l * (Percentage.Value / 100f);
|
||||
Output.Value = SKColor.FromHsl(h, s, l);
|
||||
}
|
||||
public override void Evaluate()
|
||||
{
|
||||
Input.Value.ToHsl(out float h, out float s, out float l);
|
||||
l += l * (Percentage.Value / 100f);
|
||||
Output.Value = SKColor.FromHsl(h, s, l);
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -1,11 +1,11 @@
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.VisualScripting;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.Color.CustomViewModels;
|
||||
|
||||
public class StaticSKColorValueNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
public class StaticSKColorValueNodeCustomViewModel : CustomNodeViewModel
|
||||
public StaticSKColorValueNodeCustomViewModel(StaticSKColorValueNode node, INodeScript script) : base(node, script)
|
||||
{
|
||||
public StaticSKColorValueNodeCustomViewModel(StaticSKColorValueNode node) : base(node)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -1,11 +1,10 @@
|
||||
<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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<shared:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
||||
@@ -13,4 +12,4 @@
|
||||
<shared:ColorPicker VerticalAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
Color="{Binding Node.Storage, Converter={StaticResource SKColorToColorConverter}}" />
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
@@ -1,27 +1,26 @@
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
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
|
||||
{
|
||||
[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() : base("Darken Color", "Darkens a color by a specified amount in percent")
|
||||
{
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Percentage = CreateInputPin<Numeric>("%");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Percentage = CreateInputPin<Numeric>("%");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> Percentage { get; }
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> 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 -= l * (Percentage.Value / 100f);
|
||||
Output.Value = SKColor.FromHsl(h, s, l);
|
||||
}
|
||||
public override void Evaluate()
|
||||
{
|
||||
Input.Value.ToHsl(out float h, out float s, out float l);
|
||||
l -= l * (Percentage.Value / 100f);
|
||||
Output.Value = SKColor.FromHsl(h, s, l);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,26 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
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
|
||||
{
|
||||
[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() : base("Desaturate Color", "Desaturates a color by a specified amount in percent")
|
||||
{
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Percentage = CreateInputPin<Numeric>("%");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Percentage = CreateInputPin<Numeric>("%");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> Percentage { get; }
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> 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 -= s * (Percentage.Value / 100f);
|
||||
Output.Value = SKColor.FromHsl(h, Math.Clamp(s, 0f, 100f), l);
|
||||
}
|
||||
public override void Evaluate()
|
||||
{
|
||||
Input.Value.ToHsl(out float h, out float s, out float l);
|
||||
s -= s * (Percentage.Value / 100f);
|
||||
Output.Value = SKColor.FromHsl(h, Math.Clamp(s, 0f, 100f), l);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,31 @@
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
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
|
||||
{
|
||||
[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() : base("HSL Color", "Creates a color from hue, saturation and lightness values")
|
||||
{
|
||||
H = CreateInputPin<Numeric>("H");
|
||||
S = CreateInputPin<Numeric>("S");
|
||||
L = CreateInputPin<Numeric>("L");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<Numeric> H { get; set; }
|
||||
public InputPin<Numeric> S { get; set; }
|
||||
public InputPin<Numeric> 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
|
||||
H = CreateInputPin<Numeric>("H");
|
||||
S = CreateInputPin<Numeric>("S");
|
||||
L = CreateInputPin<Numeric>("L");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<Numeric> H { get; set; }
|
||||
public InputPin<Numeric> S { get; set; }
|
||||
public InputPin<Numeric> 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
|
||||
}
|
||||
@@ -1,28 +1,27 @@
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
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
|
||||
{
|
||||
[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() : base("Invert Color", "Inverts a color")
|
||||
{
|
||||
Input = CreateInputPin<SKColor>();
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
Input = CreateInputPin<SKColor>();
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = new SKColor(
|
||||
(byte) (255 - Input.Value.Red),
|
||||
(byte) (255 - Input.Value.Green),
|
||||
(byte) (255 - Input.Value.Blue),
|
||||
Input.Value.Alpha
|
||||
);
|
||||
}
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = new SKColor(
|
||||
(byte) (255 - Input.Value.Red),
|
||||
(byte) (255 - Input.Value.Green),
|
||||
(byte) (255 - Input.Value.Blue),
|
||||
Input.Value.Alpha
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,26 @@
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
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
|
||||
{
|
||||
[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() : base("Rotate Color Hue", "Rotates the hue of a color by a specified amount in degrees")
|
||||
{
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Amount = CreateInputPin<Numeric>("Amount");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Amount = CreateInputPin<Numeric>("Amount");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> Amount { get; }
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,26 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
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
|
||||
{
|
||||
[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() : base("Saturate Color", "Saturates a color by a specified amount in percent")
|
||||
{
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Percentage = CreateInputPin<Numeric>("%");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
Input = CreateInputPin<SKColor>("Color");
|
||||
Percentage = CreateInputPin<Numeric>("%");
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> Percentage { get; }
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
public InputPin<SKColor> Input { get; }
|
||||
public InputPin<Numeric> 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 += s * (Percentage.Value / 100f);
|
||||
Output.Value = SKColor.FromHsl(h, Math.Clamp(s, 0f, 100f), l);
|
||||
}
|
||||
public override void Evaluate()
|
||||
{
|
||||
Input.Value.ToHsl(out float h, out float s, out float l);
|
||||
s += s * (Percentage.Value / 100f);
|
||||
Output.Value = SKColor.FromHsl(h, Math.Clamp(s, 0f, 100f), l);
|
||||
}
|
||||
}
|
||||
@@ -2,34 +2,33 @@
|
||||
using Artemis.VisualScripting.Nodes.Color.CustomViewModels;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
namespace Artemis.VisualScripting.Nodes.Color;
|
||||
|
||||
[Node("Color-Value", "Outputs a configurable color value.", "Static", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
|
||||
public class StaticSKColorValueNode : Node<SKColor, StaticSKColorValueNodeCustomViewModel>
|
||||
{
|
||||
[Node("Color-Value", "Outputs a configurable color value.", "Static", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
|
||||
public class StaticSKColorValueNode : Node<SKColor, StaticSKColorValueNodeCustomViewModel>
|
||||
#region Constructors
|
||||
|
||||
public StaticSKColorValueNode()
|
||||
: base("Color", "Outputs a configurable color value.")
|
||||
{
|
||||
#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;
|
||||
}
|
||||
|
||||
#endregion
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public OutputPin<SKColor> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = Storage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,46 +1,45 @@
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Color
|
||||
namespace Artemis.VisualScripting.Nodes.Color;
|
||||
|
||||
[Node("Sum (Color)", "Sums the connected color values.", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
|
||||
public class SumSKColorsNode : Node
|
||||
{
|
||||
[Node("Sum (Color)", "Sums the connected color values.", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
|
||||
public class SumSKColorsNode : Node
|
||||
#region Constructors
|
||||
|
||||
public SumSKColorsNode()
|
||||
: base("Sum", "Sums the connected color values.")
|
||||
{
|
||||
#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
|
||||
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
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<SKColor> Values { get; }
|
||||
|
||||
public OutputPin<SKColor> Sum { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,81 +1,80 @@
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes
|
||||
namespace Artemis.VisualScripting.Nodes;
|
||||
|
||||
[Node("To String", "Converts the input to a string.", "Conversion", InputType = typeof(object), OutputType = typeof(string))]
|
||||
public class ConvertToStringNode : Node
|
||||
{
|
||||
[Node("To String", "Converts the input to a string.", "Conversion", InputType = typeof(object), OutputType = typeof(string))]
|
||||
public class ConvertToStringNode : Node
|
||||
#region Constructors
|
||||
|
||||
public ConvertToStringNode()
|
||||
: base("To String", "Converts the input to a string.")
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input { get; }
|
||||
|
||||
public OutputPin<string> String { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ConvertToStringNode()
|
||||
: base("To String", "Converts the input to a string.")
|
||||
{
|
||||
Input = CreateInputPin<object>();
|
||||
String = CreateOutputPin<string>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
String.Value = Input.Value?.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
Input = CreateInputPin<object>();
|
||||
String = CreateOutputPin<string>();
|
||||
}
|
||||
|
||||
[Node("To Numeric", "Converts the input to a numeric.", "Conversion", InputType = typeof(object), OutputType = typeof(Numeric))]
|
||||
public class ConvertToNumericNode : Node
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input { get; }
|
||||
|
||||
public OutputPin<Numeric> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ConvertToNumericNode()
|
||||
: base("To Numeric", "Converts the input to a numeric.")
|
||||
{
|
||||
Input = CreateInputPin<object>();
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = Input.Value switch
|
||||
{
|
||||
int input => new Numeric(input),
|
||||
double input => new Numeric(input),
|
||||
float input => new Numeric(input),
|
||||
byte input => new Numeric(input),
|
||||
_ => TryParse(Input.Value)
|
||||
};
|
||||
}
|
||||
|
||||
private Numeric TryParse(object input)
|
||||
{
|
||||
Numeric.TryParse(input?.ToString(), out Numeric value);
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
String.Value = Input.Value?.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input { get; }
|
||||
|
||||
public OutputPin<string> String { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Node("To Numeric", "Converts the input to a numeric.", "Conversion", InputType = typeof(object), OutputType = typeof(Numeric))]
|
||||
public class ConvertToNumericNode : Node
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public ConvertToNumericNode()
|
||||
: base("To Numeric", "Converts the input to a numeric.")
|
||||
{
|
||||
Input = CreateInputPin<object>();
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<object> Input { get; }
|
||||
|
||||
public OutputPin<Numeric> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = Input.Value switch
|
||||
{
|
||||
int input => new Numeric(input),
|
||||
double input => new Numeric(input),
|
||||
float input => new Numeric(input),
|
||||
byte input => new Numeric(input),
|
||||
_ => TryParse(Input.Value)
|
||||
};
|
||||
}
|
||||
|
||||
private Numeric TryParse(object input)
|
||||
{
|
||||
Numeric.TryParse(input?.ToString(), out Numeric value);
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Artemis.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
||||
{
|
||||
public abstract class CustomNodeViewModel : PropertyChangedBase, ICustomNodeViewModel
|
||||
{
|
||||
protected CustomNodeViewModel(INode node)
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
|
||||
public INode Node { get; }
|
||||
|
||||
#region Implementation of ICustomNodeViewModel
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OnActivate()
|
||||
{
|
||||
Node.PropertyChanged += NodeOnPropertyChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OnDeactivate()
|
||||
{
|
||||
Node.PropertyChanged -= NodeOnPropertyChanged;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler NodeModified;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the <see cref="NodeModified"/> event
|
||||
/// </summary>
|
||||
protected virtual void OnNodeModified()
|
||||
{
|
||||
NodeModified?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Storage")
|
||||
OnNodeModified();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+38
-38
@@ -1,49 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Events;
|
||||
using Stylet;
|
||||
using Artemis.UI.Shared.VisualScripting;
|
||||
using DynamicData;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
|
||||
public class EnumEqualsNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
public class EnumEqualsNodeCustomViewModel : CustomNodeViewModel
|
||||
private readonly EnumEqualsNode _node;
|
||||
|
||||
public EnumEqualsNodeCustomViewModel(EnumEqualsNode node, INodeScript script) : base(node, script)
|
||||
{
|
||||
private readonly EnumEqualsNode _node;
|
||||
_node = node;
|
||||
}
|
||||
|
||||
public EnumEqualsNodeCustomViewModel(EnumEqualsNode node) : base(node)
|
||||
{
|
||||
_node = node;
|
||||
}
|
||||
public ObservableCollection<(Enum, string)> EnumValues { get; } = new();
|
||||
|
||||
public BindableCollection<(Enum, string)> EnumValues { get; } = new();
|
||||
// public override void OnActivate()
|
||||
// {
|
||||
// _node.InputPin.PinConnected += InputPinOnPinConnected;
|
||||
// _node.InputPin.PinDisconnected += InputPinOnPinDisconnected;
|
||||
//
|
||||
// if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum)
|
||||
// EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType()));
|
||||
// base.OnActivate();
|
||||
// }
|
||||
//
|
||||
// public override void OnDeactivate()
|
||||
// {
|
||||
// _node.InputPin.PinConnected -= InputPinOnPinConnected;
|
||||
// _node.InputPin.PinDisconnected -= InputPinOnPinDisconnected;
|
||||
//
|
||||
// base.OnDeactivate();
|
||||
// }
|
||||
|
||||
public override void OnActivate()
|
||||
{
|
||||
_node.InputPin.PinConnected += InputPinOnPinConnected;
|
||||
_node.InputPin.PinDisconnected += InputPinOnPinDisconnected;
|
||||
private void InputPinOnPinDisconnected(object sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
EnumValues.Clear();
|
||||
}
|
||||
|
||||
if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum)
|
||||
EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType()));
|
||||
base.OnActivate();
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
{
|
||||
_node.InputPin.PinConnected -= InputPinOnPinConnected;
|
||||
_node.InputPin.PinDisconnected -= InputPinOnPinDisconnected;
|
||||
|
||||
base.OnDeactivate();
|
||||
}
|
||||
|
||||
private void InputPinOnPinDisconnected(object sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
EnumValues.Clear();
|
||||
}
|
||||
|
||||
private void InputPinOnPinConnected(object sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
EnumValues.Clear();
|
||||
if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum)
|
||||
EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType()));
|
||||
}
|
||||
private void InputPinOnPinConnected(object sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
EnumValues.Clear();
|
||||
if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum)
|
||||
EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType()));
|
||||
}
|
||||
}
|
||||
+67
-74
@@ -1,80 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.ObjectModel;
|
||||
using Artemis.Core;
|
||||
using Stylet;
|
||||
using Artemis.UI.Shared.VisualScripting;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
|
||||
public class LayerPropertyNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
public class LayerPropertyNodeCustomViewModel : CustomNodeViewModel
|
||||
private readonly LayerPropertyNode _node;
|
||||
private ILayerProperty _selectedLayerProperty;
|
||||
|
||||
private RenderProfileElement _selectedProfileElement;
|
||||
|
||||
public LayerPropertyNodeCustomViewModel(LayerPropertyNode node, INodeScript script) : base(node, script)
|
||||
{
|
||||
private readonly LayerPropertyNode _node;
|
||||
|
||||
private RenderProfileElement _selectedProfileElement;
|
||||
private ILayerProperty _selectedLayerProperty;
|
||||
|
||||
public LayerPropertyNodeCustomViewModel(LayerPropertyNode node) : base(node)
|
||||
{
|
||||
_node = node;
|
||||
}
|
||||
|
||||
public BindableCollection<RenderProfileElement> ProfileElements { get; } = new();
|
||||
|
||||
public RenderProfileElement SelectedProfileElement
|
||||
{
|
||||
get => _selectedProfileElement;
|
||||
set
|
||||
{
|
||||
if (!SetAndNotify(ref _selectedProfileElement, value)) return;
|
||||
_node.ChangeProfileElement(_selectedProfileElement);
|
||||
GetLayerProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public BindableCollection<ILayerProperty> LayerProperties { get; } = new();
|
||||
|
||||
public ILayerProperty SelectedLayerProperty
|
||||
{
|
||||
get => _selectedLayerProperty;
|
||||
set
|
||||
{
|
||||
if (!SetAndNotify(ref _selectedLayerProperty, value)) return;
|
||||
_node.ChangeLayerProperty(_selectedLayerProperty);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetProfileElements()
|
||||
{
|
||||
ProfileElements.Clear();
|
||||
if (_node.Script.Context is not Profile profile)
|
||||
return;
|
||||
|
||||
List<RenderProfileElement> elements = new(profile.GetAllRenderElements());
|
||||
|
||||
ProfileElements.AddRange(elements.OrderBy(e => e.Order));
|
||||
_selectedProfileElement = _node.ProfileElement;
|
||||
NotifyOfPropertyChange(nameof(SelectedProfileElement));
|
||||
}
|
||||
|
||||
private void GetLayerProperties()
|
||||
{
|
||||
LayerProperties.Clear();
|
||||
if (_node.ProfileElement == null)
|
||||
return;
|
||||
|
||||
LayerProperties.AddRange(_node.ProfileElement.GetAllLayerProperties().Where(l => !l.IsHidden && l.DataBindingsSupported));
|
||||
_selectedLayerProperty = _node.LayerProperty;
|
||||
NotifyOfPropertyChange(nameof(SelectedLayerProperty));
|
||||
}
|
||||
|
||||
public override void OnActivate()
|
||||
{
|
||||
GetProfileElements();
|
||||
GetLayerProperties();
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
{
|
||||
base.OnDeactivate();
|
||||
}
|
||||
_node = node;
|
||||
}
|
||||
|
||||
public ObservableCollection<RenderProfileElement> ProfileElements { get; } = new();
|
||||
|
||||
// public RenderProfileElement SelectedProfileElement
|
||||
// {
|
||||
// get => _selectedProfileElement;
|
||||
// set
|
||||
// {
|
||||
// if (!SetAndNotify(ref _selectedProfileElement, value)) return;
|
||||
// _node.ChangeProfileElement(_selectedProfileElement);
|
||||
// GetLayerProperties();
|
||||
// }
|
||||
// }
|
||||
|
||||
public ObservableCollection<ILayerProperty> LayerProperties { get; } = new();
|
||||
|
||||
// public ILayerProperty SelectedLayerProperty
|
||||
// {
|
||||
// get => _selectedLayerProperty;
|
||||
// set
|
||||
// {
|
||||
// if (!SetAndNotify(ref _selectedLayerProperty, value)) return;
|
||||
// _node.ChangeLayerProperty(_selectedLayerProperty);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private void GetProfileElements()
|
||||
// {
|
||||
// ProfileElements.Clear();
|
||||
// if (_node.Script.Context is not Profile profile)
|
||||
// return;
|
||||
//
|
||||
// List<RenderProfileElement> elements = new(profile.GetAllRenderElements());
|
||||
//
|
||||
// ProfileElements.AddRange(elements.OrderBy(e => e.Order));
|
||||
// _selectedProfileElement = _node.ProfileElement;
|
||||
// NotifyOfPropertyChange(nameof(SelectedProfileElement));
|
||||
// }
|
||||
//
|
||||
// private void GetLayerProperties()
|
||||
// {
|
||||
// LayerProperties.Clear();
|
||||
// if (_node.ProfileElement == null)
|
||||
// return;
|
||||
//
|
||||
// LayerProperties.AddRange(_node.ProfileElement.GetAllLayerProperties().Where(l => !l.IsHidden && l.DataBindingsSupported));
|
||||
// _selectedLayerProperty = _node.LayerProperty;
|
||||
// NotifyOfPropertyChange(nameof(SelectedLayerProperty));
|
||||
// }
|
||||
//
|
||||
// public override void OnActivate()
|
||||
// {
|
||||
// GetProfileElements();
|
||||
// GetLayerProperties();
|
||||
// }
|
||||
}
|
||||
@@ -1,18 +1,47 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.Services.NodeEditor;
|
||||
using Artemis.UI.Shared.Services.NodeEditor.Commands;
|
||||
using Artemis.UI.Shared.VisualScripting;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
|
||||
public class StaticNumericValueNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
public class StaticNumericValueNodeCustomViewModel : CustomNodeViewModel
|
||||
private readonly StaticNumericValueNode _node;
|
||||
private readonly INodeEditorService _nodeEditorService;
|
||||
|
||||
public StaticNumericValueNodeCustomViewModel(StaticNumericValueNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script)
|
||||
{
|
||||
public StaticNumericValueNodeCustomViewModel(INode node) : base(node)
|
||||
{
|
||||
}
|
||||
_node = node;
|
||||
_nodeEditorService = nodeEditorService;
|
||||
|
||||
NodeModified += (_, _) => this.RaisePropertyChanged(nameof(CurrentValue));
|
||||
}
|
||||
|
||||
public class StaticStringValueNodeCustomViewModel : CustomNodeViewModel
|
||||
public Numeric? CurrentValue
|
||||
{
|
||||
public StaticStringValueNodeCustomViewModel(INode node) : base(node)
|
||||
{
|
||||
}
|
||||
get => _node.Storage;
|
||||
set => _nodeEditorService.ExecuteCommand(Script, new UpdateStorage<Numeric>(_node, value ?? new Numeric()));
|
||||
}
|
||||
}
|
||||
|
||||
public class StaticStringValueNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
private readonly StaticStringValueNode _node;
|
||||
private readonly INodeEditorService _nodeEditorService;
|
||||
|
||||
public StaticStringValueNodeCustomViewModel(StaticStringValueNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script)
|
||||
{
|
||||
_node = node;
|
||||
_nodeEditorService = nodeEditorService;
|
||||
|
||||
NodeModified += (_, _) => this.RaisePropertyChanged(nameof(CurrentValue));
|
||||
}
|
||||
|
||||
public string? CurrentValue
|
||||
{
|
||||
get => _node.Storage;
|
||||
set => _nodeEditorService.ExecuteCommand(Script, new UpdateStorage<string>(_node, value));
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<UserControl x:Class="Artemis.VisualScripting.Nodes.CustomViews.EnumEqualsNodeCustomView"
|
||||
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.CustomViews"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<ComboBox Width="140"
|
||||
materialDesign:ComboBoxAssist.ClassicMode="True"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
SelectedValue="{Binding Node.Storage}"
|
||||
ItemsSource="{Binding EnumValues}"
|
||||
SelectedValuePath="Value"
|
||||
DisplayMemberPath="Description">
|
||||
<ComboBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ComboBox.ItemsPanel>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -1,18 +0,0 @@
|
||||
<UserControl x:Class="Artemis.VisualScripting.Nodes.CustomViews.LayerPropertyNodeCustomView"
|
||||
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.CustomViews"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel>
|
||||
<ComboBox Margin="8 0"
|
||||
ItemsSource="{Binding ProfileElements}"
|
||||
SelectedValue="{Binding SelectedProfileElement}" />
|
||||
<ComboBox Margin="8 0"
|
||||
ItemsSource="{Binding LayerProperties}"
|
||||
SelectedValue="{Binding SelectedLayerProperty}"
|
||||
DisplayMemberPath="PropertyDescription.Name"/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,20 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:customViewModels="clr-namespace:Artemis.VisualScripting.Nodes.CustomViewModels"
|
||||
xmlns:converters="clr-namespace:Artemis.VisualScripting.Converters"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:behaviors="clr-namespace:Artemis.UI.Shared.Behaviors;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.VisualScripting.Nodes.CustomViews.StaticNumericValueNodeCustomView"
|
||||
x:DataType="customViewModels:StaticNumericValueNodeCustomViewModel">
|
||||
<UserControl.Resources>
|
||||
<converters:NumericConverter x:Key="NumericConverter" />
|
||||
</UserControl.Resources>
|
||||
<controls:NumberBox VerticalAlignment="Center" MinWidth="75" SimpleNumberFormat="F3" Classes="condensed">
|
||||
<Interaction.Behaviors>
|
||||
<behaviors:LostFocusNumberBoxBindingBehavior Value="{CompiledBinding CurrentValue, Converter={StaticResource NumericConverter}}"/>
|
||||
</Interaction.Behaviors>
|
||||
</controls:NumberBox>
|
||||
</UserControl>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViews
|
||||
{
|
||||
public partial class StaticNumericValueNodeCustomView : ReactiveUserControl<StaticNumericValueNodeCustomViewModel>
|
||||
{
|
||||
public StaticNumericValueNodeCustomView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<UserControl x:Class="Artemis.VisualScripting.Nodes.CustomViews.StaticNumericValueNodeCustomView"
|
||||
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:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<shared:StringToNumericConverter x:Key="StringToNumericConverter"/>
|
||||
</UserControl.Resources>
|
||||
<TextBox VerticalAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding Node.Storage, Converter={StaticResource StringToNumericConverter}}" />
|
||||
</UserControl>
|
||||
@@ -0,0 +1,15 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:customViewModels="clr-namespace:Artemis.VisualScripting.Nodes.CustomViewModels"
|
||||
xmlns:behaviors="clr-namespace:Artemis.UI.Shared.Behaviors;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.VisualScripting.Nodes.CustomViews.StaticStringValueNodeCustomView"
|
||||
x:DataType="customViewModels:StaticStringValueNodeCustomViewModel">
|
||||
<TextBox VerticalAlignment="Center" MinWidth="75" Classes="condensed">
|
||||
<Interaction.Behaviors>
|
||||
<behaviors:LostFocusTextBoxBindingBehavior Text="{CompiledBinding CurrentValue}"/>
|
||||
</Interaction.Behaviors>
|
||||
</TextBox>
|
||||
</UserControl>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.CustomViews
|
||||
{
|
||||
public partial class StaticStringValueNodeCustomView : ReactiveUserControl<StaticStringValueNodeCustomViewModel>
|
||||
{
|
||||
public StaticStringValueNodeCustomView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<UserControl x:Class="Artemis.VisualScripting.Nodes.CustomViews.StaticStringValueNodeCustomView"
|
||||
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.CustomViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<TextBox VerticalAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding Node.Storage}" />
|
||||
</UserControl>
|
||||
+79
-49
@@ -1,75 +1,105 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reactive.Disposables;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
using Stylet;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.UI.Shared.Services.NodeEditor;
|
||||
using Artemis.UI.Shared.Services.NodeEditor.Commands;
|
||||
using Artemis.UI.Shared.VisualScripting;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
|
||||
|
||||
public class DataModelEventNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
public class DataModelEventNodeCustomViewModel : CustomNodeViewModel
|
||||
private readonly DataModelEventNode _node;
|
||||
private readonly INodeEditorService _nodeEditorService;
|
||||
private bool _updating;
|
||||
private DataModelPath? _dataModelPath;
|
||||
private ObservableCollection<Module>? _modules;
|
||||
|
||||
public DataModelEventNodeCustomViewModel(DataModelEventNode node, INodeScript script, ISettingsService settingsService, INodeEditorService nodeEditorService) : base(node, script)
|
||||
{
|
||||
private readonly DataModelEventNode _node;
|
||||
private BindableCollection<Module> _modules;
|
||||
_node = node;
|
||||
_nodeEditorService = nodeEditorService;
|
||||
|
||||
public DataModelEventNodeCustomViewModel(DataModelEventNode node, ISettingsService settingsService) : base(node)
|
||||
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
|
||||
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
||||
Modules = new ObservableCollection<Module>();
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
_node = node;
|
||||
// Set up extra modules
|
||||
if (_node.Script?.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
|
||||
Modules = new ObservableCollection<Module> {scriptProfile.Configuration.Module};
|
||||
else if (_node.Script?.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
|
||||
Modules = new ObservableCollection<Module> {profileConfiguration.Module};
|
||||
|
||||
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
|
||||
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
||||
}
|
||||
// Subscribe to node changes
|
||||
_node.WhenAnyValue(n => n.Storage).Subscribe(UpdateDataModelPath).DisposeWith(d);
|
||||
this.WhenAnyValue(vm => vm.DataModelPath).Subscribe(ApplyDataModelPath).DisposeWith(d);
|
||||
|
||||
public PluginSetting<bool> ShowFullPaths { get; }
|
||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
||||
public BindableCollection<Type> FilterTypes { get; } = new() { typeof(IDataModelEvent) };
|
||||
|
||||
public BindableCollection<Module> Modules
|
||||
{
|
||||
get => _modules;
|
||||
set => SetAndNotify(ref _modules, value);
|
||||
}
|
||||
|
||||
public DataModelPath DataModelPath
|
||||
{
|
||||
get => _node.DataModelPath;
|
||||
set
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
if (ReferenceEquals(_node.DataModelPath, value))
|
||||
return;
|
||||
_dataModelPath?.Dispose();
|
||||
_dataModelPath = null;
|
||||
}).DisposeWith(d);
|
||||
});
|
||||
}
|
||||
|
||||
_node.DataModelPath?.Dispose();
|
||||
_node.DataModelPath = value;
|
||||
_node.DataModelPath.Save();
|
||||
public PluginSetting<bool> ShowFullPaths { get; }
|
||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
||||
public ObservableCollection<Type> FilterTypes { get; } = new() {typeof(IDataModelEvent)};
|
||||
|
||||
_node.Storage = _node.DataModelPath.Entity;
|
||||
}
|
||||
}
|
||||
public ObservableCollection<Module>? Modules
|
||||
{
|
||||
get => _modules;
|
||||
set => RaiseAndSetIfChanged(ref _modules, value);
|
||||
}
|
||||
|
||||
public override void OnActivate()
|
||||
public DataModelPath? DataModelPath
|
||||
{
|
||||
get => _dataModelPath;
|
||||
set => RaiseAndSetIfChanged(ref _dataModelPath, value);
|
||||
}
|
||||
|
||||
private void UpdateDataModelPath(DataModelPathEntity? entity)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Modules != null)
|
||||
if (_updating)
|
||||
return;
|
||||
|
||||
Modules = new BindableCollection<Module>();
|
||||
if (_node.Script.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
|
||||
Modules.Add(scriptProfile.Configuration.Module);
|
||||
else if (_node.Script.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
|
||||
Modules.Add(profileConfiguration.Module);
|
||||
_updating = true;
|
||||
|
||||
_node.PropertyChanged += NodeOnPropertyChanged;
|
||||
DataModelPath? old = DataModelPath;
|
||||
DataModelPath = entity != null ? new DataModelPath(entity) : null;
|
||||
old?.Dispose();
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
finally
|
||||
{
|
||||
_node.PropertyChanged -= NodeOnPropertyChanged;
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
private void ApplyDataModelPath(DataModelPath? path)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.PropertyName == nameof(DataModelNode.DataModelPath))
|
||||
OnPropertyChanged(nameof(DataModelPath));
|
||||
if (_updating)
|
||||
return;
|
||||
if (path?.Path == _node.Storage?.Path)
|
||||
return;
|
||||
|
||||
_updating = true;
|
||||
|
||||
path?.Save();
|
||||
_nodeEditorService.ExecuteCommand(Script, new UpdateStorage<DataModelPathEntity>(_node, path?.Entity, "event"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+78
-48
@@ -1,74 +1,104 @@
|
||||
using System.ComponentModel;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Reactive.Disposables;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
using Stylet;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.UI.Shared.Services.NodeEditor;
|
||||
using Artemis.UI.Shared.Services.NodeEditor.Commands;
|
||||
using Artemis.UI.Shared.VisualScripting;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
|
||||
|
||||
public class DataModelNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
public class DataModelNodeCustomViewModel : CustomNodeViewModel
|
||||
private readonly DataModelNode _node;
|
||||
private readonly INodeEditorService _nodeEditorService;
|
||||
private ObservableCollection<Module>? _modules;
|
||||
private DataModelPath? _dataModelPath;
|
||||
private bool _updating;
|
||||
|
||||
public DataModelNodeCustomViewModel(DataModelNode node, INodeScript script, ISettingsService settingsService, INodeEditorService nodeEditorService) : base(node, script)
|
||||
{
|
||||
private readonly DataModelNode _node;
|
||||
private BindableCollection<Module> _modules;
|
||||
_node = node;
|
||||
_nodeEditorService = nodeEditorService;
|
||||
|
||||
public DataModelNodeCustomViewModel(DataModelNode node, ISettingsService settingsService) : base(node)
|
||||
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
|
||||
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
_node = node;
|
||||
// Set up extra modules
|
||||
if (_node.Script?.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
|
||||
Modules = new ObservableCollection<Module> {scriptProfile.Configuration.Module};
|
||||
else if (_node.Script?.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
|
||||
Modules = new ObservableCollection<Module> {profileConfiguration.Module};
|
||||
|
||||
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
|
||||
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
||||
}
|
||||
// Subscribe to node changes
|
||||
_node.WhenAnyValue(n => n.Storage).Subscribe(UpdateDataModelPath).DisposeWith(d);
|
||||
this.WhenAnyValue(vm => vm.DataModelPath).Subscribe(ApplyDataModelPath).DisposeWith(d);
|
||||
|
||||
public PluginSetting<bool> ShowFullPaths { get; }
|
||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
||||
|
||||
public BindableCollection<Module> Modules
|
||||
{
|
||||
get => _modules;
|
||||
set => SetAndNotify(ref _modules, value);
|
||||
}
|
||||
|
||||
public DataModelPath DataModelPath
|
||||
{
|
||||
get => _node.DataModelPath;
|
||||
set
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
if (ReferenceEquals(_node.DataModelPath, value))
|
||||
return;
|
||||
_dataModelPath?.Dispose();
|
||||
_dataModelPath = null;
|
||||
}).DisposeWith(d);
|
||||
});
|
||||
}
|
||||
|
||||
_node.DataModelPath?.Dispose();
|
||||
_node.DataModelPath = value;
|
||||
_node.DataModelPath.Save();
|
||||
public PluginSetting<bool> ShowFullPaths { get; }
|
||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
||||
|
||||
_node.Storage = _node.DataModelPath.Entity;
|
||||
_node.UpdateOutputPin(false);
|
||||
}
|
||||
}
|
||||
public ObservableCollection<Module>? Modules
|
||||
{
|
||||
get => _modules;
|
||||
set => RaiseAndSetIfChanged(ref _modules, value);
|
||||
}
|
||||
|
||||
public override void OnActivate()
|
||||
public DataModelPath? DataModelPath
|
||||
{
|
||||
get => _dataModelPath;
|
||||
set => RaiseAndSetIfChanged(ref _dataModelPath, value);
|
||||
}
|
||||
|
||||
private void UpdateDataModelPath(DataModelPathEntity? entity)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Modules != null)
|
||||
if (_updating)
|
||||
return;
|
||||
|
||||
Modules = new BindableCollection<Module>();
|
||||
if (_node.Script.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null)
|
||||
Modules.Add(scriptProfile.Configuration.Module);
|
||||
else if (_node.Script.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null)
|
||||
Modules.Add(profileConfiguration.Module);
|
||||
_updating = true;
|
||||
|
||||
_node.PropertyChanged += NodeOnPropertyChanged;
|
||||
DataModelPath? old = DataModelPath;
|
||||
DataModelPath = entity != null ? new DataModelPath(entity) : null;
|
||||
old?.Dispose();
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
finally
|
||||
{
|
||||
_node.PropertyChanged -= NodeOnPropertyChanged;
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
private void ApplyDataModelPath(DataModelPath? path)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.PropertyName == nameof(DataModelNode.DataModelPath))
|
||||
OnPropertyChanged(nameof(DataModelPath));
|
||||
if (_updating)
|
||||
return;
|
||||
if (path?.Path == _node.Storage?.Path)
|
||||
return;
|
||||
|
||||
_updating = true;
|
||||
|
||||
path?.Save();
|
||||
_nodeEditorService.ExecuteCommand(Script, new UpdateStorage<DataModelPathEntity>(_node, path?.Entity, "path"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||
xmlns:customViewModels="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.CustomViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelEventNodeCustomView"
|
||||
x:DataType="customViewModels:DataModelEventNodeCustomViewModel">
|
||||
<dataModelPicker:DataModelPickerButton Classes="condensed"
|
||||
DataModelPath="{CompiledBinding DataModelPath}"
|
||||
Modules="{CompiledBinding Modules}"
|
||||
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
|
||||
FilterTypes="{CompiledBinding FilterTypes}"
|
||||
VerticalAlignment="Top"/>
|
||||
</UserControl>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViews
|
||||
{
|
||||
public partial class DataModelEventNodeCustomView : ReactiveUserControl<DataModelEventNodeCustomViewModel>
|
||||
{
|
||||
public DataModelEventNodeCustomView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
<UserControl x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelEventNodeCustomView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Artemis.VisualScripting.Nodes.CustomViews"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
xmlns:editor="clr-namespace:Artemis.VisualScripting.Editor.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<controls:DataModelPicker DataModelPath="{Binding DataModelPath}"
|
||||
Modules="{Binding Modules}"
|
||||
ShowFullPath="{Binding ShowFullPaths.Value}"
|
||||
ShowDataModelValues="{Binding ShowDataModelValues.Value}"
|
||||
FilterTypes="{Binding FilterTypes}"
|
||||
ButtonBrush="DarkGoldenrod"/>
|
||||
</StackPanel>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,14 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||
xmlns:customViewModels="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.CustomViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelNodeCustomView"
|
||||
x:DataType="customViewModels:DataModelNodeCustomViewModel">
|
||||
<dataModelPicker:DataModelPickerButton Classes="condensed"
|
||||
DataModelPath="{CompiledBinding DataModelPath}"
|
||||
Modules="{CompiledBinding Modules}"
|
||||
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}" />
|
||||
</UserControl>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViews
|
||||
{
|
||||
public partial class DataModelNodeCustomView : ReactiveUserControl<DataModelNodeCustomViewModel>
|
||||
{
|
||||
public DataModelNodeCustomView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<UserControl x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelNodeCustomView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Artemis.VisualScripting.Nodes.CustomViews"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<controls:DataModelPicker DataModelPath="{Binding DataModelPath}"
|
||||
Modules="{Binding Modules}"
|
||||
ShowFullPath="{Binding ShowFullPaths.Value}"
|
||||
ShowDataModelValues="{Binding ShowDataModelValues.Value}"
|
||||
ButtonBrush="#434343"/>
|
||||
</UserControl>
|
||||
@@ -1,191 +1,151 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ComponentModel;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Events;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel;
|
||||
|
||||
[Node("Data Model-Event", "Responds to a data model event trigger", "Data Model", OutputType = typeof(bool))]
|
||||
public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCustomViewModel>, IDisposable
|
||||
{
|
||||
[Node("Data Model-Event", "Responds to a data model event trigger", "Data Model", OutputType = typeof(bool))]
|
||||
public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCustomViewModel>, IDisposable
|
||||
private int _currentIndex;
|
||||
private Type _currentType;
|
||||
private DataModelPath? _dataModelPath;
|
||||
private DateTime _lastTrigger;
|
||||
private bool _updating;
|
||||
|
||||
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
|
||||
{
|
||||
private DataModelPath _dataModelPath;
|
||||
private DateTime _lastTrigger;
|
||||
private int _currentIndex;
|
||||
private Type _currentType;
|
||||
private bool _updating;
|
||||
_currentType = typeof(object);
|
||||
|
||||
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
|
||||
{
|
||||
_currentType = typeof(object);
|
||||
CreateCycleValues(typeof(object), 1);
|
||||
Output = CreateOutputPin(typeof(object));
|
||||
}
|
||||
CycleValues = CreateInputPinCollection(typeof(object), "", 0);
|
||||
Output = CreateOutputPin(typeof(object));
|
||||
|
||||
private void CreateCycleValues(Type type, int initialCount)
|
||||
CycleValues.PinAdded += CycleValuesOnPinAdded;
|
||||
CycleValues.PinRemoved += CycleValuesOnPinRemoved;
|
||||
CycleValues.Add(CycleValues.CreatePin());
|
||||
|
||||
// Monitor storage for changes
|
||||
StorageModified += (_, _) => UpdateDataModelPath();
|
||||
}
|
||||
|
||||
public INodeScript? Script { get; set; }
|
||||
|
||||
public InputPinCollection CycleValues { get; }
|
||||
public OutputPin Output { get; }
|
||||
|
||||
public override void Initialize(INodeScript script)
|
||||
{
|
||||
Script = script;
|
||||
|
||||
if (Storage == null)
|
||||
return;
|
||||
|
||||
UpdateDataModelPath();
|
||||
}
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
object? outputValue = null;
|
||||
if (_dataModelPath?.GetValue() is IDataModelEvent dataModelEvent)
|
||||
{
|
||||
if (CycleValues != null)
|
||||
if (dataModelEvent.LastTrigger > _lastTrigger)
|
||||
{
|
||||
CycleValues.PinAdded -= CycleValuesOnPinAdded;
|
||||
CycleValues.PinRemoved -= CycleValuesOnPinRemoved;
|
||||
foreach (IPin pin in CycleValues)
|
||||
{
|
||||
pin.PinConnected -= OnPinConnected;
|
||||
pin.PinDisconnected -= OnPinDisconnected;
|
||||
}
|
||||
_lastTrigger = dataModelEvent.LastTrigger;
|
||||
_currentIndex++;
|
||||
|
||||
RemovePinCollection(CycleValues);
|
||||
if (_currentIndex >= CycleValues.Count())
|
||||
_currentIndex = 0;
|
||||
}
|
||||
|
||||
CycleValues = CreateInputPinCollection(type, "", initialCount);
|
||||
CycleValues.PinAdded += CycleValuesOnPinAdded;
|
||||
CycleValues.PinRemoved += CycleValuesOnPinRemoved;
|
||||
foreach (IPin pin in CycleValues)
|
||||
{
|
||||
pin.PinConnected += OnPinConnected;
|
||||
pin.PinDisconnected += OnPinDisconnected;
|
||||
}
|
||||
outputValue = CycleValues.ElementAt(_currentIndex).PinValue;
|
||||
}
|
||||
|
||||
private void CycleValuesOnPinAdded(object sender, SingleValueEventArgs<IPin> e)
|
||||
if (Output.Type.IsInstanceOfType(outputValue))
|
||||
Output.Value = outputValue;
|
||||
else if (Output.Type.IsValueType)
|
||||
Output.Value = Output.Type.GetDefault()!;
|
||||
}
|
||||
|
||||
private void CycleValuesOnPinAdded(object? sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
e.Value.PinConnected += OnPinConnected;
|
||||
e.Value.PinDisconnected += OnPinDisconnected;
|
||||
}
|
||||
|
||||
private void CycleValuesOnPinRemoved(object? sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
e.Value.PinConnected -= OnPinConnected;
|
||||
e.Value.PinDisconnected -= OnPinDisconnected;
|
||||
}
|
||||
|
||||
private void OnPinDisconnected(object? sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
ProcessPinDisconnected();
|
||||
}
|
||||
|
||||
private void OnPinConnected(object? sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
ProcessPinConnected(e.Value);
|
||||
}
|
||||
|
||||
private void ProcessPinConnected(IPin source)
|
||||
{
|
||||
if (_updating)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
e.Value.PinConnected += OnPinConnected;
|
||||
e.Value.PinDisconnected += OnPinDisconnected;
|
||||
}
|
||||
_updating = true;
|
||||
|
||||
private void CycleValuesOnPinRemoved(object sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
e.Value.PinConnected -= OnPinConnected;
|
||||
e.Value.PinDisconnected -= OnPinDisconnected;
|
||||
}
|
||||
|
||||
private void OnPinDisconnected(object sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
ProcessPinDisconnected();
|
||||
}
|
||||
|
||||
private void OnPinConnected(object sender, SingleValueEventArgs<IPin> e)
|
||||
{
|
||||
IPin source = e.Value;
|
||||
IPin target = (IPin) sender;
|
||||
ProcessPinConnected(source, target);
|
||||
}
|
||||
|
||||
public InputPinCollection CycleValues { get; set; }
|
||||
public OutputPin Output { get; set; }
|
||||
public INodeScript Script { get; set; }
|
||||
|
||||
public DataModelPath DataModelPath
|
||||
{
|
||||
get => _dataModelPath;
|
||||
set => SetAndNotify(ref _dataModelPath, value);
|
||||
}
|
||||
|
||||
public override void Initialize(INodeScript script)
|
||||
{
|
||||
Script = script;
|
||||
|
||||
if (Storage == null)
|
||||
return;
|
||||
|
||||
DataModelPath = new DataModelPath(Storage);
|
||||
}
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
object outputValue = null;
|
||||
if (DataModelPath?.GetValue() is IDataModelEvent dataModelEvent)
|
||||
{
|
||||
if (dataModelEvent.LastTrigger > _lastTrigger)
|
||||
{
|
||||
_lastTrigger = dataModelEvent.LastTrigger;
|
||||
_currentIndex++;
|
||||
|
||||
if (_currentIndex >= CycleValues.Count())
|
||||
_currentIndex = 0;
|
||||
}
|
||||
|
||||
outputValue = CycleValues.ElementAt(_currentIndex).PinValue;
|
||||
}
|
||||
|
||||
if (Output.Type.IsInstanceOfType(outputValue))
|
||||
Output.Value = outputValue;
|
||||
else if (Output.Type.IsValueType)
|
||||
Output.Value = Output.Type.GetDefault()!;
|
||||
}
|
||||
|
||||
private void ProcessPinConnected(IPin source, IPin target)
|
||||
{
|
||||
if (_updating)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_updating = true;
|
||||
|
||||
// No need to change anything if the types haven't changed
|
||||
if (_currentType == source.Type)
|
||||
return;
|
||||
|
||||
int reconnectIndex = CycleValues.ToList().IndexOf(target);
|
||||
// No need to change anything if the types haven't changed
|
||||
if (_currentType != source.Type)
|
||||
ChangeCurrentType(source.Type);
|
||||
|
||||
if (reconnectIndex != -1)
|
||||
{
|
||||
CycleValues.ToList()[reconnectIndex].ConnectTo(source);
|
||||
source.ConnectTo(CycleValues.ToList()[reconnectIndex]);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeCurrentType(Type type)
|
||||
{
|
||||
CreateCycleValues(type, CycleValues.Count());
|
||||
|
||||
List<IPin> oldOutputConnections = Output.ConnectedTo.ToList();
|
||||
RemovePin(Output);
|
||||
Output = CreateOutputPin(type);
|
||||
foreach (IPin oldOutputConnection in oldOutputConnections.Where(o => o.Type.IsAssignableFrom(Output.Type)))
|
||||
{
|
||||
oldOutputConnection.DisconnectAll();
|
||||
oldOutputConnection.ConnectTo(Output);
|
||||
Output.ConnectTo(oldOutputConnection);
|
||||
}
|
||||
|
||||
_currentType = type;
|
||||
}
|
||||
|
||||
private void ProcessPinDisconnected()
|
||||
{
|
||||
if (_updating)
|
||||
return;
|
||||
try
|
||||
{
|
||||
// If there's still a connected pin, stick to the current type
|
||||
if (CycleValues.Any(v => v.ConnectedTo.Any()))
|
||||
return;
|
||||
|
||||
ChangeCurrentType(typeof(object));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePinsType(IPin source)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
finally
|
||||
{
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void UpdateDataModelPath()
|
||||
{
|
||||
DataModelPath? old = _dataModelPath;
|
||||
_dataModelPath = Storage != null ? new DataModelPath(Storage) : null;
|
||||
old?.Dispose();
|
||||
}
|
||||
|
||||
private void ChangeCurrentType(Type type)
|
||||
{
|
||||
CycleValues.ChangeType(type);
|
||||
Output.ChangeType(type);
|
||||
|
||||
_currentType = type;
|
||||
}
|
||||
|
||||
private void ProcessPinDisconnected()
|
||||
{
|
||||
if (_updating)
|
||||
return;
|
||||
try
|
||||
{
|
||||
// If there's still a connected pin, stick to the current type
|
||||
if (CycleValues.Any(v => v.ConnectedTo.Any()))
|
||||
return;
|
||||
|
||||
ChangeCurrentType(typeof(object));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
_dataModelPath?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,97 +1,82 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Artemis.Core;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
|
||||
using Stylet;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel
|
||||
namespace Artemis.VisualScripting.Nodes.DataModel;
|
||||
|
||||
[Node("Data Model-Value", "Outputs a selectable data model value.", "Data Model")]
|
||||
public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewModel>, IDisposable
|
||||
{
|
||||
[Node("Data Model-Value", "Outputs a selectable data model value.", "Data Model")]
|
||||
public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewModel>, IDisposable
|
||||
private DataModelPath? _dataModelPath;
|
||||
|
||||
public DataModelNode() : base("Data Model", "Outputs a selectable data model value")
|
||||
{
|
||||
private DataModelPath _dataModelPath;
|
||||
Output = CreateOutputPin(typeof(object));
|
||||
StorageModified += (_, _) => UpdateDataModelPath();
|
||||
}
|
||||
|
||||
public DataModelNode() : base("Data Model", "Outputs a selectable data model value")
|
||||
public INodeScript? Script { get; private set; }
|
||||
public OutputPin Output { get; }
|
||||
|
||||
public override void Initialize(INodeScript script)
|
||||
{
|
||||
Script = script;
|
||||
|
||||
if (Storage == null)
|
||||
return;
|
||||
|
||||
UpdateDataModelPath();
|
||||
}
|
||||
|
||||
private void UpdateDataModelPath()
|
||||
{
|
||||
DataModelPath? old = _dataModelPath;
|
||||
old?.Dispose();
|
||||
|
||||
_dataModelPath = Storage != null ? new DataModelPath(Storage) : null;
|
||||
if (_dataModelPath != null)
|
||||
_dataModelPath.PathValidated += DataModelPathOnPathValidated;
|
||||
UpdateOutputPin();
|
||||
}
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
if (_dataModelPath == null || !_dataModelPath.IsValid)
|
||||
return;
|
||||
|
||||
object? pathValue = _dataModelPath.GetValue();
|
||||
if (pathValue == null)
|
||||
{
|
||||
if (!Output.Type.IsValueType)
|
||||
Output.Value = null;
|
||||
}
|
||||
|
||||
public INodeScript Script { get; private set; }
|
||||
public OutputPin Output { get; private set; }
|
||||
|
||||
public DataModelPath DataModelPath
|
||||
else
|
||||
{
|
||||
get => _dataModelPath;
|
||||
set => SetAndNotify(ref _dataModelPath, value);
|
||||
}
|
||||
|
||||
public override void Initialize(INodeScript script)
|
||||
{
|
||||
Script = script;
|
||||
|
||||
if (Storage == null)
|
||||
return;
|
||||
|
||||
DataModelPath = new DataModelPath(Storage);
|
||||
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
||||
|
||||
UpdateOutputPin(false);
|
||||
}
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
if (DataModelPath.IsValid)
|
||||
{
|
||||
if (Output == null)
|
||||
UpdateOutputPin(false);
|
||||
|
||||
object pathValue = DataModelPath.GetValue();
|
||||
|
||||
if (pathValue == null)
|
||||
{
|
||||
if (!Output.Type.IsValueType)
|
||||
Output.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Output.Type == typeof(Numeric))
|
||||
Output.Value = new Numeric(pathValue);
|
||||
else
|
||||
Output.Value = pathValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateOutputPin(bool loadConnections)
|
||||
{
|
||||
Type type = DataModelPath?.GetPropertyType();
|
||||
if (Numeric.IsTypeCompatible(type))
|
||||
type = typeof(Numeric);
|
||||
|
||||
if (Output != null && Output.Type == type)
|
||||
return;
|
||||
|
||||
if (Output != null)
|
||||
{
|
||||
RemovePin(Output);
|
||||
Output = null;
|
||||
}
|
||||
|
||||
if (type != null)
|
||||
Output = CreateOutputPin(type);
|
||||
|
||||
if (loadConnections && Script is NodeScript nodeScript)
|
||||
nodeScript.LoadConnections();
|
||||
}
|
||||
|
||||
private void DataModelPathOnPathValidated(object sender, EventArgs e)
|
||||
{
|
||||
Execute.OnUIThread(() => UpdateOutputPin(true));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
DataModelPath?.Dispose();
|
||||
Output.Value = Output.Type == typeof(Numeric) ? new Numeric(pathValue) : pathValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateOutputPin()
|
||||
{
|
||||
Type? type = _dataModelPath?.GetPropertyType();
|
||||
if (Numeric.IsTypeCompatible(type))
|
||||
type = typeof(Numeric);
|
||||
type ??= typeof(object);
|
||||
|
||||
if (Output.Type != type)
|
||||
Output.ChangeType(type);
|
||||
}
|
||||
|
||||
private void DataModelPathOnPathValidated(object? sender, EventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(UpdateOutputPin);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
_dataModelPath?.Dispose();
|
||||
}
|
||||
}
|
||||
+45
-49
@@ -1,58 +1,54 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Collections.ObjectModel;
|
||||
using Artemis.Core;
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
using Stylet;
|
||||
using Artemis.UI.Shared.VisualScripting;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels;
|
||||
|
||||
public class EasingTypeNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
public class EasingTypeNodeCustomViewModel : CustomNodeViewModel
|
||||
private readonly EasingTypeNode _node;
|
||||
private NodeEasingViewModel _selectedEasingViewModel;
|
||||
|
||||
public EasingTypeNodeCustomViewModel(EasingTypeNode node, INodeScript script) : base(node, script)
|
||||
{
|
||||
private readonly EasingTypeNode _node;
|
||||
private NodeEasingViewModel _selectedEasingViewModel;
|
||||
_node = node;
|
||||
EasingViewModels = new ObservableCollection<NodeEasingViewModel>(Enum.GetValues(typeof(Easings.Functions)).Cast<Easings.Functions>().Select(e => new NodeEasingViewModel(e)));
|
||||
}
|
||||
|
||||
public EasingTypeNodeCustomViewModel(EasingTypeNode node) : base(node)
|
||||
public ObservableCollection<NodeEasingViewModel> EasingViewModels { get; }
|
||||
|
||||
public NodeEasingViewModel SelectedEasingViewModel
|
||||
{
|
||||
get => _selectedEasingViewModel;
|
||||
set
|
||||
{
|
||||
_node = node;
|
||||
EasingViewModels = new BindableCollection<NodeEasingViewModel>(Enum.GetValues(typeof(Easings.Functions)).Cast<Easings.Functions>().Select(e => new NodeEasingViewModel(e)));
|
||||
}
|
||||
|
||||
public BindableCollection<NodeEasingViewModel> EasingViewModels { get; }
|
||||
|
||||
public NodeEasingViewModel SelectedEasingViewModel
|
||||
{
|
||||
get => _selectedEasingViewModel;
|
||||
set
|
||||
{
|
||||
_selectedEasingViewModel = value;
|
||||
_node.Storage = _selectedEasingViewModel.EasingFunction;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnActivate()
|
||||
{
|
||||
_node.PropertyChanged += NodeOnPropertyChanged;
|
||||
SelectedEasingViewModel = GetNodeEasingViewModel();
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
{
|
||||
_node.PropertyChanged -= NodeOnPropertyChanged;
|
||||
}
|
||||
|
||||
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(_node.Storage))
|
||||
{
|
||||
_selectedEasingViewModel = GetNodeEasingViewModel();
|
||||
NotifyOfPropertyChange(nameof(SelectedEasingViewModel));
|
||||
}
|
||||
}
|
||||
|
||||
private NodeEasingViewModel GetNodeEasingViewModel()
|
||||
{
|
||||
return EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.Storage);
|
||||
_selectedEasingViewModel = value;
|
||||
_node.Storage = _selectedEasingViewModel.EasingFunction;
|
||||
}
|
||||
}
|
||||
|
||||
// public override void OnActivate()
|
||||
// {
|
||||
// _node.PropertyChanged += NodeOnPropertyChanged;
|
||||
// SelectedEasingViewModel = GetNodeEasingViewModel();
|
||||
// }
|
||||
//
|
||||
// public override void OnDeactivate()
|
||||
// {
|
||||
// _node.PropertyChanged -= NodeOnPropertyChanged;
|
||||
// }
|
||||
//
|
||||
// private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
// {
|
||||
// if (e.PropertyName == nameof(_node.Storage))
|
||||
// {
|
||||
// _selectedEasingViewModel = GetNodeEasingViewModel();
|
||||
// NotifyOfPropertyChange(nameof(SelectedEasingViewModel));
|
||||
// }
|
||||
// }
|
||||
|
||||
private NodeEasingViewModel GetNodeEasingViewModel()
|
||||
{
|
||||
return EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.Storage);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,27 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared;
|
||||
using Avalonia;
|
||||
using Humanizer;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels;
|
||||
|
||||
public class NodeEasingViewModel : ViewModelBase
|
||||
{
|
||||
public class NodeEasingViewModel : PropertyChangedBase
|
||||
public NodeEasingViewModel(Easings.Functions easingFunction)
|
||||
{
|
||||
public NodeEasingViewModel(Easings.Functions easingFunction)
|
||||
EasingFunction = easingFunction;
|
||||
Description = easingFunction.Humanize();
|
||||
|
||||
EasingPoints = new List<Point>();
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
EasingFunction = easingFunction;
|
||||
Description = easingFunction.Humanize();
|
||||
|
||||
EasingPoints = new PointCollection();
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
int x = i;
|
||||
double y = Easings.Interpolate(i / 10.0, EasingFunction) * 10;
|
||||
EasingPoints.Add(new Point(x, y));
|
||||
}
|
||||
int x = i;
|
||||
double y = Easings.Interpolate(i / 10.0, EasingFunction) * 10;
|
||||
EasingPoints.Add(new Point(x, y));
|
||||
}
|
||||
|
||||
public Easings.Functions EasingFunction { get; }
|
||||
public PointCollection EasingPoints { get; }
|
||||
public string Description { get; }
|
||||
}
|
||||
|
||||
public Easings.Functions EasingFunction { get; }
|
||||
public List<Point> EasingPoints { get; }
|
||||
public string Description { get; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.VisualScripting.Nodes.Easing.CustomViews.EasingTypeNodeCustomView">
|
||||
<controls:EnumComboBox Classes="condensed" MinWidth="75" Value="{Binding Node.Storage}"/>
|
||||
</UserControl>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using Artemis.VisualScripting.Nodes.Easing.CustomViewModels;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Easing.CustomViews
|
||||
{
|
||||
public partial class EasingTypeNodeCustomView : ReactiveUserControl<EasingTypeNodeCustomViewModel>
|
||||
{
|
||||
public EasingTypeNodeCustomView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<UserControl x:Class="Artemis.VisualScripting.Nodes.Easing.CustomViews.EasingTypeNodeCustomView"
|
||||
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.Easing.CustomViews"
|
||||
xmlns:viewModels="clr-namespace:Artemis.VisualScripting.Nodes.Easing.CustomViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<ComboBox VerticalAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding EasingViewModels}"
|
||||
SelectedItem="{Binding SelectedEasingViewModel}">
|
||||
<ComboBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ComboBox.ItemsPanel>
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type viewModels:NodeEasingViewModel}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Polyline Stroke="{DynamicResource MaterialDesignBody}"
|
||||
StrokeThickness="1.5"
|
||||
Points="{Binding EasingPoints}"
|
||||
Stretch="Uniform"
|
||||
Width="14"
|
||||
Height="14"
|
||||
Margin="0 0 10 0" />
|
||||
<TextBlock Text="{Binding Description}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
</UserControl>
|
||||
@@ -1,21 +1,20 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.VisualScripting.Nodes.Easing.CustomViewModels;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Easing
|
||||
namespace Artemis.VisualScripting.Nodes.Easing;
|
||||
|
||||
[Node("Easing Type", "Outputs a selectable easing type.", "Easing", OutputType = typeof(Easings.Functions))]
|
||||
public class EasingTypeNode : Node<Easings.Functions, EasingTypeNodeCustomViewModel>
|
||||
{
|
||||
[Node("Easing Type", "Outputs a selectable easing type.", "Easing", OutputType = typeof(Easings.Functions))]
|
||||
public class EasingTypeNode : Node<Easings.Functions, EasingTypeNodeCustomViewModel>
|
||||
public EasingTypeNode() : base("Easing Type", "Outputs a selectable easing type.")
|
||||
{
|
||||
public EasingTypeNode() : base("Easing Type", "Outputs a selectable easing type.")
|
||||
{
|
||||
Output = CreateOutputPin<Easings.Functions>();
|
||||
}
|
||||
Output = CreateOutputPin<Easings.Functions>();
|
||||
}
|
||||
|
||||
public OutputPin<Easings.Functions> Output { get; }
|
||||
public OutputPin<Easings.Functions> Output { get; }
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = Storage;
|
||||
}
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = Storage;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +1,66 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Easing
|
||||
namespace Artemis.VisualScripting.Nodes.Easing;
|
||||
|
||||
[Node("Numeric Easing", "Outputs an eased numeric value", "Easing", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
||||
public class NumericEasingNode : Node
|
||||
{
|
||||
[Node("Numeric Easing", "Outputs an eased numeric value", "Easing", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
||||
public class NumericEasingNode : Node
|
||||
private float _currentValue;
|
||||
private DateTime _lastEvaluate = DateTime.MinValue;
|
||||
private float _progress;
|
||||
private float _sourceValue;
|
||||
private float _targetValue;
|
||||
|
||||
public NumericEasingNode() : base("Numeric Easing", "Outputs an eased numeric value")
|
||||
{
|
||||
private DateTime _lastEvaluate = DateTime.MinValue;
|
||||
private float _progress;
|
||||
private float _currentValue;
|
||||
private float _sourceValue;
|
||||
private float _targetValue;
|
||||
Input = CreateInputPin<Numeric>();
|
||||
EasingTime = CreateInputPin<Numeric>("delay");
|
||||
EasingFunction = CreateInputPin<Easings.Functions>("function");
|
||||
|
||||
public NumericEasingNode() : base("Numeric Easing", "Outputs an eased numeric value")
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
}
|
||||
|
||||
public InputPin<Numeric> Input { get; set; }
|
||||
public InputPin<Numeric> EasingTime { get; set; }
|
||||
public InputPin<Easings.Functions> EasingFunction { get; set; }
|
||||
|
||||
public OutputPin<Numeric> Output { get; set; }
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
// If the value changed reset progress
|
||||
if (Math.Abs(_targetValue - Input.Value) > 0.001f)
|
||||
{
|
||||
Input = CreateInputPin<Numeric>();
|
||||
EasingTime = CreateInputPin<Numeric>("delay");
|
||||
EasingFunction = CreateInputPin<Easings.Functions>("function");
|
||||
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
_sourceValue = _currentValue;
|
||||
_targetValue = Input.Value;
|
||||
_progress = 0f;
|
||||
}
|
||||
|
||||
public InputPin<Numeric> Input { get; set; }
|
||||
public InputPin<Numeric> EasingTime { get; set; }
|
||||
public InputPin<Easings.Functions> EasingFunction { get; set; }
|
||||
|
||||
public OutputPin<Numeric> Output { get; set; }
|
||||
|
||||
public override void Evaluate()
|
||||
// Update until finished
|
||||
if (_progress < 1f)
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
// If the value changed reset progress
|
||||
if (Math.Abs(_targetValue - Input.Value) > 0.001f)
|
||||
{
|
||||
_sourceValue = _currentValue;
|
||||
_targetValue = Input.Value;
|
||||
_progress = 0f;
|
||||
}
|
||||
|
||||
// Update until finished
|
||||
if (_progress < 1f)
|
||||
{
|
||||
Update();
|
||||
Output.Value = new Numeric(_currentValue);
|
||||
}
|
||||
// Stop updating past 1 and use the target value
|
||||
else
|
||||
{
|
||||
Output.Value = new Numeric(_targetValue);
|
||||
}
|
||||
|
||||
_lastEvaluate = now;
|
||||
Update();
|
||||
Output.Value = new Numeric(_currentValue);
|
||||
}
|
||||
// Stop updating past 1 and use the target value
|
||||
else
|
||||
{
|
||||
Output.Value = new Numeric(_targetValue);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
TimeSpan delta = DateTime.Now - _lastEvaluate;
|
||||
_lastEvaluate = now;
|
||||
}
|
||||
|
||||
// In case of odd delta's, keep progress between 0f and 1f
|
||||
_progress = Math.Clamp(_progress + (float) delta.TotalMilliseconds / EasingTime.Value, 0f, 1f);
|
||||
private void Update()
|
||||
{
|
||||
TimeSpan delta = DateTime.Now - _lastEvaluate;
|
||||
|
||||
double eased = _sourceValue + (_targetValue - _sourceValue) * Easings.Interpolate(_progress, EasingFunction.Value);
|
||||
_currentValue = (float) eased;
|
||||
}
|
||||
// In case of odd delta's, keep progress between 0f and 1f
|
||||
_progress = Math.Clamp(_progress + (float) delta.TotalMilliseconds / EasingTime.Value, 0f, 1f);
|
||||
|
||||
double eased = _sourceValue + (_targetValue - _sourceValue) * Easings.Interpolate(_progress, EasingFunction.Value);
|
||||
_currentValue = (float) eased;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +1,65 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Easing
|
||||
namespace Artemis.VisualScripting.Nodes.Easing;
|
||||
|
||||
[Node("Color Easing", "Outputs an eased color value", "Easing", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
|
||||
public class SKColorEasingNode : Node
|
||||
{
|
||||
[Node("Color Easing", "Outputs an eased color value", "Easing", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
|
||||
public class SKColorEasingNode : Node
|
||||
private SKColor _currentValue;
|
||||
private DateTime _lastEvaluate = DateTime.MinValue;
|
||||
private float _progress;
|
||||
private SKColor _sourceValue;
|
||||
private SKColor _targetValue;
|
||||
|
||||
public SKColorEasingNode() : base("Color Easing", "Outputs an eased color value")
|
||||
{
|
||||
private DateTime _lastEvaluate = DateTime.MinValue;
|
||||
private float _progress;
|
||||
private SKColor _currentValue;
|
||||
private SKColor _sourceValue;
|
||||
private SKColor _targetValue;
|
||||
Input = CreateInputPin<SKColor>();
|
||||
EasingTime = CreateInputPin<Numeric>("delay");
|
||||
EasingFunction = CreateInputPin<Easings.Functions>("function");
|
||||
|
||||
public SKColorEasingNode() : base("Color Easing", "Outputs an eased color value")
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
}
|
||||
|
||||
public InputPin<SKColor> Input { get; set; }
|
||||
public InputPin<Numeric> EasingTime { get; set; }
|
||||
public InputPin<Easings.Functions> EasingFunction { get; set; }
|
||||
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
// If the value changed reset progress
|
||||
if (_targetValue != Input.Value)
|
||||
{
|
||||
Input = CreateInputPin<SKColor>();
|
||||
EasingTime = CreateInputPin<Numeric>("delay");
|
||||
EasingFunction = CreateInputPin<Easings.Functions>("function");
|
||||
|
||||
Output = CreateOutputPin<SKColor>();
|
||||
_sourceValue = _currentValue;
|
||||
_targetValue = Input.Value;
|
||||
_progress = 0f;
|
||||
}
|
||||
|
||||
public InputPin<SKColor> Input { get; set; }
|
||||
public InputPin<Numeric> EasingTime { get; set; }
|
||||
public InputPin<Easings.Functions> EasingFunction { get; set; }
|
||||
|
||||
public OutputPin<SKColor> Output { get; set; }
|
||||
|
||||
public override void Evaluate()
|
||||
// Update until finished
|
||||
if (_progress < 1f)
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
// If the value changed reset progress
|
||||
if (_targetValue != Input.Value)
|
||||
{
|
||||
_sourceValue = _currentValue;
|
||||
_targetValue = Input.Value;
|
||||
_progress = 0f;
|
||||
}
|
||||
|
||||
// Update until finished
|
||||
if (_progress < 1f)
|
||||
{
|
||||
Update();
|
||||
Output.Value = _currentValue;
|
||||
}
|
||||
// Stop updating past 1 and use the target value
|
||||
else
|
||||
{
|
||||
Output.Value = _targetValue;
|
||||
}
|
||||
|
||||
_lastEvaluate = now;
|
||||
Update();
|
||||
Output.Value = _currentValue;
|
||||
}
|
||||
// Stop updating past 1 and use the target value
|
||||
else
|
||||
{
|
||||
Output.Value = _targetValue;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
TimeSpan delta = DateTime.Now - _lastEvaluate;
|
||||
_lastEvaluate = now;
|
||||
}
|
||||
|
||||
// In case of odd delta's, keep progress between 0f and 1f
|
||||
_progress = Math.Clamp(_progress + (float) delta.TotalMilliseconds / EasingTime.Value, 0f, 1f);
|
||||
_currentValue = _sourceValue.Interpolate(_targetValue, (float) Easings.Interpolate(_progress, EasingFunction.Value));
|
||||
}
|
||||
private void Update()
|
||||
{
|
||||
TimeSpan delta = DateTime.Now - _lastEvaluate;
|
||||
|
||||
// In case of odd delta's, keep progress between 0f and 1f
|
||||
_progress = Math.Clamp(_progress + (float) delta.TotalMilliseconds / EasingTime.Value, 0f, 1f);
|
||||
_currentValue = _sourceValue.Interpolate(_targetValue, (float) Easings.Interpolate(_progress, EasingFunction.Value));
|
||||
}
|
||||
}
|
||||
@@ -1,128 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes
|
||||
namespace Artemis.VisualScripting.Nodes;
|
||||
|
||||
[Node("Layer/Folder Property", "Outputs the property of a selected layer or folder", "External")]
|
||||
public class LayerPropertyNode : Node<LayerPropertyNodeEntity, LayerPropertyNodeCustomViewModel>
|
||||
{
|
||||
[Node("Layer/Folder Property", "Outputs the property of a selected layer or folder", "External")]
|
||||
public class LayerPropertyNode : Node<LayerPropertyNodeEntity, LayerPropertyNodeCustomViewModel>
|
||||
private readonly object _layerPropertyLock = new();
|
||||
|
||||
public INodeScript Script { get; private set; }
|
||||
public RenderProfileElement ProfileElement { get; private set; }
|
||||
public ILayerProperty LayerProperty { get; private set; }
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
private readonly object _layerPropertyLock = new();
|
||||
|
||||
public INodeScript Script { get; private set; }
|
||||
public RenderProfileElement ProfileElement { get; private set; }
|
||||
public ILayerProperty LayerProperty { get; private set; }
|
||||
|
||||
public override void Evaluate()
|
||||
lock (_layerPropertyLock)
|
||||
{
|
||||
lock (_layerPropertyLock)
|
||||
{
|
||||
// In this case remove the pins so no further evaluations occur
|
||||
if (LayerProperty == null)
|
||||
{
|
||||
CreatePins();
|
||||
return;
|
||||
}
|
||||
|
||||
List<IDataBindingProperty> list = LayerProperty.BaseDataBinding.Properties.ToList();
|
||||
int index = 0;
|
||||
foreach (IPin pin in Pins)
|
||||
{
|
||||
OutputPin outputPin = (OutputPin) pin;
|
||||
IDataBindingProperty dataBindingProperty = list[index];
|
||||
index++;
|
||||
|
||||
// TODO: Is this really non-nullable?
|
||||
outputPin.Value = dataBindingProperty.GetValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Initialize(INodeScript script)
|
||||
{
|
||||
Script = script;
|
||||
|
||||
if (script.Context is Profile profile)
|
||||
profile.ChildRemoved += ProfileOnChildRemoved;
|
||||
|
||||
LoadLayerProperty();
|
||||
}
|
||||
|
||||
public void LoadLayerProperty()
|
||||
{
|
||||
lock (_layerPropertyLock)
|
||||
{
|
||||
if (Script.Context is not Profile profile || Storage == null)
|
||||
return;
|
||||
|
||||
RenderProfileElement element = profile.GetAllRenderElements().FirstOrDefault(l => l.EntityId == Storage.ElementId);
|
||||
|
||||
ProfileElement = element;
|
||||
LayerProperty = element?.GetAllLayerProperties().FirstOrDefault(p => p.Path == Storage.PropertyPath);
|
||||
CreatePins();
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeProfileElement(RenderProfileElement profileElement)
|
||||
{
|
||||
lock (_layerPropertyLock)
|
||||
{
|
||||
ProfileElement = profileElement;
|
||||
LayerProperty = null;
|
||||
|
||||
Storage = new LayerPropertyNodeEntity
|
||||
{
|
||||
ElementId = ProfileElement?.EntityId ?? Guid.Empty,
|
||||
PropertyPath = null
|
||||
};
|
||||
|
||||
CreatePins();
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeLayerProperty(ILayerProperty layerProperty)
|
||||
{
|
||||
lock (_layerPropertyLock)
|
||||
{
|
||||
LayerProperty = layerProperty;
|
||||
|
||||
Storage = new LayerPropertyNodeEntity
|
||||
{
|
||||
ElementId = ProfileElement?.EntityId ?? Guid.Empty,
|
||||
PropertyPath = LayerProperty?.Path
|
||||
};
|
||||
|
||||
CreatePins();
|
||||
}
|
||||
}
|
||||
|
||||
private void CreatePins()
|
||||
{
|
||||
while (Pins.Any())
|
||||
RemovePin((Pin) Pins.First());
|
||||
|
||||
// In this case remove the pins so no further evaluations occur
|
||||
if (LayerProperty == null)
|
||||
{
|
||||
CreatePins();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (IDataBindingProperty dataBindingRegistration in LayerProperty.BaseDataBinding.Properties)
|
||||
CreateOutputPin(dataBindingRegistration.ValueType, dataBindingRegistration.DisplayName);
|
||||
}
|
||||
List<IDataBindingProperty> list = LayerProperty.BaseDataBinding.Properties.ToList();
|
||||
int index = 0;
|
||||
foreach (IPin pin in Pins)
|
||||
{
|
||||
OutputPin outputPin = (OutputPin) pin;
|
||||
IDataBindingProperty dataBindingProperty = list[index];
|
||||
index++;
|
||||
|
||||
private void ProfileOnChildRemoved(object sender, EventArgs e)
|
||||
{
|
||||
if (Script.Context is not Profile profile)
|
||||
return;
|
||||
|
||||
if (!profile.GetAllRenderElements().Contains(ProfileElement))
|
||||
ChangeProfileElement(null);
|
||||
// TODO: Is this really non-nullable?
|
||||
outputPin.Value = dataBindingProperty.GetValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LayerPropertyNodeEntity
|
||||
public override void Initialize(INodeScript script)
|
||||
{
|
||||
public Guid ElementId { get; set; }
|
||||
public string PropertyPath { get; set; }
|
||||
Script = script;
|
||||
|
||||
if (script.Context is Profile profile)
|
||||
profile.ChildRemoved += ProfileOnChildRemoved;
|
||||
|
||||
LoadLayerProperty();
|
||||
}
|
||||
|
||||
public void LoadLayerProperty()
|
||||
{
|
||||
lock (_layerPropertyLock)
|
||||
{
|
||||
if (Script.Context is not Profile profile || Storage == null)
|
||||
return;
|
||||
|
||||
RenderProfileElement element = profile.GetAllRenderElements().FirstOrDefault(l => l.EntityId == Storage.ElementId);
|
||||
|
||||
ProfileElement = element;
|
||||
LayerProperty = element?.GetAllLayerProperties().FirstOrDefault(p => p.Path == Storage.PropertyPath);
|
||||
CreatePins();
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeProfileElement(RenderProfileElement profileElement)
|
||||
{
|
||||
lock (_layerPropertyLock)
|
||||
{
|
||||
ProfileElement = profileElement;
|
||||
LayerProperty = null;
|
||||
|
||||
Storage = new LayerPropertyNodeEntity
|
||||
{
|
||||
ElementId = ProfileElement?.EntityId ?? Guid.Empty,
|
||||
PropertyPath = null
|
||||
};
|
||||
|
||||
CreatePins();
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeLayerProperty(ILayerProperty layerProperty)
|
||||
{
|
||||
lock (_layerPropertyLock)
|
||||
{
|
||||
LayerProperty = layerProperty;
|
||||
|
||||
Storage = new LayerPropertyNodeEntity
|
||||
{
|
||||
ElementId = ProfileElement?.EntityId ?? Guid.Empty,
|
||||
PropertyPath = LayerProperty?.Path
|
||||
};
|
||||
|
||||
CreatePins();
|
||||
}
|
||||
}
|
||||
|
||||
private void CreatePins()
|
||||
{
|
||||
while (Pins.Any())
|
||||
RemovePin((Pin) Pins.First());
|
||||
|
||||
if (LayerProperty == null)
|
||||
return;
|
||||
|
||||
foreach (IDataBindingProperty dataBindingRegistration in LayerProperty.BaseDataBinding.Properties)
|
||||
CreateOutputPin(dataBindingRegistration.ValueType, dataBindingRegistration.DisplayName);
|
||||
}
|
||||
|
||||
private void ProfileOnChildRemoved(object sender, EventArgs e)
|
||||
{
|
||||
if (Script.Context is not Profile profile)
|
||||
return;
|
||||
|
||||
if (!profile.GetAllRenderElements().Contains(ProfileElement))
|
||||
ChangeProfileElement(null);
|
||||
}
|
||||
}
|
||||
|
||||
public class LayerPropertyNodeEntity
|
||||
{
|
||||
public Guid ElementId { get; set; }
|
||||
public string PropertyPath { get; set; }
|
||||
}
|
||||
+5
-6
@@ -1,12 +1,11 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
using Artemis.UI.Shared.VisualScripting;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Maths.CustomViewModels
|
||||
namespace Artemis.VisualScripting.Nodes.Maths.CustomViewModels;
|
||||
|
||||
public class MathExpressionNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
public class MathExpressionNodeCustomViewModel : CustomNodeViewModel
|
||||
public MathExpressionNodeCustomViewModel(INode node, INodeScript script) : base(node, script)
|
||||
{
|
||||
public MathExpressionNodeCustomViewModel(INode node) : base(node)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -1,12 +1,11 @@
|
||||
<UserControl x:Class="Artemis.VisualScripting.Nodes.Maths.CustomViews.MathExpressionNodeCustomView"
|
||||
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.Maths.CustomViews"
|
||||
mc:Ignorable="d"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<TextBox VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding Node.Storage}" />
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
@@ -1,119 +1,116 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using Artemis.VisualScripting.Nodes.Maths.CustomViewModels;
|
||||
using NoStringEvaluating.Contract;
|
||||
using NoStringEvaluating.Contract.Variables;
|
||||
using NoStringEvaluating.Models.Values;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Maths
|
||||
namespace Artemis.VisualScripting.Nodes.Maths;
|
||||
|
||||
[Node("Math Expression", "Outputs the result of a math expression.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
||||
public class MathExpressionNode : Node<string, MathExpressionNodeCustomViewModel>
|
||||
{
|
||||
[Node("Math Expression", "Outputs the result of a math expression.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
||||
public class MathExpressionNode : Node<string, MathExpressionNodeCustomViewModel>
|
||||
private readonly INoStringEvaluator _evaluator;
|
||||
private readonly PinsVariablesContainer _variables;
|
||||
|
||||
#region Constructors
|
||||
|
||||
public MathExpressionNode(INoStringEvaluator evaluator)
|
||||
: base("Math Expression", "Outputs the result of a math expression.")
|
||||
{
|
||||
private readonly INoStringEvaluator _evaluator;
|
||||
private readonly PinsVariablesContainer _variables;
|
||||
_evaluator = evaluator;
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
Values = CreateInputPinCollection<Numeric>("Values", 2);
|
||||
Values.PinAdded += (_, _) => SetPinNames();
|
||||
Values.PinRemoved += (_, _) => SetPinNames();
|
||||
_variables = new PinsVariablesContainer(Values);
|
||||
|
||||
#region Constructors
|
||||
|
||||
public MathExpressionNode(INoStringEvaluator evaluator)
|
||||
: base("Math Expression", "Outputs the result of a math expression.")
|
||||
{
|
||||
_evaluator = evaluator;
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
Values = CreateInputPinCollection<Numeric>("Values", 2);
|
||||
Values.PinAdded += (_, _) => SetPinNames();
|
||||
Values.PinRemoved += (_, _) => SetPinNames();
|
||||
_variables = new PinsVariablesContainer(Values);
|
||||
|
||||
SetPinNames();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public OutputPin<Numeric> Output { get; }
|
||||
public InputPinCollection<Numeric> Values { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
if (Storage != null)
|
||||
Output.Value = new Numeric(_evaluator.CalcNumber(Storage, _variables));
|
||||
}
|
||||
|
||||
private void SetPinNames()
|
||||
{
|
||||
int index = 1;
|
||||
foreach (IPin value in Values)
|
||||
{
|
||||
value.Name = ExcelColumnFromNumber(index).ToLower();
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ExcelColumnFromNumber(int column)
|
||||
{
|
||||
string columnString = "";
|
||||
decimal columnNumber = column;
|
||||
while (columnNumber > 0)
|
||||
{
|
||||
decimal currentLetterNumber = (columnNumber - 1) % 26;
|
||||
char currentLetter = (char) (currentLetterNumber + 65);
|
||||
columnString = currentLetter + columnString;
|
||||
columnNumber = (columnNumber - (currentLetterNumber + 1)) / 26;
|
||||
}
|
||||
|
||||
return columnString;
|
||||
}
|
||||
|
||||
#endregion
|
||||
SetPinNames();
|
||||
}
|
||||
|
||||
public class PinsVariablesContainer : IVariablesContainer
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public OutputPin<Numeric> Output { get; }
|
||||
public InputPinCollection<Numeric> Values { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
private readonly InputPinCollection<Numeric> _values;
|
||||
|
||||
public PinsVariablesContainer(InputPinCollection<Numeric> values)
|
||||
{
|
||||
_values = values;
|
||||
}
|
||||
|
||||
#region Implementation of IVariablesContainer
|
||||
|
||||
/// <inheritdoc />
|
||||
public IVariable AddOrUpdate(string name, double value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public EvaluatorValue GetValue(string name)
|
||||
{
|
||||
IPin pin = _values.FirstOrDefault(v => v.Name == name);
|
||||
if (pin?.PinValue is Numeric numeric)
|
||||
return new EvaluatorValue(numeric);
|
||||
return new EvaluatorValue(0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetValue(string name, out EvaluatorValue value)
|
||||
{
|
||||
IPin pin = _values.FirstOrDefault(v => v.Name == name);
|
||||
if (pin?.PinValue is Numeric numeric)
|
||||
{
|
||||
value = new EvaluatorValue(numeric);
|
||||
return true;
|
||||
}
|
||||
|
||||
value = new EvaluatorValue(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
if (Storage != null)
|
||||
Output.Value = new Numeric(_evaluator.CalcNumber(Storage, _variables));
|
||||
}
|
||||
|
||||
private void SetPinNames()
|
||||
{
|
||||
int index = 1;
|
||||
foreach (IPin value in Values)
|
||||
{
|
||||
value.Name = ExcelColumnFromNumber(index).ToLower();
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ExcelColumnFromNumber(int column)
|
||||
{
|
||||
string columnString = "";
|
||||
decimal columnNumber = column;
|
||||
while (columnNumber > 0)
|
||||
{
|
||||
decimal currentLetterNumber = (columnNumber - 1) % 26;
|
||||
char currentLetter = (char) (currentLetterNumber + 65);
|
||||
columnString = currentLetter + columnString;
|
||||
columnNumber = (columnNumber - (currentLetterNumber + 1)) / 26;
|
||||
}
|
||||
|
||||
return columnString;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class PinsVariablesContainer : IVariablesContainer
|
||||
{
|
||||
private readonly InputPinCollection<Numeric> _values;
|
||||
|
||||
public PinsVariablesContainer(InputPinCollection<Numeric> values)
|
||||
{
|
||||
_values = values;
|
||||
}
|
||||
|
||||
#region Implementation of IVariablesContainer
|
||||
|
||||
/// <inheritdoc />
|
||||
public IVariable AddOrUpdate(string name, double value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public EvaluatorValue GetValue(string name)
|
||||
{
|
||||
IPin pin = _values.FirstOrDefault(v => v.Name == name);
|
||||
if (pin?.PinValue is Numeric numeric)
|
||||
return new EvaluatorValue(numeric);
|
||||
return new EvaluatorValue(0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetValue(string name, out EvaluatorValue value)
|
||||
{
|
||||
IPin pin = _values.FirstOrDefault(v => v.Name == name);
|
||||
if (pin?.PinValue is Numeric numeric)
|
||||
{
|
||||
value = new EvaluatorValue(numeric);
|
||||
return true;
|
||||
}
|
||||
|
||||
value = new EvaluatorValue(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,28 +1,26 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Maths
|
||||
namespace Artemis.VisualScripting.Nodes.Maths;
|
||||
|
||||
[Node("Round", "Outputs a rounded numeric value.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
||||
public class RoundNode : Node
|
||||
{
|
||||
[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() : base("Round", "Outputs a rounded numeric value.")
|
||||
{
|
||||
Input = CreateInputPin<Numeric>();
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
}
|
||||
|
||||
public OutputPin<Numeric> Output { get; set; }
|
||||
public InputPin<Numeric> Input { get; set; }
|
||||
|
||||
#region Overrides of Node
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = new Numeric(MathF.Round(Input.Value, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
#endregion
|
||||
Input = CreateInputPin<Numeric>();
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
}
|
||||
|
||||
public OutputPin<Numeric> Output { get; set; }
|
||||
public InputPin<Numeric> Input { get; set; }
|
||||
|
||||
#region Overrides of Node
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = new Numeric(MathF.Round(Input.Value, MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,63 +1,62 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes
|
||||
namespace Artemis.VisualScripting.Nodes;
|
||||
|
||||
[Node("Numeric-Value", "Outputs a configurable static numeric value.", "Static", OutputType = typeof(Numeric))]
|
||||
public class StaticNumericValueNode : Node<Numeric, StaticNumericValueNodeCustomViewModel>
|
||||
{
|
||||
[Node("Numeric-Value", "Outputs a configurable static numeric value.", "Static", OutputType = typeof(Numeric))]
|
||||
public class StaticNumericValueNode : Node<Numeric, StaticNumericValueNodeCustomViewModel>
|
||||
#region Constructors
|
||||
|
||||
public StaticNumericValueNode()
|
||||
: base("Numeric", "Outputs a configurable numeric value.")
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public OutputPin<Numeric> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public StaticNumericValueNode()
|
||||
: base("Numeric", "Outputs a configurable numeric value.")
|
||||
{
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = Storage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
Output = CreateOutputPin<Numeric>();
|
||||
}
|
||||
|
||||
[Node("String-Value", "Outputs a configurable static string value.", "Static", OutputType = typeof(string))]
|
||||
public class StaticStringValueNode : Node<string, StaticStringValueNodeCustomViewModel>
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public OutputPin<Numeric> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public OutputPin<string> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public StaticStringValueNode()
|
||||
: base("String", "Outputs a configurable string value.")
|
||||
{
|
||||
Output = CreateOutputPin<string>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = Storage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
Output.Value = Storage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Node("String-Value", "Outputs a configurable static string value.", "Static", OutputType = typeof(string))]
|
||||
public class StaticStringValueNode : Node<string, StaticStringValueNodeCustomViewModel>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public StaticStringValueNode()
|
||||
: base("String", "Outputs a configurable string value.")
|
||||
{
|
||||
Output = CreateOutputPin<string>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public OutputPin<string> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = Storage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,39 +1,37 @@
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes
|
||||
namespace Artemis.VisualScripting.Nodes;
|
||||
|
||||
[Node("Format", "Formats the input string.", "Text", InputType = typeof(object), OutputType = typeof(string))]
|
||||
public class StringFormatNode : Node
|
||||
{
|
||||
[Node("Format", "Formats the input string.", "Text", InputType = typeof(object), OutputType = typeof(string))]
|
||||
public class StringFormatNode : Node
|
||||
#region Constructors
|
||||
|
||||
public StringFormatNode()
|
||||
: base("Format", "Formats the input string.")
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<string> Format { get; }
|
||||
public InputPinCollection<object> Values { get; }
|
||||
|
||||
public OutputPin<string> Output { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public StringFormatNode()
|
||||
: base("Format", "Formats the input string.")
|
||||
{
|
||||
Format = CreateInputPin<string>("Format");
|
||||
Values = CreateInputPinCollection<object>("Values", 1);
|
||||
Output = CreateOutputPin<string>("Result");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = string.Format(Format.Value ?? string.Empty, Values.Values.ToArray());
|
||||
}
|
||||
|
||||
#endregion
|
||||
Format = CreateInputPin<string>("Format");
|
||||
Values = CreateInputPinCollection<object>("Values");
|
||||
Output = CreateOutputPin<string>("Result");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Output.Value = string.Format(Format.Value ?? string.Empty, Values.Values.ToArray());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPin<string> Format { get; }
|
||||
public InputPinCollection<object> Values { get; }
|
||||
|
||||
public OutputPin<string> Output { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,36 +1,35 @@
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes
|
||||
namespace Artemis.VisualScripting.Nodes;
|
||||
|
||||
[Node("Sum", "Sums the connected numeric values.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
||||
public class SumNumericsNode : Node
|
||||
{
|
||||
[Node("Sum", "Sums the connected numeric values.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
||||
public class SumNumericsNode : Node
|
||||
#region Constructors
|
||||
|
||||
public SumNumericsNode()
|
||||
: base("Sum", "Sums the connected numeric values.")
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public SumNumericsNode()
|
||||
: base("Sum", "Sums the connected numeric values.")
|
||||
{
|
||||
Values = CreateInputPinCollection<Numeric>("Values", 2);
|
||||
Sum = CreateOutputPin<Numeric>("Sum");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Sum.Value = Values.Values.Sum();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<Numeric> Values { get; }
|
||||
|
||||
public OutputPin<Numeric> Sum { get; }
|
||||
|
||||
#endregion
|
||||
Values = CreateInputPinCollection<Numeric>("Values", 2);
|
||||
Sum = CreateOutputPin<Numeric>("Sum");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
Sum.Value = Values.Values.Sum();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public InputPinCollection<Numeric> Values { get; }
|
||||
|
||||
public OutputPin<Numeric> Sum { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in new issue
Block a user