diff --git a/src/Artemis.Core/Artemis.Core.csproj.DotSettings b/src/Artemis.Core/Artemis.Core.csproj.DotSettings
index babfa2469..44ebfc334 100644
--- a/src/Artemis.Core/Artemis.Core.csproj.DotSettings
+++ b/src/Artemis.Core/Artemis.Core.csproj.DotSettings
@@ -9,7 +9,11 @@
TrueTrueTrue
+ True
+ True
+ TrueTrue
+ TrueTrueTrueTrue
diff --git a/src/Artemis.Core/Events/DataBindingPropertyUpdatedEvent.cs b/src/Artemis.Core/Events/DataBindingPropertyUpdatedEvent.cs
new file mode 100644
index 000000000..52c8a99fa
--- /dev/null
+++ b/src/Artemis.Core/Events/DataBindingPropertyUpdatedEvent.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Artemis.Core
+{
+ public class DataBindingPropertyUpdatedEvent : EventArgs
+ {
+ public DataBindingPropertyUpdatedEvent(T value)
+ {
+ Value = value;
+ }
+
+ ///
+ /// The updated value that should be applied to the layer property
+ ///
+ public T Value { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/Extensions/TypeExtensions.cs b/src/Artemis.Core/Extensions/TypeExtensions.cs
index 027610874..9b82bf445 100644
--- a/src/Artemis.Core/Extensions/TypeExtensions.cs
+++ b/src/Artemis.Core/Extensions/TypeExtensions.cs
@@ -86,5 +86,13 @@ namespace Artemis.Core
);
return castable;
}
+
+ ///
+ /// Returns the default value of the given type
+ ///
+ public static object GetDefault(this Type type)
+ {
+ return type.IsValueType ? Activator.CreateInstance(type) : null;
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs
new file mode 100644
index 000000000..c0d8a49be
--- /dev/null
+++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Artemis.Core.Models.Profile.DataBindings.Converters
+{
+ public class FloatDataBindingConverter : IDataBindingConverter
+ {
+ public BaseLayerProperty BaseLayerProperty { get; set; }
+ public object Sum(object a, object b)
+ {
+ return (float) a + (float) b;
+ }
+
+ public object Interpolate(object a, object b, float progress)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ApplyValue(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public object GetValue()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
index 9442c07b9..9e34edc09 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs
@@ -17,15 +17,23 @@ namespace Artemis.Core
private readonly List _modifiers = new List();
private bool _isInitialized;
- internal DataBinding(BaseLayerProperty layerProperty, PropertyInfo targetProperty)
+ private object _currentValue;
+ private object _previousValue;
+ private float _easingProgress;
+
+ internal DataBinding(DataBindingRegistration dataBindingRegistration)
{
- LayerProperty = layerProperty;
- TargetProperty = targetProperty;
+ LayerProperty = dataBindingRegistration.LayerProperty;
+ TargetProperty = dataBindingRegistration.Property;
+ Registration = dataBindingRegistration;
+
Entity = new DataBindingEntity();
ApplyToEntity();
}
+ public DataBindingRegistration Registration { get; private set; }
+
internal DataBinding(BaseLayerProperty layerProperty, DataBindingEntity entity)
{
LayerProperty = layerProperty;
@@ -87,6 +95,8 @@ namespace Artemis.Core
{
modifier.DataBinding = this;
_modifiers.Add(modifier);
+
+ OnModifiersUpdated();
}
}
@@ -99,6 +109,8 @@ namespace Artemis.Core
{
modifier.DataBinding = null;
_modifiers.Remove(modifier);
+
+ OnModifiersUpdated();
}
}
@@ -132,14 +144,6 @@ namespace Artemis.Core
///
public object GetValue(object baseValue)
{
- // Validating this is kinda expensive, it'll fail on ChangeType later anyway ^^
- // var targetType = TargetProperty.PropertyType;
- // if (!targetType.IsCastableFrom(baseValue.GetType()))
- // {
- // throw new ArtemisCoreException($"The provided current value type ({baseValue.GetType().Name}) not match the " +
- // $"target property type ({targetType.Name})");
- // }
-
if (CompiledTargetAccessor == null)
return baseValue;
@@ -147,11 +151,54 @@ namespace Artemis.Core
foreach (var dataBindingModifier in Modifiers)
dataBindingValue = dataBindingModifier.Apply(dataBindingValue);
- return Convert.ChangeType(dataBindingValue, TargetProperty.PropertyType);
+ 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)
+ 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;
+ }
+
+ // Apply interpolation between the previous and current value
+ return GetInterpolatedValue();
}
- internal void Update(double deltaTime)
+ ///
+ /// Returns the type of the source property of this data binding
+ ///
+ public Type GetSourceType()
{
+ return SourceDataModel?.GetTypeAtPath(SourcePropertyPath);
+ }
+
+ ///
+ /// Updates the smoothing progress of the data binding
+ ///
+ ///
+ public void Update(double deltaTime)
+ {
+ }
+
+ ///
+ /// Applies the data binding to the
+ ///
+ public void ApplyToProperty()
+ {
+
+ }
+
+ private object GetInterpolatedValue()
+ {
+ if (_easingProgress >= 1.0f)
+ return _currentValue;
+
+ return Registration.Converter.Interpolate(_previousValue, _currentValue, _easingProgress);
}
internal void ApplyToEntity()
@@ -227,6 +274,20 @@ namespace Artemis.Core
var lambda = Expression.Lambda>(returnValue, parameter);
CompiledTargetAccessor = lambda.Compile();
}
+
+ #region Events
+
+ ///
+ /// Occurs when a modifier is added or removed
+ ///
+ public event EventHandler ModifiersUpdated;
+
+ protected virtual void OnModifiersUpdated()
+ {
+ ModifiersUpdated?.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
}
///
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs
index 24ee17a39..cff4ea1c7 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs
@@ -4,6 +4,7 @@ using System.Linq.Expressions;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Services;
using Artemis.Storage.Entities.Profile.DataBindings;
+using LiteDB.Engine;
using Microsoft.VisualBasic;
using Newtonsoft.Json;
@@ -82,14 +83,9 @@ namespace Artemis.Core
public object ParameterStaticValue { get; private set; }
///
- /// Gets the compiled function that evaluates this predicate if it of a dynamic
+ /// A compiled expression tree that when given a matching data model returns the value of the modifiers parameter
///
- public Func
public bool DataBindingsSupported { get; protected internal set; } = true;
- ///
- /// Gets a read-only collection of the currently applied data bindings
- ///
- public IReadOnlyCollection DataBindings => _dataBindings.AsReadOnly();
-
///
/// Gets or sets whether keyframes are enabled on this property, has no effect if is
/// False
@@ -104,18 +106,6 @@ namespace Artemis.Core
///
public abstract Type GetPropertyType();
- ///
- /// Returns a list of properties to which data bindings can be applied
- ///
- ///
- public abstract List GetDataBindingProperties();
-
- ///
- /// Called when the provided data binding must be applied to a property
- ///
- ///
- protected abstract void ApplyDataBinding(DataBinding dataBinding);
-
///
/// Applies the provided property entity to the layer property by deserializing the JSON base value and keyframe values
///
@@ -132,23 +122,26 @@ namespace Artemis.Core
#region Data bindings
- ///
- /// Applies the current to the layer property
- ///
- public void ApplyDataBindings()
+ internal DataBindingRegistration RegisterDataBindingProperty(PropertyInfo property, IDataBindingConverter converter)
+ {
+ var registration = new DataBindingRegistration(this, property, converter);
+ _dataBindingRegistrations.Add(registration);
+ return registration;
+ }
+
+ internal void InitializeDataBindings(IDataModelService dataModelService, IDataBindingService dataBindingService)
{
foreach (var dataBinding in DataBindings)
- ApplyDataBinding(dataBinding);
+ dataBinding.Initialize(dataModelService, dataBindingService);
}
///
/// Adds a new data binding targeting the given property to the collection
///
- /// The property the new data binding should target
/// The newly created data binding
- public DataBinding AddDataBinding(PropertyInfo targetProperty)
+ public DataBinding EnableDataBinding(DataBindingRegistration dataBindingRegistration)
{
- var dataBinding = new DataBinding(this, targetProperty);
+ var dataBinding = new DataBinding(this, dataBindingProperty);
_dataBindings.Add(dataBinding);
return dataBinding;
@@ -158,13 +151,11 @@ namespace Artemis.Core
/// Removes the provided data binding from the collection
///
/// The data binding to remove
- public void RemoveDataBinding(DataBinding dataBinding)
+ public void DisableDataBinding(DataBinding dataBinding)
{
_dataBindings.Remove(dataBinding);
}
-
-
#endregion
#region Events
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
index 59a2af329..3edb15b0f 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
@@ -2,7 +2,9 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Linq.Expressions;
using System.Reflection;
+using Artemis.Core.DataModelExpansions;
using Artemis.Storage.Entities.Profile;
using Newtonsoft.Json;
@@ -16,7 +18,7 @@ namespace Artemis.Core
///
///
/// The type of property encapsulated in this layer property
- public class LayerProperty : BaseLayerProperty
+ public abstract class LayerProperty : BaseLayerProperty
{
private T _baseValue;
private bool _isInitialized;
@@ -198,41 +200,6 @@ namespace Artemis.Core
OnUpdated();
}
- private void UpdateKeyframes()
- {
- if (!KeyframesSupported || !KeyframesEnabled)
- return;
-
- // The current keyframe is the last keyframe before the current time
- CurrentKeyframe = _keyframes.LastOrDefault(k => k.Position <= ProfileElement.TimelinePosition);
- // Keyframes are sorted by position so we can safely assume the next keyframe's position is after the current
- var nextIndex = _keyframes.IndexOf(CurrentKeyframe) + 1;
- NextKeyframe = _keyframes.Count > nextIndex ? _keyframes[nextIndex] : null;
-
- // No need to update the current value if either of the keyframes are null
- if (CurrentKeyframe == null)
- CurrentValue = _keyframes.Any() ? _keyframes[0].Value : BaseValue;
- else if (NextKeyframe == null)
- CurrentValue = CurrentKeyframe.Value;
- // Only determine progress and current value if both keyframes are present
- else
- {
- var timeDiff = NextKeyframe.Position - CurrentKeyframe.Position;
- var keyframeProgress = (float) ((ProfileElement.TimelinePosition - CurrentKeyframe.Position).TotalMilliseconds / timeDiff.TotalMilliseconds);
- var keyframeProgressEased = (float) Easings.Interpolate(keyframeProgress, CurrentKeyframe.EasingFunction);
- UpdateCurrentValue(keyframeProgress, keyframeProgressEased);
- }
- }
-
- private void UpdateDataBindings(double deltaTime)
- {
- foreach (var dataBinding in DataBindings)
- {
- dataBinding.Update(deltaTime);
- ApplyDataBinding(dataBinding);
- }
- }
-
///
/// Sorts the keyframes in ascending order by position
///
@@ -303,20 +270,88 @@ namespace Artemis.Core
Position = k.Position,
EasingFunction = (int) k.EasingFunction
}));
+
+ PropertyEntity.DataBindingEntities.Clear();
+ foreach (var dataBinding in DataBindings)
+ {
+ dataBinding.ApplyToEntity();
+ PropertyEntity.DataBindingEntities.Add(dataBinding.Entity);
+ }
+ }
+
+ private void UpdateKeyframes()
+ {
+ if (!KeyframesSupported || !KeyframesEnabled)
+ return;
+
+ // The current keyframe is the last keyframe before the current time
+ CurrentKeyframe = _keyframes.LastOrDefault(k => k.Position <= ProfileElement.TimelinePosition);
+ // Keyframes are sorted by position so we can safely assume the next keyframe's position is after the current
+ var nextIndex = _keyframes.IndexOf(CurrentKeyframe) + 1;
+ NextKeyframe = _keyframes.Count > nextIndex ? _keyframes[nextIndex] : null;
+
+ // No need to update the current value if either of the keyframes are null
+ if (CurrentKeyframe == null)
+ CurrentValue = _keyframes.Any() ? _keyframes[0].Value : BaseValue;
+ else if (NextKeyframe == null)
+ CurrentValue = CurrentKeyframe.Value;
+ // Only determine progress and current value if both keyframes are present
+ else
+ {
+ var timeDiff = NextKeyframe.Position - CurrentKeyframe.Position;
+ var keyframeProgress = (float) ((ProfileElement.TimelinePosition - CurrentKeyframe.Position).TotalMilliseconds / timeDiff.TotalMilliseconds);
+ var keyframeProgressEased = (float) Easings.Interpolate(keyframeProgress, CurrentKeyframe.EasingFunction);
+ UpdateCurrentValue(keyframeProgress, keyframeProgressEased);
+ }
}
#region Data bindings
- ///
- public override List GetDataBindingProperties()
+ public void RegisterDataBindingProperty(Expression> propertyLambda, IDataBindingConverter converter)
{
- return new List {GetType().GetProperty(nameof(CurrentValue))};
+
+ var propertyInfo = ReflectionUtilities.GetPropertyInfo(CurrentValue, propertyLambda);
+
}
- ///
- protected override void ApplyDataBinding(DataBinding dataBinding)
+ ///
+ /// Registers the provided property to be available for data binding using a data binding property of type
+ ///
+ ///
+ /// The type of data binding property to use
+ /// The name of the property
+ ///
+ public TD RegisterDataBindingProperty
(string propertyName, IDataBindingConverter converter) where TD : BaseDataBindingProperty
{
- CurrentValue = (T) dataBinding.GetValue(CurrentValue);
+ var property = typeof(T).GetProperty(propertyName);
+ if (property == null)
+ {
+ throw new ArtemisCoreException($"Cannot register data binding property for property {propertyName} " +
+ $"because it does not exist on type {typeof(T).Name}");
+ }
+
+ // Create an instance of the converter
+ var dataBindingOperator = (TD) Activator.CreateInstance(typeof(TD), property);
+ if (dataBindingOperator == null)
+ throw new ArtemisCoreException($"Cannot register data binding, failed to create an instance of {typeof(TD).Name}");
+ if (dataBindingOperator.PropertyType != property.PropertyType)
+ {
+ throw new ArtemisCoreException($"Cannot register data binding property for property {propertyName} using a {typeof(TD).Name} " +
+ $"because it does not support type {typeof(T).Name}");
+ }
+
+ AddDataBindingConverter(dataBindingOperator);
+
+ return dataBindingOperator;
+ }
+
+ private void UpdateDataBindings(double deltaTime)
+ {
+ foreach (var dataBinding in DataBindings)
+ {
+ dataBinding.Update(deltaTime);
+ dataBinding.ApplyToProperty();
+ }
}
#endregion
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs
index fbe8968ac..e9c289e75 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs
@@ -1,7 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
using SkiaSharp;
namespace Artemis.Core
@@ -11,10 +8,15 @@ namespace Artemis.Core
{
internal SKColorLayerProperty()
{
+ RegisterDataBindingProperty(color => color.Alpha, new SKColorDataBindingConverter(SKColorDataBindingConverter.Channel.Alpha));
+ RegisterDataBindingProperty(color => color.Red, new SKColorDataBindingConverter(SKColorDataBindingConverter.Channel.Red));
+ RegisterDataBindingProperty(color => color.Green, new SKColorDataBindingConverter(SKColorDataBindingConverter.Channel.Green));
+ RegisterDataBindingProperty(color => color.Blue, new SKColorDataBindingConverter(SKColorDataBindingConverter.Channel.Blue));
+ RegisterDataBindingProperty(color => color.Hue, new SKColorDataBindingConverter(SKColorDataBindingConverter.Channel.Hue));
}
///
- /// Implicitly converts an to an
+ /// Implicitly converts an to an ¶
///
///
///
@@ -28,29 +30,84 @@ namespace Artemis.Core
{
CurrentValue = CurrentKeyframe.Value.Interpolate(NextKeyframe.Value, keyframeProgressEased);
}
+ }
- ///
- public override List GetDataBindingProperties()
+ internal class SKColorDataBindingConverter : IDataBindingConverter
+ {
+ private readonly Channel _channel;
+
+ public SKColorDataBindingConverter(Channel channel)
{
- return typeof(SKColor).GetProperties().ToList();
+ _channel = channel;
}
- ///
- protected override void ApplyDataBinding(DataBinding dataBinding)
+ public BaseLayerProperty BaseLayerProperty { get; set; }
+
+ public object Sum(object a, object b)
{
- if (dataBinding.TargetProperty.Name == nameof(CurrentValue.Alpha))
- CurrentValue = CurrentValue.WithAlpha((byte) dataBinding.GetValue(BaseValue.Alpha));
- else if (dataBinding.TargetProperty.Name == nameof(CurrentValue.Red))
- CurrentValue = CurrentValue.WithRed((byte) dataBinding.GetValue(BaseValue.Red));
- else if (dataBinding.TargetProperty.Name == nameof(CurrentValue.Green))
- CurrentValue = CurrentValue.WithGreen((byte) dataBinding.GetValue(BaseValue.Green));
- else if (dataBinding.TargetProperty.Name == nameof(CurrentValue.Blue))
- CurrentValue = CurrentValue.WithBlue((byte) dataBinding.GetValue(BaseValue.Blue));
- else if (dataBinding.TargetProperty.Name == nameof(CurrentValue.Hue))
+ return (float) a + (float) b;
+ }
+
+ public object Interpolate(object a, object b, float progress)
+ {
+ var diff = (float) b - (float) a;
+ return diff * progress;
+ }
+
+ public void ApplyValue(object value)
+ {
+ var property = (SKColorLayerProperty) BaseLayerProperty;
+ switch (_channel)
{
- CurrentValue.ToHsv(out var h, out var s, out var v);
- CurrentValue = SKColor.FromHsv((float) dataBinding.GetValue(h), s, v);
+ case Channel.Alpha:
+ property.CurrentValue = property.CurrentValue.WithAlpha((byte) value);
+ break;
+ case Channel.Red:
+ property.CurrentValue = property.CurrentValue.WithRed((byte) value);
+ break;
+ case Channel.Green:
+ property.CurrentValue = property.CurrentValue.WithGreen((byte) value);
+ break;
+ case Channel.Blue:
+ property.CurrentValue = property.CurrentValue.WithBlue((byte) value);
+ break;
+ case Channel.Hue:
+ property.CurrentValue.ToHsv(out var h, out var s, out var v);
+ property.CurrentValue = SKColor.FromHsv((float) value, s, v);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
}
}
+
+ public object GetValue()
+ {
+ var property = (SKColorLayerProperty) BaseLayerProperty;
+ switch (_channel)
+ {
+ case Channel.Alpha:
+ return property.CurrentValue.Alpha;
+ case Channel.Red:
+ return property.CurrentValue.Red;
+ case Channel.Green:
+ return property.CurrentValue.Green;
+ case Channel.Blue:
+ return property.CurrentValue.Blue;
+ case Channel.Hue:
+ property.CurrentValue.ToHsv(out var h, out _, out _);
+ return h;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public enum Channel
+ {
+ Alpha,
+ Red,
+ Green,
+ Blue,
+ Hue
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKPointLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKPointLayerProperty.cs
index e69eac535..75c0a934c 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKPointLayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKPointLayerProperty.cs
@@ -27,20 +27,5 @@ namespace Artemis.Core
var yDiff = NextKeyframe.Value.Y - CurrentKeyframe.Value.Y;
CurrentValue = new SKPoint(CurrentKeyframe.Value.X + xDiff * keyframeProgressEased, CurrentKeyframe.Value.Y + yDiff * keyframeProgressEased);
}
-
- ///
- public override List GetDataBindingProperties()
- {
- return typeof(SKPoint).GetProperties().Where(p => p.CanWrite).ToList();
- }
-
- ///
- protected override void ApplyDataBinding(DataBinding dataBinding)
- {
- if (dataBinding.TargetProperty.Name == nameof(CurrentValue.X))
- CurrentValue = new SKPoint((float) dataBinding.GetValue(BaseValue), CurrentValue.Y);
- else if (dataBinding.TargetProperty.Name == nameof(CurrentValue.Y))
- CurrentValue = new SKPoint(CurrentValue.X, (float) dataBinding.GetValue(BaseValue));
- }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKSizeLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKSizeLayerProperty.cs
index 326f74527..5db8b2a35 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKSizeLayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKSizeLayerProperty.cs
@@ -27,20 +27,5 @@ namespace Artemis.Core
var heightDiff = NextKeyframe.Value.Height - CurrentKeyframe.Value.Height;
CurrentValue = new SKSize(CurrentKeyframe.Value.Width + widthDiff * keyframeProgressEased, CurrentKeyframe.Value.Height + heightDiff * keyframeProgressEased);
}
-
- ///
- public override List GetDataBindingProperties()
- {
- return typeof(SKSize).GetProperties().Where(p => p.CanWrite).ToList();
- }
-
- ///
- protected override void ApplyDataBinding(DataBinding dataBinding)
- {
- if (dataBinding.TargetProperty.Name == nameof(CurrentValue.Height))
- CurrentValue = new SKSize(CurrentValue.Width, (float) dataBinding.GetValue(BaseValue));
- else if (dataBinding.TargetProperty.Name == nameof(CurrentValue.Width))
- CurrentValue = new SKSize((float) dataBinding.GetValue(BaseValue), CurrentValue.Width);
- }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
index c3d5b01f3..34aac49d9 100644
--- a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
@@ -311,5 +311,17 @@ namespace Artemis.Core
}
#endregion
+
+ ///
+ /// Returns all the layer properties of this profile element
+ ///
+ public virtual List GetAllLayerProperties()
+ {
+ var result = new List();
+ foreach (var baseLayerEffect in LayerEffects)
+ result.AddRange(baseLayerEffect.BaseProperties.GetAllLayerProperties());
+
+ return result;
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/DataBindingService.cs b/src/Artemis.Core/Services/DataBindingService.cs
index 8a82ae864..4a215c211 100644
--- a/src/Artemis.Core/Services/DataBindingService.cs
+++ b/src/Artemis.Core/Services/DataBindingService.cs
@@ -15,6 +15,8 @@ namespace Artemis.Core.Services
{
_logger = logger;
_registeredDataBindingModifierTypes = new List();
+
+ RegisterBuiltInModifiers();
}
public IReadOnlyCollection RegisteredDataBindingModifierTypes
@@ -98,5 +100,10 @@ namespace Artemis.Core.Services
dataBindingModifier.Entity.ModifierType
);
}
+
+ private void RegisterBuiltInModifiers()
+ {
+ RegisterModifierType(Constants.CorePluginInfo, new MultiplicationModifierType());
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/Interfaces/IRenderElementService.cs b/src/Artemis.Core/Services/Interfaces/IRenderElementService.cs
index bbb760dcf..79319f578 100644
--- a/src/Artemis.Core/Services/Interfaces/IRenderElementService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IRenderElementService.cs
@@ -54,5 +54,6 @@ namespace Artemis.Core.Services
void RemoveLayerEffect(BaseLayerEffect layerEffect);
void InstantiateDisplayConditions(RenderProfileElement renderElement);
+ void InstantiateDataBindings(RenderProfileElement renderElement);
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/RenderElementService.cs b/src/Artemis.Core/Services/RenderElementService.cs
index ec6901764..6b26c94de 100644
--- a/src/Artemis.Core/Services/RenderElementService.cs
+++ b/src/Artemis.Core/Services/RenderElementService.cs
@@ -10,16 +10,18 @@ namespace Artemis.Core.Services
internal class RenderElementService : IRenderElementService
{
private readonly IDataModelService _dataModelService;
+ private readonly IDataBindingService _dataBindingService;
private readonly IKernel _kernel;
private readonly ILogger _logger;
private readonly IPluginService _pluginService;
- public RenderElementService(IKernel kernel, ILogger logger, IPluginService pluginService, IDataModelService dataModelService)
+ public RenderElementService(IKernel kernel, ILogger logger, IPluginService pluginService, IDataModelService dataModelService, IDataBindingService dataBindingService)
{
_kernel = kernel;
_logger = logger;
_pluginService = pluginService;
_dataModelService = dataModelService;
+ _dataBindingService = dataBindingService;
}
public Layer CreateLayer(Profile profile, ProfileElement parent, string name)
@@ -35,6 +37,7 @@ namespace Artemis.Core.Services
InstantiateLayerBrush(layer);
InstantiateLayerEffects(layer);
InstantiateDisplayConditions(layer);
+ InstantiateDataBindings(layer);
return layer;
}
@@ -156,5 +159,11 @@ namespace Artemis.Core.Services
_logger.Warning(e, $"Failed to init display conditions for {renderElement}");
}
}
+
+ public void InstantiateDataBindings(RenderProfileElement renderElement)
+ {
+ foreach (var baseLayerProperty in renderElement.GetAllLayerProperties())
+ baseLayerProperty.InitializeDataBindings(_dataModelService, _dataBindingService);
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs
index 78a9e7155..f66031fca 100644
--- a/src/Artemis.Core/Services/Storage/ProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/ProfileService.cs
@@ -299,6 +299,7 @@ namespace Artemis.Core.Services
_renderElementService.RemoveLayerEffect(layerLayerEffect);
_renderElementService.InstantiateDisplayConditions(folder);
+ _renderElementService.InstantiateDataBindings(folder);
}
}
@@ -324,6 +325,7 @@ namespace Artemis.Core.Services
_renderElementService.RemoveLayerEffect(layerLayerEffect);
_renderElementService.InstantiateDisplayConditions(layer);
+ _renderElementService.InstantiateDataBindings(layer);
}
}
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
index b25dd3614..f0b2b2a02 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
@@ -14,9 +14,9 @@ namespace Artemis.UI.Shared
private bool _closed;
private T _inputValue;
- protected DataModelInputViewModel(DataModelPropertyAttribute description, T initialValue)
+ protected DataModelInputViewModel(DataModelPropertyAttribute targetDescription, T initialValue)
{
- Description = description;
+ TargetDescription = targetDescription;
InputValue = initialValue;
}
@@ -26,7 +26,7 @@ namespace Artemis.UI.Shared
set => SetAndNotify(ref _inputValue, value);
}
- public DataModelPropertyAttribute Description { get; }
+ public DataModelPropertyAttribute TargetDescription { get; }
internal override object InternalGuard { get; } = null;
///
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionView.xaml b/src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionView.xaml
deleted file mode 100644
index f74af0f0b..000000000
--- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionView.xaml
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml
new file mode 100644
index 000000000..ca1dbb905
--- /dev/null
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionView.xaml.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml.cs
similarity index 75%
rename from src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionView.xaml.cs
rename to src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml.cs
index fc0034294..8a45bde5d 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionView.xaml.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml.cs
@@ -1,14 +1,14 @@
using System.Windows;
using System.Windows.Controls;
-namespace Artemis.UI.Shared
+namespace Artemis.UI.Shared.Input
{
///
- /// Interaction logic for DataModelSelectionView.xaml
+ /// Interaction logic for DataModelDynamicView.xaml
///
- public partial class DataModelSelectionView : UserControl
+ public partial class DataModelDynamicView : UserControl
{
- public DataModelSelectionView()
+ public DataModelDynamicView()
{
InitializeComponent();
}
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs
similarity index 89%
rename from src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionViewModel.cs
rename to src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs
index 029290827..bc718153d 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelSelectionViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs
@@ -11,22 +11,21 @@ using Stylet;
// Remove, annoying while working on it
#pragma warning disable 1591
-namespace Artemis.UI.Shared
+namespace Artemis.UI.Shared.Input
{
- public class DataModelSelectionViewModel : PropertyChangedBase
+ public class DataModelDynamicViewModel : PropertyChangedBase
{
private readonly IDataModelUIService _dataModelUIService;
private readonly Module _module;
private readonly Timer _updateTimer;
private Brush _buttonBrush = new SolidColorBrush(Color.FromRgb(171, 71, 188));
-
private DataModelPropertiesViewModel _dataModelViewModel;
private bool _isDataModelViewModelOpen;
- private bool _isEnabled;
+ private bool _isEnabled = true;
private string _placeholder = "Select a property";
private DataModelVisualizationViewModel _selectedPropertyViewModel;
- public DataModelSelectionViewModel(Module module, ISettingsService settingsService, IDataModelUIService dataModelUIService)
+ internal DataModelDynamicViewModel(Module module, ISettingsService settingsService, IDataModelUIService dataModelUIService)
{
_module = module;
_dataModelUIService = dataModelUIService;
@@ -38,22 +37,18 @@ namespace Artemis.UI.Shared
Initialize();
}
- public string Placeholder
- {
- get => _placeholder;
- set => SetAndNotify(ref _placeholder, value);
- }
-
public Brush ButtonBrush
{
get => _buttonBrush;
set => SetAndNotify(ref _buttonBrush, value);
}
- public DelegateCommand SelectPropertyCommand { get; }
- public Type[] FilterTypes { get; set; }
- public PluginSetting ShowDataModelValues { get; }
+ public string Placeholder
+ {
+ get => _placeholder;
+ set => SetAndNotify(ref _placeholder, value);
+ }
public bool IsEnabled
{
@@ -61,6 +56,10 @@ namespace Artemis.UI.Shared
set => SetAndNotify(ref _isEnabled, value);
}
+ public Type[] FilterTypes { get; set; }
+ public DelegateCommand SelectPropertyCommand { get; }
+ public PluginSetting ShowDataModelValues { get; }
+
public DataModelPropertiesViewModel DataModelViewModel
{
get => _dataModelViewModel;
@@ -117,14 +116,15 @@ namespace Artemis.UI.Shared
return;
SelectedPropertyViewModel = selected;
- OnPropertySelected(new DataModelPropertySelectedEventArgs(selected));
+ OnPropertySelected(new DataModelInputDynamicEventArgs(selected));
}
+
#region Events
- public event EventHandler PropertySelected;
+ public event EventHandler PropertySelected;
- protected virtual void OnPropertySelected(DataModelPropertySelectedEventArgs e)
+ protected virtual void OnPropertySelected(DataModelInputDynamicEventArgs e)
{
PropertySelected?.Invoke(this, e);
}
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticView.xaml b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticView.xaml
new file mode 100644
index 000000000..6afe0edba
--- /dev/null
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticView.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticView.xaml.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticView.xaml.cs
new file mode 100644
index 000000000..5aacbb841
--- /dev/null
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticView.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace Artemis.UI.Shared.Input
+{
+ ///
+ /// Interaction logic for DataModelStaticView.xaml
+ ///
+ public partial class DataModelStaticView : UserControl
+ {
+ public DataModelStaticView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs
new file mode 100644
index 000000000..7d4e23214
--- /dev/null
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Windows.Media;
+using Artemis.Core;
+using Artemis.Core.DataModelExpansions;
+using Artemis.UI.Shared.Services;
+using Stylet;
+
+// Remove, annoying while working on it
+#pragma warning disable 1591
+
+namespace Artemis.UI.Shared.Input
+{
+ public class DataModelStaticViewModel : PropertyChangedBase
+ {
+ private readonly IDataModelUIService _dataModelUIService;
+ private Brush _buttonBrush = new SolidColorBrush(Color.FromRgb(171, 71, 188));
+ private DataModelInputViewModel _inputViewModel;
+ private string _placeholder = "Enter a value";
+ private DataModelPropertyAttribute _targetDescription;
+ private Type _targetType;
+ private int _transitionIndex;
+ private object _value;
+
+ internal DataModelStaticViewModel(Type targetType, IDataModelUIService dataModelUIService)
+ {
+ TargetType = targetType;
+ _dataModelUIService = dataModelUIService;
+ }
+
+ public Brush ButtonBrush
+ {
+ get => _buttonBrush;
+ set => SetAndNotify(ref _buttonBrush, value);
+ }
+
+ public int TransitionIndex
+ {
+ get => _transitionIndex;
+ set => SetAndNotify(ref _transitionIndex, value);
+ }
+
+ public DataModelInputViewModel InputViewModel
+ {
+ get => _inputViewModel;
+ private set => SetAndNotify(ref _inputViewModel, value);
+ }
+
+ public Type TargetType
+ {
+ get => _targetType;
+ set => SetAndNotify(ref _targetType, value);
+ }
+
+ public DataModelPropertyAttribute TargetDescription
+ {
+ get => _targetDescription;
+ set => SetAndNotify(ref _targetDescription, value);
+ }
+
+ public object Value
+ {
+ get => _value;
+ set => SetAndNotify(ref _value, value);
+ }
+
+ public string Placeholder
+ {
+ get => _placeholder;
+ set => SetAndNotify(ref _placeholder, value);
+ }
+
+ public void ActivateInputViewModel()
+ {
+ TransitionIndex = 1;
+ InputViewModel = _dataModelUIService.GetDataModelInputViewModel(
+ TargetType,
+ TargetDescription,
+ Value,
+ ApplyFreeInput
+ );
+ }
+
+ public void UpdateTargetType(Type target)
+ {
+ TargetType = target ?? throw new ArgumentNullException(nameof(target));
+
+ // If the type changed, reset to the default type
+ if (!target.IsCastableFrom(Value.GetType()))
+ {
+ // Force the VM to close if it was open and apply the new value
+ ApplyFreeInput(target.GetDefault(), true);
+ }
+ }
+
+ private void ApplyFreeInput(object value, bool submitted)
+ {
+ if (submitted)
+ OnValueUpdated(new DataModelInputStaticEventArgs(value));
+
+ TransitionIndex = 0;
+ InputViewModel = null;
+ Value = value;
+ }
+
+ #region Events
+
+ public event EventHandler ValueUpdated;
+
+ protected virtual void OnValueUpdated(DataModelInputStaticEventArgs e)
+ {
+ ValueUpdated?.Invoke(this, e);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Events/DataModelPropertySelectedEventArgs.cs b/src/Artemis.UI.Shared/Events/DataModelInputDynamicEventArgs.cs
similarity index 58%
rename from src/Artemis.UI.Shared/Events/DataModelPropertySelectedEventArgs.cs
rename to src/Artemis.UI.Shared/Events/DataModelInputDynamicEventArgs.cs
index 81bb38629..9f7649dbb 100644
--- a/src/Artemis.UI.Shared/Events/DataModelPropertySelectedEventArgs.cs
+++ b/src/Artemis.UI.Shared/Events/DataModelInputDynamicEventArgs.cs
@@ -2,11 +2,11 @@
namespace Artemis.UI.Shared
{
- public class DataModelPropertySelectedEventArgs : EventArgs
+ public class DataModelInputDynamicEventArgs : EventArgs
{
public DataModelVisualizationViewModel DataModelVisualizationViewModel { get; }
- public DataModelPropertySelectedEventArgs(DataModelVisualizationViewModel dataModelVisualizationViewModel)
+ public DataModelInputDynamicEventArgs(DataModelVisualizationViewModel dataModelVisualizationViewModel)
{
DataModelVisualizationViewModel = dataModelVisualizationViewModel;
}
diff --git a/src/Artemis.UI.Shared/Events/DataModelInputStaticEventArgs.cs b/src/Artemis.UI.Shared/Events/DataModelInputStaticEventArgs.cs
new file mode 100644
index 000000000..278681dd6
--- /dev/null
+++ b/src/Artemis.UI.Shared/Events/DataModelInputStaticEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Artemis.UI.Shared
+{
+ public class DataModelInputStaticEventArgs : EventArgs
+ {
+ public object Value { get; }
+
+ public DataModelInputStaticEventArgs(object value)
+ {
+ Value = value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Services/DataModelUIService.cs b/src/Artemis.UI.Shared/Services/DataModelUIService.cs
index b8ead4820..73e34e9e6 100644
--- a/src/Artemis.UI.Shared/Services/DataModelUIService.cs
+++ b/src/Artemis.UI.Shared/Services/DataModelUIService.cs
@@ -5,6 +5,7 @@ using Artemis.Core;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using Artemis.Core.Services;
+using Artemis.UI.Shared.Input;
using Ninject;
using Ninject.Parameters;
@@ -179,9 +180,15 @@ namespace Artemis.UI.Shared.Services
}
}
- public DataModelSelectionViewModel GetDataModelSelectionViewModel(Module module)
+ public DataModelDynamicViewModel GetDynamicSelectionViewModel(Module module)
{
- return _kernel.Get(new ConstructorArgument("module", module));
+ return _kernel.Get(new ConstructorArgument("module", module));
+ }
+
+ public DataModelStaticViewModel GetStaticInputViewModel(Type targetType)
+ {
+ if (targetType == null) throw new ArgumentNullException(nameof(targetType));
+ return _kernel.Get(new ConstructorArgument("targetType", targetType));
}
private DataModelInputViewModel InstantiateDataModelInputViewModel(DataModelVisualizationRegistration registration, DataModelPropertyAttribute description, object initialValue)
diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs
index f4ee8cc13..049a1bf11 100644
--- a/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs
+++ b/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using Artemis.Core;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
+using Artemis.UI.Shared.Input;
namespace Artemis.UI.Shared.Services
{
@@ -28,6 +29,7 @@ namespace Artemis.UI.Shared.Services
DataModelDisplayViewModel GetDataModelDisplayViewModel(Type propertyType);
DataModelInputViewModel GetDataModelInputViewModel(Type propertyType, DataModelPropertyAttribute description, object initialValue, Action updateCallback);
- DataModelSelectionViewModel GetDataModelSelectionViewModel(Module module);
+ DataModelDynamicViewModel GetDynamicSelectionViewModel(Module module);
+ DataModelStaticViewModel GetStaticInputViewModel(Type targetType);
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputViewModel.cs b/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputViewModel.cs
index f4953e318..9099ea2c6 100644
--- a/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputViewModel.cs
@@ -8,7 +8,7 @@ namespace Artemis.UI.DataModelVisualization.Input
{
public class DoubleDataModelInputViewModel : DataModelInputViewModel
{
- public DoubleDataModelInputViewModel(DataModelPropertyAttribute description, double initialValue) : base(description, initialValue)
+ public DoubleDataModelInputViewModel(DataModelPropertyAttribute targetDescription, double initialValue) : base(targetDescription, initialValue)
{
}
diff --git a/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputViewModel.cs b/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputViewModel.cs
index 9317f38e3..f4fce549f 100644
--- a/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputViewModel.cs
@@ -7,7 +7,7 @@ namespace Artemis.UI.DataModelVisualization.Input
{
public class IntDataModelInputViewModel : DataModelInputViewModel
{
- public IntDataModelInputViewModel(DataModelPropertyAttribute description, int initialValue) : base(description, initialValue)
+ public IntDataModelInputViewModel(DataModelPropertyAttribute targetDescription, int initialValue) : base(targetDescription, initialValue)
{
}
diff --git a/src/Artemis.UI/DataModelVisualization/Input/StringDataModelInputViewModel.cs b/src/Artemis.UI/DataModelVisualization/Input/StringDataModelInputViewModel.cs
index f7a42f01a..4f8818eca 100644
--- a/src/Artemis.UI/DataModelVisualization/Input/StringDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DataModelVisualization/Input/StringDataModelInputViewModel.cs
@@ -5,7 +5,7 @@ namespace Artemis.UI.DataModelVisualization.Input
{
public class StringDataModelInputViewModel : DataModelInputViewModel
{
- public StringDataModelInputViewModel(DataModelPropertyAttribute description, string initialValue) : base(description, initialValue)
+ public StringDataModelInputViewModel(DataModelPropertyAttribute targetDescription, string initialValue) : base(targetDescription, initialValue)
{
}
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml
index f8edd20cf..a3aaf5c56 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml
@@ -62,8 +62,8 @@
Style="{StaticResource DisplayConditionButtonLeftClickMenu}"
Background="#7B7B7B"
BorderBrush="#7B7B7B"
- Content="{Binding SelectedModifierType.Description}">
-
+ Content="{Binding SelectedModifierType.Description}"
+ Click="PropertyButton_OnClick">
@@ -85,34 +85,7 @@
-
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml.cs
index ab48662ff..53ba23175 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml.cs
@@ -22,5 +22,15 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
{
InitializeComponent();
}
+
+ private void PropertyButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ // DataContext is not set when using left button, I don't know why but there it is
+ if (sender is Button button && button.ContextMenu != null)
+ {
+ button.ContextMenu.DataContext = button.DataContext;
+ button.ContextMenu.IsOpen = true;
+ }
+ }
}
}
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierViewModel.cs
index 3b76ea7e4..af6bf2689 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierViewModel.cs
@@ -1,7 +1,10 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
+using Artemis.UI.Exceptions;
using Artemis.UI.Shared;
+using Artemis.UI.Shared.Input;
using Artemis.UI.Shared.Services;
using Stylet;
@@ -13,6 +16,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private readonly IDataModelUIService _dataModelUIService;
private readonly IProfileEditorService _profileEditorService;
private DataBindingModifierType _selectedModifierType;
+ private DataModelDynamicViewModel _dynamicSelectionViewModel;
+ private DataModelStaticViewModel _staticInputViewModel;
public DataBindingModifierViewModel(DataBindingModifier modifier,
IDataBindingService dataBindingService,
@@ -32,11 +37,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
SelectModifierTypeCommand = new DelegateCommand(ExecuteSelectModifierTypeCommand);
// Initialize async, no need to wait for it
- Task.Run(Initialize);
+ Execute.PostToUIThread(Initialize);
}
- public DelegateCommand SelectModifierTypeCommand { get; set; }
-
+ public DelegateCommand SelectModifierTypeCommand { get; }
public PluginSetting ShowDataModelValues { get; }
public DataBindingModifier Modifier { get; }
public BindableCollection ModifierTypes { get; }
@@ -47,30 +51,65 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
set => SetAndNotify(ref _selectedModifierType, value);
}
- public DataModelSelectionViewModel ParameterSelectionViewModel { get; private set; }
+ public DataModelDynamicViewModel DynamicSelectionViewModel
+ {
+ get => _dynamicSelectionViewModel;
+ private set => SetAndNotify(ref _dynamicSelectionViewModel, value);
+ }
+
+ public DataModelStaticViewModel StaticInputViewModel
+ {
+ get => _staticInputViewModel;
+ private set => SetAndNotify(ref _staticInputViewModel, value);
+ }
private void Initialize()
{
- ParameterSelectionViewModel = _dataModelUIService.GetDataModelSelectionViewModel(_profileEditorService.GetCurrentModule());
- ParameterSelectionViewModel.PropertySelected += ParameterSelectionViewModelOnPropertySelected;
- ParameterSelectionViewModel.FilterTypes = new[] {Modifier.DataBinding.TargetProperty.PropertyType};
+ var sourceType = Modifier.DataBinding.GetSourceType();
+ if (sourceType == null)
+ throw new ArtemisUIException("Cannot initialize a data binding modifier VM for a data binding without a source");
+
+ if (Modifier.ParameterType == ProfileRightSideType.Dynamic)
+ {
+ StaticInputViewModel = null;
+ DynamicSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
+ DynamicSelectionViewModel.PropertySelected += ParameterSelectionViewModelOnPropertySelected;
+ DynamicSelectionViewModel.FilterTypes = new[] {sourceType};
+ }
+ else
+ {
+ DynamicSelectionViewModel = null;
+ StaticInputViewModel = _dataModelUIService.GetStaticInputViewModel(sourceType);
+ StaticInputViewModel.ValueUpdated += StaticInputViewModelOnValueUpdated;
+ }
Update();
}
- private void ParameterSelectionViewModelOnPropertySelected(object sender, DataModelPropertySelectedEventArgs e)
+ private void ParameterSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
{
Modifier.UpdateParameter(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.PropertyPath);
}
+ private void StaticInputViewModelOnValueUpdated(object sender, DataModelInputStaticEventArgs e)
+ {
+ Modifier.UpdateParameter(e.Value);
+ }
+
private void Update()
{
+ var sourceType = Modifier.DataBinding.GetSourceType();
+
// Modifier type
ModifierTypes.Clear();
- ModifierTypes.AddRange(_dataBindingService.GetCompatibleModifierTypes(Modifier.DataBinding.TargetProperty.PropertyType));
+ ModifierTypes.AddRange(_dataBindingService.GetCompatibleModifierTypes(sourceType));
SelectedModifierType = Modifier.ModifierType;
- ParameterSelectionViewModel.PopulateSelectedPropertyViewModel(Modifier.ParameterDataModel, Modifier.ParameterPropertyPath);
+ // Parameter
+ if (DynamicSelectionViewModel != null)
+ DynamicSelectionViewModel?.PopulateSelectedPropertyViewModel(Modifier.ParameterDataModel, Modifier.ParameterPropertyPath);
+ else if (StaticInputViewModel != null)
+ StaticInputViewModel.Value = Modifier.ParameterStaticValue;
}
private void ExecuteSelectModifierTypeCommand(object context)
@@ -83,5 +122,20 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
Update();
}
+
+ public void Delete()
+ {
+ Modifier.DataBinding.RemoveModifier(Modifier);
+ }
+
+ public void SwapType()
+ {
+ if (Modifier.ParameterType == ProfileRightSideType.Dynamic)
+ Modifier.UpdateParameter(Modifier.DataBinding.GetSourceType().GetDefault());
+ else
+ Modifier.UpdateParameter(null, null);
+
+ Initialize();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml.cs
index 24e8655ff..61f02ab77 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml.cs
@@ -12,15 +12,5 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
{
InitializeComponent();
}
-
- private void PropertyButton_OnClick(object sender, RoutedEventArgs e)
- {
- // DataContext is not set when using left button, I don't know why but there it is
- if (sender is Button button && button.ContextMenu != null)
- {
- button.ContextMenu.DataContext = button.DataContext;
- button.ContextMenu.IsOpen = true;
- }
- }
}
}
\ 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 f3e99961d..6c65e55bf 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs
@@ -1,33 +1,27 @@
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Reflection;
-using System.Threading.Tasks;
using System.Timers;
using Artemis.Core;
-using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared;
+using Artemis.UI.Shared.Input;
using Artemis.UI.Shared.Services;
-using Artemis.UI.Utilities;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
{
public class DataBindingViewModel : PropertyChangedBase
{
- private readonly IDataModelUIService _dataModelUIService;
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
+ private readonly IDataModelUIService _dataModelUIService;
private readonly IProfileEditorService _profileEditorService;
private readonly Timer _updateTimer;
private DataBinding _dataBinding;
private bool _isDataBindingEnabled;
- private DataModelPropertiesViewModel _sourceDataModel;
- private DataModelVisualizationViewModel _selectedSourceProperty;
- private bool _sourceDataModelOpen;
+ private DataModelDynamicViewModel _targetSelectionViewModel;
private object _testInputValue;
private object _testResultValue;
- private DataModelSelectionViewModel _targetSelectionViewModel;
public DataBindingViewModel(BaseLayerProperty layerProperty,
PropertyInfo targetProperty,
@@ -41,12 +35,14 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
_updateTimer = new Timer(500);
DisplayName = targetProperty.Name.ToUpper();
+ ModifierViewModels = new BindableCollection();
LayerProperty = layerProperty;
TargetProperty = targetProperty;
DataBinding = layerProperty.DataBindings.FirstOrDefault(d => d.TargetProperty == targetProperty);
- ModifierViewModels = new BindableCollection();
+ if (DataBinding != null)
+ DataBinding.ModifiersUpdated += DataBindingOnModifiersUpdated;
_isDataBindingEnabled = DataBinding != null;
@@ -59,7 +55,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
public string DisplayName { get; }
public BindableCollection ModifierViewModels { get; }
- public DataModelSelectionViewModel TargetSelectionViewModel
+ public DataModelDynamicViewModel TargetSelectionViewModel
{
get => _targetSelectionViewModel;
private set => SetAndNotify(ref _targetSelectionViewModel, value);
@@ -106,9 +102,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
return;
DataBinding = LayerProperty.AddDataBinding(TargetProperty);
+ DataBinding.ModifiersUpdated += DataBindingOnModifiersUpdated;
Update();
+
+ _profileEditorService.UpdateSelectedProfileElement();
}
+
public void RemoveDataBinding()
{
if (DataBinding == null)
@@ -117,7 +117,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
var toRemove = DataBinding;
DataBinding = null;
LayerProperty.RemoveDataBinding(toRemove);
+ toRemove.ModifiersUpdated -= DataBindingOnModifiersUpdated;
Update();
+
+ _profileEditorService.UpdateSelectedProfileElement();
}
public void AddModifier()
@@ -128,12 +131,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
var modifier = new DataBindingModifier(ProfileRightSideType.Dynamic);
DataBinding.AddModifier(modifier);
- ModifierViewModels.Add(_dataBindingsVmFactory.DataBindingModifierViewModel(modifier));
+ _profileEditorService.UpdateSelectedProfileElement();
}
private void Initialize()
{
- TargetSelectionViewModel = _dataModelUIService.GetDataModelSelectionViewModel(_profileEditorService.GetCurrentModule());
+ TargetSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected;
Update();
@@ -153,11 +156,19 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
TargetSelectionViewModel.IsEnabled = true;
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataBinding.SourceDataModel, DataBinding.SourcePropertyPath);
TargetSelectionViewModel.FilterTypes = new[] {DataBinding.TargetProperty.PropertyType};
+
+ UpdateModifierViewModels();
}
- private void TargetSelectionViewModelOnPropertySelected(object sender, DataModelPropertySelectedEventArgs e)
+ private void DataBindingOnModifiersUpdated(object sender, EventArgs e)
+ {
+ UpdateModifierViewModels();
+ }
+
+ private void TargetSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
{
DataBinding.UpdateSource(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.PropertyPath);
+ _profileEditorService.UpdateSelectedProfileElement();
}
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
@@ -184,6 +195,5 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
foreach (var dataBindingModifier in DataBinding.Modifiers)
ModifierViewModels.Add(_dataBindingsVmFactory.DataBindingModifierViewModel(dataBindingModifier));
}
-
}
}
\ No newline at end of file