Profile editor - Moved layer property input to the Shared UI project

This commit is contained in:
SpoinkyNL committed 2020-06-02 22:23:09 +02:00
1 parent eda57f6d32
commit 92faafe1de
71 files changed
+1211 -434

No files matched your search

@@ -16,6 +16,8 @@ using Artemis.UI.Events;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Events;
using Artemis.UI.Shared.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
@@ -1,18 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using Ninject;
using Ninject.Parameters;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
public class LayerPropertyGroupViewModel : LayerPropertyBaseViewModel
{
public LayerPropertyGroupViewModel(IProfileEditorService profileEditorService, LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription)
public LayerPropertyGroupViewModel(IProfileEditorService profileEditorService, LayerPropertyGroup layerPropertyGroup,
PropertyGroupDescriptionAttribute propertyGroupDescription)
{
ProfileEditorService = profileEditorService;
@@ -43,36 +47,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public TreePropertyGroupViewModel TreePropertyGroupViewModel { get; set; }
public TimelinePropertyGroupViewModel TimelinePropertyGroupViewModel { get; set; }
private void PopulateChildren()
{
// Get all properties and property groups and create VMs for them
foreach (var propertyInfo in LayerPropertyGroup.GetType().GetProperties())
{
var propertyAttribute = (PropertyDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyDescriptionAttribute));
var groupAttribute = (PropertyGroupDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyGroupDescriptionAttribute));
var value = propertyInfo.GetValue(LayerPropertyGroup);
// Create VMs for properties on the group
if (propertyAttribute != null && value is BaseLayerProperty baseLayerProperty)
{
var viewModel = ProfileEditorService.CreateLayerPropertyViewModel(baseLayerProperty, propertyAttribute);
if (viewModel != null)
Children.Add(viewModel);
}
// Create VMs for child groups on this group, resulting in a nested structure
else if (groupAttribute != null && value is LayerPropertyGroup layerPropertyGroup)
{
Children.Add(new LayerPropertyGroupViewModel(ProfileEditorService, layerPropertyGroup, groupAttribute));
}
}
}
public override List<BaseLayerPropertyKeyframe> GetKeyframes(bool expandedOnly)
{
var result = new List<BaseLayerPropertyKeyframe>();
if (expandedOnly && !IsExpanded || LayerPropertyGroup.IsHidden)
return result;
foreach (var layerPropertyBaseViewModel in Children)
result.AddRange(layerPropertyBaseViewModel.GetKeyframes(expandedOnly));
@@ -101,6 +81,48 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
return result;
}
private void PopulateChildren()
{
// Get all properties and property groups and create VMs for them
foreach (var propertyInfo in LayerPropertyGroup.GetType().GetProperties())
{
var propertyAttribute = (PropertyDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyDescriptionAttribute));
var groupAttribute = (PropertyGroupDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyGroupDescriptionAttribute));
var value = propertyInfo.GetValue(LayerPropertyGroup);
// Create VMs for properties on the group
if (propertyAttribute != null && value is BaseLayerProperty baseLayerProperty)
{
var viewModel = CreateLayerPropertyViewModel(baseLayerProperty, propertyAttribute);
if (viewModel != null)
Children.Add(viewModel);
}
// Create VMs for child groups on this group, resulting in a nested structure
else if (groupAttribute != null && value is LayerPropertyGroup layerPropertyGroup)
Children.Add(new LayerPropertyGroupViewModel(ProfileEditorService, layerPropertyGroup, groupAttribute));
}
}
private LayerPropertyBaseViewModel CreateLayerPropertyViewModel(BaseLayerProperty baseLayerProperty, PropertyDescriptionAttribute propertyDescription)
{
// Go through the pain of instantiating a generic type VM now via reflection to make things a lot simpler down the line
var genericType = baseLayerProperty.GetType().Name == typeof(LayerProperty<>).Name
? baseLayerProperty.GetType().GetGenericArguments()[0]
: baseLayerProperty.GetType().BaseType.GetGenericArguments()[0];
// Only create entries for types supported by a tree input VM
if (!genericType.IsEnum && ProfileEditorService.RegisteredPropertyEditors.All(r => r.SupportedType != genericType))
return null;
var genericViewModel = typeof(LayerPropertyViewModel<>).MakeGenericType(genericType);
var parameters = new IParameter[]
{
new ConstructorArgument("layerProperty", baseLayerProperty),
new ConstructorArgument("propertyDescription", propertyDescription)
};
return (LayerPropertyBaseViewModel) ProfileEditorService.Kernel.Get(genericViewModel, parameters);
}
private void LayerPropertyGroupOnVisibilityChanged(object sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(IsVisible));
@@ -2,37 +2,39 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.UI.Exceptions;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.PropertyInput;
using Artemis.UI.Shared.PropertyInput;
using Artemis.UI.Shared.Services.Interfaces;
using Humanizer;
using Ninject;
using Ninject.Parameters;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
public class LayerPropertyViewModel<T> : LayerPropertyViewModel
{
public LayerPropertyViewModel(IProfileEditorService profileEditorService, LayerProperty<T> layerProperty, PropertyDescriptionAttribute propertyDescription)
: base(profileEditorService, layerProperty)
public LayerPropertyViewModel(IProfileEditorService profileEditorService, LayerProperty<T> layerProperty) : base(profileEditorService, layerProperty)
{
LayerProperty = layerProperty;
PropertyDescription = propertyDescription;
TreePropertyViewModel = ProfileEditorService.CreateTreePropertyViewModel(this);
TreePropertyViewModel = CreateTreePropertyViewModel();
TimelinePropertyViewModel = new TimelinePropertyViewModel<T>(this, profileEditorService);
TreePropertyBaseViewModel = TreePropertyViewModel;
TimelinePropertyBaseViewModel = TimelinePropertyViewModel;
// Generate a fallback name if the description does not contain one
if (PropertyDescription.Name == null)
if (LayerProperty.PropertyDescription.Name == null)
{
var propertyInfo = LayerProperty.Parent?.GetType().GetProperties().FirstOrDefault(p => ReferenceEquals(p.GetValue(LayerProperty.Parent), LayerProperty));
if (propertyInfo != null)
PropertyDescription.Name = propertyInfo.Name.Humanize();
LayerProperty.PropertyDescription.Name = propertyInfo.Name.Humanize();
else
PropertyDescription.Name = $"Unknown {typeof(T).Name} property";
LayerProperty.PropertyDescription.Name = $"Unknown {typeof(T).Name} property";
}
LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged;
@@ -69,6 +71,29 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
ProfileEditorService.UpdateProfilePreview();
}
private TreePropertyViewModel<T> CreateTreePropertyViewModel()
{
// Make sure there is a supported property editor VM, unless the type is an enum, then we'll use the EnumPropertyInputViewModel
Type vmType = null;
if (typeof(T).IsEnum)
vmType = typeof(EnumPropertyInputViewModel<>).MakeGenericType(typeof(T));
else
{
var registration = ProfileEditorService.RegisteredPropertyEditors.FirstOrDefault(r => r.SupportedType == typeof(T));
if (registration != null)
vmType = registration.ViewModelType;
}
if (vmType == null)
throw new ArtemisUIException($"Cannot create a tree property view model for type {typeof(T)}, found no matching property editor");
var parameters = new IParameter[]
{
new ConstructorArgument("layerProperty", LayerProperty)
};
return new TreePropertyViewModel<T>(this, (PropertyInputViewModel<T>) ProfileEditorService.Kernel.Get(vmType, parameters), ProfileEditorService);
}
private void LayerPropertyOnVisibilityChanged(object sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(IsVisible));
@@ -86,7 +111,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public IProfileEditorService ProfileEditorService { get; }
public BaseLayerProperty BaseLayerProperty { get; }
public PropertyDescriptionAttribute PropertyDescription { get; protected set; }
public TreePropertyViewModel TreePropertyBaseViewModel { get; set; }
public TimelinePropertyViewModel TimelinePropertyBaseViewModel { get; set; }
}
@@ -5,6 +5,7 @@ using System.Windows.Input;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Utilities;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
@@ -3,6 +3,7 @@ using System.Linq;
using Artemis.UI.Exceptions;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
@@ -1,103 +0,0 @@
using System;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract
{
public abstract class PropertyInputViewModel<T> : ValidatingModelBase, IDisposable
{
private T _inputValue;
protected PropertyInputViewModel(LayerPropertyViewModel<T> layerPropertyViewModel)
{
LayerPropertyViewModel = layerPropertyViewModel;
LayerPropertyViewModel.LayerProperty.Updated += LayerPropertyOnUpdated;
UpdateInputValue();
}
protected PropertyInputViewModel(LayerPropertyViewModel<T> layerPropertyViewModel, IModelValidator validator) : base(validator)
{
LayerPropertyViewModel = layerPropertyViewModel;
LayerPropertyViewModel.LayerProperty.Updated += LayerPropertyOnUpdated;
UpdateInputValue();
}
public LayerPropertyViewModel<T> LayerPropertyViewModel { get; }
public bool InputDragging { get; private set; }
public T InputValue
{
get => _inputValue;
set
{
_inputValue = value;
ApplyInputValue();
}
}
public virtual void Dispose()
{
LayerPropertyViewModel.LayerProperty.Updated -= LayerPropertyOnUpdated;
}
protected virtual void OnInputValueApplied()
{
}
protected virtual void OnInputValueChanged()
{
}
private void LayerPropertyOnUpdated(object sender, EventArgs e)
{
UpdateInputValue();
}
private void UpdateInputValue()
{
// Avoid unnecessary UI updates and validator cycles
if (_inputValue != null && _inputValue.Equals(LayerPropertyViewModel.LayerProperty.CurrentValue) || _inputValue == null && LayerPropertyViewModel.LayerProperty.CurrentValue == null)
return;
// Override the input value
_inputValue = LayerPropertyViewModel.LayerProperty.CurrentValue;
// Notify a change in the input value
OnInputValueChanged();
NotifyOfPropertyChange(nameof(InputValue));
// Force the validator to run with the overridden value
if (Validator != null)
Validate();
}
protected void ApplyInputValue()
{
// Force the validator to run
if (Validator != null)
Validate();
// Only apply the input value to the layer property if the validator found no errors
if (!HasErrors)
LayerPropertyViewModel.SetCurrentValue(_inputValue, !InputDragging);
OnInputValueChanged();
OnInputValueApplied();
}
#region Event handlers
public void InputDragStarted(object sender, EventArgs e)
{
InputDragging = true;
}
public void InputDragEnded(object sender, EventArgs e)
{
InputDragging = false;
LayerPropertyViewModel.ProfileEditorService.UpdateSelectedProfileElement();
}
#endregion
}
}
@@ -1,25 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.BrushPropertyInputView"
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:propertyInput="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type propertyInput:BrushPropertyInputViewModel}}">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 5 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputPrefix}" />
<ComboBox Width="132"
Margin="0 2"
Padding="0 -1"
Height="15"
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
ItemsSource="{Binding Path=ComboboxValues}"
SelectedValuePath="Value"
DisplayMemberPath="Description"
SelectedValue="{Binding Path=InputValue}" />
<TextBlock Margin="5 0 0 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,67 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.Events;
using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.LayerBrush;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
using Artemis.UI.Shared.Utilities;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput
{
public class BrushPropertyInputViewModel : PropertyInputViewModel<LayerBrushReference>
{
private readonly ILayerService _layerService;
private readonly IPluginService _pluginService;
public BrushPropertyInputViewModel(LayerPropertyViewModel<LayerBrushReference> layerPropertyViewModel, ILayerService layerService, IPluginService pluginService)
: base(layerPropertyViewModel)
{
_layerService = layerService;
_pluginService = pluginService;
ComboboxValues = new BindableCollection<ValueDescription>();
_pluginService.PluginLoaded += PluginServiceOnPluginLoaded;
UpdateEnumValues();
}
public BindableCollection<ValueDescription> ComboboxValues { get; }
public void UpdateEnumValues()
{
var layerBrushProviders = _pluginService.GetPluginsOfType<LayerBrushProvider>();
var descriptors = layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors).ToList();
var enumValues = new List<ValueDescription>();
foreach (var layerBrushDescriptor in descriptors)
{
var brushName = layerBrushDescriptor.LayerBrushType.Name;
var brushGuid = layerBrushDescriptor.LayerBrushProvider.PluginInfo.Guid;
if (InputValue != null && InputValue.BrushType == brushName && InputValue.BrushPluginGuid == brushGuid)
enumValues.Add(new ValueDescription {Description = layerBrushDescriptor.DisplayName, Value = InputValue});
else
enumValues.Add(new ValueDescription {Description = layerBrushDescriptor.DisplayName, Value = new LayerBrushReference {BrushType = brushName, BrushPluginGuid = brushGuid}});
}
ComboboxValues.Clear();
ComboboxValues.AddRange(enumValues);
}
public override void Dispose()
{
_pluginService.PluginLoaded -= PluginServiceOnPluginLoaded;
base.Dispose();
}
private void PluginServiceOnPluginLoaded(object sender, PluginEventArgs e)
{
UpdateEnumValues();
}
protected override void OnInputValueApplied()
{
_layerService.InstantiateLayerBrush(LayerPropertyViewModel.LayerProperty.Layer);
}
}
}
@@ -1,22 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.ColorGradientPropertyInputView"
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:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:propertyInput="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="800"
d:DataContext="{d:DesignInstance propertyInput:ColorGradientPropertyInputViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 5 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputPrefix}" />
<controls:GradientPicker Width="132"
Margin="0 2"
Padding="0 -1"
ColorGradient="{Binding InputValue}"
DialogClosed="{s:Action DialogClosed}"
DialogHost="PropertyTreeDialogHost" />
<TextBlock Margin="5 0 0 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,18 +0,0 @@
using System;
using Artemis.Core.Models.Profile.Colors;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput
{
public class ColorGradientPropertyInputViewModel : PropertyInputViewModel<ColorGradient>
{
public ColorGradientPropertyInputViewModel(LayerPropertyViewModel<ColorGradient> layerPropertyViewModel) : base(layerPropertyViewModel)
{
}
public void DialogClosed(object sender, EventArgs e)
{
ApplyInputValue();
}
}
}
@@ -1,23 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.EnumPropertyInputView"
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 5 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputPrefix}" />
<ComboBox Width="132"
Margin="0 2"
Padding="0 -1"
Height="15"
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
ItemsSource="{Binding Path=EnumValues}"
SelectedValuePath="Value"
DisplayMemberPath="Description"
SelectedValue="{Binding Path=InputValue}" />
<TextBlock Margin="5 0 0 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
using Artemis.UI.Shared.Utilities;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput
{
public class EnumPropertyInputViewModel<T> : PropertyInputViewModel<T> where T : Enum
{
public EnumPropertyInputViewModel(LayerPropertyViewModel<T> layerPropertyViewModel) : base(layerPropertyViewModel)
{
EnumValues = EnumUtilities.GetAllValuesAndDescriptions(typeof(T));
}
public IEnumerable<ValueDescription> EnumValues { get; }
}
}
@@ -1,24 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.FloatPropertyInputView"
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:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:propertyInput="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance propertyInput:FloatPropertyInputViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 5 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputPrefix}" />
<controls:DraggableFloat Value="{Binding InputValue}"
materialDesign:ValidationAssist.UsePopup="True"
StepSize="{Binding LayerPropertyViewModel.PropertyDescription.InputStepSize}"
DragStarted="{s:Action InputDragStarted}"
DragEnded="{s:Action InputDragEnded}" />
<TextBlock Margin="5 0 0 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,28 +0,0 @@
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
using FluentValidation;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput
{
public class FloatPropertyInputViewModel : PropertyInputViewModel<float>
{
public FloatPropertyInputViewModel(LayerPropertyViewModel<float> layerPropertyViewModel, IModelValidator<FloatPropertyInputViewModel> validator)
: base(layerPropertyViewModel, validator)
{
}
}
public class FloatPropertyInputViewModelValidator : AbstractValidator<FloatPropertyInputViewModel>
{
public FloatPropertyInputViewModelValidator()
{
RuleFor(vm => vm.InputValue)
.LessThanOrEqualTo(vm => (float) vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is float);
RuleFor(vm => vm.InputValue)
.GreaterThanOrEqualTo(vm => (float) vm.LayerPropertyViewModel.PropertyDescription.MinInputValue)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MinInputValue is float);
}
}
}
@@ -1,24 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.IntPropertyInputView"
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:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:propertyInput="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance propertyInput:IntPropertyInputViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 5 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputPrefix}" />
<controls:DraggableFloat Value="{Binding InputValue}"
materialDesign:ValidationAssist.UsePopup="True"
StepSize="{Binding LayerPropertyViewModel.PropertyDescription.InputStepSize}"
DragStarted="{s:Action InputDragStarted}"
DragEnded="{s:Action InputDragEnded}" />
<TextBlock Margin="5 0 0 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,28 +0,0 @@
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
using FluentValidation;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput
{
public class IntPropertyInputViewModel : PropertyInputViewModel<int>
{
public IntPropertyInputViewModel(LayerPropertyViewModel<int> layerPropertyViewModel, IModelValidator<IntPropertyInputViewModel> validator)
: base(layerPropertyViewModel, validator)
{
}
}
public class IntPropertyInputViewModelValidator : AbstractValidator<IntPropertyInputViewModel>
{
public IntPropertyInputViewModelValidator()
{
RuleFor(vm => vm.InputValue)
.LessThanOrEqualTo(vm => (int) vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is int);
RuleFor(vm => vm.InputValue)
.GreaterThanOrEqualTo(vm => (int) vm.LayerPropertyViewModel.PropertyDescription.MinInputValue)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MinInputValue is int);
}
}
}
@@ -1,25 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.SKColorPropertyInputView"
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:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
xmlns:artemis="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:propertyInput="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="800"
d:DataContext="{d:DesignInstance propertyInput:SKColorPropertyInputViewModel}">
<UserControl.Resources>
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 5 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputPrefix}" />
<controls:ColorPicker Width="132"
Margin="0 -2 0 3"
Padding="0 -1"
Color="{Binding InputValue, Converter={StaticResource SKColorToColorConverter}}" />
<TextBlock Margin="5 0 0 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,12 +0,0 @@
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
using SkiaSharp;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput
{
public class SKColorPropertyInputViewModel : PropertyInputViewModel<SKColor>
{
public SKColorPropertyInputViewModel(LayerPropertyViewModel<SKColor> layerPropertyViewModel) : base(layerPropertyViewModel)
{
}
}
}
@@ -1,29 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.SKPointPropertyInputView"
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:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:propertyInput="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="800"
d:DataContext="{d:DesignInstance propertyInput:SKPointPropertyInputViewModel}">
<StackPanel Orientation="Horizontal" KeyboardNavigation.IsTabStop="True">
<TextBlock Margin="0 0 5 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputPrefix}" />
<controls:DraggableFloat ToolTip="X-coordinate (horizontal)"
Value="{Binding X}"
StepSize="{Binding LayerPropertyViewModel.PropertyDescription.InputStepSize}"
DragStarted="{s:Action InputDragStarted}"
DragEnded="{s:Action InputDragEnded}" />
<TextBlock Margin="5 0" VerticalAlignment="Bottom">,</TextBlock>
<controls:DraggableFloat ToolTip="Y-coordinate (vertical)"
Value="{Binding Y}"
StepSize="{Binding LayerPropertyViewModel.PropertyDescription.InputStepSize}"
DragStarted="{s:Action InputDragStarted}"
DragEnded="{s:Action InputDragEnded}" />
<TextBlock Margin="5 0 0 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,57 +0,0 @@
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
using FluentValidation;
using PropertyChanged;
using SkiaSharp;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput
{
public class SKPointPropertyInputViewModel : PropertyInputViewModel<SKPoint>
{
public SKPointPropertyInputViewModel(LayerPropertyViewModel<SKPoint> layerPropertyViewModel, IModelValidator<SKPointPropertyInputViewModel> validator)
: base(layerPropertyViewModel, validator)
{
}
// Since SKPoint is immutable we need to create properties that replace the SKPoint entirely
[DependsOn(nameof(InputValue))]
public float X
{
get => InputValue.X;
set => InputValue = new SKPoint(value, Y);
}
[DependsOn(nameof(InputValue))]
public float Y
{
get => InputValue.Y;
set => InputValue = new SKPoint(X, value);
}
protected override void OnInputValueChanged()
{
NotifyOfPropertyChange(nameof(X));
NotifyOfPropertyChange(nameof(Y));
}
}
public class SKPointPropertyInputViewModelValidator : AbstractValidator<SKPointPropertyInputViewModel>
{
public SKPointPropertyInputViewModelValidator()
{
RuleFor(vm => vm.X)
.LessThanOrEqualTo(vm => ((SKPoint) vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue).X)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is SKPoint);
RuleFor(vm => vm.X)
.GreaterThanOrEqualTo(vm => ((SKPoint) vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue).X)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is SKPoint);
RuleFor(vm => vm.Y)
.LessThanOrEqualTo(vm => ((SKPoint) vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue).Y)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is SKPoint);
RuleFor(vm => vm.Y)
.GreaterThanOrEqualTo(vm => ((SKPoint) vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue).Y)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is SKPoint);
}
}
}
@@ -1,28 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.SKSizePropertyInputView"
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:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:SKSizePropertyInputViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 5 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputPrefix}" />
<controls:DraggableFloat ToolTip="Height"
Value="{Binding Height}"
StepSize="{Binding LayerPropertyViewModel.PropertyDescription.InputStepSize}"
DragStarted="{s:Action InputDragStarted}"
DragEnded="{s:Action InputDragEnded}" />
<TextBlock Margin="5 0" VerticalAlignment="Bottom">,</TextBlock>
<controls:DraggableFloat ToolTip="Width"
Value="{Binding Width}"
StepSize="{Binding LayerPropertyViewModel.PropertyDescription.InputStepSize}"
DragStarted="{s:Action InputDragStarted}"
DragEnded="{s:Action InputDragEnded}" />
<TextBlock Margin="5 0 0 4" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,57 +0,0 @@
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
using FluentValidation;
using PropertyChanged;
using SkiaSharp;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput
{
public class SKSizePropertyInputViewModel : PropertyInputViewModel<SKSize>
{
public SKSizePropertyInputViewModel(LayerPropertyViewModel<SKSize> layerPropertyViewModel, IModelValidator<SKSizePropertyInputViewModel> validator)
: base(layerPropertyViewModel, validator)
{
}
// Since SKSize is immutable we need to create properties that replace the SKSize entirely
[DependsOn(nameof(InputValue))]
public float Width
{
get => InputValue.Width;
set => InputValue = new SKSize(value, Height);
}
[DependsOn(nameof(InputValue))]
public float Height
{
get => InputValue.Height;
set => InputValue = new SKSize(Width, value);
}
protected override void OnInputValueChanged()
{
NotifyOfPropertyChange(nameof(Width));
NotifyOfPropertyChange(nameof(Height));
}
}
public class SKSizePropertyInputViewModelValidator : AbstractValidator<SKSizePropertyInputViewModel>
{
public SKSizePropertyInputViewModelValidator()
{
RuleFor(vm => vm.Width)
.LessThanOrEqualTo(vm => ((SKSize)vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue).Width)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is SKSize);
RuleFor(vm => vm.Width)
.GreaterThanOrEqualTo(vm => ((SKSize)vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue).Width)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is SKSize);
RuleFor(vm => vm.Height)
.LessThanOrEqualTo(vm => ((SKSize)vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue).Height)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is SKSize);
RuleFor(vm => vm.Height)
.GreaterThanOrEqualTo(vm => ((SKSize)vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue).Height)
.When(vm => vm.LayerPropertyViewModel.PropertyDescription.MaxInputValue is SKSize);
}
}
}
@@ -1,12 +1,12 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.TreePropertyView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type local:TreePropertyViewModel}}">
<Grid Height="22">
@@ -32,11 +32,18 @@
Padding="0,0,5,0"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"
Text="{Binding LayerPropertyViewModel.PropertyDescription.Name}"
ToolTip="{Binding LayerPropertyViewModel.PropertyDescription.Description}"
Text="{Binding LayerPropertyViewModel.LayerProperty.PropertyDescription.Name}"
ToolTip="{Binding LayerPropertyViewModel.LayerProperty.PropertyDescription.Description}"
HorizontalAlignment="Left" />
<ContentControl Grid.Column="2" Margin="20 0" s:View.Model="{Binding PropertyInputViewModel}" />
<ContentControl Grid.Column="2" Margin="20 0" s:View.Model="{Binding PropertyInputViewModel}">
<ContentControl.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0 0 5 4" />
<Setter Property="VerticalAlignment" Value="Bottom" />
</Style>
</ContentControl.Resources>
</ContentControl>
<Button Grid.Column="3"
Style="{StaticResource MaterialDesignOutlinedButton}"
@@ -50,4 +57,4 @@
<TextBlock FontSize="10">DATA BINDING</TextBlock>
</Button>
</Grid>
</UserControl>
</UserControl>
@@ -3,8 +3,8 @@ using System.Linq;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Utilities;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput.Abstract;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.PropertyInput;
using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree
{
@@ -47,7 +47,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree
));
}
// If disabling keyframes, set the base value to the current value
else if (!enable && LayerPropertyViewModel.LayerProperty.Keyframes.Any())
else if (!enable && LayerPropertyViewModel.LayerProperty.Keyframes.Any())
LayerPropertyViewModel.LayerProperty.BaseValue = LayerPropertyViewModel.LayerProperty.CurrentValue;
LayerPropertyViewModel.LayerProperty.KeyframesEnabled = enable;
@@ -5,6 +5,7 @@ using Artemis.Core.Models.Profile;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using GongSolutions.Wpf.DragDrop;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
@@ -9,6 +9,7 @@ using Artemis.Core.Models.Profile.LayerShapes;
using Artemis.Core.Models.Surface;
using Artemis.UI.Extensions;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using RGB.NET.Core;
using Stylet;
using Rectangle = Artemis.Core.Models.Profile.LayerShapes.Rectangle;
@@ -16,6 +16,7 @@ using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools;
using Artemis.UI.Screens.Shared;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
@@ -338,7 +339,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
UpdateCanSelectEditTool();
}
private void SelectedLayerOnLayerBrushUpdated(object? sender, EventArgs e)
private void SelectedLayerOnLayerBrushUpdated(object sender, EventArgs e)
{
UpdateCanSelectEditTool();
}
@@ -5,6 +5,7 @@ using System.Windows.Media;
using Artemis.Core.Models.Profile;
using Artemis.UI.Events;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using SkiaSharp;
using SkiaSharp.Views.WPF;
using Stylet;
@@ -5,6 +5,7 @@ using System.Windows.Input;
using Artemis.Core.Models.Profile;
using Artemis.UI.Properties;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
@@ -5,6 +5,7 @@ using System.Windows.Input;
using Artemis.Core.Models.Profile;
using Artemis.UI.Properties;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
@@ -1,5 +1,6 @@
using System.Windows.Input;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
@@ -2,6 +2,7 @@
using System.Windows;
using System.Windows.Input;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{