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

Nodes - Added color gradient easing node

Color ramp node - Fixed 1 and multiples of 1 being treated as 0
This commit is contained in:
Robert 2022-10-30 18:13:47 +01:00
parent 147e050e69
commit cbf2cd1736
5 changed files with 119 additions and 2 deletions

View File

@ -468,6 +468,8 @@ public class ColorGradient : IList<ColorGradientStop>, IList, INotifyCollectionC
{
_stops.Add(item);
item.ColorGradient = this;
// Update the position, reapplying the overlap-check in Position's setter
item.Position = item.Position;
item.PropertyChanged += ItemOnPropertyChanged;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, _stops.IndexOf(item)));
@ -624,4 +626,36 @@ public class ColorGradient : IList<ColorGradientStop>, IList, INotifyCollectionC
}
#endregion
public ColorGradient Interpolate(ColorGradient targetValue, float progress)
{
ColorGradient interpolated = new(this);
// Add new stops
if (targetValue.Count > interpolated.Count)
{
// Prefer the stops on a vacant position
foreach (ColorGradientStop stop in targetValue.Take(targetValue.Count - interpolated.Count))
interpolated.Add(new ColorGradientStop(GetColor(stop.Position), stop.Position));
}
// Interpolate stops
int index = 0;
foreach (ColorGradientStop stop in interpolated.ToList())
{
if (index < targetValue.Count)
{
ColorGradientStop targetStop = targetValue[index];
stop.Interpolate(targetStop, progress);
}
// Interpolate stops not on the target gradient
else
{
stop.Color = stop.Color.Interpolate(targetValue.GetColor(stop.Position), progress);
}
index++;
}
return interpolated;
}
}

View File

@ -95,4 +95,10 @@ public class ColorGradientStop : CorePropertyChanged
}
#endregion
public void Interpolate(ColorGradientStop targetValue, float progress)
{
Color = Color.Interpolate(targetValue.Color, progress);
Position = Position + ((targetValue.Position - Position) * progress);
}
}

View File

@ -237,7 +237,7 @@ public class LayerProperty<T> : CorePropertyChanged, ILayerProperty
}
/// <summary>
/// Gets or sets the base value of this layer property without any keyframes applied
/// Gets or sets the base value of this layer property without any keyframes or data bindings applied
/// </summary>
public T BaseValue
{

View File

@ -22,7 +22,13 @@ public class RampSKColorNode : Node<ColorGradient, RampSKColorNodeCustomViewMode
public override void Evaluate()
{
Output.Value = Storage?.GetColor(Input.Value % 1.0) ?? SKColor.Empty;
// Wrap the input between 0 and 1
// 1 % 1 = 0, 2 % 1 = 0 etc. but we want that to be 1 but 0 should stay 0, call me stupid but this works and makes sense
float value = Input.Value % 1;
if (value == 0 && Input.Value != 0)
value = 1;
Output.Value = Storage?.GetColor(value) ?? SKColor.Empty;
}
#endregion

View File

@ -0,0 +1,71 @@
using Artemis.Core;
namespace Artemis.VisualScripting.Nodes.Easing;
[Node("Color Gradient Easing", "Outputs an eased color gradient value", "Easing", InputType = typeof(ColorGradient), OutputType = typeof(ColorGradient))]
public class ColorGradientEasingNode : Node
{
private DateTime _lastEvaluate = DateTime.MinValue;
private float _progress;
private ColorGradient? _currentValue;
private ColorGradient? _sourceValue;
private ColorGradient? _targetValue;
public ColorGradientEasingNode()
{
Input = CreateInputPin<ColorGradient>();
EasingTime = CreateInputPin<Numeric>("delay");
EasingFunction = CreateInputPin<Easings.Functions>("function");
Output = CreateOutputPin<ColorGradient>();
}
public InputPin<ColorGradient> Input { get; set; }
public InputPin<Numeric> EasingTime { get; set; }
public InputPin<Easings.Functions> EasingFunction { get; set; }
public OutputPin<ColorGradient> Output { get; set; }
public override void Evaluate()
{
DateTime now = DateTime.Now;
if (Input.Value == null)
return;
// If the value changed reset progress
if (!Equals(_targetValue, Input.Value))
{
_sourceValue = _currentValue ?? new ColorGradient(Input.Value);
_targetValue = new ColorGradient(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()
{
if (_sourceValue == null || _targetValue == null)
return;
float easingTime = EasingTime.Value != 0f ? EasingTime.Value : 1f;
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, 0f, 1f);
_currentValue = _sourceValue.Interpolate(_targetValue, (float) Easings.Interpolate(_progress, EasingFunction.Value));
}
}