mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Profile editor - Reimplemented more of the timeline
This commit is contained in:
parent
13a006ba48
commit
db9d9fb4e6
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.LayerBrushes;
|
using Artemis.Core.LayerBrushes;
|
||||||
using Artemis.Core.LayerEffects;
|
using Artemis.Core.LayerEffects;
|
||||||
@ -672,6 +673,13 @@ namespace Artemis.Core
|
|||||||
if (descriptor == null)
|
if (descriptor == null)
|
||||||
throw new ArgumentNullException(nameof(descriptor));
|
throw new ArgumentNullException(nameof(descriptor));
|
||||||
|
|
||||||
|
if (LayerBrush != null)
|
||||||
|
{
|
||||||
|
var brush = LayerBrush;
|
||||||
|
LayerBrush = null;
|
||||||
|
brush.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the brush reference matches the brush
|
// Ensure the brush reference matches the brush
|
||||||
var current = General.BrushReference.CurrentValue;
|
var current = General.BrushReference.CurrentValue;
|
||||||
if (current.BrushPluginGuid != descriptor.LayerBrushProvider.PluginInfo.Guid || current.BrushType != descriptor.LayerBrushType.Name)
|
if (current.BrushPluginGuid != descriptor.LayerBrushProvider.PluginInfo.Guid || current.BrushType != descriptor.LayerBrushType.Name)
|
||||||
@ -721,7 +729,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
|
|
||||||
private void LayerBrushStoreOnLayerBrushRemoved(object sender, LayerBrushStoreEvent e)
|
private void LayerBrushStoreOnLayerBrushRemoved(object sender, LayerBrushStoreEvent e)
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace Artemis.Core
|
|||||||
public abstract class LayerProperty<T> : ILayerProperty
|
public abstract class LayerProperty<T> : ILayerProperty
|
||||||
{
|
{
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="LayerProperty{T}" /> class
|
/// Creates a new instance of the <see cref="LayerProperty{T}" /> class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -274,19 +274,6 @@ namespace Artemis.Core
|
|||||||
OnKeyframeRemoved();
|
OnKeyframeRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes all keyframes from the layer property
|
|
||||||
/// </summary>
|
|
||||||
public void ClearKeyframes()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
throw new ObjectDisposedException("LayerProperty");
|
|
||||||
|
|
||||||
var keyframes = new List<LayerPropertyKeyframe<T>>(_keyframes);
|
|
||||||
foreach (var layerPropertyKeyframe in keyframes)
|
|
||||||
RemoveKeyframe(layerPropertyKeyframe);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sorts the keyframes in ascending order by position
|
/// Sorts the keyframes in ascending order by position
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -343,6 +330,11 @@ namespace Artemis.Core
|
|||||||
return (DataBindingRegistration<T, TProperty>) match;
|
return (DataBindingRegistration<T, TProperty>) match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<IDataBindingRegistration> GetAllDataBindingRegistrations()
|
||||||
|
{
|
||||||
|
return _dataBindingRegistrations;
|
||||||
|
}
|
||||||
|
|
||||||
public void RegisterDataBindingProperty<TProperty>(Expression<Func<T, TProperty>> propertyLambda, DataBindingConverter<T, TProperty> converter)
|
public void RegisterDataBindingProperty<TProperty>(Expression<Func<T, TProperty>> propertyLambda, DataBindingConverter<T, TProperty> converter)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
@ -593,7 +585,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
foreach (var dataBinding in _dataBindings)
|
foreach (var dataBinding in _dataBindings)
|
||||||
dataBinding.Dispose();
|
dataBinding.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,10 +89,7 @@ namespace Artemis.UI.Shared.Input
|
|||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
// Get the data models
|
// Get the data models
|
||||||
DataModelViewModel = _dataModelUIService.GetMainDataModelVisualization();
|
DataModelViewModel = _dataModelUIService.GetPluginDataModelVisualization(_module, true);
|
||||||
if (!_dataModelUIService.GetPluginExtendsDataModel(_module))
|
|
||||||
DataModelViewModel.Children.Add(_dataModelUIService.GetPluginDataModelVisualization(_module));
|
|
||||||
|
|
||||||
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
|
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
|
||||||
|
|
||||||
_updateTimer.Start();
|
_updateTimer.Start();
|
||||||
|
|||||||
@ -32,7 +32,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
public DataModelPropertiesViewModel GetMainDataModelVisualization()
|
public DataModelPropertiesViewModel GetMainDataModelVisualization()
|
||||||
{
|
{
|
||||||
var viewModel = new DataModelPropertiesViewModel(null, null, null);
|
var viewModel = new DataModelPropertiesViewModel(null, null, null);
|
||||||
foreach (var dataModelExpansion in _dataModelService.DataModelExpansions)
|
foreach (var dataModelExpansion in _dataModelService.GetDataModels())
|
||||||
viewModel.Children.Add(new DataModelPropertiesViewModel(dataModelExpansion, viewModel, null));
|
viewModel.Children.Add(new DataModelPropertiesViewModel(dataModelExpansion, viewModel, null));
|
||||||
|
|
||||||
// Update to populate children
|
// Update to populate children
|
||||||
@ -41,8 +41,23 @@ namespace Artemis.UI.Shared.Services
|
|||||||
return viewModel;
|
return viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataModelPropertiesViewModel GetPluginDataModelVisualization(Plugin plugin)
|
public DataModelPropertiesViewModel GetPluginDataModelVisualization(Plugin plugin, bool includeMainDataModel)
|
||||||
{
|
{
|
||||||
|
if (includeMainDataModel)
|
||||||
|
{
|
||||||
|
var mainDataModel = GetMainDataModelVisualization();
|
||||||
|
|
||||||
|
// If the main data model already includes the plugin data model we're done
|
||||||
|
if (mainDataModel.Children.Any(c => c.DataModel.PluginInfo.Instance == plugin))
|
||||||
|
return mainDataModel;
|
||||||
|
// Otherwise get just the plugin data model and add it
|
||||||
|
var pluginDataModel = GetPluginDataModelVisualization(plugin, false);
|
||||||
|
if (pluginDataModel != null)
|
||||||
|
mainDataModel.Children.Add(pluginDataModel);
|
||||||
|
|
||||||
|
return mainDataModel;
|
||||||
|
}
|
||||||
|
|
||||||
var dataModel = _dataModelService.GetPluginDataModel(plugin);
|
var dataModel = _dataModelService.GetPluginDataModel(plugin);
|
||||||
if (dataModel == null)
|
if (dataModel == null)
|
||||||
return null;
|
return null;
|
||||||
@ -55,12 +70,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
viewModel.UpdateRequested += (sender, args) => viewModel.Update(this);
|
viewModel.UpdateRequested += (sender, args) => viewModel.Update(this);
|
||||||
return viewModel;
|
return viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetPluginExtendsDataModel(Plugin plugin)
|
|
||||||
{
|
|
||||||
return _dataModelService.GetPluginExtendsDataModel(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelVisualizationRegistration RegisterDataModelInput<T>(PluginInfo pluginInfo, IReadOnlyCollection<Type> compatibleConversionTypes = null) where T : DataModelInputViewModel
|
public DataModelVisualizationRegistration RegisterDataModelInput<T>(PluginInfo pluginInfo, IReadOnlyCollection<Type> compatibleConversionTypes = null) where T : DataModelInputViewModel
|
||||||
{
|
{
|
||||||
if (compatibleConversionTypes == null)
|
if (compatibleConversionTypes == null)
|
||||||
|
|||||||
@ -12,14 +12,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
IReadOnlyCollection<DataModelVisualizationRegistration> RegisteredDataModelEditors { get; }
|
IReadOnlyCollection<DataModelVisualizationRegistration> RegisteredDataModelEditors { get; }
|
||||||
IReadOnlyCollection<DataModelVisualizationRegistration> RegisteredDataModelDisplays { get; }
|
IReadOnlyCollection<DataModelVisualizationRegistration> RegisteredDataModelDisplays { get; }
|
||||||
DataModelPropertiesViewModel GetMainDataModelVisualization();
|
DataModelPropertiesViewModel GetMainDataModelVisualization();
|
||||||
DataModelPropertiesViewModel GetPluginDataModelVisualization(Plugin plugin);
|
DataModelPropertiesViewModel GetPluginDataModelVisualization(Plugin plugin, bool includeMainDataModel);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether the given plugin expands the main data model
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="plugin"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
bool GetPluginExtendsDataModel(Plugin plugin);
|
|
||||||
|
|
||||||
DataModelVisualizationRegistration RegisterDataModelInput<T>(PluginInfo pluginInfo, IReadOnlyCollection<Type> compatibleConversionTypes) where T : DataModelInputViewModel;
|
DataModelVisualizationRegistration RegisterDataModelInput<T>(PluginInfo pluginInfo, IReadOnlyCollection<Type> compatibleConversionTypes) where T : DataModelInputViewModel;
|
||||||
DataModelVisualizationRegistration RegisterDataModelDisplay<T>(PluginInfo pluginInfo) where T : DataModelDisplayViewModel;
|
DataModelVisualizationRegistration RegisterDataModelDisplay<T>(PluginInfo pluginInfo) where T : DataModelDisplayViewModel;
|
||||||
|
|||||||
@ -71,21 +71,21 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
|
|
||||||
public interface IDataBindingsVmFactory : IVmFactory
|
public interface IDataBindingsVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
DataBindingsViewModel DataBindingsViewModel(BaseLayerProperty layerProperty);
|
IDataBindingViewModel DataBindingViewModel(IDataBindingRegistration registration);
|
||||||
DataBindingViewModel DataBindingViewModel(DataBindingRegistration registration);
|
DataBindingModifierViewModel<TLayerProperty, TProperty> DataBindingModifierViewModel<TLayerProperty, TProperty>(DataBindingModifier<TLayerProperty, TProperty> modifier);
|
||||||
DataBindingModifierViewModel DataBindingModifierViewModel(DataBindingModifier modifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ILayerPropertyVmFactory : IVmFactory
|
public interface ILayerPropertyVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
LayerPropertyViewModel LayerPropertyViewModel(ILayerProperty layerProperty);
|
LayerPropertyViewModel LayerPropertyViewModel(ILayerProperty layerProperty);
|
||||||
|
|
||||||
LayerPropertyGroupViewModel LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup);
|
LayerPropertyGroupViewModel LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup);
|
||||||
TreePropertyViewModel<T> LayerPropertyGroupViewModel<T>(LayerProperty<T> layerProperty);
|
|
||||||
TreeGroupViewModel TreeGroupViewModel(LayerPropertyGroupViewModel layerPropertyGroupViewModel);
|
TreeGroupViewModel TreeGroupViewModel(LayerPropertyGroupViewModel layerPropertyGroupViewModel);
|
||||||
TimelineGroupViewModel TimelineGroupViewModel(LayerPropertyGroupViewModel layerPropertyGroupViewModel);
|
TimelineGroupViewModel TimelineGroupViewModel(LayerPropertyGroupViewModel layerPropertyGroupViewModel);
|
||||||
LayerPropertyGroupViewModel LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription);
|
|
||||||
TreeViewModel TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
TreeViewModel TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
||||||
EffectsViewModel EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel);
|
EffectsViewModel EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel);
|
||||||
TimelineViewModel TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
TimelineViewModel TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
||||||
|
TimelineSegmentViewModel TimelineSegmentViewModel(SegmentViewModelType segment, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11,13 +11,12 @@ namespace Artemis.UI.PropertyInput
|
|||||||
public class BrushPropertyInputViewModel : PropertyInputViewModel<LayerBrushReference>
|
public class BrushPropertyInputViewModel : PropertyInputViewModel<LayerBrushReference>
|
||||||
{
|
{
|
||||||
private readonly IPluginService _pluginService;
|
private readonly IPluginService _pluginService;
|
||||||
private readonly IRenderElementService _renderElementService;
|
|
||||||
private List<LayerBrushDescriptor> _descriptors;
|
private List<LayerBrushDescriptor> _descriptors;
|
||||||
|
|
||||||
public BrushPropertyInputViewModel(LayerProperty<LayerBrushReference> layerProperty, IProfileEditorService profileEditorService,
|
public BrushPropertyInputViewModel(LayerProperty<LayerBrushReference> layerProperty,
|
||||||
IRenderElementService renderElementService, IPluginService pluginService) : base(layerProperty, profileEditorService)
|
IProfileEditorService profileEditorService,
|
||||||
|
IPluginService pluginService) : base(layerProperty, profileEditorService)
|
||||||
{
|
{
|
||||||
_renderElementService = renderElementService;
|
|
||||||
_pluginService = pluginService;
|
_pluginService = pluginService;
|
||||||
|
|
||||||
_pluginService.PluginEnabled += PluginServiceOnPluginLoaded;
|
_pluginService.PluginEnabled += PluginServiceOnPluginLoaded;
|
||||||
@ -54,11 +53,8 @@ namespace Artemis.UI.PropertyInput
|
|||||||
|
|
||||||
protected override void OnInputValueApplied()
|
protected override void OnInputValueApplied()
|
||||||
{
|
{
|
||||||
if (LayerProperty.ProfileElement is Layer layer)
|
if (LayerProperty.ProfileElement is Layer layer)
|
||||||
{
|
layer.ChangeLayerBrush(SelectedDescriptor);
|
||||||
_renderElementService.RemoveLayerBrush(layer);
|
|
||||||
_renderElementService.InstantiateLayerBrush(layer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetBrushByDescriptor(LayerBrushDescriptor value)
|
private void SetBrushByDescriptor(LayerBrushDescriptor value)
|
||||||
|
|||||||
@ -308,10 +308,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
if (DisplayConditionListPredicate.ListDataModel == null || DisplayConditionListPredicate.ListPropertyPath == null)
|
if (DisplayConditionListPredicate.ListDataModel == null || DisplayConditionListPredicate.ListPropertyPath == null)
|
||||||
throw new ArtemisUIException("Cannot create a list predicate without first selecting a target list");
|
throw new ArtemisUIException("Cannot create a list predicate without first selecting a target list");
|
||||||
|
|
||||||
var dataModel = _dataModelUIService.GetMainDataModelVisualization();
|
var dataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
||||||
if (!_dataModelUIService.GetPluginExtendsDataModel(_profileEditorService.GetCurrentModule()))
|
|
||||||
dataModel.Children.Add(_dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule()));
|
|
||||||
|
|
||||||
var listDataModel = (DataModelListViewModel) dataModel.GetChildByPath(
|
var listDataModel = (DataModelListViewModel) dataModel.GetChildByPath(
|
||||||
DisplayConditionListPredicate.ListDataModel.PluginInfo.Guid,
|
DisplayConditionListPredicate.ListDataModel.PluginInfo.Guid,
|
||||||
DisplayConditionListPredicate.ListPropertyPath
|
DisplayConditionListPredicate.ListPropertyPath
|
||||||
|
|||||||
@ -109,10 +109,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
// Get the data models
|
// Get the data models
|
||||||
TargetDataModel = _dataModelUIService.GetMainDataModelVisualization();
|
TargetDataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
||||||
if (!_dataModelUIService.GetPluginExtendsDataModel(_profileEditorService.GetCurrentModule()))
|
|
||||||
TargetDataModel.Children.Add(_dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule()));
|
|
||||||
|
|
||||||
TargetDataModel.UpdateRequested += TargetDataModelUpdateRequested;
|
TargetDataModel.UpdateRequested += TargetDataModelUpdateRequested;
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
|
|||||||
@ -168,14 +168,9 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
// Get the data models
|
// Get the data models
|
||||||
LeftSideDataModel = _dataModelUIService.GetMainDataModelVisualization();
|
LeftSideDataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
||||||
RightSideDataModel = _dataModelUIService.GetMainDataModelVisualization();
|
RightSideDataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
||||||
if (!_dataModelUIService.GetPluginExtendsDataModel(_profileEditorService.GetCurrentModule()))
|
|
||||||
{
|
|
||||||
LeftSideDataModel.Children.Add(_dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule()));
|
|
||||||
RightSideDataModel.Children.Add(_dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which types are currently supported
|
// Determine which types are currently supported
|
||||||
var editors = _dataModelUIService.RegisteredDataModelEditors;
|
var editors = _dataModelUIService.RegisteredDataModelEditors;
|
||||||
_supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
|
_supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using Artemis.Core;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Exceptions;
|
using Artemis.UI.Exceptions;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
@ -10,16 +8,16 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
||||||
{
|
{
|
||||||
public class DataBindingModifierViewModel : PropertyChangedBase
|
public class DataBindingModifierViewModel<TLayerProperty, TProperty> : PropertyChangedBase
|
||||||
{
|
{
|
||||||
private readonly IDataBindingService _dataBindingService;
|
private readonly IDataBindingService _dataBindingService;
|
||||||
private readonly IDataModelUIService _dataModelUIService;
|
private readonly IDataModelUIService _dataModelUIService;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private DataBindingModifierType _selectedModifierType;
|
|
||||||
private DataModelDynamicViewModel _dynamicSelectionViewModel;
|
private DataModelDynamicViewModel _dynamicSelectionViewModel;
|
||||||
|
private DataBindingModifierType _selectedModifierType;
|
||||||
private DataModelStaticViewModel _staticInputViewModel;
|
private DataModelStaticViewModel _staticInputViewModel;
|
||||||
|
|
||||||
public DataBindingModifierViewModel(DataBindingModifier modifier,
|
public DataBindingModifierViewModel(DataBindingModifier<TLayerProperty, TProperty> modifier,
|
||||||
IDataBindingService dataBindingService,
|
IDataBindingService dataBindingService,
|
||||||
ISettingsService settingsService,
|
ISettingsService settingsService,
|
||||||
IDataModelUIService dataModelUIService,
|
IDataModelUIService dataModelUIService,
|
||||||
@ -42,7 +40,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
|
|
||||||
public DelegateCommand SelectModifierTypeCommand { get; }
|
public DelegateCommand SelectModifierTypeCommand { get; }
|
||||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
public PluginSetting<bool> ShowDataModelValues { get; }
|
||||||
public DataBindingModifier Modifier { get; }
|
public DataBindingModifier<TLayerProperty, TProperty> Modifier { get; }
|
||||||
public BindableCollection<DataBindingModifierType> ModifierTypes { get; }
|
public BindableCollection<DataBindingModifierType> ModifierTypes { get; }
|
||||||
|
|
||||||
public DataBindingModifierType SelectedModifierType
|
public DataBindingModifierType SelectedModifierType
|
||||||
@ -62,7 +60,22 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
get => _staticInputViewModel;
|
get => _staticInputViewModel;
|
||||||
private set => SetAndNotify(ref _staticInputViewModel, value);
|
private set => SetAndNotify(ref _staticInputViewModel, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
private void ParameterSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
|
private void ParameterSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
|
||||||
{
|
{
|
||||||
Modifier.UpdateParameter(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.PropertyPath);
|
Modifier.UpdateParameter(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.PropertyPath);
|
||||||
@ -89,7 +102,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
StaticInputViewModel = null;
|
StaticInputViewModel = null;
|
||||||
DynamicSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
DynamicSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
||||||
DynamicSelectionViewModel.PropertySelected += ParameterSelectionViewModelOnPropertySelected;
|
DynamicSelectionViewModel.PropertySelected += ParameterSelectionViewModelOnPropertySelected;
|
||||||
DynamicSelectionViewModel.FilterTypes = new[] { sourceType };
|
DynamicSelectionViewModel.FilterTypes = new[] {sourceType};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -120,20 +133,5 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
|
|
||||||
Update();
|
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);
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10,23 +10,23 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
||||||
{
|
{
|
||||||
public class DataBindingViewModel : PropertyChangedBase, IDisposable
|
public class DataBindingViewModel<TLayerProperty, TProperty> : Screen, IDataBindingViewModel
|
||||||
{
|
{
|
||||||
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
|
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
|
||||||
private readonly IDataModelUIService _dataModelUIService;
|
private readonly IDataModelUIService _dataModelUIService;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private DataBinding _dataBinding;
|
private DataBinding<TLayerProperty, TProperty> _dataBinding;
|
||||||
private int _easingTime;
|
private int _easingTime;
|
||||||
private bool _isDataBindingEnabled;
|
private bool _isDataBindingEnabled;
|
||||||
private bool _isEasingTimeEnabled;
|
private bool _isEasingTimeEnabled;
|
||||||
private DataBindingMode _selectedDataBindingMode;
|
private DataBindingMode _selectedDataBindingMode;
|
||||||
private TimelineEasingViewModel _selectedEasingViewModel;
|
private TimelineEasingViewModel _selectedEasingViewModel;
|
||||||
private DataModelDynamicViewModel _targetSelectionViewModel;
|
private DataModelDynamicViewModel _targetSelectionViewModel;
|
||||||
private object _testInputValue;
|
private TProperty _testInputValue;
|
||||||
private object _testResultValue;
|
private TProperty _testResultValue;
|
||||||
private bool _updating;
|
private bool _updating;
|
||||||
|
|
||||||
public DataBindingViewModel(DataBindingRegistration registration,
|
public DataBindingViewModel(DataBindingRegistration<TLayerProperty, TProperty> registration,
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IDataModelUIService dataModelUIService,
|
IDataModelUIService dataModelUIService,
|
||||||
IDataBindingsVmFactory dataBindingsVmFactory)
|
IDataBindingsVmFactory dataBindingsVmFactory)
|
||||||
@ -40,7 +40,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
|
|
||||||
DataBindingModes = new BindableCollection<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(DataBindingMode)));
|
DataBindingModes = new BindableCollection<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(DataBindingMode)));
|
||||||
EasingViewModels = new BindableCollection<TimelineEasingViewModel>();
|
EasingViewModels = new BindableCollection<TimelineEasingViewModel>();
|
||||||
ModifierViewModels = new BindableCollection<DataBindingModifierViewModel>();
|
ModifierViewModels = new BindableCollection<DataBindingModifierViewModel<TLayerProperty, TProperty>>();
|
||||||
|
|
||||||
DataBinding = Registration.DataBinding;
|
DataBinding = Registration.DataBinding;
|
||||||
if (DataBinding != null)
|
if (DataBinding != null)
|
||||||
@ -52,12 +52,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
Execute.PostToUIThread(Initialize);
|
Execute.PostToUIThread(Initialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataBindingRegistration Registration { get; }
|
public DataBindingRegistration<TLayerProperty, TProperty> Registration { get; }
|
||||||
public string DisplayName { get; }
|
|
||||||
|
|
||||||
public BindableCollection<ValueDescription> DataBindingModes { get; }
|
public BindableCollection<ValueDescription> DataBindingModes { get; }
|
||||||
public BindableCollection<TimelineEasingViewModel> EasingViewModels { get; }
|
public BindableCollection<TimelineEasingViewModel> EasingViewModels { get; }
|
||||||
public BindableCollection<DataBindingModifierViewModel> ModifierViewModels { get; }
|
public BindableCollection<DataBindingModifierViewModel<TLayerProperty, TProperty>> ModifierViewModels { get; }
|
||||||
|
|
||||||
public DataBindingMode SelectedDataBindingMode
|
public DataBindingMode SelectedDataBindingMode
|
||||||
{
|
{
|
||||||
@ -114,7 +113,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataBinding DataBinding
|
public DataBinding<TLayerProperty, TProperty> DataBinding
|
||||||
{
|
{
|
||||||
get => _dataBinding;
|
get => _dataBinding;
|
||||||
set
|
set
|
||||||
@ -124,13 +123,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object TestInputValue
|
public TProperty TestInputValue
|
||||||
{
|
{
|
||||||
get => _testInputValue;
|
get => _testInputValue;
|
||||||
set => SetAndNotify(ref _testInputValue, value);
|
set => SetAndNotify(ref _testInputValue, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object TestResultValue
|
public TProperty TestResultValue
|
||||||
{
|
{
|
||||||
get => _testResultValue;
|
get => _testResultValue;
|
||||||
set => SetAndNotify(ref _testResultValue, value);
|
set => SetAndNotify(ref _testResultValue, value);
|
||||||
@ -167,7 +166,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
if (DataBinding == null)
|
if (DataBinding == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var modifier = new DataBindingModifier(ProfileRightSideType.Dynamic);
|
var modifier = new DataBindingModifier<TLayerProperty, TProperty>(ProfileRightSideType.Dynamic);
|
||||||
DataBinding.AddModifier(modifier);
|
DataBinding.AddModifier(modifier);
|
||||||
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
@ -175,7 +174,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
EasingViewModels.AddRange(Enum.GetValues(typeof(Easings.Functions)).Cast<Easings.Functions>().Select(v => new TimelineEasingViewModel(null, v)));
|
EasingViewModels.AddRange(Enum.GetValues(typeof(Easings.Functions)).Cast<Easings.Functions>().Select(v => new TimelineEasingViewModel(v, false)));
|
||||||
TargetSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
TargetSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
||||||
TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected;
|
TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected;
|
||||||
_profileEditorService.ProfilePreviewUpdated += ProfileEditorServiceOnProfilePreviewUpdated;
|
_profileEditorService.ProfilePreviewUpdated += ProfileEditorServiceOnProfilePreviewUpdated;
|
||||||
@ -229,9 +228,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
var currentValue = TargetSelectionViewModel.SelectedPropertyViewModel?.GetCurrentValue();
|
var currentValue = TargetSelectionViewModel.SelectedPropertyViewModel?.GetCurrentValue();
|
||||||
if (currentValue == null && Registration.Property.PropertyType.IsValueType)
|
if (currentValue == null && Registration.Property.PropertyType.IsValueType)
|
||||||
currentValue = Activator.CreateInstance(Registration.Property.PropertyType);
|
currentValue = Activator.CreateInstance(Registration.Property.PropertyType);
|
||||||
|
|
||||||
TestInputValue = Convert.ChangeType(currentValue, Registration.Property.PropertyType);
|
TestInputValue = currentValue is TProperty testInputValue ? testInputValue : default;
|
||||||
TestResultValue = DataBinding?.GetValue(TestInputValue);
|
if (DataBinding != null)
|
||||||
|
TestResultValue = DataBinding.GetValue(TestInputValue);
|
||||||
|
else
|
||||||
|
TestInputValue = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateModifierViewModels()
|
private void UpdateModifierViewModels()
|
||||||
@ -268,4 +270,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
DataBinding.ModifiersUpdated -= DataBindingOnModifiersUpdated;
|
DataBinding.ModifiersUpdated -= DataBindingOnModifiersUpdated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IDataBindingViewModel : IScreen, IDisposable
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,16 +0,0 @@
|
|||||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DataBindingsTabsView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
|
||||||
<TabControl ItemsSource="{Binding Tabs}" DisplayMemberPath="DisplayName" Style="{StaticResource MaterialDesignTabControl}">
|
|
||||||
<TabControl.ContentTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<ContentControl s:View.Model="{Binding}" TextElement.Foreground="{DynamicResource MaterialDesignBody}" />
|
|
||||||
</DataTemplate>
|
|
||||||
</TabControl.ContentTemplate>
|
|
||||||
</TabControl>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|
||||||
{
|
|
||||||
public class DataBindingsTabsViewModel : PropertyChangedBase
|
|
||||||
{
|
|
||||||
public DataBindingsTabsViewModel()
|
|
||||||
{
|
|
||||||
Tabs = new BindableCollection<DataBindingViewModel>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BindableCollection<DataBindingViewModel> Tabs { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,14 +3,14 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
d:DataContext="{d:DesignInstance local:DataBindingsViewModel}">
|
<TabControl ItemsSource="{Binding Items}" DisplayMemberPath="DisplayName" Style="{StaticResource MaterialDesignTabControl}">
|
||||||
<Grid>
|
<TabControl.ContentTemplate>
|
||||||
<!-- Use tabs for multiple properties only, only one of these VMs is set -->
|
<DataTemplate>
|
||||||
<ContentControl s:View.Model="{Binding DataBindingsTabsViewModel}" />
|
<ContentControl s:View.Model="{Binding}" TextElement.Foreground="{DynamicResource MaterialDesignBody}" />
|
||||||
<ContentControl s:View.Model="{Binding DataBindingViewModel}" />
|
</DataTemplate>
|
||||||
</Grid>
|
</TabControl.ContentTemplate>
|
||||||
|
</TabControl>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -6,58 +6,27 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
||||||
{
|
{
|
||||||
public class DataBindingsViewModel : PropertyChangedBase, IDisposable
|
public class DataBindingsViewModel<T> : Conductor<IDataBindingViewModel>.Collection.AllActive
|
||||||
{
|
{
|
||||||
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
|
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
|
||||||
private DataBindingsTabsViewModel _dataBindingsTabsViewModel;
|
|
||||||
private DataBindingViewModel _dataBindingViewModel;
|
public DataBindingsViewModel(LayerProperty<T> layerProperty, IDataBindingsVmFactory dataBindingsVmFactory)
|
||||||
|
|
||||||
public DataBindingsViewModel(BaseLayerProperty layerProperty, IDataBindingsVmFactory dataBindingsVmFactory)
|
|
||||||
{
|
{
|
||||||
_dataBindingsVmFactory = dataBindingsVmFactory;
|
_dataBindingsVmFactory = dataBindingsVmFactory;
|
||||||
LayerProperty = layerProperty;
|
LayerProperty = layerProperty;
|
||||||
Initialise();
|
Initialise();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseLayerProperty LayerProperty { get; }
|
public LayerProperty<T> LayerProperty { get; }
|
||||||
|
|
||||||
public DataBindingViewModel DataBindingViewModel
|
|
||||||
{
|
|
||||||
get => _dataBindingViewModel;
|
|
||||||
set => SetAndNotify(ref _dataBindingViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataBindingsTabsViewModel DataBindingsTabsViewModel
|
|
||||||
{
|
|
||||||
get => _dataBindingsTabsViewModel;
|
|
||||||
set => SetAndNotify(ref _dataBindingsTabsViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Initialise()
|
private void Initialise()
|
||||||
{
|
{
|
||||||
DataBindingViewModel?.Dispose();
|
var registrations = LayerProperty.GetAllDataBindingRegistrations();
|
||||||
DataBindingViewModel = null;
|
|
||||||
DataBindingsTabsViewModel = null;
|
|
||||||
|
|
||||||
var registrations = LayerProperty.DataBindingRegistrations;
|
|
||||||
if (registrations == null || registrations.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Create a data binding VM for each data bindable property. These VMs will be responsible for retrieving
|
// Create a data binding VM for each data bindable property. These VMs will be responsible for retrieving
|
||||||
// and creating the actual data bindings
|
// and creating the actual data bindings
|
||||||
if (registrations.Count == 1)
|
foreach (var registration in registrations)
|
||||||
DataBindingViewModel = _dataBindingsVmFactory.DataBindingViewModel(registrations.First());
|
ActivateItem(_dataBindingsVmFactory.DataBindingViewModel(registration));
|
||||||
else
|
|
||||||
{
|
|
||||||
DataBindingsTabsViewModel = new DataBindingsTabsViewModel();
|
|
||||||
foreach (var registration in registrations)
|
|
||||||
DataBindingsTabsViewModel.Tabs.Add(_dataBindingsVmFactory.DataBindingViewModel(registration));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
DataBindingViewModel?.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,28 +289,26 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
SelectedLayer.LayerBrushUpdated += SelectedLayerOnLayerBrushUpdated;
|
SelectedLayer.LayerBrushUpdated += SelectedLayerOnLayerBrushUpdated;
|
||||||
|
|
||||||
// Add the built-in root groups of the layer
|
// Add the built-in root groups of the layer
|
||||||
var generalAttribute = Attribute.GetCustomAttribute(
|
LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.General));
|
||||||
SelectedLayer.GetType().GetProperty(nameof(SelectedLayer.General)),
|
LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.Transform));
|
||||||
typeof(PropertyGroupDescriptionAttribute)
|
|
||||||
);
|
|
||||||
var transformAttribute = Attribute.GetCustomAttribute(
|
|
||||||
SelectedLayer.GetType().GetProperty(nameof(SelectedLayer.Transform)),
|
|
||||||
typeof(PropertyGroupDescriptionAttribute)
|
|
||||||
);
|
|
||||||
LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.General, (PropertyGroupDescriptionAttribute) generalAttribute));
|
|
||||||
LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.Transform, (PropertyGroupDescriptionAttribute) transformAttribute));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeViewModel = _layerPropertyVmFactory.TreeViewModel(this, LayerPropertyGroups);
|
TreeViewModel = _layerPropertyVmFactory.TreeViewModel(this, LayerPropertyGroups);
|
||||||
|
|
||||||
TimelineViewModel?.Dispose();
|
DeactivateItem(TimelineViewModel);
|
||||||
|
DeactivateItem(StartTimelineSegmentViewModel);
|
||||||
|
DeactivateItem(MainTimelineSegmentViewModel);
|
||||||
|
DeactivateItem(EndTimelineSegmentViewModel);
|
||||||
|
|
||||||
TimelineViewModel = _layerPropertyVmFactory.TimelineViewModel(this, LayerPropertyGroups);
|
TimelineViewModel = _layerPropertyVmFactory.TimelineViewModel(this, LayerPropertyGroups);
|
||||||
|
ActivateItem(TimelineViewModel);
|
||||||
|
|
||||||
StartTimelineSegmentViewModel?.Dispose();
|
StartTimelineSegmentViewModel?.Dispose();
|
||||||
StartTimelineSegmentViewModel = new TimelineSegmentViewModel(ProfileEditorService, SegmentViewModelType.Start);
|
StartTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.Start, LayerPropertyGroups);
|
||||||
MainTimelineSegmentViewModel?.Dispose();
|
MainTimelineSegmentViewModel?.Dispose();
|
||||||
MainTimelineSegmentViewModel = new TimelineSegmentViewModel(ProfileEditorService, SegmentViewModelType.Main);
|
MainTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.Main, LayerPropertyGroups);
|
||||||
EndTimelineSegmentViewModel?.Dispose();
|
EndTimelineSegmentViewModel?.Dispose();
|
||||||
EndTimelineSegmentViewModel = new TimelineSegmentViewModel(ProfileEditorService, SegmentViewModelType.End);
|
EndTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.End, LayerPropertyGroups);
|
||||||
|
|
||||||
ApplyLayerBrush();
|
ApplyLayerBrush();
|
||||||
ApplyEffects();
|
ApplyEffects();
|
||||||
@ -346,19 +344,19 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
|
|
||||||
if (SelectedLayer.LayerBrush != null)
|
if (SelectedLayer.LayerBrush != null)
|
||||||
{
|
{
|
||||||
// Add the rout group of the brush
|
// TODO: wat?
|
||||||
|
// Add the root group of the brush
|
||||||
// The root group of the brush has no attribute so let's pull one out of our sleeve
|
// The root group of the brush has no attribute so let's pull one out of our sleeve
|
||||||
var brushDescription = new PropertyGroupDescriptionAttribute
|
var brushDescription = new PropertyGroupDescriptionAttribute
|
||||||
{
|
{
|
||||||
Name = SelectedLayer.LayerBrush.Descriptor.DisplayName,
|
Name = SelectedLayer.LayerBrush.Descriptor.DisplayName,
|
||||||
Description = SelectedLayer.LayerBrush.Descriptor.Description
|
Description = SelectedLayer.LayerBrush.Descriptor.Description
|
||||||
};
|
};
|
||||||
_brushPropertyGroup = _layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.LayerBrush.BaseProperties, brushDescription);
|
_brushPropertyGroup = _layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.LayerBrush.BaseProperties);
|
||||||
LayerPropertyGroups.Add(_brushPropertyGroup);
|
LayerPropertyGroups.Add(_brushPropertyGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
SortProperties();
|
SortProperties();
|
||||||
TimelineViewModel.Update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyEffects()
|
private void ApplyEffects()
|
||||||
@ -382,18 +380,18 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
if (LayerPropertyGroups.Any(l => l.LayerPropertyGroup.LayerEffect == layerEffect))
|
if (LayerPropertyGroups.Any(l => l.LayerPropertyGroup.LayerEffect == layerEffect))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Add the rout group of the brush
|
// TODO: wat?
|
||||||
|
// Add the root group of the brush
|
||||||
// The root group of the brush has no attribute so let's pull one out of our sleeve
|
// The root group of the brush has no attribute so let's pull one out of our sleeve
|
||||||
var brushDescription = new PropertyGroupDescriptionAttribute
|
var brushDescription = new PropertyGroupDescriptionAttribute
|
||||||
{
|
{
|
||||||
Name = layerEffect.Descriptor.DisplayName,
|
Name = layerEffect.Descriptor.DisplayName,
|
||||||
Description = layerEffect.Descriptor.Description
|
Description = layerEffect.Descriptor.Description
|
||||||
};
|
};
|
||||||
LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerEffect.BaseProperties, brushDescription));
|
LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerEffect.BaseProperties));
|
||||||
}
|
}
|
||||||
|
|
||||||
SortProperties();
|
SortProperties();
|
||||||
TimelineViewModel.Update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SortProperties()
|
private void SortProperties()
|
||||||
@ -422,7 +420,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
LayerPropertyGroups.Move(LayerPropertyGroups.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count);
|
LayerPropertyGroups.Move(LayerPropertyGroups.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Drag and drop
|
#region Drag and drop
|
||||||
@ -437,8 +435,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
var source = dropInfo.Data as LayerPropertyGroupViewModel;
|
var source = dropInfo.Data as LayerPropertyGroupViewModel;
|
||||||
var target = dropInfo.TargetItem as LayerPropertyGroupViewModel;
|
var target = dropInfo.TargetItem as LayerPropertyGroupViewModel;
|
||||||
|
|
||||||
if (source == target ||
|
if (source == target ||
|
||||||
target?.TreeGroupViewModel.GroupType != LayerEffectRoot ||
|
target?.TreeGroupViewModel.GroupType != LayerEffectRoot ||
|
||||||
source?.TreeGroupViewModel.GroupType != LayerEffectRoot)
|
source?.TreeGroupViewModel.GroupType != LayerEffectRoot)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -557,13 +555,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
|
|
||||||
private TimeSpan CalculateEndTime()
|
private TimeSpan CalculateEndTime()
|
||||||
{
|
{
|
||||||
var keyframeTimes = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframePositions(false)).ToList();
|
var keyframeViewModels = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframeViewModels(false)).ToList();
|
||||||
|
|
||||||
// If there are no keyframes, don't stop at all
|
// If there are no keyframes, don't stop at all
|
||||||
if (!keyframeTimes.Any())
|
if (!keyframeViewModels.Any())
|
||||||
return TimeSpan.MaxValue;
|
return TimeSpan.MaxValue;
|
||||||
// If there are keyframes, stop after the last keyframe + 10 sec
|
// If there are keyframes, stop after the last keyframe + 10 sec
|
||||||
return keyframeTimes.Max().Add(TimeSpan.FromSeconds(10));
|
return keyframeViewModels.Max(k => k.Position).Add(TimeSpan.FromSeconds(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||||
@ -620,7 +618,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
// If holding down shift, snap to the closest segment or keyframe
|
// If holding down shift, snap to the closest segment or keyframe
|
||||||
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
|
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
|
||||||
{
|
{
|
||||||
var snapTimes = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframePositions(true)).ToList();
|
var snapTimes = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframeViewModels(true)).Select(k => k.Position).ToList();
|
||||||
var snappedTime = ProfileEditorService.SnapToTimeline(newTime, TimeSpan.FromMilliseconds(1000f / ProfileEditorService.PixelsPerSecond * 5), true, false, snapTimes);
|
var snappedTime = ProfileEditorService.SnapToTimeline(newTime, TimeSpan.FromMilliseconds(1000f / ProfileEditorService.PixelsPerSecond * 5), true, false, snapTimes);
|
||||||
ProfileEditorService.CurrentTime = snappedTime;
|
ProfileEditorService.CurrentTime = snappedTime;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -82,21 +82,54 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
NotifyOfPropertyChange(nameof(IsExpanded));
|
NotifyOfPropertyChange(nameof(IsExpanded));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TimeSpan> GetAllKeyframePositions(bool expandedOnly)
|
public List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels(bool expandedOnly)
|
||||||
{
|
{
|
||||||
var result = new List<TimeSpan>();
|
var result = new List<ITimelineKeyframeViewModel>();
|
||||||
if (expandedOnly == IsExpanded)
|
if (expandedOnly == IsExpanded)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
foreach (var child in Children)
|
foreach (var child in Children)
|
||||||
{
|
{
|
||||||
if (child is LayerPropertyViewModel layerPropertyViewModel)
|
if (child is LayerPropertyViewModel layerPropertyViewModel)
|
||||||
result.AddRange(layerPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframePositions());
|
result.AddRange(layerPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframeViewModels());
|
||||||
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
|
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
|
||||||
result.AddRange(layerPropertyGroupViewModel.GetAllKeyframePositions(expandedOnly));
|
result.AddRange(layerPropertyGroupViewModel.GetAllKeyframeViewModels(expandedOnly));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the keyframes between the <paramref name="start"/> and <paramref name="end"/> position from this property group
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">The position at which to start removing keyframes, if null this will start at the first keyframe</param>
|
||||||
|
/// <param name="end">The position at which to start removing keyframes, if null this will end at the last keyframe</param>
|
||||||
|
public virtual void WipeKeyframes(TimeSpan? start, TimeSpan? end)
|
||||||
|
{
|
||||||
|
foreach (var child in Children)
|
||||||
|
{
|
||||||
|
if (child is LayerPropertyViewModel layerPropertyViewModel)
|
||||||
|
layerPropertyViewModel.TimelinePropertyViewModel.WipeKeyframes(start, end);
|
||||||
|
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
|
||||||
|
layerPropertyGroupViewModel.WipeKeyframes(start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shifts the keyframes between the <paramref name="start"/> and <paramref name="end"/> position by the provided <paramref name="amount"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">The position at which to start shifting keyframes, if null this will start at the first keyframe</param>
|
||||||
|
/// <param name="end">The position at which to start shifting keyframes, if null this will end at the last keyframe</param>
|
||||||
|
/// <param name="amount">The amount to shift the keyframes for</param>
|
||||||
|
public void ShiftKeyframes(TimeSpan? start, TimeSpan? end, TimeSpan amount)
|
||||||
|
{
|
||||||
|
foreach (var child in Children)
|
||||||
|
{
|
||||||
|
if (child is LayerPropertyViewModel layerPropertyViewModel)
|
||||||
|
layerPropertyViewModel.TimelinePropertyViewModel.ShiftKeyframes(start, end, amount);
|
||||||
|
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
|
||||||
|
layerPropertyGroupViewModel.ShiftKeyframes(start, end, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,8 +41,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
{
|
{
|
||||||
KeyframePositions.Clear();
|
KeyframePositions.Clear();
|
||||||
KeyframePositions.AddRange(LayerPropertyGroupViewModel
|
KeyframePositions.AddRange(LayerPropertyGroupViewModel
|
||||||
.GetAllKeyframePositions(false)
|
.GetAllKeyframeViewModels(false)
|
||||||
.Select(p => p.TotalSeconds * _profileEditorService.PixelsPerSecond));
|
.Select(p => p.Position.TotalSeconds * _profileEditorService.PixelsPerSecond));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,7 +7,7 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
||||||
{
|
{
|
||||||
public class TimelineKeyframeViewModel<T> : Screen, IDisposable
|
public class TimelineKeyframeViewModel<T> : Screen, ITimelineKeyframeViewModel
|
||||||
{
|
{
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
|
|
||||||
@ -31,12 +31,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
set => SetAndNotify(ref _easingViewModels, value);
|
set => SetAndNotify(ref _easingViewModels, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSelected
|
|
||||||
{
|
|
||||||
get => _isSelected;
|
|
||||||
set => SetAndNotify(ref _isSelected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double X
|
public double X
|
||||||
{
|
{
|
||||||
get => _x;
|
get => _x;
|
||||||
@ -49,6 +43,14 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
set => SetAndNotify(ref _timestamp, value);
|
set => SetAndNotify(ref _timestamp, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get => _isSelected;
|
||||||
|
set => SetAndNotify(ref _isSelected, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSpan Position => LayerPropertyKeyframe.Position;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
LayerPropertyKeyframe.PropertyChanged -= LayerPropertyKeyframeOnPropertyChanged;
|
LayerPropertyKeyframe.PropertyChanged -= LayerPropertyKeyframeOnPropertyChanged;
|
||||||
@ -110,9 +112,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
_offset = null;
|
_offset = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveOffsetToKeyframe(TimelineKeyframeViewModel<T> keyframeViewModel)
|
public void SaveOffsetToKeyframe(ITimelineKeyframeViewModel source)
|
||||||
{
|
{
|
||||||
if (keyframeViewModel == this)
|
if (source == this)
|
||||||
{
|
{
|
||||||
_offset = null;
|
_offset = null;
|
||||||
return;
|
return;
|
||||||
@ -121,15 +123,15 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
if (_offset != null)
|
if (_offset != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_offset = LayerPropertyKeyframe.Position - keyframeViewModel.LayerPropertyKeyframe.Position;
|
_offset = LayerPropertyKeyframe.Position - source.Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyOffsetToKeyframe(TimelineKeyframeViewModel<T> keyframeViewModel)
|
public void ApplyOffsetToKeyframe(ITimelineKeyframeViewModel source)
|
||||||
{
|
{
|
||||||
if (keyframeViewModel == this || _offset == null)
|
if (source == this || _offset == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdatePosition(keyframeViewModel.LayerPropertyKeyframe.Position + _offset.Value);
|
UpdatePosition(source.Position + _offset.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdatePosition(TimeSpan position)
|
public void UpdatePosition(TimeSpan position)
|
||||||
@ -148,6 +150,18 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
|
|
||||||
#region Context menu actions
|
#region Context menu actions
|
||||||
|
|
||||||
|
public void ContextMenuOpening()
|
||||||
|
{
|
||||||
|
CreateEasingViewModels();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ContextMenuClosing()
|
||||||
|
{
|
||||||
|
foreach (var timelineEasingViewModel in EasingViewModels)
|
||||||
|
timelineEasingViewModel.EasingModeSelected -= TimelineEasingViewModelOnEasingModeSelected;
|
||||||
|
EasingViewModels.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public void Copy()
|
public void Copy()
|
||||||
{
|
{
|
||||||
var newKeyframe = new LayerPropertyKeyframe<T>(
|
var newKeyframe = new LayerPropertyKeyframe<T>(
|
||||||
@ -180,4 +194,26 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ITimelineKeyframeViewModel : IScreen, IDisposable
|
||||||
|
{
|
||||||
|
bool IsSelected { get; set; }
|
||||||
|
TimeSpan Position { get; }
|
||||||
|
|
||||||
|
#region Movement
|
||||||
|
|
||||||
|
void SaveOffsetToKeyframe(ITimelineKeyframeViewModel source);
|
||||||
|
void ApplyOffsetToKeyframe(ITimelineKeyframeViewModel source);
|
||||||
|
void UpdatePosition(TimeSpan position);
|
||||||
|
void ReleaseMovement();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Context menu actions
|
||||||
|
|
||||||
|
void Copy();
|
||||||
|
void Delete();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -21,9 +21,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
LayerPropertyViewModel = layerPropertyViewModel;
|
LayerPropertyViewModel = layerPropertyViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TimeSpan> GetAllKeyframePositions()
|
public List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels()
|
||||||
{
|
{
|
||||||
return LayerProperty.Keyframes.Select(k => k.Position).ToList();
|
return Items.Cast<ITimelineKeyframeViewModel>().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateKeyframes()
|
private void UpdateKeyframes()
|
||||||
@ -49,6 +49,30 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
timelineKeyframeViewModel.Update();
|
timelineKeyframeViewModel.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WipeKeyframes(TimeSpan? start, TimeSpan? end)
|
||||||
|
{
|
||||||
|
start ??= TimeSpan.Zero;
|
||||||
|
end ??= TimeSpan.MaxValue;
|
||||||
|
|
||||||
|
var toShift = LayerProperty.Keyframes.Where(k => k.Position >= start && k.Position <= end).ToList();
|
||||||
|
foreach (var keyframe in toShift)
|
||||||
|
LayerProperty.RemoveKeyframe(keyframe);
|
||||||
|
|
||||||
|
UpdateKeyframes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShiftKeyframes(TimeSpan? start, TimeSpan? end, TimeSpan amount)
|
||||||
|
{
|
||||||
|
start ??= TimeSpan.Zero;
|
||||||
|
end ??= TimeSpan.MaxValue;
|
||||||
|
|
||||||
|
var toShift = LayerProperty.Keyframes.Where(k => k.Position >= start && k.Position <= end).ToList();
|
||||||
|
foreach (var keyframe in toShift)
|
||||||
|
keyframe.Position += amount;
|
||||||
|
|
||||||
|
UpdateKeyframes();
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -56,6 +80,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
|
|
||||||
public interface ITimelinePropertyViewModel : IScreen, IDisposable
|
public interface ITimelinePropertyViewModel : IScreen, IDisposable
|
||||||
{
|
{
|
||||||
List<TimeSpan> GetAllKeyframePositions();
|
List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels();
|
||||||
|
void WipeKeyframes(TimeSpan? start, TimeSpan? end);
|
||||||
|
void ShiftKeyframes(TimeSpan? start, TimeSpan? end, TimeSpan amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18,10 +18,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
private bool _showRepeatButton;
|
private bool _showRepeatButton;
|
||||||
private bool _showSegmentName;
|
private bool _showSegmentName;
|
||||||
|
|
||||||
public TimelineSegmentViewModel(IProfileEditorService profileEditorService, SegmentViewModelType segment)
|
public TimelineSegmentViewModel(SegmentViewModelType segment, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups,
|
||||||
|
IProfileEditorService profileEditorService)
|
||||||
{
|
{
|
||||||
ProfileEditorService = profileEditorService;
|
ProfileEditorService = profileEditorService;
|
||||||
Segment = segment;
|
Segment = segment;
|
||||||
|
LayerPropertyGroups = layerPropertyGroups;
|
||||||
SelectedProfileElement = ProfileEditorService.SelectedProfileElement;
|
SelectedProfileElement = ProfileEditorService.SelectedProfileElement;
|
||||||
|
|
||||||
switch (Segment)
|
switch (Segment)
|
||||||
@ -47,6 +49,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
public RenderProfileElement SelectedProfileElement { get; }
|
public RenderProfileElement SelectedProfileElement { get; }
|
||||||
|
|
||||||
public SegmentViewModelType Segment { get; }
|
public SegmentViewModelType Segment { get; }
|
||||||
|
public BindableCollection<LayerPropertyGroupViewModel> LayerPropertyGroups { get; }
|
||||||
public IProfileEditorService ProfileEditorService { get; }
|
public IProfileEditorService ProfileEditorService { get; }
|
||||||
public string ToolTip { get; }
|
public string ToolTip { get; }
|
||||||
|
|
||||||
@ -130,7 +133,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
|
|
||||||
public void DisableSegment()
|
public void DisableSegment()
|
||||||
{
|
{
|
||||||
var keyframes = SelectedProfileElement.GetAllKeyframes();
|
|
||||||
var startSegmentEnd = SelectedProfileElement.StartSegmentLength;
|
var startSegmentEnd = SelectedProfileElement.StartSegmentLength;
|
||||||
var mainSegmentEnd = SelectedProfileElement.StartSegmentLength + SelectedProfileElement.MainSegmentLength;
|
var mainSegmentEnd = SelectedProfileElement.StartSegmentLength + SelectedProfileElement.MainSegmentLength;
|
||||||
|
|
||||||
@ -139,22 +141,19 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
if (Segment == SegmentViewModelType.Start)
|
if (Segment == SegmentViewModelType.Start)
|
||||||
{
|
{
|
||||||
// Remove keyframes that fall in this segment
|
// Remove keyframes that fall in this segment
|
||||||
foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position <= startSegmentEnd))
|
WipeKeyframes(null, startSegmentEnd);
|
||||||
baseLayerPropertyKeyframe.Remove();
|
|
||||||
SelectedProfileElement.StartSegmentLength = TimeSpan.Zero;
|
SelectedProfileElement.StartSegmentLength = TimeSpan.Zero;
|
||||||
}
|
}
|
||||||
else if (Segment == SegmentViewModelType.Main)
|
else if (Segment == SegmentViewModelType.Main)
|
||||||
{
|
{
|
||||||
// Remove keyframes that fall in this segment
|
// Remove keyframes that fall in this segment
|
||||||
foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position > startSegmentEnd && k.Position <= mainSegmentEnd))
|
WipeKeyframes(startSegmentEnd, startSegmentEnd);
|
||||||
baseLayerPropertyKeyframe.Remove();
|
|
||||||
SelectedProfileElement.MainSegmentLength = TimeSpan.Zero;
|
SelectedProfileElement.MainSegmentLength = TimeSpan.Zero;
|
||||||
}
|
}
|
||||||
else if (Segment == SegmentViewModelType.End)
|
else if (Segment == SegmentViewModelType.End)
|
||||||
{
|
{
|
||||||
// Remove keyframes that fall in this segment
|
// Remove keyframes that fall in this segment
|
||||||
foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position > mainSegmentEnd))
|
WipeKeyframes(mainSegmentEnd, null);
|
||||||
baseLayerPropertyKeyframe.Remove();
|
|
||||||
SelectedProfileElement.EndSegmentLength = TimeSpan.Zero;
|
SelectedProfileElement.EndSegmentLength = TimeSpan.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,8 +187,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
else if (Segment == SegmentViewModelType.End)
|
else if (Segment == SegmentViewModelType.End)
|
||||||
segmentEnd = SelectedProfileElement.TimelineLength;
|
segmentEnd = SelectedProfileElement.TimelineLength;
|
||||||
|
|
||||||
foreach (var baseLayerPropertyKeyframe in SelectedProfileElement.GetAllKeyframes().Where(k => k.Position > segmentEnd))
|
ShiftKeyframes(segmentEnd, null, amount);
|
||||||
baseLayerPropertyKeyframe.Position += amount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SegmentMouseDown(object sender, MouseButtonEventArgs e)
|
public void SegmentMouseDown(object sender, MouseButtonEventArgs e)
|
||||||
@ -227,7 +225,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
|
|
||||||
// If holding down shift, snap to the closest element on the timeline
|
// If holding down shift, snap to the closest element on the timeline
|
||||||
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
|
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
|
||||||
newTime = ProfileEditorService.SnapToTimeline(newTime, TimeSpan.FromMilliseconds(1000f / ProfileEditorService.PixelsPerSecond * 5), false, true, true);
|
{
|
||||||
|
var keyframeTimes = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframeViewModels(true)).Select(k => k.Position).ToList();
|
||||||
|
newTime = ProfileEditorService.SnapToTimeline(newTime, TimeSpan.FromMilliseconds(1000f / ProfileEditorService.PixelsPerSecond * 5), false, true, keyframeTimes);
|
||||||
|
}
|
||||||
// If holding down control, round to the closest 50ms
|
// If holding down control, round to the closest 50ms
|
||||||
else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
||||||
newTime = TimeSpan.FromMilliseconds(Math.Round(newTime.TotalMilliseconds / 50.0) * 50.0);
|
newTime = TimeSpan.FromMilliseconds(Math.Round(newTime.TotalMilliseconds / 50.0) * 50.0);
|
||||||
@ -272,7 +273,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
NotifyOfPropertyChange(nameof(RepeatSegment));
|
NotifyOfPropertyChange(nameof(RepeatSegment));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void ProfileEditorServiceOnPixelsPerSecondChanged(object? sender, EventArgs e)
|
private void ProfileEditorServiceOnPixelsPerSecondChanged(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
NotifyOfPropertyChange(nameof(SegmentWidth));
|
NotifyOfPropertyChange(nameof(SegmentWidth));
|
||||||
@ -291,6 +291,18 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
ShowRepeatButton = SegmentWidth > 45 && IsMainSegment;
|
ShowRepeatButton = SegmentWidth > 45 && IsMainSegment;
|
||||||
ShowDisableButton = SegmentWidth > 25;
|
ShowDisableButton = SegmentWidth > 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WipeKeyframes(TimeSpan? start, TimeSpan? end)
|
||||||
|
{
|
||||||
|
foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
|
||||||
|
layerPropertyGroupViewModel.WipeKeyframes(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShiftKeyframes(TimeSpan? start, TimeSpan? end, TimeSpan amount)
|
||||||
|
{
|
||||||
|
foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
|
||||||
|
layerPropertyGroupViewModel.ShiftKeyframes(start, end, amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SegmentViewModelType
|
public enum SegmentViewModelType
|
||||||
|
|||||||
@ -14,7 +14,7 @@ using Stylet;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
||||||
{
|
{
|
||||||
public class TimelineViewModel : PropertyChangedBase, IViewAware, IDisposable
|
public class TimelineViewModel : Screen, IDisposable
|
||||||
{
|
{
|
||||||
private readonly LayerPropertiesViewModel _layerPropertiesViewModel;
|
private readonly LayerPropertiesViewModel _layerPropertiesViewModel;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
@ -105,7 +105,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
// if (e.LeftButton == MouseButtonState.Released)
|
// if (e.LeftButton == MouseButtonState.Released)
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
var viewModel = (sender as Ellipse)?.DataContext as TimelineKeyframeViewModel;
|
var viewModel = (sender as Ellipse)?.DataContext as ITimelineKeyframeViewModel;
|
||||||
if (viewModel == null)
|
if (viewModel == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
|
|
||||||
public void KeyframeMouseMove(object sender, MouseEventArgs e)
|
public void KeyframeMouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
var viewModel = (sender as Ellipse)?.DataContext as TimelineKeyframeViewModel;
|
var viewModel = (sender as Ellipse)?.DataContext as ITimelineKeyframeViewModel;
|
||||||
if (viewModel == null)
|
if (viewModel == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -142,24 +142,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
|
|
||||||
#region Context menu actions
|
#region Context menu actions
|
||||||
|
|
||||||
public void ContextMenuOpening(object sender, ContextMenuEventArgs e)
|
public void Copy(ITimelineKeyframeViewModel viewModel)
|
||||||
{
|
|
||||||
var viewModel = (sender as Ellipse)?.DataContext as TimelineKeyframeViewModel;
|
|
||||||
viewModel?.CreateEasingViewModels();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ContextMenuClosing(object sender, ContextMenuEventArgs e)
|
|
||||||
{
|
|
||||||
var viewModel = (sender as Ellipse)?.DataContext as TimelineKeyframeViewModel;
|
|
||||||
viewModel?.EasingViewModels.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Copy(TimelineKeyframeViewModel viewModel)
|
|
||||||
{
|
{
|
||||||
viewModel.Copy();
|
viewModel.Copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Delete(TimelineKeyframeViewModel viewModel)
|
public void Delete(ITimelineKeyframeViewModel viewModel)
|
||||||
{
|
{
|
||||||
viewModel.Delete();
|
viewModel.Delete();
|
||||||
}
|
}
|
||||||
@ -198,7 +186,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
|
|
||||||
#region Keyframe movement
|
#region Keyframe movement
|
||||||
|
|
||||||
public void MoveSelectedKeyframes(TimeSpan cursorTime, TimelineKeyframeViewModel sourceKeyframeViewModel)
|
public void MoveSelectedKeyframes(TimeSpan cursorTime, ITimelineKeyframeViewModel sourceKeyframeViewModel)
|
||||||
{
|
{
|
||||||
// Ensure the selection rectangle doesn't show, the view isn't aware of different types of dragging
|
// Ensure the selection rectangle doesn't show, the view isn't aware of different types of dragging
|
||||||
SelectionRectangle.Rect = new Rect();
|
SelectionRectangle.Rect = new Rect();
|
||||||
@ -214,8 +202,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
TimeSpan.FromMilliseconds(1000f / _profileEditorService.PixelsPerSecond * 5),
|
TimeSpan.FromMilliseconds(1000f / _profileEditorService.PixelsPerSecond * 5),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
keyframeViewModels.Where(k => k != sourceKeyframeViewModel).Select(k => k.Position).ToList()
|
||||||
sourceKeyframeViewModel.BaseLayerPropertyKeyframe
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +254,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
SelectionRectangle.Rect = selectedRect;
|
SelectionRectangle.Rect = selectedRect;
|
||||||
|
|
||||||
var keyframeViewModels = GetAllKeyframeViewModels();
|
var keyframeViewModels = GetAllKeyframeViewModels();
|
||||||
var selectedKeyframes = HitTestUtilities.GetHitViewModels<TimelineKeyframeViewModel>((Visual) sender, SelectionRectangle);
|
var selectedKeyframes = HitTestUtilities.GetHitViewModels<ITimelineKeyframeViewModel>((Visual) sender, SelectionRectangle);
|
||||||
foreach (var keyframeViewModel in keyframeViewModels)
|
foreach (var keyframeViewModel in keyframeViewModels)
|
||||||
keyframeViewModel.IsSelected = selectedKeyframes.Contains(keyframeViewModel);
|
keyframeViewModel.IsSelected = selectedKeyframes.Contains(keyframeViewModel);
|
||||||
|
|
||||||
@ -287,7 +274,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectKeyframe(TimelineKeyframeViewModel clicked, bool selectBetween, bool toggle)
|
public void SelectKeyframe(ITimelineKeyframeViewModel clicked, bool selectBetween, bool toggle)
|
||||||
{
|
{
|
||||||
var keyframeViewModels = GetAllKeyframeViewModels();
|
var keyframeViewModels = GetAllKeyframeViewModels();
|
||||||
if (selectBetween)
|
if (selectBetween)
|
||||||
@ -329,33 +316,15 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TimelineKeyframeViewModel> GetAllKeyframeViewModels()
|
private List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels()
|
||||||
{
|
{
|
||||||
var viewModels = new List<LayerPropertyBaseViewModel>();
|
var viewModels = new List<ITimelineKeyframeViewModel>();
|
||||||
foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
|
foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
|
||||||
viewModels.AddRange(layerPropertyGroupViewModel.GetAllChildren());
|
viewModels.AddRange(layerPropertyGroupViewModel.GetAllKeyframeViewModels(false));
|
||||||
|
|
||||||
var keyframes = viewModels.Where(vm => vm is LayerPropertyViewModel)
|
return viewModels;
|
||||||
.SelectMany(vm => ((LayerPropertyViewModel) vm).TimelinePropertyBaseViewModel.TimelineKeyframeViewModels)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return keyframes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IViewAware
|
|
||||||
|
|
||||||
public void AttachView(UIElement view)
|
|
||||||
{
|
|
||||||
if (View != null)
|
|
||||||
throw new InvalidOperationException(string.Format("Tried to attach View {0} to ViewModel {1}, but it already has a view attached", view.GetType().Name, GetType().Name));
|
|
||||||
|
|
||||||
View = view;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UIElement View { get; set; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,7 +3,6 @@ using System.Linq;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.UI.Properties;
|
using Artemis.UI.Properties;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
|
||||||
@ -11,13 +10,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools
|
|||||||
{
|
{
|
||||||
public class SelectionToolViewModel : VisualizationToolViewModel
|
public class SelectionToolViewModel : VisualizationToolViewModel
|
||||||
{
|
{
|
||||||
private readonly IRenderElementService _renderElementService;
|
|
||||||
private Rect _dragRectangle;
|
private Rect _dragRectangle;
|
||||||
|
|
||||||
public SelectionToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, IRenderElementService renderElementService)
|
public SelectionToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
|
||||||
: base(profileViewModel, profileEditorService)
|
|
||||||
{
|
{
|
||||||
_renderElementService = renderElementService;
|
|
||||||
using (var stream = new MemoryStream(Resources.aero_crosshair))
|
using (var stream = new MemoryStream(Resources.aero_crosshair))
|
||||||
{
|
{
|
||||||
Cursor = new Cursor(stream);
|
Cursor = new Cursor(stream);
|
||||||
@ -57,7 +53,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools
|
|||||||
// If no layer selected, apply it to a new layer in the selected folder
|
// If no layer selected, apply it to a new layer in the selected folder
|
||||||
else if (ProfileEditorService.SelectedProfileElement is Folder folder)
|
else if (ProfileEditorService.SelectedProfileElement is Folder folder)
|
||||||
{
|
{
|
||||||
var newLayer = _renderElementService.CreateLayer(folder.Profile, folder, "New layer");
|
var newLayer = new Layer(folder, "New layer");
|
||||||
newLayer.AddLeds(selectedLeds);
|
newLayer.AddLeds(selectedLeds);
|
||||||
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
|
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
|
||||||
ProfileEditorService.UpdateSelectedProfileElement();
|
ProfileEditorService.UpdateSelectedProfileElement();
|
||||||
@ -66,7 +62,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var rootFolder = ProfileEditorService.SelectedProfile.GetRootFolder();
|
var rootFolder = ProfileEditorService.SelectedProfile.GetRootFolder();
|
||||||
var newLayer = _renderElementService.CreateLayer(rootFolder.Profile, rootFolder, "New layer");
|
var newLayer = new Layer(rootFolder, "New layer");
|
||||||
newLayer.AddLeds(selectedLeds);
|
newLayer.AddLeds(selectedLeds);
|
||||||
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
|
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
|
||||||
ProfileEditorService.UpdateSelectedProfileElement();
|
ProfileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user