Layer effects - WIP commit

Profile editor - Show brush icons at different parts in the editor
This commit is contained in:
SpoinkyNL committed 2020-06-10 00:20:43 +02:00
1 parent ac23d89f3e
commit f178c3d790
28 files changed
+618 -63

No files matched your search

@@ -0,0 +1,57 @@
<UserControl x:Class="Artemis.UI.PropertyInput.EffectPropertyInputView"
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.PropertyInput"
xmlns:layerEffect="clr-namespace:Artemis.Core.Plugins.LayerEffect;assembly=Artemis.Core"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type propertyInput:EffectPropertyInputViewModel}}">
<UserControl.Resources>
<ControlTemplate x:Key="SimpleTemplate">
<StackPanel d:DataContext="{d:DesignInstance {x:Type layerEffect:LayerEffectDescriptor}}" Orientation="Horizontal">
<materialDesign:PackIcon Kind="{Binding Icon}" Height="13" Width="13" Margin="0 1 3 0" />
<TextBlock Text="{Binding DisplayName}" />
</StackPanel>
</ControlTemplate>
<ControlTemplate x:Key="ExtendedTemplate">
<Grid d:DataContext="{d:DesignInstance {x:Type layerEffect:LayerEffectDescriptor}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<materialDesign:PackIcon Grid.Row="0" Grid.RowSpan="2" Kind="{Binding Icon}" Height="20" Width="20" Margin="-5 -2 10 0" VerticalAlignment="Center"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding DisplayName}" TextWrapping="Wrap" MaxWidth="350"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Description}" TextWrapping="Wrap" MaxWidth="350" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" />
</Grid>
</ControlTemplate>
<DataTemplate x:Key="DescriptorTemplate">
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource ExtendedTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="{x:Null}">
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource SimpleTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<TextBlock Width="10" Text="{Binding LayerProperty.PropertyDescription.InputPrefix}" />
<ComboBox Width="132"
Margin="0 2"
Padding="0 -1"
Height="15"
materialDesign:ComboBoxAssist.ClassicMode="True"
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
ItemsSource="{Binding Path=Descriptors}"
SelectedValue="{Binding Path=SelectedDescriptor}"
ItemTemplate="{StaticResource DescriptorTemplate}" />
<TextBlock Width="10" Text="{Binding LayerProperty.PropertyDescription.InputAffix}" />
</StackPanel>
</UserControl>
@@ -0,0 +1,68 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.Events;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.LayerEffect;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.Shared.PropertyInput;
using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.PropertyInput
{
public class EffectPropertyInputViewModel : PropertyInputViewModel<LayerEffectReference>
{
private readonly ILayerService _layerService;
private readonly IPluginService _pluginService;
public EffectPropertyInputViewModel(LayerProperty<LayerEffectReference> layerProperty, IProfileEditorService profileEditorService,
ILayerService layerService, IPluginService pluginService) : base(layerProperty, profileEditorService)
{
_layerService = layerService;
_pluginService = pluginService;
_pluginService.PluginEnabled += PluginServiceOnPluginLoaded;
_pluginService.PluginDisabled += PluginServiceOnPluginLoaded;
UpdateEnumValues();
}
public List<LayerEffectDescriptor> Descriptors { get; set; }
public LayerEffectDescriptor SelectedDescriptor
{
get => Descriptors.FirstOrDefault(d => d.LayerEffectProvider.PluginInfo.Guid == InputValue?.EffectPluginGuid && d.LayerEffectType.Name == InputValue?.EffectType);
set => SetEffectByDescriptor(value);
}
public void UpdateEnumValues()
{
var layerEffectProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
Descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
NotifyOfPropertyChange(nameof(SelectedDescriptor));
}
public override void Dispose()
{
_pluginService.PluginEnabled -= PluginServiceOnPluginLoaded;
_pluginService.PluginDisabled -= PluginServiceOnPluginLoaded;
base.Dispose();
}
protected override void OnInputValueApplied()
{
_layerService.InstantiateLayerEffect(LayerProperty.Layer);
}
private void SetEffectByDescriptor(LayerEffectDescriptor value)
{
InputValue = new LayerEffectReference {EffectPluginGuid = value.LayerEffectProvider.PluginInfo.Guid, EffectType = value.LayerEffectType.Name};
}
private void PluginServiceOnPluginLoaded(object sender, PluginEventArgs e)
{
UpdateEnumValues();
}
}
}
@@ -21,6 +21,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
public class LayerPropertiesViewModel : ProfileEditorPanelViewModel
{
private LayerPropertyGroupViewModel _brushPropertyGroup;
public LayerPropertiesViewModel(IProfileEditorService profileEditorService, ICoreService coreService, ISettingsService settingsService)
{
ProfileEditorService = profileEditorService;
@@ -111,6 +113,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
layerPropertyGroupViewModel.Dispose();
LayerPropertyGroups.Clear();
_brushPropertyGroup = null;
if (profileElement is Layer layer)
{
@@ -148,17 +151,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
if (SelectedLayer == null)
return;
var hideRenderRelatedProperties = SelectedLayer.LayerBrush != null && SelectedLayer.LayerBrush.BrushType == LayerBrushType.RgbNet;
var hideRenderRelatedProperties = SelectedLayer?.LayerBrush?.BrushType == LayerBrushType.Regular && SelectedLayer.LayerBrush.SupportsTransformation;
SelectedLayer.General.ShapeType.IsHidden = hideRenderRelatedProperties;
SelectedLayer.General.FillType.IsHidden = hideRenderRelatedProperties;
SelectedLayer.General.BlendMode.IsHidden = hideRenderRelatedProperties;
SelectedLayer.Transform.IsHidden = hideRenderRelatedProperties;
// Get rid of the old layer properties group
if (LayerPropertyGroups.Count == 3)
if (_brushPropertyGroup != null)
{
LayerPropertyGroups[2].Dispose();
LayerPropertyGroups.RemoveAt(2);
LayerPropertyGroups.Remove(_brushPropertyGroup);
_brushPropertyGroup = null;
}
if (SelectedLayer.LayerBrush != null)
@@ -170,7 +172,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
Name = SelectedLayer.LayerBrush.Descriptor.DisplayName,
Description = SelectedLayer.LayerBrush.Descriptor.Description
};
LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(ProfileEditorService, SelectedLayer.LayerBrush.BaseProperties, brushDescription));
_brushPropertyGroup = new LayerPropertyGroupViewModel(ProfileEditorService, SelectedLayer.LayerBrush.BaseProperties, brushDescription);
LayerPropertyGroups.Add(_brushPropertyGroup);
}
TimelineViewModel.UpdateKeyframes();
@@ -15,7 +15,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
public class LayerPropertyGroupViewModel : LayerPropertyBaseViewModel
{
public LayerPropertyGroupViewModel(IProfileEditorService profileEditorService, LayerPropertyGroup layerPropertyGroup,
public enum ViewModelType
{
General,
Transform,
LayerBrushRoot,
LayerEffectRoot,
None
}
public LayerPropertyGroupViewModel(IProfileEditorService profileEditorService, LayerPropertyGroup layerPropertyGroup,
PropertyGroupDescriptionAttribute propertyGroupDescription)
{
ProfileEditorService = profileEditorService;
@@ -26,11 +35,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
TreePropertyGroupViewModel = new TreePropertyGroupViewModel(this);
TimelinePropertyGroupViewModel = new TimelinePropertyGroupViewModel(this);
PopulateChildren();
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
PopulateChildren();
DetermineType();
}
public override bool IsExpanded
{
get => LayerPropertyGroup.Layer.IsPropertyGroupExpanded(LayerPropertyGroup);
@@ -38,6 +47,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
}
public override bool IsVisible => !LayerPropertyGroup.IsHidden;
public ViewModelType GroupType { get; set; }
public IProfileEditorService ProfileEditorService { get; }
@@ -81,6 +91,20 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
return result;
}
private void DetermineType()
{
if (LayerPropertyGroup is LayerGeneralProperties)
GroupType = ViewModelType.General;
else if (LayerPropertyGroup is LayerTransformProperties)
GroupType = ViewModelType.Transform;
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerBrush != null)
GroupType = ViewModelType.LayerBrushRoot;
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerEffect != null)
GroupType = ViewModelType.LayerEffectRoot;
else
GroupType = ViewModelType.None;
}
private void PopulateChildren()
{
// Get all properties and property groups and create VMs for them
@@ -106,10 +130,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
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]
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;
@@ -0,0 +1,119 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.TreePropertyGroupView"
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"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:TreePropertyGroupViewModel}"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel>
<!-- Type: None -->
<TextBlock
Text="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Name}"
ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}"
VerticalAlignment="Center"
Margin="0 5">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="None">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<!-- Type: General -->
<StackPanel Orientation="Horizontal" Margin="0 5">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="General">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<materialDesign:PackIcon Kind="HammerWrench" Margin="0 -1 5 0" />
<TextBlock ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}">General</TextBlock>
</StackPanel>
<!-- Type: Transform -->
<StackPanel Orientation="Horizontal" Margin="0 5">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="Transform">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<materialDesign:PackIcon Kind="TransitConnectionVariant" Margin="0 -1 5 0" />
<TextBlock ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}">Transform</TextBlock>
</StackPanel>
<!-- Type: LayerBrushRoot -->
<StackPanel Orientation="Horizontal" Margin="0 5">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="LayerBrushRoot">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<materialDesign:PackIcon Grid.Column="0" Kind="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Icon}" Margin="0 -1 5 0" />
<TextBlock ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Description}">Brush -&#160;</TextBlock>
<TextBlock Text="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.DisplayName}"
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Description}" />
</StackPanel>
<!-- Type: LayerEffectRoot -->
<Grid Height="22">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="LayerEffectRoot">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<materialDesign:PackIcon Grid.Column="0" Kind="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Icon}" Margin="0 5 5 0" />
<TextBlock Grid.Column="1" ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}" Margin="0 5">
Effect -&#160;
</TextBlock>
<TextBlock Grid.Column="2"
Text="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.DisplayName}"
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}"
Margin="0 5" />
<Button Grid.Column="3"
Style="{StaticResource MaterialDesignOutlinedButton}"
Margin="0 1"
Padding="0"
Width="80"
Height="20"
ToolTip="Change the property's data binding"
VerticalAlignment="Center">
<TextBlock FontSize="10">DELETE EFFECT</TextBlock>
</Button>
</Grid>
</StackPanel>
</UserControl>
@@ -96,11 +96,7 @@
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type layerProperties:LayerPropertyGroupViewModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding PropertyGroupDescription.Name}"
ToolTip="{Binding PropertyGroupDescription.Description}" Margin="5 0"
VerticalAlignment="Center" />
</StackPanel>
<ContentControl s:View.Model="{Binding TreePropertyGroupViewModel}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type layerProperties:LayerPropertyViewModel}">
<ContentControl s:View.Model="{Binding TreePropertyBaseViewModel}" />
@@ -53,7 +53,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
case Core.Plugins.Abstract.Module _:
return PackIconKind.GearBox;
case LayerBrushProvider _:
return PackIconKind.Brush;
return PackIconKind.Brush;
case LayerEffectProvider _:
return PackIconKind.AutoAwesome;
}
return PackIconKind.Plugin;
@@ -30,6 +30,7 @@ namespace Artemis.UI.Services
{
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(BrushPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(ColorGradientPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(EffectPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(FloatPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(IntPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKColorPropertyInputViewModel));