diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
index ddb682a2a..c1e86d9cf 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using Artemis.Storage.Entities.Profile.DataBindings;
namespace Artemis.Core
@@ -7,8 +6,6 @@ namespace Artemis.Core
///
public class DataBinding : IDataBinding
{
- private readonly List> _modifiers = new List>();
-
private TProperty _currentValue;
private bool _disposed;
private TimeSpan _easingProgress;
@@ -63,51 +60,9 @@ namespace Artemis.Core
/// Gets ors ets the easing function of the data binding
///
public Easings.Functions EasingFunction { get; set; }
-
-
+
internal DataBindingEntity Entity { get; }
-
- ///
- /// Updates the smoothing progress of the data binding
- ///
- /// The time in seconds that passed since the last update
- public void Update(double deltaTime)
- {
- if (_disposed)
- throw new ObjectDisposedException("DataBinding");
-
- // Data bindings cannot go back in time like brushes
- deltaTime = Math.Max(0, deltaTime);
-
- _easingProgress = _easingProgress.Add(TimeSpan.FromSeconds(deltaTime));
- if (_easingProgress > EasingTime)
- _easingProgress = EasingTime;
- }
-
- ///
- public void Apply()
- {
- if (_disposed)
- throw new ObjectDisposedException("DataBinding");
-
- if (Converter == null)
- return;
-
- TProperty converterValue = Converter.GetValue();
- TProperty value = GetValue(converterValue);
- Converter.ApplyValue(value);
- }
-
- ///
- public void Dispose()
- {
- _disposed = true;
-
- Registration.DataBinding = null;
- DataBindingMode?.Dispose();
- }
-
-
+
///
/// Gets the current value of the data binding
///
@@ -179,6 +134,46 @@ namespace Artemis.Core
return Converter.Interpolate(_previousValue, _currentValue, Easings.Interpolate(easingAmount, EasingFunction));
}
+ ///
+ /// Updates the smoothing progress of the data binding
+ ///
+ /// The time in seconds that passed since the last update
+ public void Update(double deltaTime)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException("DataBinding");
+
+ // Data bindings cannot go back in time like brushes
+ deltaTime = Math.Max(0, deltaTime);
+
+ _easingProgress = _easingProgress.Add(TimeSpan.FromSeconds(deltaTime));
+ if (_easingProgress > EasingTime)
+ _easingProgress = EasingTime;
+ }
+
+ ///
+ public void Apply()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException("DataBinding");
+
+ if (Converter == null)
+ return;
+
+ TProperty converterValue = Converter.GetValue();
+ TProperty value = GetValue(converterValue);
+ Converter.ApplyValue(value);
+ }
+
+ ///
+ public void Dispose()
+ {
+ _disposed = true;
+
+ Registration.DataBinding = null;
+ DataBindingMode?.Dispose();
+ }
+
#region Mode management
///
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs
index 4d89aa732..c8f2301ac 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs
@@ -82,7 +82,7 @@ namespace Artemis.Core
///
/// Converts the provided object to a type of
///
- public virtual TProperty ConvertFromObject(object source)
+ public virtual TProperty ConvertFromObject(object? source)
{
return (TProperty) Convert.ChangeType(source, typeof(TProperty));
}
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Modes/DataBindingModifier.cs b/src/Artemis.Core/Models/Profile/DataBindings/Modes/DataBindingModifier.cs
index 8b29c8ea6..d570463de 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/Modes/DataBindingModifier.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/Modes/DataBindingModifier.cs
@@ -1,6 +1,4 @@
using System;
-using System.Linq.Expressions;
-using Artemis.Core.DataModelExpansions;
using Artemis.Storage.Entities.Profile.DataBindings;
using Newtonsoft.Json;
@@ -50,14 +48,9 @@ namespace Artemis.Core
public int Order { get; set; }
///
- /// Gets the currently used instance of the parameter data model
+ /// Gets the path of the parameter property
///
- public DataModel ParameterDataModel { get; private set; }
-
- ///
- /// Gets the path of the parameter property in the
- ///
- public string ParameterPropertyPath { get; private set; }
+ public DataModelPath? ParameterPath { get; set; }
///
/// Gets the parameter static value, only used it is
@@ -65,13 +58,144 @@ namespace Artemis.Core
///
public object ParameterStaticValue { get; private set; }
- ///
- /// A compiled expression tree that when given a matching data model returns the value of the modifiers parameter
- ///
- public Func CompiledParameterAccessor { get; set; }
-
internal DataBindingModifierEntity Entity { get; set; }
+ ///
+ /// Applies the modifier to the provided value
+ ///
+ /// The value to apply the modifier to, should be of the same type as the data binding target
+ /// The modified value
+ public object Apply(object? currentValue)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException("DataBindingModifier");
+
+ if (ModifierType == null)
+ return currentValue;
+
+ if (!ModifierType.SupportsParameter)
+ return ModifierType.Apply(currentValue, null);
+
+ if (ParameterType == ProfileRightSideType.Dynamic && ParameterPath != null && ParameterPath.IsValid)
+ {
+ object? value = ParameterPath.GetValue();
+ return ModifierType.Apply(currentValue, value);
+ }
+
+ if (ParameterType == ProfileRightSideType.Static)
+ return ModifierType.Apply(currentValue, ParameterStaticValue);
+
+ return currentValue;
+ }
+
+ ///
+ /// Updates the modifier type of the modifier and re-compiles the expression
+ ///
+ ///
+ public void UpdateModifierType(DataBindingModifierType modifierType)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException("DataBindingModifier");
+
+ // Calling CreateExpression will clear compiled expressions
+ if (modifierType == null)
+ {
+ ModifierType = null;
+ return;
+ }
+
+ Type targetType = DirectDataBinding.DataBinding.GetTargetType();
+ if (!modifierType.SupportsType(targetType))
+ throw new ArtemisCoreException($"Cannot apply modifier type {modifierType.GetType().Name} to this modifier because " +
+ $"it does not support this data binding's type {targetType.Name}");
+
+ ModifierType = modifierType;
+ }
+
+ ///
+ /// Updates the parameter of the modifier and makes the modifier dynamic
+ ///
+ /// The path pointing to the parameter
+ public void UpdateParameterDynamic(DataModelPath? path)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException("DataBindingModifier");
+
+ if (path != null && !path.IsValid)
+ throw new ArtemisCoreException("Cannot update parameter of data binding modifier to an invalid path");
+
+ ParameterPath?.Dispose();
+ ParameterPath = path != null ? new DataModelPath(path) : null;
+
+ ParameterType = ProfileRightSideType.Dynamic;
+ }
+
+ ///
+ /// Updates the parameter of the modifier, makes the modifier static and re-compiles the expression
+ ///
+ /// The static value to use as a parameter
+ public void UpdateParameterStatic(object staticValue)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException("DataBindingModifier");
+
+ ParameterType = ProfileRightSideType.Static;
+ ParameterPath?.Dispose();
+ ParameterPath = null;
+
+ Type parameterType = ModifierType?.ParameterType ?? DirectDataBinding.DataBinding.GetTargetType();
+
+ // If not null ensure the types match and if not, convert it
+ if (staticValue != null && staticValue.GetType() == parameterType)
+ ParameterStaticValue = staticValue;
+ else if (staticValue != null)
+ ParameterStaticValue = Convert.ChangeType(staticValue, parameterType);
+ // If null create a default instance for value types or simply make it null for reference types
+ else if (parameterType.IsValueType)
+ ParameterStaticValue = Activator.CreateInstance(parameterType);
+ else
+ ParameterStaticValue = null;
+ }
+
+ private void Initialize()
+ {
+ DataBindingModifierTypeStore.DataBindingModifierAdded += DataBindingModifierTypeStoreOnDataBindingModifierAdded;
+ DataBindingModifierTypeStore.DataBindingModifierRemoved += DataBindingModifierTypeStoreOnDataBindingModifierRemoved;
+
+ // Modifier type
+ if (Entity.ModifierTypePluginGuid != null && ModifierType == null)
+ {
+ DataBindingModifierType modifierType = DataBindingModifierTypeStore.Get(Entity.ModifierTypePluginGuid.Value, Entity.ModifierType)?.DataBindingModifierType;
+ if (modifierType != null)
+ UpdateModifierType(modifierType);
+ }
+
+ // Dynamic parameter
+ if (ParameterType == ProfileRightSideType.Dynamic && Entity.ParameterPath != null)
+ {
+ ParameterPath = new DataModelPath(null, Entity.ParameterPath);
+ }
+ // Static parameter
+ else if (ParameterType == ProfileRightSideType.Static && Entity.ParameterStaticValue != null && ParameterStaticValue == null)
+ {
+ // Use the target type so JSON.NET has a better idea what to do
+ Type parameterType = ModifierType?.ParameterType ?? DirectDataBinding.DataBinding.GetTargetType();
+ object staticValue;
+
+ try
+ {
+ staticValue = JsonConvert.DeserializeObject(Entity.ParameterStaticValue, parameterType);
+ }
+ // If deserialization fails, use the type's default
+ catch (JsonSerializationException e)
+ {
+ DeserializationLogger.LogModifierDeserializationFailure(GetType().Name, e);
+ staticValue = Activator.CreateInstance(parameterType);
+ }
+
+ UpdateParameterStatic(staticValue);
+ }
+ }
///
public void Save()
@@ -79,6 +203,10 @@ namespace Artemis.Core
if (_disposed)
throw new ObjectDisposedException("DataBindingModifier");
+ // Don't save an invalid state
+ if (ParameterPath != null && !ParameterPath.IsValid)
+ return;
+
if (!DirectDataBinding.Entity.Modifiers.Contains(Entity))
DirectDataBinding.Entity.Modifiers.Add(Entity);
@@ -94,11 +222,8 @@ namespace Artemis.Core
Entity.ParameterType = (int) ParameterType;
// Parameter
- if (ParameterDataModel != null)
- {
- Entity.ParameterDataModelGuid = ParameterDataModel.PluginInfo.Guid;
- Entity.ParameterPropertyPath = ParameterPropertyPath;
- }
+ ParameterPath?.Save();
+ Entity.ParameterPath = ParameterPath?.Entity;
Entity.ParameterStaticValue = JsonConvert.SerializeObject(ParameterStaticValue);
}
@@ -125,186 +250,8 @@ namespace Artemis.Core
DataBindingModifierTypeStore.DataBindingModifierAdded -= DataBindingModifierTypeStoreOnDataBindingModifierAdded;
DataBindingModifierTypeStore.DataBindingModifierRemoved -= DataBindingModifierTypeStoreOnDataBindingModifierRemoved;
- DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
- DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
- }
- ///
- /// Applies the modifier to the provided value
- ///
- /// The value to apply the modifier to, should be of the same type as the data binding target
- /// The modified value
- public object Apply(object currentValue)
- {
- if (_disposed)
- throw new ObjectDisposedException("DataBindingModifier");
-
- if (ModifierType == null)
- return currentValue;
-
- if (!ModifierType.SupportsParameter)
- return ModifierType.Apply(currentValue, null);
-
- if (ParameterType == ProfileRightSideType.Dynamic && CompiledParameterAccessor != null)
- {
- object value = CompiledParameterAccessor(ParameterDataModel);
- return ModifierType.Apply(currentValue, value);
- }
-
- if (ParameterType == ProfileRightSideType.Static)
- return ModifierType.Apply(currentValue, ParameterStaticValue);
-
- return currentValue;
- }
-
- ///
- /// Updates the modifier type of the modifier and re-compiles the expression
- ///
- ///
- public void UpdateModifierType(DataBindingModifierType modifierType)
- {
- if (_disposed)
- throw new ObjectDisposedException("DataBindingModifier");
-
- // Calling CreateExpression will clear compiled expressions
- if (modifierType == null)
- {
- ModifierType = null;
- CreateExpression();
- return;
- }
-
- Type targetType = DirectDataBinding.DataBinding.GetTargetType();
- if (!modifierType.SupportsType(targetType))
- {
- throw new ArtemisCoreException($"Cannot apply modifier type {modifierType.GetType().Name} to this modifier because " +
- $"it does not support this data binding's type {targetType.Name}");
- }
-
- ModifierType = modifierType;
- CreateExpression();
- }
-
- ///
- /// Updates the parameter of the modifier, makes the modifier dynamic and re-compiles the expression
- ///
- /// The data model of the parameter
- /// The path pointing to the parameter inside the data model
- public void UpdateParameter(DataModel? dataModel, string? path)
- {
- if (_disposed)
- throw new ObjectDisposedException("DataBindingModifier");
-
- if (dataModel != null && path == null)
- throw new ArtemisCoreException("If a data model is provided, a path is also required");
- if (dataModel == null && path != null)
- throw new ArtemisCoreException("If path is provided, a data model is also required");
-
- if (dataModel != null)
- {
- if (!dataModel.ContainsPath(path))
- throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
- }
-
- ParameterType = ProfileRightSideType.Dynamic;
- ParameterDataModel = dataModel;
- ParameterPropertyPath = path;
-
- CreateExpression();
- }
-
- ///
- /// Updates the parameter of the modifier, makes the modifier static and re-compiles the expression
- ///
- /// The static value to use as a parameter
- public void UpdateParameter(object staticValue)
- {
- if (_disposed)
- throw new ObjectDisposedException("DataBindingModifier");
-
- ParameterType = ProfileRightSideType.Static;
- ParameterDataModel = null;
- ParameterPropertyPath = null;
-
- Type parameterType = ModifierType?.ParameterType ?? DirectDataBinding.DataBinding.GetTargetType();
-
- // If not null ensure the types match and if not, convert it
- if (staticValue != null && staticValue.GetType() == parameterType)
- ParameterStaticValue = staticValue;
- else if (staticValue != null)
- ParameterStaticValue = Convert.ChangeType(staticValue, parameterType);
- // If null create a default instance for value types or simply make it null for reference types
- else if (parameterType.IsValueType)
- ParameterStaticValue = Activator.CreateInstance(parameterType);
- else
- ParameterStaticValue = null;
-
- CreateExpression();
- }
-
- private void Initialize()
- {
- DataBindingModifierTypeStore.DataBindingModifierAdded += DataBindingModifierTypeStoreOnDataBindingModifierAdded;
- DataBindingModifierTypeStore.DataBindingModifierRemoved += DataBindingModifierTypeStoreOnDataBindingModifierRemoved;
- DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
- DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
-
- // Modifier type
- if (Entity.ModifierTypePluginGuid != null && ModifierType == null)
- {
- DataBindingModifierType modifierType = DataBindingModifierTypeStore.Get(Entity.ModifierTypePluginGuid.Value, Entity.ModifierType)?.DataBindingModifierType;
- if (modifierType != null)
- UpdateModifierType(modifierType);
- }
-
- // Dynamic parameter
- if (ParameterType == ProfileRightSideType.Dynamic && Entity.ParameterDataModelGuid != null && ParameterDataModel == null)
- {
- DataModel dataModel = DataModelStore.Get(Entity.ParameterDataModelGuid.Value)?.DataModel;
- if (dataModel != null && dataModel.ContainsPath(Entity.ParameterPropertyPath))
- UpdateParameter(dataModel, Entity.ParameterPropertyPath);
- }
- // Static parameter
- else if (ParameterType == ProfileRightSideType.Static && Entity.ParameterStaticValue != null && ParameterStaticValue == null)
- {
- // Use the target type so JSON.NET has a better idea what to do
- Type parameterType = ModifierType?.ParameterType ?? DirectDataBinding.DataBinding.GetTargetType();
- object staticValue;
-
- try
- {
- staticValue = JsonConvert.DeserializeObject(Entity.ParameterStaticValue, parameterType);
- }
- // If deserialization fails, use the type's default
- catch (JsonSerializationException e)
- {
- DeserializationLogger.LogModifierDeserializationFailure(GetType().Name, e);
- staticValue = Activator.CreateInstance(parameterType);
- }
-
- UpdateParameter(staticValue);
- }
- }
-
- private void CreateExpression()
- {
- CompiledParameterAccessor = null;
-
- if (ModifierType == null)
- return;
-
- if (ParameterType == ProfileRightSideType.Dynamic && ModifierType.SupportsParameter)
- {
- if (ParameterDataModel == null)
- return;
-
- // If the right side value is null, the constant type cannot be inferred and must be provided based on the data binding target
- Expression parameterAccessor = ExpressionUtilities.CreateDataModelAccessor(
- ParameterDataModel, ParameterPropertyPath, "parameter", out ParameterExpression rightSideParameter
- );
- Expression> lambda = Expression.Lambda>(Expression.Convert(parameterAccessor, typeof(object)), rightSideParameter);
- CompiledParameterAccessor = lambda.Compile();
- }
+ ParameterPath?.Dispose();
}
#region Event handlers
@@ -325,21 +272,6 @@ namespace Artemis.Core
UpdateModifierType(null);
}
- private void DataModelStoreOnDataModelAdded(object sender, DataModelStoreEvent e)
- {
- DataModel dataModel = e.Registration.DataModel;
- if (dataModel.PluginInfo.Guid == Entity.ParameterDataModelGuid && dataModel.ContainsPath(Entity.ParameterPropertyPath))
- UpdateParameter(dataModel, Entity.ParameterPropertyPath);
- }
-
- private void DataModelStoreOnDataModelRemoved(object sender, DataModelStoreEvent e)
- {
- if (e.Registration.DataModel != ParameterDataModel)
- return;
- ParameterDataModel = null;
- CompiledParameterAccessor = null;
- }
-
#endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Modes/DirectDataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/Modes/DirectDataBinding.cs
index b92144f42..f22ee61d5 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/Modes/DirectDataBinding.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/Modes/DirectDataBinding.cs
@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Linq.Expressions;
-using Artemis.Core.DataModelExpansions;
using Artemis.Storage.Entities.Profile.DataBindings;
namespace Artemis.Core
@@ -20,31 +17,20 @@ namespace Artemis.Core
DataBinding = dataBinding;
Entity = entity;
- Initialize();
Load();
}
- internal DirectDataBindingEntity Entity { get; }
-
///
- /// Gets the currently used instance of the data model that contains the source of the data binding
+ /// Gets the path of the source property
///
- public DataModel SourceDataModel { get; private set; }
-
- ///
- /// Gets the path of the source property in the
- ///
- public string SourcePropertyPath { get; private set; }
+ public DataModelPath? SourcePath { get; private set; }
///
/// Gets a list of modifiers applied to this data binding
///
public IReadOnlyList> Modifiers => _modifiers.AsReadOnly();
- ///
- /// Gets the compiled function that gets the current value of the data binding target
- ///
- public Func CompiledTargetAccessor { get; private set; }
+ internal DirectDataBindingEntity Entity { get; }
///
public DataBinding DataBinding { get; }
@@ -55,10 +41,10 @@ namespace Artemis.Core
if (_disposed)
throw new ObjectDisposedException("DirectDataBinding");
- if (CompiledTargetAccessor == null)
+ if (SourcePath == null || !SourcePath.IsValid)
return baseValue;
- object dataBindingValue = CompiledTargetAccessor(SourceDataModel);
+ object? dataBindingValue = SourcePath.GetValue();
foreach (DataBindingModifier dataBindingModifier in Modifiers)
dataBindingValue = dataBindingModifier.Apply(dataBindingValue);
@@ -72,11 +58,10 @@ namespace Artemis.Core
{
_disposed = true;
- DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
- DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
-
foreach (DataBindingModifier dataBindingModifier in Modifiers)
dataBindingModifier.Dispose();
+
+ SourcePath?.Dispose();
}
#endregion
@@ -86,7 +71,9 @@ namespace Artemis.Core
///
public void Load()
{
- // Data model is done during Initialize
+ // Source
+ if (Entity.SourcePath != null)
+ SourcePath = new DataModelPath(null, Entity.SourcePath);
// Modifiers
foreach (DataBindingModifierEntity dataBindingModifierEntity in Entity.Modifiers)
@@ -98,12 +85,12 @@ namespace Artemis.Core
///
public void Save()
{
- // Data model
- if (SourceDataModel != null)
- {
- Entity.SourceDataModelGuid = SourceDataModel.PluginInfo.Guid;
- Entity.SourcePropertyPath = SourcePropertyPath;
- }
+ // Don't save an invalid state
+ if (SourcePath != null && !SourcePath.IsValid)
+ return;
+
+ SourcePath?.Save();
+ Entity.SourcePath = SourcePath?.Entity;
// Modifiers
Entity.Modifiers.Clear();
@@ -113,76 +100,30 @@ namespace Artemis.Core
#endregion
- #region Initialization
-
- private void Initialize()
- {
- DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
- DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
-
- // Source
- if (Entity.SourceDataModelGuid != null && SourceDataModel == null)
- {
- DataModel dataModel = DataModelStore.Get(Entity.SourceDataModelGuid.Value)?.DataModel;
- if (dataModel != null && dataModel.ContainsPath(Entity.SourcePropertyPath))
- UpdateSource(dataModel, Entity.SourcePropertyPath);
- }
- }
-
- private void CreateExpression()
- {
- Type listType = SourceDataModel.GetListTypeInPath(SourcePropertyPath);
- if (listType != null)
- throw new ArtemisCoreException($"Cannot create a regular accessor at path {SourcePropertyPath} because the path contains a list");
-
- ParameterExpression parameter = Expression.Parameter(typeof(DataModel), "targetDataModel");
- Expression accessor = SourcePropertyPath.Split('.').Aggregate(
- Expression.Convert(parameter, SourceDataModel.GetType()), // Cast to the appropriate type
- Expression.Property
- );
-
- UnaryExpression returnValue = Expression.Convert(accessor, typeof(object));
-
- Expression> lambda = Expression.Lambda>(returnValue, parameter);
- CompiledTargetAccessor = lambda.Compile();
- }
-
- #endregion
-
#region Source
///
/// Returns the type of the source property of this data binding
///
- public Type GetSourceType()
+ public Type? GetSourceType()
{
- return SourceDataModel?.GetTypeAtPath(SourcePropertyPath);
+ return SourcePath?.GetPropertyType();
}
///
- /// Updates the source of the data binding and re-compiles the expression
+ /// Updates the source of the data binding
///
- /// The data model of the source
- /// The path pointing to the source inside the data model
- public void UpdateSource(DataModel dataModel, string path)
+ /// The path pointing to the source
+ public void UpdateSource(DataModelPath? path)
{
if (_disposed)
throw new ObjectDisposedException("DirectDataBinding");
- if (dataModel != null && path == null)
- throw new ArtemisCoreException("If a data model is provided, a path is also required");
- if (dataModel == null && path != null)
- throw new ArtemisCoreException("If path is provided, a data model is also required");
+ if (path != null && !path.IsValid)
+ throw new ArtemisCoreException("Cannot update source of data binding to an invalid path");
- if (dataModel != null)
- {
- if (!dataModel.ContainsPath(path))
- throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
- }
-
- SourceDataModel = dataModel;
- SourcePropertyPath = path;
- CreateExpression();
+ SourcePath?.Dispose();
+ SourcePath = path != null ? new DataModelPath(path) : null;
}
#endregion
@@ -239,31 +180,12 @@ namespace Artemis.Core
#endregion
- #region Event handlers
-
- private void DataModelStoreOnDataModelAdded(object sender, DataModelStoreEvent e)
- {
- DataModel dataModel = e.Registration.DataModel;
- if (dataModel.PluginInfo.Guid == Entity.SourceDataModelGuid && dataModel.ContainsPath(Entity.SourcePropertyPath))
- UpdateSource(dataModel, Entity.SourcePropertyPath);
- }
-
- private void DataModelStoreOnDataModelRemoved(object sender, DataModelStoreEvent e)
- {
- if (SourceDataModel != e.Registration.DataModel)
- return;
- SourceDataModel = null;
- CompiledTargetAccessor = null;
- }
-
- #endregion
-
#region Events
///
/// Occurs when a modifier is added or removed
///
- public event EventHandler ModifiersUpdated;
+ public event EventHandler? ModifiersUpdated;
protected virtual void OnModifiersUpdated()
{
diff --git a/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingModifierEntity.cs b/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingModifierEntity.cs
index cef799f14..c4139737c 100644
--- a/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingModifierEntity.cs
+++ b/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingModifierEntity.cs
@@ -10,8 +10,7 @@ namespace Artemis.Storage.Entities.Profile.DataBindings
public int Order { get; set; }
public int ParameterType { get; set; }
- public Guid? ParameterDataModelGuid { get; set; }
- public string ParameterPropertyPath { get; set; }
+ public DataModelPathEntity ParameterPath { get; set; }
// Stored as a string to be able to control serialization and deserialization ourselves
public string ParameterStaticValue { get; set; }
diff --git a/src/Artemis.Storage/Entities/Profile/DataBindings/DirectDataBindingEntity.cs b/src/Artemis.Storage/Entities/Profile/DataBindings/DirectDataBindingEntity.cs
index ce1fc189e..e8a14cb9f 100644
--- a/src/Artemis.Storage/Entities/Profile/DataBindings/DirectDataBindingEntity.cs
+++ b/src/Artemis.Storage/Entities/Profile/DataBindings/DirectDataBindingEntity.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace Artemis.Storage.Entities.Profile.DataBindings
{
@@ -10,9 +9,7 @@ namespace Artemis.Storage.Entities.Profile.DataBindings
Modifiers = new List();
}
- public Guid? SourceDataModelGuid { get; set; }
- public string SourcePropertyPath { get; set; }
-
+ public DataModelPathEntity SourcePath { get; set; }
public List Modifiers { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs
index 0de5a854f..153e9ca40 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs
@@ -20,10 +20,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private bool _isEasingTimeEnabled;
private DataBindingModeType _selectedDataBindingMode;
private TimelineEasingViewModel _selectedEasingViewModel;
-
- private bool _updating;
private bool _applyTestResultToLayer;
+ private bool _updating;
+ private bool _updatingTestResult;
public DataBindingViewModel(DataBindingRegistration registration,
IProfileEditorService profileEditorService,
@@ -74,7 +74,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
public bool ApplyTestResultToLayer
{
get => _applyTestResultToLayer;
- set => SetAndNotify(ref _applyTestResultToLayer, value);
+ set
+ {
+ if (!SetAndNotify(ref _applyTestResultToLayer, value)) return;
+ _profileEditorService.UpdateProfilePreview();
+ }
}
public TimelineEasingViewModel SelectedEasingViewModel
@@ -111,6 +115,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
{
_updateTimer.Dispose();
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
+
+ Registration.LayerProperty.Updated -= LayerPropertyOnUpdated;
}
private void Initialize()
@@ -119,6 +125,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
_updateTimer.Start();
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
+ Registration.LayerProperty.Updated += LayerPropertyOnUpdated;
CreateDataBindingModeModeViewModel();
Update();
@@ -216,14 +223,22 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private void UpdateTestResult()
{
+ if (_updating || _updatingTestResult)
+ return;
+
+ _updatingTestResult = true;
+
if (Registration.DataBinding == null || ActiveItem == null)
{
TestInputValue.UpdateValue(default);
TestResultValue.UpdateValue(default);
+ _updatingTestResult = false;
return;
}
+ // While playing in preview data bindings aren't updated
Registration.DataBinding.Update(0.04);
+
if (ActiveItem.SupportsTestValue)
{
TProperty currentValue = Registration.Converter.ConvertFromObject(ActiveItem?.GetTestValue() ?? default(TProperty));
@@ -235,11 +250,15 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
if (ApplyTestResultToLayer)
{
- Registration.DataBinding.Apply();
- _profileEditorService.UpdateProfilePreview();
+ // TODO: A bit crappy, the ProfileEditorService should really be doing this
+ bool playing = ((Parent as Screen)?.Parent as LayerPropertiesViewModel)?.Playing ?? true;
+ if (!playing)
+ _profileEditorService.UpdateProfilePreview();
}
+
+ _updatingTestResult = false;
}
-
+
private void EnableDataBinding()
{
if (Registration.DataBinding != null)
@@ -264,6 +283,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
{
UpdateTestResult();
}
+
+ private void LayerPropertyOnUpdated(object? sender, LayerPropertyEventArgs e)
+ {
+ if (ApplyTestResultToLayer)
+ Registration.DataBinding?.Apply();
+ }
}
public interface IDataBindingViewModel : IScreen, IDisposable
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DirectDataBinding/DataBindingModifierViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DirectDataBinding/DataBindingModifierViewModel.cs
index de58da9d9..e4d1b57e9 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DirectDataBinding/DataBindingModifierViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DirectDataBinding/DataBindingModifierViewModel.cs
@@ -94,10 +94,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
if (Modifier.ParameterType == ProfileRightSideType.Dynamic)
{
Type sourceType = Modifier.DirectDataBinding.GetSourceType();
- Modifier.UpdateParameter((Modifier.ModifierType.ParameterType ?? sourceType).GetDefault());
+ Modifier.UpdateParameterStatic((Modifier.ModifierType.ParameterType ?? sourceType).GetDefault());
}
else
- Modifier.UpdateParameter(null, null);
+ Modifier.UpdateParameterDynamic(null);
Update();
_profileEditorService.UpdateSelectedProfileElement();
@@ -105,13 +105,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
private void ParameterSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
{
- Modifier.UpdateParameter(e.DataModelPath.Target, e.DataModelPath.Path);
+ Modifier.UpdateParameterDynamic(e.DataModelPath);
_profileEditorService.UpdateSelectedProfileElement();
}
private void StaticInputViewModelOnValueUpdated(object sender, DataModelInputStaticEventArgs e)
{
- Modifier.UpdateParameter(e.Value);
+ Modifier.UpdateParameterStatic(e.Value);
_profileEditorService.UpdateSelectedProfileElement();
}
@@ -166,11 +166,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
SelectedModifierType = Modifier.ModifierType;
// Parameter
- throw new NotImplementedException();
- // if (DynamicSelectionViewModel != null)
- // DynamicSelectionViewModel.PopulateSelectedPropertyViewModel(Modifier.ParameterDataModel, Modifier.ParameterPropertyPath);
- // else if (StaticInputViewModel != null)
- // StaticInputViewModel.Value = Modifier.ParameterStaticValue;
+ if (DynamicSelectionViewModel != null)
+ DynamicSelectionViewModel.ChangeDataModelPath(Modifier.ParameterPath);
+ else if (StaticInputViewModel != null)
+ StaticInputViewModel.Value = Modifier.ParameterStaticValue;
}
private void ExecuteSelectModifierTypeCommand(object context)
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DirectDataBinding/DirectDataBindingModeViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DirectDataBinding/DirectDataBindingModeViewModel.cs
index a74d645fd..cfaa109b3 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DirectDataBinding/DirectDataBindingModeViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DirectDataBinding/DirectDataBindingModeViewModel.cs
@@ -56,18 +56,16 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
public void Update()
{
- throw new NotImplementedException();
- // TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DirectDataBinding.SourceDataModel, DirectDataBinding.SourcePropertyPath);
+ TargetSelectionViewModel.ChangeDataModelPath(DirectDataBinding.SourcePath);
TargetSelectionViewModel.FilterTypes = new[] {DirectDataBinding.DataBinding.GetTargetType()};
- CanAddModifier = DirectDataBinding.SourceDataModel != null;
+ CanAddModifier = DirectDataBinding.SourcePath != null && DirectDataBinding.SourcePath.IsValid;
UpdateModifierViewModels();
}
public object GetTestValue()
{
- throw new NotImplementedException();
- // return TargetSelectionViewModel.SelectedPropertyViewModel?.GetCurrentValue();
+ return DirectDataBinding.SourcePath?.GetValue();
}
#region IDisposable
@@ -114,8 +112,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
private void TargetSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
{
- throw new NotImplementedException();
- // DirectDataBinding.UpdateSource(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.Path);
+ DirectDataBinding.UpdateSource(e.DataModelPath);
Update();
_profileEditorService.UpdateSelectedProfileElement();
@@ -143,6 +140,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
modifierViewModel.Dispose();
}
+ // Don't create children without a source or with an invalid source
+ if (DirectDataBinding.SourcePath == null || !DirectDataBinding.SourcePath.IsValid)
+ return;
+
// Add missing VMs
foreach (DataBindingModifier modifier in DirectDataBinding.Modifiers)
{