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

Profiles - Made data bindings compatible with timeline changes

This commit is contained in:
SpoinkyNL 2020-11-02 22:09:29 +01:00
parent 997ab005d8
commit 0f5c2b80c4
23 changed files with 175 additions and 163 deletions

View File

@ -293,6 +293,10 @@ namespace Artemis.Core
if (Operator == null || LeftPath == null || !LeftPath.IsValid) if (Operator == null || LeftPath == null || !LeftPath.IsValid)
return false; return false;
// If the operator does not support a right side, immediately evaluate with null
if (Operator.RightSideType == null)
return Operator.InternalEvaluate(LeftPath.GetValue(), null);
// Compare with a static value // Compare with a static value
if (PredicateType == ProfileRightSideType.Static) if (PredicateType == ProfileRightSideType.Static)
{ {

View File

@ -55,11 +55,14 @@ namespace Artemis.Core
private object? GetEventPathValue(DataModelPath path, object target) private object? GetEventPathValue(DataModelPath path, object target)
{ {
if (!(path.Target is EventPredicateWrapperDataModel wrapper)) lock (path)
throw new ArtemisCoreException("Data model condition event predicate has a path with an invalid target"); {
if (!(path.Target is EventPredicateWrapperDataModel wrapper))
throw new ArtemisCoreException("Data model condition event predicate has a path with an invalid target");
wrapper.UntypedArguments = target; wrapper.UntypedArguments = target;
return path.GetValue(); return path.GetValue();
}
} }
#region Initialization #region Initialization
@ -124,6 +127,10 @@ namespace Artemis.Core
if (Operator == null || LeftPath == null || !LeftPath.IsValid) if (Operator == null || LeftPath == null || !LeftPath.IsValid)
return false; return false;
// If the operator does not support a right side, immediately evaluate with null
if (Operator.RightSideType == null)
return Operator.InternalEvaluate(GetEventPathValue(LeftPath, target), null);
// Compare with a static value // Compare with a static value
if (PredicateType == ProfileRightSideType.Static) if (PredicateType == ProfileRightSideType.Static)
{ {

View File

@ -60,9 +60,9 @@ namespace Artemis.Core
/// Gets ors ets the easing function of the data binding /// Gets ors ets the easing function of the data binding
/// </summary> /// </summary>
public Easings.Functions EasingFunction { get; set; } public Easings.Functions EasingFunction { get; set; }
internal DataBindingEntity Entity { get; } internal DataBindingEntity Entity { get; }
/// <summary> /// <summary>
/// Gets the current value of the data binding /// Gets the current value of the data binding
/// </summary> /// </summary>
@ -139,16 +139,24 @@ namespace Artemis.Core
/// </summary> /// </summary>
/// <param name="timeline">The timeline to apply during update</param> /// <param name="timeline">The timeline to apply during update</param>
public void Update(Timeline timeline) public void Update(Timeline timeline)
{
UpdateWithDelta(timeline.Delta);
}
/// <summary>
/// Updates the smoothing progress of the data binding
/// </summary>
/// <param name="delta">The delta to apply during update</param>
public void UpdateWithDelta(TimeSpan delta)
{ {
if (_disposed) if (_disposed)
throw new ObjectDisposedException("DataBinding"); throw new ObjectDisposedException("DataBinding");
// Data bindings cannot go back in time like brushes // Data bindings cannot go back in time like brushes
TimeSpan deltaTime = timeline.Delta; if (delta < TimeSpan.Zero)
if (deltaTime < TimeSpan.Zero) delta = TimeSpan.Zero;
deltaTime = TimeSpan.Zero;
_easingProgress = _easingProgress.Add(deltaTime); _easingProgress = _easingProgress.Add(delta);
if (_easingProgress > EasingTime) if (_easingProgress > EasingTime)
_easingProgress = EasingTime; _easingProgress = EasingTime;
} }

View File

@ -42,10 +42,8 @@ namespace Artemis.Core
CurrentValue = BaseValue; CurrentValue = BaseValue;
if (ProfileElement.ApplyKeyframesEnabled) UpdateKeyframes(timeline);
UpdateKeyframes(timeline); UpdateDataBindings(timeline);
if (ProfileElement.ApplyDataBindingsEnabled)
UpdateDataBindings(timeline);
OnUpdated(); OnUpdated();
} }
@ -421,6 +419,10 @@ namespace Artemis.Core
private void UpdateDataBindings(Timeline timeline) private void UpdateDataBindings(Timeline timeline)
{ {
// To avoid data bindings applying at non-regular updating (during editing) only update when not overriden
if (timeline.IsOverridden)
return;
foreach (IDataBinding dataBinding in _dataBindings) foreach (IDataBinding dataBinding in _dataBindings)
{ {
dataBinding.Update(timeline); dataBinding.Update(timeline);

View File

@ -15,8 +15,6 @@ namespace Artemis.Core
{ {
protected RenderProfileElement() protected RenderProfileElement()
{ {
ApplyDataBindingsEnabled = true;
ApplyKeyframesEnabled = true;
Timeline = new Timeline(); Timeline = new Timeline();
LayerEffectStore.LayerEffectAdded += LayerEffectStoreOnLayerEffectAdded; LayerEffectStore.LayerEffectAdded += LayerEffectStoreOnLayerEffectAdded;
@ -300,16 +298,6 @@ namespace Artemis.Core
set => SetAndNotify(ref _displayCondition, value); set => SetAndNotify(ref _displayCondition, value);
} }
/// <summary>
/// Gets or sets whether keyframes should be applied when this profile element updates
/// </summary>
public bool ApplyKeyframesEnabled { get; set; }
/// <summary>
/// Gets or sets whether data bindings should be applied when this profile element updates
/// </summary>
public bool ApplyDataBindingsEnabled { get; set; }
/// <summary> /// <summary>
/// Evaluates the display conditions on this element and applies any required changes to the <see cref="Timeline"/> /// Evaluates the display conditions on this element and applies any required changes to the <see cref="Timeline"/>
/// </summary> /// </summary>

View File

@ -137,6 +137,11 @@ namespace Artemis.Core
/// </summary> /// </summary>
public bool IsFinished => Position > Length || Length == TimeSpan.Zero; public bool IsFinished => Position > Length || Length == TimeSpan.Zero;
/// <summary>
/// Gets a boolean indicating whether the timeline progress has been overridden
/// </summary>
public bool IsOverridden { get; private set; }
#region Segments #region Segments
/// <summary> /// <summary>
@ -293,6 +298,7 @@ namespace Artemis.Core
{ {
Delta += delta; Delta += delta;
Position += delta; Position += delta;
IsOverridden = false;
if (stickToMainSegment && Position >= MainSegmentStartPosition) if (stickToMainSegment && Position >= MainSegmentStartPosition)
{ {
@ -371,6 +377,8 @@ namespace Artemis.Core
{ {
Delta += position - Position; Delta += position - Position;
Position = position; Position = position;
IsOverridden = true;
if (stickToMainSegment && Position >= MainSegmentStartPosition) if (stickToMainSegment && Position >= MainSegmentStartPosition)
Position = MainSegmentStartPosition + TimeSpan.FromMilliseconds(Position.TotalMilliseconds % MainSegmentLength.TotalMilliseconds); Position = MainSegmentStartPosition + TimeSpan.FromMilliseconds(Position.TotalMilliseconds % MainSegmentLength.TotalMilliseconds);

View File

@ -43,7 +43,7 @@ namespace Artemis.Core
/// The action to call every time the interval has passed. The delta time parameter represents the /// The action to call every time the interval has passed. The delta time parameter represents the
/// time passed since the last update in seconds /// time passed since the last update in seconds
/// </param> /// </param>
/// <returns>The resulting plugin update registration</returns> /// <returns>The resulting plugin update registration which can be used to stop the update</returns>
public PluginUpdateRegistration AddTimedUpdate(TimeSpan interval, Action<double> action) public PluginUpdateRegistration AddTimedUpdate(TimeSpan interval, Action<double> action)
{ {
if (action == null) if (action == null)

View File

@ -16,12 +16,21 @@
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DataModelConditions.xaml" /> <ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DataModelConditions.xaml" />
<ResourceDictionary> <ResourceDictionary>
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" /> <shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<Style x:Key="DataModelConditionButtonCornerToggle" BasedOn="{StaticResource DataModelConditionButton}" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding DisplaySwitchButton}" Value="True">
<Setter Property="materialDesign:ButtonAssist.CornerRadius" Value="0 2 2 0" />
</DataTrigger>
<DataTrigger Binding="{Binding DisplaySwitchButton}" Value="False">
<Setter Property="materialDesign:ButtonAssist.CornerRadius" Value="2" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary> </ResourceDictionary>
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid>
<Grid Margin="3 -4">
<StackPanel Orientation="Horizontal" Visibility="{Binding InputViewModel, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}"> <StackPanel Orientation="Horizontal" Visibility="{Binding InputViewModel, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}">
<Button Style="{StaticResource MaterialDesignFlatDarkBgButton}" <Button Style="{StaticResource MaterialDesignFlatDarkBgButton}"
Background="{Binding SwitchButtonBrush}" Background="{Binding SwitchButtonBrush}"
@ -31,15 +40,14 @@
Width="22" Width="22"
FontSize="12" FontSize="12"
materialDesign:ButtonAssist.CornerRadius="2 0 0 2" materialDesign:ButtonAssist.CornerRadius="2 0 0 2"
Margin="0 0 -3 0" Margin="3 0 -3 0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
ToolTip="Switch to data model value" ToolTip="Switch to data model value"
Command="{s:Action SwitchToDynamic}" Command="{s:Action SwitchToDynamic}"
Visibility="{Binding DisplaySwitchButton, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"> Visibility="{Binding DisplaySwitchButton, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<materialDesign:PackIcon Kind="SwapHorizontal" /> <materialDesign:PackIcon Kind="SwapHorizontal" />
</Button> </Button>
<Button Style="{StaticResource DataModelConditionButton}" <Button Style="{StaticResource DataModelConditionButtonCornerToggle}"
materialDesign:ButtonAssist.CornerRadius="0 2 2 0"
Background="{Binding ButtonBrush}" Background="{Binding ButtonBrush}"
BorderBrush="{Binding ButtonBrush}" BorderBrush="{Binding ButtonBrush}"
Command="{s:Action ActivateInputViewModel}" Command="{s:Action ActivateInputViewModel}"

View File

@ -15,7 +15,7 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="0 3"> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
@ -52,7 +52,7 @@
triggered triggered
</TextBlock> </TextBlock>
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" Margin="0 4 0 0"> <ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" Margin="0 3 0 0">
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" /> <ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />

View File

@ -133,7 +133,7 @@
<materialDesign:PackIcon Kind="Add" Width="18" Height="18" /> <materialDesign:PackIcon Kind="Add" Width="18" Height="18" />
</Button> </Button>
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items, IsAsync=True}"> <ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items, IsAsync=True}" Margin="0 3 0 0">
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" /> <ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />

View File

@ -131,7 +131,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
// Remove VMs of effects no longer applied on the layer // Remove VMs of effects no longer applied on the layer
Items.RemoveRange(Items.Where(c => !DataModelConditionGroup.Children.Contains(c.Model)).ToList()); Items.RemoveRange(Items.Where(c => !DataModelConditionGroup.Children.Contains(c.Model)).ToList());
List<DataModelConditionViewModel> viewModels = new List<DataModelConditionViewModel>();
foreach (DataModelConditionPart childModel in Model.Children) foreach (DataModelConditionPart childModel in Model.Children)
{ {
if (Items.Any(c => c.Model == childModel)) if (Items.Any(c => c.Model == childModel))
@ -140,32 +139,28 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
switch (childModel) switch (childModel)
{ {
case DataModelConditionGroup dataModelConditionGroup: case DataModelConditionGroup dataModelConditionGroup:
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionGroupViewModel(dataModelConditionGroup, GroupType)); Items.Add(_dataModelConditionsVmFactory.DataModelConditionGroupViewModel(dataModelConditionGroup, GroupType));
break; break;
case DataModelConditionList dataModelConditionList: case DataModelConditionList dataModelConditionList:
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionListViewModel(dataModelConditionList)); Items.Add(_dataModelConditionsVmFactory.DataModelConditionListViewModel(dataModelConditionList));
break; break;
case DataModelConditionEvent dataModelConditionEvent: case DataModelConditionEvent dataModelConditionEvent:
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionEventViewModel(dataModelConditionEvent)); Items.Add(_dataModelConditionsVmFactory.DataModelConditionEventViewModel(dataModelConditionEvent));
break; break;
case DataModelConditionGeneralPredicate dataModelConditionGeneralPredicate: case DataModelConditionGeneralPredicate dataModelConditionGeneralPredicate:
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionGeneralPredicateViewModel(dataModelConditionGeneralPredicate)); Items.Add(_dataModelConditionsVmFactory.DataModelConditionGeneralPredicateViewModel(dataModelConditionGeneralPredicate));
break; break;
case DataModelConditionListPredicate dataModelConditionListPredicate: case DataModelConditionListPredicate dataModelConditionListPredicate:
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionListPredicateViewModel(dataModelConditionListPredicate)); Items.Add(_dataModelConditionsVmFactory.DataModelConditionListPredicateViewModel(dataModelConditionListPredicate));
break; break;
case DataModelConditionEventPredicate dataModelConditionEventPredicate: case DataModelConditionEventPredicate dataModelConditionEventPredicate:
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionEventPredicateViewModel(dataModelConditionEventPredicate)); Items.Add(_dataModelConditionsVmFactory.DataModelConditionEventPredicateViewModel(dataModelConditionEventPredicate));
break; break;
} }
} }
if (viewModels.Any())
Items.AddRange(viewModels);
// Ensure the items are in the same order as on the model // Ensure the items are in the same order as on the model
((BindableCollection<DataModelConditionViewModel>) Items).Sort(i => Model.Children.IndexOf(i.Model)); ((BindableCollection<DataModelConditionViewModel>) Items).Sort(i => Model.Children.IndexOf(i.Model));
foreach (DataModelConditionViewModel childViewModel in Items) foreach (DataModelConditionViewModel childViewModel in Items)
childViewModel.Update(); childViewModel.Update();

View File

@ -16,7 +16,7 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="0 3"> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />

View File

@ -21,7 +21,7 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="0 3"> <Grid Margin="0 0 0 3">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />

View File

@ -21,7 +21,7 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="0 3"> <Grid Margin="0 0 0 3">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />

View File

@ -21,7 +21,7 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="0 3"> <Grid Margin="0 0 0 3">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />

View File

@ -5,18 +5,13 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet" xmlns:s="https://github.com/canton7/Stylet"
xmlns:dd="urn:gong-wpf-dragdrop" xmlns:Converters="clr-namespace:Artemis.UI.Converters" xmlns:dd="urn:gong-wpf-dragdrop"
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"> d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources> <UserControl.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DataModelConditions.xaml" /> <ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DataModelConditions.xaml" />
<ResourceDictionary>
<Converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
@ -27,43 +22,16 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button Grid.Row="0" <Button Grid.Row="0"
Style="{StaticResource DataModelConditionButtonLeftClickMenu}" Style="{StaticResource DataModelConditionButton}"
Background="{StaticResource PrimaryHueMidBrush}" Background="{StaticResource PrimaryHueMidBrush}"
BorderBrush="{StaticResource PrimaryHueMidBrush}" BorderBrush="{StaticResource PrimaryHueMidBrush}"
HorizontalAlignment="Right"> HorizontalAlignment="Right"
Command="{s:Action AddCondition}">
ADD CONDITION ADD CONDITION
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Add static condition"
ToolTip="A condition that compares with a static input"
Command="{s:Action AddCondition}"
CommandParameter="Static">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="FormTextarea" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Add dynamic condition"
ToolTip="A condition that compares with a data model property"
Command="{s:Action AddCondition}"
CommandParameter="Dynamic">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="Link" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Add list condition"
ToolTip="A condition that evaluates on items in a list"
Command="{s:Action AddCondition}"
CommandParameter="List">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="FormatListBulleted" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button> </Button>
<ListBox Grid.Row="1" <ListBox Grid.Row="1"
ItemsSource="{Binding ConditionViewModels}" ItemsSource="{Binding Items}"
materialDesign:RippleAssist.IsDisabled="True" materialDesign:RippleAssist.IsDisabled="True"
dd:DragDrop.IsDragSource="True" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" dd:DragDrop.IsDropTarget="True"

View File

@ -10,7 +10,7 @@ using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.ConditionalDataBinding namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.ConditionalDataBinding
{ {
public class ConditionalDataBindingModeViewModel<TLayerProperty, TProperty> : Screen, IDataBindingModeViewModel public class ConditionalDataBindingModeViewModel<TLayerProperty, TProperty> : Conductor<DataBindingConditionViewModel<TLayerProperty, TProperty>>.Collection.AllActive, IDataBindingModeViewModel
{ {
private readonly IDataBindingsVmFactory _dataBindingsVmFactory; private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
@ -24,18 +24,83 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.Conditio
_dataBindingsVmFactory = dataBindingsVmFactory; _dataBindingsVmFactory = dataBindingsVmFactory;
ConditionalDataBinding = conditionalDataBinding; ConditionalDataBinding = conditionalDataBinding;
ConditionViewModels = new BindableCollection<DataBindingConditionViewModel<TLayerProperty, TProperty>>();
Initialize();
} }
public ConditionalDataBinding<TLayerProperty, TProperty> ConditionalDataBinding { get; } public ConditionalDataBinding<TLayerProperty, TProperty> ConditionalDataBinding { get; }
public BindableCollection<DataBindingConditionViewModel<TLayerProperty, TProperty>> ConditionViewModels { get; }
public void AddCondition()
{
DataBindingCondition<TLayerProperty, TProperty> condition = ConditionalDataBinding.AddCondition();
// Find the VM of the new condition
DataBindingConditionViewModel<TLayerProperty, TProperty> viewModel = Items.First(c => c.DataBindingCondition == condition);
viewModel.ActiveItem.AddCondition();
_profileEditorService.UpdateSelectedProfileElement();
}
protected override void OnInitialActivate()
{
base.OnInitialActivate();
Initialize();
}
private void UpdateItems()
{
_updating = true;
// Remove old VMs
List<DataBindingConditionViewModel<TLayerProperty, TProperty>> toRemove = Items.Where(c => !ConditionalDataBinding.Conditions.Contains(c.DataBindingCondition)).ToList();
foreach (DataBindingConditionViewModel<TLayerProperty, TProperty> dataBindingConditionViewModel in toRemove)
{
Items.Remove(dataBindingConditionViewModel);
dataBindingConditionViewModel.Dispose();
}
// Add missing VMs
foreach (DataBindingCondition<TLayerProperty, TProperty> condition in ConditionalDataBinding.Conditions)
if (Items.All(c => c.DataBindingCondition != condition))
Items.Add(_dataBindingsVmFactory.DataBindingConditionViewModel(condition));
// Fix order
((BindableCollection<DataBindingConditionViewModel<TLayerProperty, TProperty>>) Items).Sort(c => c.DataBindingCondition.Order);
_updating = false;
}
private void Initialize()
{
ConditionalDataBinding.ConditionsUpdated += ConditionalDataBindingOnConditionsUpdated;
Items.CollectionChanged += ItemsOnCollectionChanged;
UpdateItems();
}
private void ItemsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_updating || e.Action != NotifyCollectionChangedAction.Add)
return;
for (int index = 0; index < Items.Count; index++)
{
DataBindingConditionViewModel<TLayerProperty, TProperty> conditionViewModel = Items[index];
conditionViewModel.DataBindingCondition.Order = index + 1;
}
ConditionalDataBinding.ApplyOrder();
_profileEditorService.UpdateSelectedProfileElement();
}
private void ConditionalDataBindingOnConditionsUpdated(object sender, EventArgs e)
{
UpdateItems();
}
public bool SupportsTestValue => false; public bool SupportsTestValue => false;
public void Update() public void Update()
{ {
UpdateConditionViewModels(); UpdateItems();
} }
public object GetTestValue() public object GetTestValue()
@ -49,64 +114,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.Conditio
{ {
ConditionalDataBinding.ConditionsUpdated -= ConditionalDataBindingOnConditionsUpdated; ConditionalDataBinding.ConditionsUpdated -= ConditionalDataBindingOnConditionsUpdated;
foreach (DataBindingConditionViewModel<TLayerProperty, TProperty> conditionViewModel in ConditionViewModels) foreach (DataBindingConditionViewModel<TLayerProperty, TProperty> conditionViewModel in Items)
conditionViewModel.Dispose(); conditionViewModel.Dispose();
ConditionViewModels.Clear(); Items.Clear();
} }
#endregion #endregion
private void UpdateConditionViewModels()
{
_updating = true;
// Remove old VMs
List<DataBindingConditionViewModel<TLayerProperty, TProperty>> toRemove = ConditionViewModels.Where(c => !ConditionalDataBinding.Conditions.Contains(c.DataBindingCondition)).ToList();
foreach (DataBindingConditionViewModel<TLayerProperty, TProperty> dataBindingConditionViewModel in toRemove)
{
ConditionViewModels.Remove(dataBindingConditionViewModel);
dataBindingConditionViewModel.Dispose();
}
// Add missing VMs
foreach (DataBindingCondition<TLayerProperty, TProperty> condition in ConditionalDataBinding.Conditions)
{
if (ConditionViewModels.All(c => c.DataBindingCondition != condition))
ConditionViewModels.Add(_dataBindingsVmFactory.DataBindingConditionViewModel(condition));
}
// Fix order
ConditionViewModels.Sort(c => c.DataBindingCondition.Order);
_updating = false;
}
private void Initialize()
{
ConditionalDataBinding.ConditionsUpdated += ConditionalDataBindingOnConditionsUpdated;
ConditionViewModels.CollectionChanged += ConditionViewModelsOnCollectionChanged;
UpdateConditionViewModels();
}
private void ConditionViewModelsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_updating || e.Action != NotifyCollectionChangedAction.Add)
return;
for (int index = 0; index < ConditionViewModels.Count; index++)
{
DataBindingConditionViewModel<TLayerProperty, TProperty> conditionViewModel = ConditionViewModels[index];
conditionViewModel.DataBindingCondition.Order = index + 1;
}
ConditionalDataBinding.ApplyOrder();
_profileEditorService.UpdateSelectedProfileElement();
}
private void ConditionalDataBindingOnConditionsUpdated(object sender, EventArgs e)
{
UpdateConditionViewModels();
}
} }
} }

View File

@ -18,7 +18,7 @@
IsTabStop="False" /> IsTabStop="False" />
<ContentControl Grid.Row="1" <ContentControl Grid.Row="1"
Margin="26 5 0 0" Margin="26 2 0 0"
s:View.Model="{Binding ValueViewModel}" s:View.Model="{Binding ValueViewModel}"
VerticalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"

View File

@ -13,6 +13,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.Conditio
public class DataBindingConditionViewModel<TLayerProperty, TProperty> : Conductor<DataModelConditionGroupViewModel>, IDisposable public class DataBindingConditionViewModel<TLayerProperty, TProperty> : Conductor<DataModelConditionGroupViewModel>, IDisposable
{ {
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly IDataModelConditionsVmFactory _dataModelConditionsVmFactory;
private readonly IDataModelUIService _dataModelUIService;
public DataBindingConditionViewModel(DataBindingCondition<TLayerProperty, TProperty> dataBindingCondition, public DataBindingConditionViewModel(DataBindingCondition<TLayerProperty, TProperty> dataBindingCondition,
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
@ -20,22 +22,28 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.Conditio
IDataModelUIService dataModelUIService) IDataModelUIService dataModelUIService)
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_dataModelConditionsVmFactory = dataModelConditionsVmFactory;
_dataModelUIService = dataModelUIService;
DataBindingCondition = dataBindingCondition; DataBindingCondition = dataBindingCondition;
ActiveItem = dataModelConditionsVmFactory.DataModelConditionGroupViewModel(DataBindingCondition.Condition, ConditionGroupType.General);
ActiveItem.IsRootGroup = true;
ActiveItem.Update();
ActiveItem.Updated += ActiveItemOnUpdated;
ValueViewModel = dataModelUIService.GetStaticInputViewModel(typeof(TProperty), null);
ValueViewModel.ValueUpdated += ValueViewModelOnValueUpdated;
ValueViewModel.Value = DataBindingCondition.Value;
} }
public DataBindingCondition<TLayerProperty, TProperty> DataBindingCondition { get; } public DataBindingCondition<TLayerProperty, TProperty> DataBindingCondition { get; }
public DataModelStaticViewModel ValueViewModel { get; set; } public DataModelStaticViewModel ValueViewModel { get; set; }
protected override void OnInitialActivate()
{
base.OnInitialActivate();
ActiveItem = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(DataBindingCondition.Condition, ConditionGroupType.General);
ActiveItem.IsRootGroup = true;
ActiveItem.Update();
ActiveItem.Updated += ActiveItemOnUpdated;
ValueViewModel = _dataModelUIService.GetStaticInputViewModel(typeof(TProperty), null);
ValueViewModel.ValueUpdated += ValueViewModelOnValueUpdated;
ValueViewModel.Value = DataBindingCondition.Value;
}
public void Dispose() public void Dispose()
{ {
ValueViewModel.Dispose(); ValueViewModel.Dispose();

View File

@ -44,7 +44,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
EasingViewModels = new BindableCollection<TimelineEasingViewModel>(); EasingViewModels = new BindableCollection<TimelineEasingViewModel>();
TestInputValue = dataModelUIService.GetDataModelDisplayViewModel(typeof(TProperty), null, true); TestInputValue = dataModelUIService.GetDataModelDisplayViewModel(typeof(TProperty), null, true);
TestResultValue = dataModelUIService.GetDataModelDisplayViewModel(typeof(TProperty), null, true); TestResultValue = dataModelUIService.GetDataModelDisplayViewModel(typeof(TProperty), null, true);
}
protected override void OnInitialActivate()
{
base.OnInitialActivate();
Initialize(); Initialize();
} }
@ -237,7 +241,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
} }
// While playing in preview data bindings aren't updated // While playing in preview data bindings aren't updated
Registration.DataBinding.Update(Registration.LayerProperty.ProfileElement.Timeline); Registration.DataBinding.UpdateWithDelta(TimeSpan.FromMilliseconds(40));
if (ActiveItem.SupportsTestValue) if (ActiveItem.SupportsTestValue)
{ {

View File

@ -48,7 +48,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
// and creating the actual data bindings // and creating the actual data bindings
foreach (IDataBindingRegistration registration in registrations) foreach (IDataBindingRegistration registration in registrations)
Items.Add(_dataBindingsVmFactory.DataBindingViewModel(registration)); Items.Add(_dataBindingsVmFactory.DataBindingViewModel(registration));
SelectedItemIndex = 0; SelectedItemIndex = 0;
} }

View File

@ -55,9 +55,9 @@
DialogTheme="Inherit" DialogTheme="Inherit"
SnackbarMessageQueue="{Binding MainMessageQueue}"> SnackbarMessageQueue="{Binding MainMessageQueue}">
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding SidebarViewModel.IsSidebarOpen}"> <materialDesign:DrawerHost IsLeftDrawerOpen="{Binding SidebarViewModel.IsSidebarOpen}" >
<materialDesign:DrawerHost.LeftDrawerContent> <materialDesign:DrawerHost.LeftDrawerContent>
<ContentControl s:View.Model="{Binding SidebarViewModel}" Width="280" ClipToBounds="False" /> <ContentControl s:View.Model="{Binding SidebarViewModel}" Width="280" />
</materialDesign:DrawerHost.LeftDrawerContent> </materialDesign:DrawerHost.LeftDrawerContent>
<DockPanel> <DockPanel>
<mde:AppBar Type="Dense" <mde:AppBar Type="Dense"

View File

@ -21,7 +21,7 @@
<Image Grid.Row="0" <Image Grid.Row="0"
Grid.RowSpan="2" Grid.RowSpan="2"
Source="/Resources/Images/Sidebar/sidebar-header.png" Source="/Resources/Images/Sidebar/sidebar-header.png"
Stretch="None" Stretch="UniformToFill"
VerticalAlignment="Top" Height="120" /> VerticalAlignment="Top" Height="120" />
<TextBlock Grid.Row="1" <TextBlock Grid.Row="1"
Style="{StaticResource MaterialDesignHeadline6TextBlock}" Style="{StaticResource MaterialDesignHeadline6TextBlock}"