diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs
index 32879ff29..eb337ba54 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs
@@ -3,40 +3,46 @@
namespace Artemis.Core
{
///
- public class FloatDataBindingConverter : IDataBindingConverter
+ public class FloatDataBindingConverter : DataBindingConverter
{
- ///
- public Type SupportedType => typeof(float);
-
- ///
- public bool SupportsSum => true;
-
- ///
- public bool SupportsInterpolate => true;
-
- ///
- public object Sum(BaseLayerProperty layerProperty, object a, object b)
+ public FloatDataBindingConverter()
{
- return (float) a + (float) b;
+ SupportedType = typeof(float);
+ SupportsSum = true;
+ SupportsInterpolate = true;
}
///
- public object Interpolate(BaseLayerProperty layerProperty, object a, object b, float progress)
+ public override object Sum(object a, object b)
{
- var diff = (float) b - (float) a;
- return diff * progress;
+ return Convert.ToSingle(a) + Convert.ToSingle(b);
}
///
- public void ApplyValue(BaseLayerProperty layerProperty, object value)
+ public override object Interpolate(object a, object b, double progress)
{
- layerProperty.CurrentValue = value;
+ var floatA = Convert.ToSingle(a);
+ var floatB = Convert.ToSingle(b);
+ var diff = floatB - floatA;
+ return floatA + diff * progress;
}
///
- public object GetValue(BaseLayerProperty layerProperty)
+ public override void ApplyValue(object value)
{
- return layerProperty.CurrentValue;
+ var floatValue = Convert.ToSingle(value);
+ if (DataBinding.LayerProperty.PropertyDescription.MaxInputValue is float max)
+ floatValue = Math.Min(floatValue, max);
+ if (DataBinding.LayerProperty.PropertyDescription.MinInputValue is float min)
+ floatValue = Math.Max(floatValue, min);
+
+ ValueSetter?.Invoke(floatValue);
+ }
+
+ ///
+ public override object GetValue()
+ {
+ return ValueGetter?.Invoke();
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/GeneralDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/GeneralDataBindingConverter.cs
index 637d5f437..561ef8784 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/Converters/GeneralDataBindingConverter.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/GeneralDataBindingConverter.cs
@@ -3,39 +3,37 @@
namespace Artemis.Core
{
///
- public class GeneralDataBindingConverter : IDataBindingConverter
+ public class GeneralDataBindingConverter : DataBindingConverter
{
- ///
- public Type SupportedType => typeof(object);
+ public GeneralDataBindingConverter()
+ {
+ SupportedType = typeof(object);
+ SupportsSum = false;
+ SupportsInterpolate = false;
+ }
///
- public bool SupportsSum => false;
-
- ///
- public bool SupportsInterpolate => false;
-
- ///
- public object Sum(BaseLayerProperty layerProperty, object a, object b)
+ public override object Sum(object a, object b)
{
throw new NotSupportedException();
}
///
- public object Interpolate(BaseLayerProperty layerProperty, object a, object b, float progress)
+ public override object Interpolate(object a, object b, double progress)
{
throw new NotSupportedException();
}
///
- public void ApplyValue(BaseLayerProperty layerProperty, object value)
+ public override void ApplyValue(object value)
{
- layerProperty.CurrentValue = value;
+ ValueSetter?.Invoke(value);
}
///
- public object GetValue(BaseLayerProperty layerProperty)
+ public override object GetValue()
{
- return layerProperty.CurrentValue;
+ return ValueGetter?.Invoke();
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/IntDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/IntDataBindingConverter.cs
index c34eaf779..c3466a43f 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/Converters/IntDataBindingConverter.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/IntDataBindingConverter.cs
@@ -3,40 +3,46 @@
namespace Artemis.Core
{
///
- public class IntDataBindingConverter : IDataBindingConverter
+ public class IntDataBindingConverter : DataBindingConverter
{
- ///
- public Type SupportedType => typeof(int);
+ public IntDataBindingConverter()
+ {
+ SupportedType = typeof(int);
+ SupportsSum = true;
+ SupportsInterpolate = true;
+ }
+
+ ///
+ /// Gets or sets the mode used for rounding during interpolation. Defaults to
+ ///
+ ///
+ public MidpointRounding InterpolationRoundingMode { get; set; } = MidpointRounding.AwayFromZero;
///
- public bool SupportsSum => true;
-
- ///
- public bool SupportsInterpolate => true;
-
- ///
- public object Sum(BaseLayerProperty layerProperty, object a, object b)
+ public override object Sum(object a, object b)
{
return (int) a + (int) b;
}
///
- public object Interpolate(BaseLayerProperty layerProperty, object a, object b, float progress)
+ public override object Interpolate(object a, object b, double progress)
{
- var diff = (int) b - (int) a;
- return diff * progress;
+ var intA = (int) a;
+ var intB = (int) b;
+ var diff = intB - intA;
+ return (int) Math.Round(intA + diff * progress, InterpolationRoundingMode);
}
///
- public void ApplyValue(BaseLayerProperty layerProperty, object value)
+ public override void ApplyValue(object value)
{
- layerProperty.CurrentValue = value;
+ ValueSetter?.Invoke(value);
}
///
- public object GetValue(BaseLayerProperty layerProperty)
+ public override object GetValue()
{
- return layerProperty.CurrentValue;
+ return ValueGetter?.Invoke();
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/Internal/SKColorPartDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/Internal/SKColorPartDataBindingConverter.cs
index 8176e9efc..3073a9721 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/Converters/Internal/SKColorPartDataBindingConverter.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/Internal/SKColorPartDataBindingConverter.cs
@@ -4,52 +4,41 @@ using SkiaSharp;
namespace Artemis.Core
{
// This is internal because it's mainly a proof-of-concept
- internal class SKColorPartDataBindingConverter : IDataBindingConverter
+ internal class SKColorPartDataBindingConverter : DataBindingConverter
{
private readonly Channel _channel;
public SKColorPartDataBindingConverter(Channel channel)
{
_channel = channel;
- }
- // This depends on what channel was passed
- public Type SupportedType
- {
- get
+ SupportsSum = true;
+ SupportsInterpolate = true;
+ SupportedType = _channel switch
{
- switch (_channel)
- {
- case Channel.Alpha:
- case Channel.Red:
- case Channel.Green:
- case Channel.Blue:
- return typeof(byte);
- case Channel.Hue:
- return typeof(float);
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
+ Channel.Alpha => typeof(byte),
+ Channel.Red => typeof(byte),
+ Channel.Green => typeof(byte),
+ Channel.Blue => typeof(byte),
+ Channel.Hue => typeof(float),
+ _ => throw new ArgumentOutOfRangeException()
+ };
}
- public bool SupportsSum => true;
- public bool SupportsInterpolate => true;
-
- public object Sum(BaseLayerProperty layerProperty, object a, object b)
+ public override object Sum(object a, object b)
{
return (float) a + (float) b;
}
- public object Interpolate(BaseLayerProperty layerProperty, object a, object b, float progress)
+ public override object Interpolate(object a, object b, double progress)
{
var diff = (float) b - (float) a;
return diff * progress;
}
- public void ApplyValue(BaseLayerProperty layerProperty, object value)
+ public override void ApplyValue(object value)
{
- var property = (SKColorLayerProperty) layerProperty;
+ var property = (SKColorLayerProperty) DataBinding.LayerProperty;
switch (_channel)
{
case Channel.Alpha:
@@ -73,9 +62,9 @@ namespace Artemis.Core
}
}
- public object GetValue(BaseLayerProperty layerProperty)
+ public override object GetValue()
{
- var property = (SKColorLayerProperty) layerProperty;
+ var property = (SKColorLayerProperty) DataBinding.LayerProperty;
switch (_channel)
{
case Channel.Alpha:
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
index 2d926fea3..0bb00863f 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
@@ -15,11 +15,11 @@ namespace Artemis.Core
public class DataBinding
{
private readonly List _modifiers = new List();
- private bool _isInitialized;
private object _currentValue;
+ private bool _isInitialized;
private object _previousValue;
- private float _easingProgress;
+ private TimeSpan _easingProgress;
internal DataBinding(DataBindingRegistration dataBindingRegistration)
{
@@ -38,30 +38,23 @@ namespace Artemis.Core
ApplyToDataBinding();
}
- private void ApplyRegistration(DataBindingRegistration dataBindingRegistration)
- {
- Converter = dataBindingRegistration.Converter;
- Registration = dataBindingRegistration;
- TargetProperty = dataBindingRegistration.Property;
- }
-
///
/// Gets the layer property this data binding targets
///
public BaseLayerProperty LayerProperty { get; }
///
- /// Gets the data binding registration this data binding is based upon
+ /// Gets the data binding registration this data binding is based upon
///
public DataBindingRegistration Registration { get; private set; }
///
- /// Gets the converter used to apply this data binding to the
+ /// Gets the converter used to apply this data binding to the
///
- public IDataBindingConverter Converter { get; private set; }
+ public DataBindingConverter Converter { get; private set; }
///
- /// Gets the property on the this data binding targets
+ /// Gets the property on the this data binding targets
///
public PropertyInfo TargetProperty { get; private set; }
@@ -167,21 +160,32 @@ namespace Artemis.Core
var value = Convert.ChangeType(dataBindingValue, TargetProperty.PropertyType);
// If no easing is to be applied simple return whatever the current value is
- if (EasingTime == TimeSpan.Zero || Converter.SupportsInterpolate)
+ if (EasingTime == TimeSpan.Zero || !Converter.SupportsInterpolate)
return value;
// If the value changed, update the current and previous values used for easing
if (!Equals(value, _currentValue))
- {
- _previousValue = GetInterpolatedValue();
- _currentValue = value;
- _easingProgress = 0f;
- }
+ ResetEasing(value);
// Apply interpolation between the previous and current value
return GetInterpolatedValue();
}
+ private void ResetEasing(object value)
+ {
+ _previousValue = GetInterpolatedValue();
+ _currentValue = value;
+ _easingProgress = TimeSpan.Zero;
+ }
+
+ ///
+ /// Returns the type of the target property of this data binding
+ ///
+ public Type GetTargetType()
+ {
+ return TargetProperty.PropertyType;
+ }
+
///
/// Returns the type of the source property of this data binding
///
@@ -191,21 +195,26 @@ namespace Artemis.Core
}
///
- /// Updates the smoothing progress of the data binding
+ /// Updates the smoothing progress of the data binding
///
- ///
+ /// The time in seconds that passed since the last update
public void Update(double deltaTime)
{
-
+ _easingProgress = _easingProgress.Add(TimeSpan.FromSeconds(deltaTime));
+ if (_easingProgress > EasingTime)
+ _easingProgress = EasingTime;
}
///
- /// Updates the value on the according to the data binding
+ /// Updates the value on the according to the data binding
///
public void ApplyToProperty()
{
- var value = GetValue(Converter.GetValue(LayerProperty));
- Converter.ApplyValue(LayerProperty, GetValue(value));
+ if (Converter == null)
+ return;
+
+ var value = GetValue(Converter.GetValue());
+ Converter.ApplyValue(GetValue(value));
}
internal void ApplyToEntity()
@@ -232,8 +241,7 @@ namespace Artemis.Core
internal void ApplyToDataBinding()
{
// General
- Registration = LayerProperty.DataBindingRegistrations.FirstOrDefault(p => p.Property.Name == Entity.TargetProperty);
- TargetProperty = Registration?.Property;
+ ApplyRegistration(LayerProperty.DataBindingRegistrations.FirstOrDefault(p => p.Property.Name == Entity.TargetProperty));
Mode = (DataBindingMode) Entity.DataBindingMode;
EasingTime = Entity.EasingTime;
@@ -266,14 +274,33 @@ namespace Artemis.Core
_isInitialized = true;
}
+ private void ApplyRegistration(DataBindingRegistration dataBindingRegistration)
+ {
+ if (dataBindingRegistration != null)
+ dataBindingRegistration.DataBinding = this;
+
+ Converter = dataBindingRegistration?.Converter;
+ Registration = dataBindingRegistration;
+ TargetProperty = dataBindingRegistration?.Property;
+
+ if (GetTargetType().IsValueType)
+ {
+ if (_currentValue == null)
+ _currentValue = GetTargetType().GetDefault();
+ if (_previousValue == null)
+ _previousValue = _currentValue;
+ }
+
+ Converter?.Initialize(this);
+ }
+
private object GetInterpolatedValue()
{
- if (_easingProgress == 0f)
- return _previousValue;
- if (_easingProgress == 1f || !Converter.SupportsInterpolate)
+ if (_easingProgress == EasingTime || !Converter.SupportsInterpolate)
return _currentValue;
- return Converter.Interpolate(LayerProperty, _previousValue, _currentValue, _easingProgress);
+ var easingAmount = _easingProgress.TotalSeconds / EasingTime.TotalSeconds;
+ return Converter.Interpolate(_previousValue, _currentValue, Easings.Interpolate(easingAmount, EasingFunction));
}
private void CreateExpression()
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs
new file mode 100644
index 000000000..3ee8756d2
--- /dev/null
+++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Artemis.Core
+{
+ ///
+ /// A data binding converter that acts as the bridge between a and a
+ ///
+ ///
+ public abstract class DataBindingConverter
+ {
+ internal Func