mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 20:06:33 +00:00
Data bindings - Finished main functionality
This commit is contained in:
1 parent
d49b574bda
commit
e7c3fbe675
23 files changed
+214
-135
No files matched your search
+3
-17
@@ -30,14 +30,14 @@ namespace Artemis.Core
|
||||
/// <inheritdoc />
|
||||
public override float Interpolate(float a, float b, double progress)
|
||||
{
|
||||
var diff = a - b;
|
||||
var diff = b - a;
|
||||
return (float) (a + diff * progress);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ApplyValue(float value)
|
||||
{
|
||||
if (SetExpression == null)
|
||||
if (ValueTypeSetExpression == null)
|
||||
return;
|
||||
|
||||
if (DataBinding.LayerProperty.PropertyDescription.MaxInputValue is float max)
|
||||
@@ -45,21 +45,7 @@ namespace Artemis.Core
|
||||
if (DataBinding.LayerProperty.PropertyDescription.MinInputValue is float min)
|
||||
value = Math.Max(value, min);
|
||||
|
||||
var test = new SKSize(5,5);
|
||||
test.Width = 10;
|
||||
|
||||
SetExpression(DataBinding.LayerProperty.CurrentValue, value);
|
||||
}
|
||||
|
||||
private void Mehtest(ref SKSize test)
|
||||
{
|
||||
test.Width = 20;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override float GetValue()
|
||||
{
|
||||
return GetExpression(DataBinding.LayerProperty.CurrentValue);
|
||||
base.ApplyValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
-12
@@ -22,17 +22,5 @@ namespace Artemis.Core
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ApplyValue(object value)
|
||||
{
|
||||
SetExpression?.Invoke(DataBinding.LayerProperty.CurrentValue, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object GetValue()
|
||||
{
|
||||
return GetExpression(DataBinding.LayerProperty.CurrentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,17 +37,5 @@ namespace Artemis.Core
|
||||
var diff = b - a;
|
||||
return (int) Math.Round(a + diff * progress, InterpolationRoundingMode);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ApplyValue(int value)
|
||||
{
|
||||
SetExpression?.Invoke(DataBinding.LayerProperty.CurrentValue, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetValue()
|
||||
{
|
||||
return GetExpression(DataBinding.LayerProperty.CurrentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-15
@@ -24,7 +24,7 @@ namespace Artemis.Core
|
||||
public override byte Interpolate(byte a, byte b, double progress)
|
||||
{
|
||||
var diff = b - a;
|
||||
return ClampToByte(diff * progress);
|
||||
return ClampToByte(a + diff * progress);
|
||||
}
|
||||
|
||||
public override void ApplyValue(byte value)
|
||||
@@ -48,21 +48,10 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
public override byte GetValue()
|
||||
public override byte ConvertFromObject(object source)
|
||||
{
|
||||
switch (_channel)
|
||||
{
|
||||
case Channel.Alpha:
|
||||
return DataBinding.LayerProperty.CurrentValue.Alpha;
|
||||
case Channel.Red:
|
||||
return DataBinding.LayerProperty.CurrentValue.Red;
|
||||
case Channel.Green:
|
||||
return DataBinding.LayerProperty.CurrentValue.Green;
|
||||
case Channel.Blue:
|
||||
return DataBinding.LayerProperty.CurrentValue.Blue;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
var saveValue = Convert.ToDouble(source);
|
||||
return ClampToByte(saveValue);
|
||||
}
|
||||
|
||||
private static byte ClampToByte(double value)
|
||||
|
||||
@@ -206,8 +206,8 @@ namespace Artemis.Core
|
||||
foreach (var dataBindingModifier in Modifiers)
|
||||
dataBindingValue = dataBindingModifier.Apply(dataBindingValue);
|
||||
|
||||
var value = (TProperty) Convert.ChangeType(dataBindingValue, typeof(TProperty));
|
||||
|
||||
TProperty value = Converter.ConvertFromObject(dataBindingValue);
|
||||
|
||||
// If no easing is to be applied simple return whatever the current value is
|
||||
if (EasingTime == TimeSpan.Zero || !Converter.SupportsInterpolate)
|
||||
return value;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
@@ -19,7 +18,9 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// A dynamically compiled setter pointing to the data bound property
|
||||
/// </summary>
|
||||
public Action<TLayerProperty, TProperty> SetExpression { get; private set; }
|
||||
public Action<TProperty> ValueTypeSetExpression { get; private set; }
|
||||
|
||||
public Action<TLayerProperty, TProperty> ReferenceTypeSetExpression { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data binding this converter is applied to
|
||||
@@ -59,12 +60,29 @@ namespace Artemis.Core
|
||||
/// Applies the <paramref name="value" /> to the layer property
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public abstract void ApplyValue(TProperty value);
|
||||
public virtual void ApplyValue(TProperty value)
|
||||
{
|
||||
if (ReferenceTypeSetExpression != null)
|
||||
ReferenceTypeSetExpression(DataBinding.LayerProperty.CurrentValue, value);
|
||||
else if (ValueTypeSetExpression != null)
|
||||
ValueTypeSetExpression(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current base value of the data binding
|
||||
/// </summary>
|
||||
public abstract TProperty GetValue();
|
||||
public virtual TProperty GetValue()
|
||||
{
|
||||
return GetExpression(DataBinding.LayerProperty.CurrentValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the provided object to a type of <typeparamref name="TProperty" />
|
||||
/// </summary>
|
||||
public virtual TProperty ConvertFromObject(object source)
|
||||
{
|
||||
return (TProperty) Convert.ChangeType(source, typeof(TProperty));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the data binding converter has been initialized and the <see cref="DataBinding" /> is available
|
||||
@@ -77,40 +95,76 @@ namespace Artemis.Core
|
||||
{
|
||||
DataBinding = dataBinding;
|
||||
GetExpression = dataBinding.Registration.PropertyExpression.Compile();
|
||||
SetExpression = CreateValueSetter();
|
||||
CreateSetExpression();
|
||||
|
||||
OnInitialized();
|
||||
}
|
||||
|
||||
private Action<TLayerProperty, TProperty> CreateValueSetter()
|
||||
private void CreateSetExpression()
|
||||
{
|
||||
MethodInfo setterMethod = null;
|
||||
|
||||
if (DataBinding.Registration.Member != null)
|
||||
// If the registration does not point towards a member of LayerProperty<T>.CurrentValue, assign directly to LayerProperty<T>.CurrentValue
|
||||
if (DataBinding.Registration.Member == null)
|
||||
{
|
||||
if (DataBinding.Registration.Member is PropertyInfo propertyInfo)
|
||||
setterMethod = propertyInfo.GetSetMethod();
|
||||
CreateSetCurrentValueExpression();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure the member of LayerProperty<T>.CurrentValue has a setter
|
||||
MethodInfo setterMethod = null;
|
||||
if (DataBinding.Registration.Member is PropertyInfo propertyInfo)
|
||||
setterMethod = propertyInfo.GetSetMethod();
|
||||
// If there is no setter, the built-in data binding cannot do its job, stay null
|
||||
if (setterMethod == null)
|
||||
return null;
|
||||
return;
|
||||
|
||||
var parameter = Expression.Parameter(typeof(TLayerProperty), "currentValue");
|
||||
// If LayerProperty<T>.CurrentValue is a value type, assign it directly to LayerProperty<T>.CurrentValue after applying the changes
|
||||
if (typeof(TLayerProperty).IsValueType)
|
||||
CreateSetValueTypeExpression();
|
||||
// If it is a reference type it can safely be updated by its reference
|
||||
else
|
||||
CreateSetReferenceTypeExpression();
|
||||
}
|
||||
|
||||
private void CreateSetReferenceTypeExpression()
|
||||
{
|
||||
var propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
||||
|
||||
|
||||
var parameter = Expression.Parameter(typeof(TLayerProperty), "currentValue");
|
||||
var memberAccess = Expression.MakeMemberAccess(parameter, DataBinding.Registration.Member);
|
||||
var assignment = Expression.Assign(memberAccess, propertyValue);
|
||||
var lambda = Expression.Lambda<Action<TLayerProperty, TProperty>>(assignment, parameter, propertyValue);
|
||||
var referenceTypeLambda = Expression.Lambda<Action<TLayerProperty, TProperty>>(assignment, parameter, propertyValue);
|
||||
|
||||
if (typeof(TLayerProperty).IsValueType)
|
||||
{
|
||||
// var layerProperty = Expression.Constant(DataBinding.LayerProperty);
|
||||
// var layerPropertyMemberAccess = Expression.MakeMemberAccess(layerProperty, DataBinding.LayerProperty.GetType().GetMember(nameof(DataBinding.LayerProperty.CurrentValue))[0]);
|
||||
// var assingment = Expression.Assign()
|
||||
}
|
||||
ReferenceTypeSetExpression = referenceTypeLambda.Compile();
|
||||
}
|
||||
|
||||
return lambda.Compile();
|
||||
private void CreateSetValueTypeExpression()
|
||||
{
|
||||
var propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
||||
var variableCurrent = Expression.Variable(typeof(TLayerProperty), "current");
|
||||
var layerProperty = Expression.Constant(DataBinding.LayerProperty);
|
||||
var layerPropertyMemberAccess = Expression.MakeMemberAccess(layerProperty,
|
||||
DataBinding.LayerProperty.GetType().GetMember(nameof(DataBinding.LayerProperty.CurrentValue))[0]);
|
||||
|
||||
var body = Expression.Block(
|
||||
new[] {variableCurrent},
|
||||
Expression.Assign(variableCurrent, layerPropertyMemberAccess),
|
||||
Expression.Assign(Expression.MakeMemberAccess(variableCurrent, DataBinding.Registration.Member), propertyValue),
|
||||
Expression.Assign(layerPropertyMemberAccess, variableCurrent)
|
||||
);
|
||||
|
||||
var valueTypeLambda = Expression.Lambda<Action<TProperty>>(body, propertyValue);
|
||||
ValueTypeSetExpression = valueTypeLambda.Compile();
|
||||
}
|
||||
|
||||
private void CreateSetCurrentValueExpression()
|
||||
{
|
||||
var propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
||||
var layerProperty = Expression.Constant(DataBinding.LayerProperty);
|
||||
var layerPropertyMemberAccess = Expression.MakeMemberAccess(layerProperty,
|
||||
DataBinding.LayerProperty.GetType().GetMember(nameof(DataBinding.LayerProperty.CurrentValue))[0]);
|
||||
|
||||
var body = Expression.Assign(layerPropertyMemberAccess, propertyValue);
|
||||
var lambda = Expression.Lambda<Action<TProperty>>(body, propertyValue);
|
||||
ValueTypeSetExpression = lambda.Compile();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,18 +16,20 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataBindingModifier{TLayerProperty,TProperty}" /> class
|
||||
/// </summary>
|
||||
/// <param name="dataBinding">The data binding the modifier is to be applied to</param>
|
||||
/// <param name="parameterType">The type of the parameter, can either be dynamic (based on a data model value) or static</param>
|
||||
public DataBindingModifier(ProfileRightSideType parameterType)
|
||||
public DataBindingModifier(DataBinding<TLayerProperty, TProperty> dataBinding, ProfileRightSideType parameterType)
|
||||
{
|
||||
_dataBinding = dataBinding ?? throw new ArgumentNullException(nameof(dataBinding));
|
||||
ParameterType = parameterType;
|
||||
Entity = new DataBindingModifierEntity();
|
||||
Save();
|
||||
Initialize();
|
||||
Save();
|
||||
}
|
||||
|
||||
internal DataBindingModifier(DataBinding<TLayerProperty, TProperty> dataBinding, DataBindingModifierEntity entity)
|
||||
{
|
||||
DataBinding = dataBinding;
|
||||
_dataBinding = dataBinding;
|
||||
Entity = entity;
|
||||
Load();
|
||||
Initialize();
|
||||
|
||||
+7
-1
@@ -31,10 +31,16 @@ namespace Artemis.Core
|
||||
public abstract string Icon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this modifier supports a parameter, defaults to true
|
||||
/// Gets or sets whether this modifier supports a parameter, defaults to <c>true</c>
|
||||
/// </summary>
|
||||
public bool SupportsParameter { get; protected set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the preferred parameter type
|
||||
/// <para>If <c>null</c>, the parameter type will match the source property</para>
|
||||
/// </summary>
|
||||
public Type PreferredParameterType { get; protected set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the given type is supported by the modifier
|
||||
/// </summary>
|
||||
|
||||
@@ -5,6 +5,11 @@ namespace Artemis.Core
|
||||
{
|
||||
internal class DivideModifierType : DataBindingModifierType
|
||||
{
|
||||
public DivideModifierType()
|
||||
{
|
||||
PreferredParameterType = typeof(float);
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
|
||||
|
||||
public override string Description => "Divide by";
|
||||
|
||||
@@ -5,6 +5,11 @@ namespace Artemis.Core
|
||||
{
|
||||
internal class MultiplicationModifierType : DataBindingModifierType
|
||||
{
|
||||
public MultiplicationModifierType()
|
||||
{
|
||||
PreferredParameterType = typeof(float);
|
||||
}
|
||||
|
||||
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
|
||||
|
||||
public override string Description => "Multiply by";
|
||||
|
||||
@@ -682,9 +682,9 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
// Ensure the brush reference matches the brush
|
||||
var current = General.BrushReference.CurrentValue;
|
||||
var current = General.BrushReference.BaseValue;
|
||||
if (!descriptor.MatchesLayerBrushReference(current))
|
||||
General.BrushReference.CurrentValue = new LayerBrushReference(descriptor);
|
||||
General.BrushReference.BaseValue = new LayerBrushReference(descriptor);
|
||||
|
||||
ActivateLayerBrush();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user