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

Nodes - Added easing nodes

Nodes - Update data model node to honor profile editor settings
This commit is contained in:
Robert 2021-08-23 12:26:13 +02:00
parent 9d6a61f1e5
commit 64b78cbf9e
13 changed files with 430 additions and 7 deletions

View File

@ -19,7 +19,7 @@
<DataTemplate x:Key="DataModelDataTemplate">
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
<DataTrigger Binding="{Binding Data.ShowDataModelValues, Source={StaticResource DataContextProxy}}" Value="True">
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
</DataTrigger>
</DataTemplate.Triggers>

View File

@ -247,7 +247,7 @@ namespace Artemis.UI.Shared
object? value = Parent == null || Parent.IsRootViewModel ? DataModel : DataModelPath?.GetValue();
if (value is DataModel dataModel)
{
foreach (var (key, dynamicChild) in dataModel.DynamicChildren)
foreach (string key in dataModel.DynamicChildren.Keys.ToList())
{
string childPath = AppendToPath(key);
if (Children.Any(c => c.Path != null && c.Path.Equals(childPath)))

View File

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

View File

@ -1,6 +1,7 @@
using System.ComponentModel;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Stylet;
namespace Artemis.VisualScripting.Nodes.CustomViewModels
@ -10,11 +11,17 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels
private readonly DataModelNode _node;
private BindableCollection<Module> _modules;
public DataModelNodeCustomViewModel(DataModelNode node) : base(node)
public DataModelNodeCustomViewModel(DataModelNode node, ISettingsService settingsService) : base(node)
{
_node = node;
ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
}
public PluginSetting<bool> ShowFullPaths { get; }
public PluginSetting<bool> ShowDataModelValues { get; }
public BindableCollection<Module> Modules
{
get => _modules;
@ -41,7 +48,7 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels
_node.UpdateOutputPin();
}
}
public override void OnActivate()
{
if (Modules != null)

View File

@ -8,5 +8,9 @@
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}" ButtonBrush="#434343"/>
<controls:DataModelPicker DataModelPath="{Binding DataModelPath}"
Modules="{Binding Modules}"
ShowFullPath="{Binding ShowFullPaths.Value}"
ShowDataModelValues="{Binding ShowDataModelValues.Value}"
ButtonBrush="#434343"/>
</UserControl>

View File

@ -0,0 +1,55 @@
using System;
using System.ComponentModel;
using System.Linq;
using Artemis.Core;
using Artemis.VisualScripting.Nodes.CustomViewModels;
using Stylet;
namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels
{
public class EasingTypeNodeCustomViewModel : CustomNodeViewModel
{
private readonly EasingTypeNode _node;
private NodeEasingViewModel _selectedEasingViewModel;
public EasingTypeNodeCustomViewModel(EasingTypeNode node) : base(node)
{
_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 = EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.EasingFunction);
}
public override void OnDeactivate()
{
_node.PropertyChanged -= NodeOnPropertyChanged;
}
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Node.Storage))
{
_selectedEasingViewModel = EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.EasingFunction);
NotifyOfPropertyChange(nameof(SelectedEasingViewModel));
}
}
}
}

View File

@ -0,0 +1,29 @@
using System.Windows;
using System.Windows.Media;
using Artemis.Core;
using Humanizer;
using Stylet;
namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels
{
public class NodeEasingViewModel : PropertyChangedBase
{
public NodeEasingViewModel(Easings.Functions easingFunction)
{
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));
}
}
public Easings.Functions EasingFunction { get; }
public PointCollection EasingPoints { get; }
public string Description { get; }
}
}

View File

@ -0,0 +1,35 @@
<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>

View File

@ -0,0 +1,68 @@
using System;
using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Double Easing", "Outputs an eased double value")]
public class DoubleEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;
private float _progress;
private double _currentValue;
private double _sourceValue;
private double _targetValue;
public DoubleEasingNode() : base("Double Easing", "Outputs an eased double value")
{
Input = CreateInputPin<double>();
EasingTime = CreateInputPin<float>("delay");
EasingFunction = CreateInputPin<Easings.Functions>("function");
Output = CreateOutputPin<double>();
}
public InputPin<double> Input { get; set; }
public InputPin<float> EasingTime { get; set; }
public InputPin<Easings.Functions> EasingFunction { get; set; }
public OutputPin<double> 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)
{
_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;
}
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);
double eased = _sourceValue + (_targetValue - _sourceValue) * Easings.Interpolate(_progress, EasingFunction.Value);
_currentValue = eased;
}
}
}

View File

@ -0,0 +1,22 @@
using Artemis.Core;
using Artemis.VisualScripting.Nodes.Easing.CustomViewModels;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Easing Type", "Outputs a selectable easing type.")]
public class EasingTypeNode : Node<EasingTypeNodeCustomViewModel>
{
public EasingTypeNode() : base("Easing Type", "Outputs a selectable easing type.")
{
Output = CreateOutputPin<Easings.Functions>();
}
public OutputPin<Easings.Functions> Output { get; }
public Easings.Functions EasingFunction => Storage as Easings.Functions? ?? Easings.Functions.Linear;
public override void Evaluate()
{
Output.Value = EasingFunction;
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Float Easing", "Outputs an eased float value")]
public class FloatEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;
private float _progress;
private float _currentValue;
private float _sourceValue;
private float _targetValue;
public FloatEasingNode() : base("Float Easing", "Outputs an eased float value")
{
Input = CreateInputPin<float>();
EasingTime = CreateInputPin<float>("delay");
EasingFunction = CreateInputPin<Easings.Functions>("function");
Output = CreateOutputPin<float>();
}
public InputPin<float> Input { get; set; }
public InputPin<float> EasingTime { get; set; }
public InputPin<Easings.Functions> EasingFunction { get; set; }
public OutputPin<float> 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)
{
_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;
}
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);
double eased = _sourceValue + (_targetValue - _sourceValue) * Easings.Interpolate(_progress, EasingFunction.Value);
_currentValue = (float) eased;
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Integer Easing", "Outputs an eased integer value")]
public class IntEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;
private float _progress;
private int _currentValue;
private int _sourceValue;
private int _targetValue;
public IntEasingNode() : base("Integer Easing", "Outputs an eased integer value")
{
Input = CreateInputPin<int>();
EasingTime = CreateInputPin<float>("delay");
EasingFunction = CreateInputPin<Easings.Functions>("function");
Output = CreateOutputPin<int>();
}
public InputPin<int> Input { get; set; }
public InputPin<float> EasingTime { get; set; }
public InputPin<Easings.Functions> EasingFunction { get; set; }
public OutputPin<int> Output { get; set; }
public override void Evaluate()
{
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;
}
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);
double eased = _sourceValue + (_targetValue - _sourceValue) * Easings.Interpolate(_progress, EasingFunction.Value);
_currentValue = (int) Math.Round(eased, MidpointRounding.AwayFromZero);
}
}
}

View File

@ -0,0 +1,67 @@
using System;
using Artemis.Core;
using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Easing
{
[Node("Color Easing", "Outputs an eased color value")]
public class SKColorEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;
private float _progress;
private SKColor _currentValue;
private SKColor _sourceValue;
private SKColor _targetValue;
public SKColorEasingNode() : base("Color Easing", "Outputs an eased color value")
{
Input = CreateInputPin<SKColor>();
EasingTime = CreateInputPin<float>("delay");
EasingFunction = CreateInputPin<Easings.Functions>("function");
Output = CreateOutputPin<SKColor>();
}
public InputPin<SKColor> Input { get; set; }
public InputPin<float> 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)
{
_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;
}
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));
}
}
}