mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
190 lines
7.8 KiB
C#
190 lines
7.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Artemis.Core;
|
|
using Artemis.Core.LayerBrushes;
|
|
using Artemis.Core.LayerEffects;
|
|
using Artemis.UI.Ninject.Factories;
|
|
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
|
|
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
|
|
using Artemis.UI.Screens.ProfileEditor.Properties.Tree;
|
|
using Artemis.UI.Shared;
|
|
using Artemis.UI.Shared.Services.PropertyInput;
|
|
using DynamicData;
|
|
using DynamicData.Binding;
|
|
|
|
namespace Artemis.UI.Screens.ProfileEditor.Properties;
|
|
|
|
public class PropertyGroupViewModel : PropertyViewModelBase, IDisposable
|
|
{
|
|
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
|
private readonly IPropertyInputService _propertyInputService;
|
|
private bool _hasChildren;
|
|
private bool _isExpanded;
|
|
private bool _isVisible;
|
|
private ReadOnlyObservableCollection<ILayerPropertyKeyframe> _keyframes = null!;
|
|
private IDisposable _keyframeSubscription = null!;
|
|
|
|
public PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, ILayerPropertyVmFactory layerPropertyVmFactory, IPropertyInputService propertyInputService)
|
|
{
|
|
_layerPropertyVmFactory = layerPropertyVmFactory;
|
|
_propertyInputService = propertyInputService;
|
|
LayerPropertyGroup = layerPropertyGroup;
|
|
TreeGroupViewModel = layerPropertyVmFactory.TreeGroupViewModel(this);
|
|
TimelineGroupViewModel = layerPropertyVmFactory.TimelineGroupViewModel(this);
|
|
|
|
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
|
|
_isVisible = !LayerPropertyGroup.IsHidden;
|
|
|
|
PopulateChildren();
|
|
}
|
|
|
|
public PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, ILayerPropertyVmFactory layerPropertyVmFactory, IPropertyInputService propertyInputService, BaseLayerBrush layerBrush)
|
|
{
|
|
_layerPropertyVmFactory = layerPropertyVmFactory;
|
|
_propertyInputService = propertyInputService;
|
|
LayerBrush = layerBrush;
|
|
LayerPropertyGroup = layerPropertyGroup;
|
|
TreeGroupViewModel = layerPropertyVmFactory.TreeGroupViewModel(this);
|
|
TimelineGroupViewModel = layerPropertyVmFactory.TimelineGroupViewModel(this);
|
|
|
|
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
|
|
_isVisible = !LayerPropertyGroup.IsHidden;
|
|
|
|
PopulateChildren();
|
|
}
|
|
|
|
public PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, ILayerPropertyVmFactory layerPropertyVmFactory, IPropertyInputService propertyInputService, BaseLayerEffect layerEffect)
|
|
{
|
|
_layerPropertyVmFactory = layerPropertyVmFactory;
|
|
_propertyInputService = propertyInputService;
|
|
LayerEffect = layerEffect;
|
|
LayerPropertyGroup = layerPropertyGroup;
|
|
TreeGroupViewModel = layerPropertyVmFactory.TreeGroupViewModel(this);
|
|
TimelineGroupViewModel = layerPropertyVmFactory.TimelineGroupViewModel(this);
|
|
|
|
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
|
|
_isVisible = !LayerPropertyGroup.IsHidden;
|
|
|
|
PopulateChildren();
|
|
}
|
|
|
|
public ObservableCollection<PropertyViewModelBase> Children { get; private set; } = null!;
|
|
public LayerPropertyGroup LayerPropertyGroup { get; }
|
|
public BaseLayerBrush? LayerBrush { get; }
|
|
public BaseLayerEffect? LayerEffect { get; }
|
|
|
|
public TreeGroupViewModel TreeGroupViewModel { get; }
|
|
public TimelineGroupViewModel TimelineGroupViewModel { get; }
|
|
|
|
public bool IsVisible
|
|
{
|
|
get => _isVisible;
|
|
set => RaiseAndSetIfChanged(ref _isVisible, value);
|
|
}
|
|
|
|
public bool IsExpanded
|
|
{
|
|
get => _isExpanded;
|
|
set => RaiseAndSetIfChanged(ref _isExpanded, value);
|
|
}
|
|
|
|
public bool HasChildren
|
|
{
|
|
get => _hasChildren;
|
|
set => RaiseAndSetIfChanged(ref _hasChildren, value);
|
|
}
|
|
|
|
public override ReadOnlyObservableCollection<ILayerPropertyKeyframe> Keyframes => _keyframes;
|
|
|
|
public List<ILayerPropertyKeyframe> GetAllKeyframes(bool expandedOnly)
|
|
{
|
|
List<ILayerPropertyKeyframe> result = new();
|
|
if (expandedOnly && !IsExpanded)
|
|
return result;
|
|
|
|
foreach (PropertyViewModelBase child in Children)
|
|
{
|
|
if (child is PropertyViewModel profileElementPropertyViewModel)
|
|
result.AddRange(profileElementPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframes());
|
|
else if (child is PropertyGroupViewModel profileElementPropertyGroupViewModel)
|
|
result.AddRange(profileElementPropertyGroupViewModel.GetAllKeyframes(expandedOnly));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels(bool expandedOnly)
|
|
{
|
|
List<ITimelineKeyframeViewModel> result = new();
|
|
if (expandedOnly && !IsExpanded)
|
|
return result;
|
|
|
|
foreach (PropertyViewModelBase child in Children)
|
|
{
|
|
if (child is PropertyViewModel profileElementPropertyViewModel)
|
|
result.AddRange(profileElementPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframeViewModels());
|
|
else if (child is PropertyGroupViewModel profileElementPropertyGroupViewModel)
|
|
result.AddRange(profileElementPropertyGroupViewModel.GetAllKeyframeViewModels(expandedOnly));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private void PopulateChildren()
|
|
{
|
|
Children = new ObservableCollection<PropertyViewModelBase>();
|
|
|
|
// Get all properties and property groups and create VMs for them
|
|
// The group has methods for getting this without reflection but then we lose the order of the properties as they are defined on the group
|
|
// Sorting is done to ensure properties defined by the Core (such as on layers) are always on top.
|
|
foreach (PropertyInfo propertyInfo in LayerPropertyGroup.GetType().GetProperties().OrderBy(p => p.DeclaringType?.Assembly != Constants.CoreAssembly))
|
|
{
|
|
if (Attribute.IsDefined(propertyInfo, typeof(LayerPropertyIgnoreAttribute)))
|
|
continue;
|
|
|
|
if (typeof(ILayerProperty).IsAssignableFrom(propertyInfo.PropertyType))
|
|
{
|
|
ILayerProperty? value = (ILayerProperty?) propertyInfo.GetValue(LayerPropertyGroup);
|
|
// Ensure a supported input VM was found, otherwise don't add it
|
|
if (value != null && _propertyInputService.CanCreatePropertyInputViewModel(value))
|
|
Children.Add(_layerPropertyVmFactory.PropertyViewModel(value));
|
|
}
|
|
else if (typeof(LayerPropertyGroup).IsAssignableFrom(propertyInfo.PropertyType))
|
|
{
|
|
LayerPropertyGroup? value = (LayerPropertyGroup?) propertyInfo.GetValue(LayerPropertyGroup);
|
|
if (value != null)
|
|
Children.Add(_layerPropertyVmFactory.PropertyGroupViewModel(value));
|
|
}
|
|
}
|
|
|
|
HasChildren = Children.Any(i => i is PropertyViewModel {IsVisible: true} or PropertyGroupViewModel {IsVisible: true});
|
|
_keyframeSubscription = Children
|
|
.ToObservableChangeSet()
|
|
.TransformMany(c => c.Keyframes)
|
|
.Bind(out ReadOnlyObservableCollection<ILayerPropertyKeyframe> keyframes)
|
|
.Subscribe();
|
|
|
|
_keyframes = keyframes;
|
|
}
|
|
|
|
private void LayerPropertyGroupOnVisibilityChanged(object? sender, EventArgs e)
|
|
{
|
|
IsVisible = !LayerPropertyGroup.IsHidden;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Dispose()
|
|
{
|
|
LayerPropertyGroup.VisibilityChanged -= LayerPropertyGroupOnVisibilityChanged;
|
|
foreach (ViewModelBase viewModelBase in Children)
|
|
{
|
|
if (viewModelBase is IDisposable disposable)
|
|
disposable.Dispose();
|
|
}
|
|
|
|
_keyframeSubscription.Dispose();
|
|
}
|
|
} |