mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Nodes - Added math expression node
Node - Fix visual script cable present event unregister
This commit is contained in:
parent
ecdca26cd3
commit
e356d59daa
@ -8,7 +8,7 @@ namespace Artemis.Core
|
||||
{
|
||||
INode Node { get; }
|
||||
|
||||
string Name { get; }
|
||||
string Name { get; set; }
|
||||
PinDirection Direction { get; }
|
||||
Type Type { get; }
|
||||
object PinValue { get; }
|
||||
|
||||
@ -10,9 +10,15 @@ namespace Artemis.Core
|
||||
#region Properties & Fields
|
||||
|
||||
public INode Node { get; }
|
||||
public string Name { get; }
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetAndNotify(ref _name, value);
|
||||
}
|
||||
|
||||
private bool _isEvaluated;
|
||||
|
||||
public bool IsEvaluated
|
||||
{
|
||||
get => _isEvaluated;
|
||||
@ -20,6 +26,7 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
private readonly List<IPin> _connectedTo = new();
|
||||
private string _name;
|
||||
public IReadOnlyList<IPin> ConnectedTo => new ReadOnlyCollection<IPin>(_connectedTo);
|
||||
|
||||
public abstract PinDirection Direction { get; }
|
||||
|
||||
@ -28,6 +28,7 @@ namespace Artemis.UI.Shared
|
||||
{
|
||||
_gradientConverter = new ColorGradientToGradientStopsConverter();
|
||||
InitializeComponent();
|
||||
Unloaded += OnUnloaded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -121,7 +122,7 @@ namespace Artemis.UI.Shared
|
||||
|
||||
private void UpdateGradientStops()
|
||||
{
|
||||
GradientPreview.GradientStops = (GradientStopCollection)_gradientConverter.Convert(ColorGradient, null!, null!, null!);
|
||||
GradientPreview.GradientStops = (GradientStopCollection) _gradientConverter.Convert(ColorGradient, null!, null!, null!);
|
||||
}
|
||||
|
||||
private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e)
|
||||
@ -137,6 +138,11 @@ namespace Artemis.UI.Shared
|
||||
});
|
||||
}
|
||||
|
||||
private void OnUnloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ColorGradient.CollectionChanged -= GradientChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@ using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Stylet;
|
||||
using Artemis.UI.Utilities;
|
||||
using Artemis.VisualScripting.Ninject;
|
||||
using Ninject;
|
||||
using Serilog;
|
||||
using Stylet;
|
||||
@ -127,6 +128,8 @@ namespace Artemis.UI
|
||||
kernel.Load<SharedUIModule>();
|
||||
// Load the core assembly's module
|
||||
kernel.Load<CoreModule>();
|
||||
// Load the nodes module
|
||||
kernel.Load<NoStringNinjectModule>();
|
||||
|
||||
base.ConfigureIoC(kernel);
|
||||
}
|
||||
|
||||
@ -289,13 +289,6 @@
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" LineHeight="25" Margin="10 0 0 0">
|
||||
- Ben.Demystifier
|
||||
<Hyperlink Style="{StaticResource ArtemisHyperlink}"
|
||||
RequestNavigate="{s:Action OpenHyperlink}"
|
||||
NavigateUri="https://github.com/benaadams/Ben.Demystifier">
|
||||
https://github.com/benaadams/Ben.Demystifier
|
||||
</Hyperlink>
|
||||
<LineBreak />
|
||||
- EmbedIO
|
||||
<Hyperlink Style="{StaticResource ArtemisHyperlink}"
|
||||
RequestNavigate="{s:Action OpenHyperlink}"
|
||||
@ -380,6 +373,13 @@
|
||||
http://www.ninject.org/
|
||||
</Hyperlink>
|
||||
<LineBreak />
|
||||
- NoStringEvaluating
|
||||
<Hyperlink Style="{StaticResource ArtemisHyperlink}"
|
||||
RequestNavigate="{s:Action OpenHyperlink}"
|
||||
NavigateUri="https://github.com/KovtunV/NoStringEvaluating">
|
||||
https://github.com/KovtunV/NoStringEvaluating
|
||||
</Hyperlink>
|
||||
<LineBreak />
|
||||
- Ookii.Dialogs.Wpf
|
||||
<Hyperlink Style="{StaticResource ArtemisHyperlink}"
|
||||
RequestNavigate="{s:Action OpenHyperlink}"
|
||||
|
||||
@ -281,6 +281,11 @@
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "umBECCoMC+sOUgm083yFr8SxTobUOcPFH4AXigdO2xJiszCHAnmeDl4qPphJt+oaJ/XIfV1wOjIts2nRnki61Q=="
|
||||
},
|
||||
"Microsoft.Extensions.ObjectPool": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.9",
|
||||
"contentHash": "grj0e6Me0EQsgaurV0fxP0xd8sz8eZVK+Jb816DPzNADHaqXaXJD3xZX9SFjyDl3ykAYvD0y77o5vRd9Hzsk9g=="
|
||||
},
|
||||
"Microsoft.NETCore.Platforms": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
@ -382,6 +387,14 @@
|
||||
"Ninject": "3.3.3"
|
||||
}
|
||||
},
|
||||
"NoStringEvaluating": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.1",
|
||||
"contentHash": "dYvWeDdSXrfWreWu17XUNCZD1QAbeMuyOLwVxNBBy+mbs1O/QjsYr1uQPCJWqYRF2Rd5nQBLFbFWybz4Ndh68g==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.ObjectPool": "5.0.9"
|
||||
}
|
||||
},
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
@ -1479,6 +1492,8 @@
|
||||
"Artemis.Core": "1.0.0",
|
||||
"Artemis.UI.Shared": "2.0.0",
|
||||
"JetBrains.Annotations": "2021.1.0",
|
||||
"Ninject": "3.3.4",
|
||||
"NoStringEvaluating": "2.2.1",
|
||||
"SkiaSharp": "2.80.3",
|
||||
"Stylet": "1.3.6"
|
||||
}
|
||||
|
||||
@ -37,6 +37,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2021.1.0" />
|
||||
<PackageReference Include="Ninject" Version="3.3.4" />
|
||||
<PackageReference Include="NoStringEvaluating" Version="2.2.1" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
<PackageReference Include="Stylet" Version="1.3.6" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -88,9 +88,9 @@ namespace Artemis.VisualScripting.Editor.Controls
|
||||
private void OnUnloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Cable?.From != null)
|
||||
Cable.From.PropertyChanged += OnPinPropertyChanged;
|
||||
Cable.From.PropertyChanged -= OnPinPropertyChanged;
|
||||
if (Cable?.To != null)
|
||||
Cable.To.PropertyChanged += OnPinPropertyChanged;
|
||||
Cable.To.PropertyChanged -= OnPinPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnPathMouseDown(object sender, MouseButtonEventArgs args)
|
||||
|
||||
@ -71,6 +71,9 @@ namespace Artemis.VisualScripting.Editor.Controls
|
||||
private void OnUnloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LayoutUpdated -= OnLayoutUpdated;
|
||||
if (Pin != null)
|
||||
Pin.Node.Node.PropertyChanged -= OnNodePropertyChanged;
|
||||
|
||||
_nodePresenter = null;
|
||||
}
|
||||
|
||||
|
||||
56
src/Artemis.VisualScripting/Ninject/NoStringNinjectModule.cs
Normal file
56
src/Artemis.VisualScripting/Ninject/NoStringNinjectModule.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Ninject.Modules;
|
||||
using NoStringEvaluating;
|
||||
using NoStringEvaluating.Contract;
|
||||
using NoStringEvaluating.Models.Values;
|
||||
using NoStringEvaluating.Services.Cache;
|
||||
using NoStringEvaluating.Services.Checking;
|
||||
using NoStringEvaluating.Services.Parsing;
|
||||
using NoStringEvaluating.Services.Parsing.NodeReaders;
|
||||
|
||||
namespace Artemis.VisualScripting.Ninject
|
||||
{
|
||||
public class NoStringNinjectModule : NinjectModule
|
||||
{
|
||||
public override void Load()
|
||||
{
|
||||
// Pooling
|
||||
Bind<ObjectPool<Stack<InternalEvaluatorValue>>>()
|
||||
.ToConstant(ObjectPool.Create<Stack<InternalEvaluatorValue>>())
|
||||
.InSingletonScope();
|
||||
|
||||
Bind<ObjectPool<List<InternalEvaluatorValue>>>()
|
||||
.ToConstant(ObjectPool.Create<List<InternalEvaluatorValue>>())
|
||||
.InSingletonScope();
|
||||
|
||||
Bind<ObjectPool<ExtraTypeIdContainer>>()
|
||||
.ToConstant(ObjectPool.Create<ExtraTypeIdContainer>())
|
||||
.InSingletonScope();
|
||||
|
||||
// Parser
|
||||
Bind<IFormulaCache>().To<FormulaCache>().InSingletonScope();
|
||||
Bind<IFunctionReader>().To<FunctionReader>().InSingletonScope();
|
||||
Bind<IFormulaParser>().To<FormulaParser>().InSingletonScope();
|
||||
|
||||
// Checker
|
||||
Bind<IFormulaChecker>().To<FormulaChecker>().InSingletonScope();
|
||||
|
||||
// Evaluator
|
||||
Bind<INoStringEvaluator>().To<NoStringEvaluator>().InSingletonScope();
|
||||
|
||||
// Options
|
||||
NoStringEvaluatorOptions opt = new NoStringEvaluatorOptions().SetWordQuotationMark("!");
|
||||
opt.UpdateConstants();
|
||||
|
||||
// If needed
|
||||
InjectUserDefinedFunctions();
|
||||
}
|
||||
|
||||
private void InjectUserDefinedFunctions()
|
||||
{
|
||||
IFunctionReader functionReader = (IFunctionReader) Kernel!.GetService(typeof(IFunctionReader));
|
||||
NoStringFunctionsInitializer.InitializeFunctions(functionReader, typeof(NoStringNinjectModule));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
using System.ComponentModel;
|
||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||
|
||||
namespace Artemis.VisualScripting.Nodes.Maths.CustomViewModels
|
||||
{
|
||||
public class MathExpressionNodeCustomViewModel : CustomNodeViewModel
|
||||
{
|
||||
private readonly MathExpressionNode _node;
|
||||
|
||||
public MathExpressionNodeCustomViewModel(MathExpressionNode node) : base(node)
|
||||
{
|
||||
_node = node;
|
||||
}
|
||||
|
||||
public string Input
|
||||
{
|
||||
get => (string)_node.Storage;
|
||||
set => _node.Storage = value;
|
||||
}
|
||||
|
||||
public override void OnActivate()
|
||||
{
|
||||
_node.PropertyChanged += NodeOnPropertyChanged;
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
{
|
||||
_node.PropertyChanged -= NodeOnPropertyChanged;
|
||||
}
|
||||
|
||||
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(Node.Storage))
|
||||
OnPropertyChanged(nameof(Input));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
<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"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<TextBox VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding Input}" />
|
||||
</UserControl>
|
||||
112
src/Artemis.VisualScripting/Nodes/Maths/ExpressionNode.cs
Normal file
112
src/Artemis.VisualScripting/Nodes/Maths/ExpressionNode.cs
Normal file
@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
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
|
||||
{
|
||||
[Node("Math Expression", "Outputs the result of a math expression.", "Math", OutputType = typeof(int))]
|
||||
public class MathExpressionNode : Node<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.")
|
||||
{
|
||||
_evaluator = evaluator;
|
||||
Output = CreateOutputPin<float>();
|
||||
Values = CreateInputPinCollection<float>("Values", 2);
|
||||
Values.PinAdded += (_, _) => SetPinNames();
|
||||
Values.PinRemoved += (_, _) => SetPinNames();
|
||||
_variables = new PinsVariablesContainer(Values);
|
||||
|
||||
SetPinNames();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public OutputPin<float> Output { get; }
|
||||
public InputPinCollection<float> Values { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
if (Storage is string formula)
|
||||
Output.Value = (float) _evaluator.CalcNumber(formula, _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<float> _values;
|
||||
|
||||
public PinsVariablesContainer(InputPinCollection<float> 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);
|
||||
return pin == null ? new EvaluatorValue(0) : new EvaluatorValue((double) pin.PinValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetValue(string name, out EvaluatorValue value)
|
||||
{
|
||||
IPin pin = _values.FirstOrDefault(v => v.Name == name);
|
||||
double unboxed = (float) pin.PinValue;
|
||||
value = pin == null ? new EvaluatorValue(0) : new EvaluatorValue(unboxed);
|
||||
|
||||
return pin != null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,25 @@
|
||||
"resolved": "2021.1.0",
|
||||
"contentHash": "n9JSw5Z+F+6gp9vSv4aLH6p/bx3GAYA6FZVq1wJq/TJySv/kPgFKLGFeS7A8Xa5X4/GWorh5gd43yjamUgnBNA=="
|
||||
},
|
||||
"Ninject": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.3.4, )",
|
||||
"resolved": "3.3.4",
|
||||
"contentHash": "CmbWW97FfJuh4LEOVZM/spqXl4KAulRUjqeMwRd5J9rDMQArmIYaDMU3pyzXXHT062tbF0OPIMwI7tSOtprPfg==",
|
||||
"dependencies": {
|
||||
"System.Reflection.Emit.ILGeneration": "4.3.0",
|
||||
"System.Reflection.Emit.Lightweight": "4.3.0"
|
||||
}
|
||||
},
|
||||
"NoStringEvaluating": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.2.1, )",
|
||||
"resolved": "2.2.1",
|
||||
"contentHash": "dYvWeDdSXrfWreWu17XUNCZD1QAbeMuyOLwVxNBBy+mbs1O/QjsYr1uQPCJWqYRF2Rd5nQBLFbFWybz4Ndh68g==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.ObjectPool": "5.0.9"
|
||||
}
|
||||
},
|
||||
"SkiaSharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.80.3, )",
|
||||
@ -107,6 +126,11 @@
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "umBECCoMC+sOUgm083yFr8SxTobUOcPFH4AXigdO2xJiszCHAnmeDl4qPphJt+oaJ/XIfV1wOjIts2nRnki61Q=="
|
||||
},
|
||||
"Microsoft.Extensions.ObjectPool": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.9",
|
||||
"contentHash": "grj0e6Me0EQsgaurV0fxP0xd8sz8eZVK+Jb816DPzNADHaqXaXJD3xZX9SFjyDl3ykAYvD0y77o5vRd9Hzsk9g=="
|
||||
},
|
||||
"Microsoft.NETCore.Platforms": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
@ -196,15 +220,6 @@
|
||||
"resolved": "13.0.1",
|
||||
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
|
||||
},
|
||||
"Ninject": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.3.4",
|
||||
"contentHash": "CmbWW97FfJuh4LEOVZM/spqXl4KAulRUjqeMwRd5J9rDMQArmIYaDMU3pyzXXHT062tbF0OPIMwI7tSOtprPfg==",
|
||||
"dependencies": {
|
||||
"System.Reflection.Emit.ILGeneration": "4.3.0",
|
||||
"System.Reflection.Emit.Lightweight": "4.3.0"
|
||||
}
|
||||
},
|
||||
"Ninject.Extensions.ChildKernel": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.3.0",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user