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

Layer effects - WIP commit

Profile editor - Show brush icons at different parts in the editor
This commit is contained in:
SpoinkyNL 2020-06-10 00:20:43 +02:00
parent c99a3aaf3b
commit 2493c2cbf1
28 changed files with 618 additions and 63 deletions

View File

@ -116,6 +116,11 @@ namespace Artemis.Core.Models.Profile
/// </summary> /// </summary>
public BaseLayerBrush LayerBrush { get; internal set; } public BaseLayerBrush LayerBrush { get; internal set; }
/// <summary>
/// The layer effect that will apply pre- and/or post-processing to the layer
/// </summary>
public BaseLayerEffect LayerEffect { get; set; }
public override string ToString() public override string ToString()
{ {
return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
@ -150,6 +155,7 @@ namespace Artemis.Core.Models.Profile
General.ApplyToEntity(); General.ApplyToEntity();
Transform.ApplyToEntity(); Transform.ApplyToEntity();
LayerBrush?.BaseProperties.ApplyToEntity(); LayerBrush?.BaseProperties.ApplyToEntity();
LayerEffect?.BaseProperties.ApplyToEntity();
// LEDs // LEDs
LayerEntity.Leds.Clear(); LayerEntity.Leds.Clear();
@ -220,22 +226,26 @@ namespace Artemis.Core.Models.Profile
General.Override(TimeSpan.Zero); General.Override(TimeSpan.Zero);
Transform.Override(TimeSpan.Zero); Transform.Override(TimeSpan.Zero);
LayerBrush.BaseProperties.Override(TimeSpan.Zero); LayerBrush.BaseProperties.Override(TimeSpan.Zero);
LayerEffect?.BaseProperties?.Override(TimeSpan.Zero);
} }
else else
{ {
General.Update(deltaTime); General.Update(deltaTime);
Transform.Update(deltaTime); Transform.Update(deltaTime);
LayerBrush.BaseProperties.Update(deltaTime); LayerBrush.BaseProperties.Update(deltaTime);
LayerEffect?.BaseProperties?.Update(deltaTime);
} }
LayerBrush.Update(deltaTime); LayerBrush.Update(deltaTime);
LayerEffect?.Update(deltaTime);
} }
public void OverrideProgress(TimeSpan timeOverride) public void OverrideProgress(TimeSpan timeOverride)
{ {
General.Override(timeOverride); General.Override(timeOverride);
Transform.Override(timeOverride); Transform.Override(timeOverride);
LayerBrush?.BaseProperties.Override(timeOverride); LayerBrush?.BaseProperties?.Override(timeOverride);
LayerEffect?.BaseProperties?.Override(timeOverride);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -256,22 +266,26 @@ namespace Artemis.Core.Models.Profile
paint.BlendMode = General.BlendMode.CurrentValue; paint.BlendMode = General.BlendMode.CurrentValue;
paint.Color = new SKColor(0, 0, 0, (byte) (Transform.Opacity.CurrentValue * 2.55f)); paint.Color = new SKColor(0, 0, 0, (byte) (Transform.Opacity.CurrentValue * 2.55f));
switch (General.FillType.CurrentValue) LayerEffect?.PreProcess(canvas, canvasInfo, Path, paint);
{
case LayerFillType.Stretch: if (!LayerBrush.SupportsTransformation)
StretchRender(canvas, canvasInfo, paint); SimpleRender(canvas, canvasInfo, paint);
break; else if (General.FillType.CurrentValue == LayerFillType.Stretch)
case LayerFillType.Clip: StretchRender(canvas, canvasInfo, paint);
ClipRender(canvas, canvasInfo, paint); else if (General.FillType.CurrentValue == LayerFillType.Clip)
break; ClipRender(canvas, canvasInfo, paint);
default:
throw new ArgumentOutOfRangeException(); LayerEffect?.PostProcess(canvas, canvasInfo, Path, paint);
}
} }
canvas.Restore(); canvas.Restore();
} }
private void SimpleRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint)
{
LayerBrush.InternalRender(canvas, canvasInfo, new SKPath(LayerShape.Path), paint);
}
private void StretchRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint) private void StretchRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint)
{ {
// Apply transformations // Apply transformations
@ -295,7 +309,7 @@ namespace Artemis.Core.Models.Profile
private void ClipRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint) private void ClipRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint)
{ {
// Apply transformations // Apply transformation
var sizeProperty = Transform.Scale.CurrentValue; var sizeProperty = Transform.Scale.CurrentValue;
var rotationProperty = Transform.Rotation.CurrentValue; var rotationProperty = Transform.Rotation.CurrentValue;
@ -412,6 +426,7 @@ namespace Artemis.Core.Models.Profile
internal void Deactivate() internal void Deactivate()
{ {
DeactivateLayerBrush(); DeactivateLayerBrush();
DeactivateLayerEffect();
} }
internal void DeactivateLayerBrush() internal void DeactivateLayerBrush()
@ -423,7 +438,19 @@ namespace Artemis.Core.Models.Profile
LayerBrush = null; LayerBrush = null;
brush.Dispose(); brush.Dispose();
LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid); LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid && p.Path.StartsWith("LayerBrush."));
}
internal void DeactivateLayerEffect()
{
if (LayerEffect == null)
return;
var effect = LayerEffect;
LayerEffect = null;
effect.Dispose();
LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == effect.PluginInfo.Guid && p.Path.StartsWith("LayerEffect."));
} }
internal void PopulateLeds(ArtemisSurface surface) internal void PopulateLeds(ArtemisSurface surface)
@ -451,6 +478,7 @@ namespace Artemis.Core.Models.Profile
public event EventHandler RenderPropertiesUpdated; public event EventHandler RenderPropertiesUpdated;
public event EventHandler ShapePropertiesUpdated; public event EventHandler ShapePropertiesUpdated;
public event EventHandler LayerBrushUpdated; public event EventHandler LayerBrushUpdated;
public event EventHandler LayerEffectUpdated;
private void OnRenderPropertiesUpdated() private void OnRenderPropertiesUpdated()
{ {
@ -467,6 +495,11 @@ namespace Artemis.Core.Models.Profile
LayerBrushUpdated?.Invoke(this, EventArgs.Empty); LayerBrushUpdated?.Invoke(this, EventArgs.Empty);
} }
internal void OnLayerEffectUpdated()
{
LayerEffectUpdated?.Invoke(this, EventArgs.Empty);
}
#endregion #endregion
} }

View File

@ -0,0 +1,21 @@
using System;
using Artemis.Core.Plugins.LayerEffect;
namespace Artemis.Core.Models.Profile
{
/// <summary>
/// A reference to a <see cref="LayerEffectDescriptor" />
/// </summary>
public class LayerEffectReference
{
/// <summary>
/// The GUID of the plugin the effect descriptor resides in
/// </summary>
public Guid EffectPluginGuid { get; set; }
/// <summary>
/// The full type name of the effect descriptor
/// </summary>
public string EffectType { get; set; }
}
}

View File

@ -18,6 +18,9 @@ namespace Artemis.Core.Models.Profile
[PropertyDescription(Name = "Brush type", Description = "The type of brush to use for this layer")] [PropertyDescription(Name = "Brush type", Description = "The type of brush to use for this layer")]
public LayerBrushReferenceLayerProperty BrushReference { get; set; } public LayerBrushReferenceLayerProperty BrushReference { get; set; }
[PropertyDescription(Name = "Effect type", Description = "The type of effect to use for this layer")]
public LayerEffectReferenceLayerProperty EffectReference { get; set; }
protected override void PopulateDefaults() protected override void PopulateDefaults()
{ {
ShapeType.DefaultValue = LayerShapeType.Rectangle; ShapeType.DefaultValue = LayerShapeType.Rectangle;

View File

@ -13,10 +13,5 @@ namespace Artemis.Core.Models.Profile.LayerProperties.Attributes
/// The user-friendly description for this property, shown in the UI. /// The user-friendly description for this property, shown in the UI.
/// </summary> /// </summary>
public string Description { get; set; } public string Description { get; set; }
/// <summary>
/// Whether to expand this property by default, this is useful for important parent properties.
/// </summary>
public bool ExpandByDefault { get; set; }
} }
} }

View File

@ -0,0 +1,22 @@
using Artemis.Core.Exceptions;
namespace Artemis.Core.Models.Profile.LayerProperties.Types
{
/// <summary>
/// A special layer property used to configure the selected layer effect
/// </summary>
public class LayerEffectReferenceLayerProperty : LayerProperty<LayerEffectReference>
{
internal LayerEffectReferenceLayerProperty()
{
KeyframesSupported = false;
}
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
{
throw new ArtemisCoreException("Layer effect references do not support keyframes.");
}
public static implicit operator LayerEffectReference(LayerEffectReferenceLayerProperty p) => p.CurrentValue;
}
}

View File

@ -8,6 +8,8 @@ using Artemis.Core.Exceptions;
using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.Core.Plugins.Exceptions; using Artemis.Core.Plugins.Exceptions;
using Artemis.Core.Plugins.LayerBrush.Abstract;
using Artemis.Core.Plugins.LayerEffect.Abstract;
using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile;
@ -53,6 +55,16 @@ namespace Artemis.Core.Models.Profile
public PropertyGroupDescriptionAttribute GroupDescription { get; internal set; } public PropertyGroupDescriptionAttribute GroupDescription { get; internal set; }
/// <summary>
/// The layer brush this property group belongs to
/// </summary>
public BaseLayerBrush LayerBrush { get; internal set; }
/// <summary>
/// The layer effect this property group belongs to
/// </summary>
public BaseLayerEffect LayerEffect { get; internal set; }
/// <summary> /// <summary>
/// Gets or sets whether the property is hidden in the UI /// Gets or sets whether the property is hidden in the UI
/// </summary> /// </summary>
@ -158,6 +170,8 @@ namespace Artemis.Core.Models.Profile
instance.Parent = this; instance.Parent = this;
instance.GroupDescription = (PropertyGroupDescriptionAttribute) propertyGroupDescription; instance.GroupDescription = (PropertyGroupDescriptionAttribute) propertyGroupDescription;
instance.LayerBrush = LayerBrush;
instance.LayerEffect = LayerEffect;
instance.InitializeProperties(layerService, layer, $"{path}{propertyInfo.Name}."); instance.InitializeProperties(layerService, layer, $"{path}{propertyInfo.Name}.");
propertyInfo.SetValue(this, instance); propertyInfo.SetValue(this, instance);

View File

@ -1,4 +1,8 @@
using System; using System.Collections.Generic;
using System.Collections.ObjectModel;
using Artemis.Core.Plugins.Exceptions;
using Artemis.Core.Plugins.LayerEffect;
using Artemis.Core.Plugins.LayerEffect.Abstract;
namespace Artemis.Core.Plugins.Abstract namespace Artemis.Core.Plugins.Abstract
{ {
@ -6,16 +10,37 @@ namespace Artemis.Core.Plugins.Abstract
/// <summary> /// <summary>
/// Allows you to create one or more <see cref="LayerEffect" />s usable by profile layers. /// Allows you to create one or more <see cref="LayerEffect" />s usable by profile layers.
/// </summary> /// </summary>
public class LayerEffectProvider : Plugin public abstract class LayerEffectProvider : Plugin
{ {
public override void EnablePlugin() private readonly List<LayerEffectDescriptor> _layerEffectDescriptors;
protected LayerEffectProvider()
{ {
throw new NotImplementedException(); _layerEffectDescriptors = new List<LayerEffectDescriptor>();
} }
public override void DisablePlugin() /// <summary>
/// A read-only collection of all layer effects added with <see cref="AddLayerEffectDescriptor{T}" />
/// </summary>
public ReadOnlyCollection<LayerEffectDescriptor> LayerEffectDescriptors => _layerEffectDescriptors.AsReadOnly();
/// <summary>
/// Adds a layer effect descriptor for a given layer effect, so that it appears in the UI.
/// <para>Note: You do not need to manually remove these on disable</para>
/// </summary>
/// <typeparam name="T">The type of the layer effect you wish to register</typeparam>
/// <param name="displayName">The name to display in the UI</param>
/// <param name="description">The description to display in the UI</param>
/// <param name="icon">
/// The Material icon to display in the UI, a full reference can be found
/// <see href="https://materialdesignicons.com">here</see>
/// </param>
protected void AddLayerEffectDescriptor<T>(string displayName, string description, string icon) where T : BaseLayerEffect
{ {
throw new NotImplementedException(); if (!Enabled)
throw new ArtemisPluginException(PluginInfo, "Can only add a layer effect descriptor when the plugin is enabled");
_layerEffectDescriptors.Add(new LayerEffectDescriptor(displayName, description, icon, typeof(T), this));
} }
} }
} }

View File

@ -36,6 +36,11 @@ namespace Artemis.Core.Plugins.LayerBrush.Abstract
/// </summary> /// </summary>
public virtual LayerPropertyGroup BaseProperties => null; public virtual LayerPropertyGroup BaseProperties => null;
/// <summary>
/// Gets whether the brush supports transformations, RGB.NET brushes never support transformation
/// </summary>
public bool SupportsTransformation { get; protected set; }
public void Dispose() public void Dispose()
{ {
DisableLayerBrush(); DisableLayerBrush();

View File

@ -38,6 +38,7 @@ namespace Artemis.Core.Plugins.LayerBrush.Abstract
internal void InitializeProperties(ILayerService layerService) internal void InitializeProperties(ILayerService layerService)
{ {
Properties = Activator.CreateInstance<T>(); Properties = Activator.CreateInstance<T>();
Properties.LayerBrush = this;
Properties.InitializeProperties(layerService, Layer, "LayerBrush."); Properties.InitializeProperties(layerService, Layer, "LayerBrush.");
PropertiesInitialized = true; PropertiesInitialized = true;

View File

@ -35,19 +35,14 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract
internal set => _properties = value; internal set => _properties = value;
} }
/// <summary>
/// Called when all layer properties in this effect have been initialized
/// </summary>
protected virtual void OnPropertiesInitialized()
{
}
internal void InitializeProperties(ILayerService layerService) internal void InitializeProperties(ILayerService layerService)
{ {
Properties = Activator.CreateInstance<T>(); Properties = Activator.CreateInstance<T>();
Properties.LayerEffect = this;
Properties.InitializeProperties(layerService, Layer, "LayerEffect."); Properties.InitializeProperties(layerService, Layer, "LayerEffect.");
OnPropertiesInitialized();
PropertiesInitialized = true; PropertiesInitialized = true;
EnableLayerEffect();
} }
internal override void Initialize(ILayerService layerService) internal override void Initialize(ILayerService layerService)

View File

@ -1,6 +1,8 @@
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Plugins.LayerBrush;
using Artemis.Core.Plugins.LayerBrush.Abstract; using Artemis.Core.Plugins.LayerBrush.Abstract;
using Artemis.Core.Plugins.LayerEffect;
using Artemis.Core.Plugins.LayerEffect.Abstract;
namespace Artemis.Core.Services.Interfaces namespace Artemis.Core.Services.Interfaces
{ {
@ -23,5 +25,14 @@ namespace Artemis.Core.Services.Interfaces
/// <param name="layer">The layer to instantiate the brush for</param> /// <param name="layer">The layer to instantiate the brush for</param>
/// <returns></returns> /// <returns></returns>
BaseLayerBrush InstantiateLayerBrush(Layer layer); BaseLayerBrush InstantiateLayerBrush(Layer layer);
/// <summary>
/// Instantiates and adds the <see cref="BaseLayerEffect" /> described by the provided
/// <see cref="LayerEffectDescriptor" />
/// to the <see cref="Layer" />.
/// </summary>
/// <param name="layer">The layer to instantiate the effect for</param>
/// <returns></returns>
BaseLayerEffect InstantiateLayerEffect(Layer layer);
} }
} }

View File

@ -5,6 +5,7 @@ using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Plugins.LayerBrush;
using Artemis.Core.Plugins.LayerBrush.Abstract; using Artemis.Core.Plugins.LayerBrush.Abstract;
using Artemis.Core.Plugins.LayerEffect.Abstract;
using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Interfaces;
using Ninject; using Ninject;
using Ninject.Parameters; using Ninject.Parameters;
@ -34,8 +35,9 @@ namespace Artemis.Core.Services
layer.General.InitializeProperties(this, layer, "General."); layer.General.InitializeProperties(this, layer, "General.");
layer.Transform.InitializeProperties(this, layer, "Transform."); layer.Transform.InitializeProperties(this, layer, "Transform.");
// With the properties loaded, the layer brush can be instantiated // With the properties loaded, the layer brush and effect can be instantiated
InstantiateLayerBrush(layer); InstantiateLayerBrush(layer);
InstantiateLayerEffect(layer);
return layer; return layer;
} }
@ -68,5 +70,34 @@ namespace Artemis.Core.Services
return brush; return brush;
} }
public BaseLayerEffect InstantiateLayerEffect(Layer layer)
{
layer.DeactivateLayerEffect();
var descriptorReference = layer.General.EffectReference?.CurrentValue;
if (descriptorReference == null)
return null;
// Get a matching descriptor
var layerEffectProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
var descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
var descriptor = descriptors.FirstOrDefault(d => d.LayerEffectProvider.PluginInfo.Guid == descriptorReference.EffectPluginGuid &&
d.LayerEffectType.Name == descriptorReference.EffectType);
if (descriptor == null)
return null;
var effect = (BaseLayerEffect)_kernel.Get(descriptor.LayerEffectType);
effect.Layer = layer;
effect.Descriptor = descriptor;
layer.LayerEffect = effect;
effect.Initialize(this);
effect.Update(0);
layer.OnLayerEffectUpdated();
return effect;
}
} }
} }

View File

@ -94,7 +94,7 @@ namespace Artemis.Core.Services.Storage
if (profile != null) if (profile != null)
{ {
InitializeLayerProperties(profile); InitializeLayerProperties(profile);
InstantiateLayerBrushes(profile); InstantiateLayers(profile);
} }
} }
@ -165,22 +165,25 @@ namespace Artemis.Core.Services.Storage
private void InitializeLayerProperties(Profile profile) private void InitializeLayerProperties(Profile profile)
{ {
foreach (var layer in profile.GetAllLayers().Where(l => l.LayerBrush == null)) foreach (var layer in profile.GetAllLayers())
{ {
if (!layer.General.PropertiesInitialized) if (!layer.General.PropertiesInitialized)
layer.General.InitializeProperties(_layerService, layer, "General."); layer.General.InitializeProperties(_layerService, layer, "General.");
if (!layer.Transform.PropertiesInitialized) if (!layer.Transform.PropertiesInitialized)
layer.Transform.InitializeProperties(_layerService, layer, "Transform."); layer.Transform.InitializeProperties(_layerService, layer, "Transform.");
} }
;
} }
private void InstantiateLayerBrushes(Profile profile) private void InstantiateLayers(Profile profile)
{ {
// Only instantiate brushes for layers without an existing brush instance // Only instantiate brushes for layers without an existing brush/effect instance
foreach (var layer in profile.GetAllLayers().Where(l => l.LayerBrush == null)) foreach (var layer in profile.GetAllLayers())
_layerService.InstantiateLayerBrush(layer); {
if (layer.LayerBrush == null)
_layerService.InstantiateLayerBrush(layer);
if (layer.LayerEffect == null)
_layerService.InstantiateLayerEffect(layer);
}
} }
private void ActiveProfilesPopulateLeds(ArtemisSurface surface) private void ActiveProfilesPopulateLeds(ArtemisSurface surface)
@ -194,7 +197,7 @@ namespace Artemis.Core.Services.Storage
{ {
var profileModules = _pluginService.GetPluginsOfType<ProfileModule>(); var profileModules = _pluginService.GetPluginsOfType<ProfileModule>();
foreach (var profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList()) foreach (var profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList())
InstantiateLayerBrushes(profileModule.ActiveProfile); InstantiateLayers(profileModule.ActiveProfile);
} }
#region Event handlers #region Event handlers

View File

@ -18,7 +18,7 @@ namespace Artemis.Storage.Entities.Profile
public List<KeyframeEntity> KeyframeEntities { get; set; } public List<KeyframeEntity> KeyframeEntities { get; set; }
} }
public class KeyframeEntity public class KeyframeEntity
{ {
public TimeSpan Position { get; set; } public TimeSpan Position { get; set; }

View File

@ -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>

View File

@ -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();
}
}
}

View File

@ -21,6 +21,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{ {
public class LayerPropertiesViewModel : ProfileEditorPanelViewModel public class LayerPropertiesViewModel : ProfileEditorPanelViewModel
{ {
private LayerPropertyGroupViewModel _brushPropertyGroup;
public LayerPropertiesViewModel(IProfileEditorService profileEditorService, ICoreService coreService, ISettingsService settingsService) public LayerPropertiesViewModel(IProfileEditorService profileEditorService, ICoreService coreService, ISettingsService settingsService)
{ {
ProfileEditorService = profileEditorService; ProfileEditorService = profileEditorService;
@ -111,6 +113,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
foreach (var layerPropertyGroupViewModel in LayerPropertyGroups) foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
layerPropertyGroupViewModel.Dispose(); layerPropertyGroupViewModel.Dispose();
LayerPropertyGroups.Clear(); LayerPropertyGroups.Clear();
_brushPropertyGroup = null;
if (profileElement is Layer layer) if (profileElement is Layer layer)
{ {
@ -148,17 +151,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
if (SelectedLayer == null) if (SelectedLayer == null)
return; 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.ShapeType.IsHidden = hideRenderRelatedProperties;
SelectedLayer.General.FillType.IsHidden = hideRenderRelatedProperties; SelectedLayer.General.FillType.IsHidden = hideRenderRelatedProperties;
SelectedLayer.General.BlendMode.IsHidden = hideRenderRelatedProperties; SelectedLayer.General.BlendMode.IsHidden = hideRenderRelatedProperties;
SelectedLayer.Transform.IsHidden = hideRenderRelatedProperties; SelectedLayer.Transform.IsHidden = hideRenderRelatedProperties;
// Get rid of the old layer properties group if (_brushPropertyGroup != null)
if (LayerPropertyGroups.Count == 3)
{ {
LayerPropertyGroups[2].Dispose(); LayerPropertyGroups.Remove(_brushPropertyGroup);
LayerPropertyGroups.RemoveAt(2); _brushPropertyGroup = null;
} }
if (SelectedLayer.LayerBrush != null) if (SelectedLayer.LayerBrush != null)
@ -170,7 +172,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
Name = SelectedLayer.LayerBrush.Descriptor.DisplayName, Name = SelectedLayer.LayerBrush.Descriptor.DisplayName,
Description = SelectedLayer.LayerBrush.Descriptor.Description 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(); TimelineViewModel.UpdateKeyframes();

View File

@ -15,7 +15,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{ {
public class LayerPropertyGroupViewModel : LayerPropertyBaseViewModel 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) PropertyGroupDescriptionAttribute propertyGroupDescription)
{ {
ProfileEditorService = profileEditorService; ProfileEditorService = profileEditorService;
@ -26,11 +35,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
TreePropertyGroupViewModel = new TreePropertyGroupViewModel(this); TreePropertyGroupViewModel = new TreePropertyGroupViewModel(this);
TimelinePropertyGroupViewModel = new TimelinePropertyGroupViewModel(this); TimelinePropertyGroupViewModel = new TimelinePropertyGroupViewModel(this);
PopulateChildren();
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged; LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
PopulateChildren();
DetermineType();
} }
public override bool IsExpanded public override bool IsExpanded
{ {
get => LayerPropertyGroup.Layer.IsPropertyGroupExpanded(LayerPropertyGroup); get => LayerPropertyGroup.Layer.IsPropertyGroupExpanded(LayerPropertyGroup);
@ -38,6 +47,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
} }
public override bool IsVisible => !LayerPropertyGroup.IsHidden; public override bool IsVisible => !LayerPropertyGroup.IsHidden;
public ViewModelType GroupType { get; set; }
public IProfileEditorService ProfileEditorService { get; } public IProfileEditorService ProfileEditorService { get; }
@ -81,6 +91,20 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
return result; 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() private void PopulateChildren()
{ {
// Get all properties and property groups and create VMs for them // 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) 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 // 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 var genericType = baseLayerProperty.GetType().Name == typeof(LayerProperty<>).Name
? baseLayerProperty.GetType().GetGenericArguments()[0] ? baseLayerProperty.GetType().GetGenericArguments()[0]
: baseLayerProperty.GetType().BaseType.GetGenericArguments()[0]; : baseLayerProperty.GetType().BaseType.GetGenericArguments()[0];
// Only create entries for types supported by a tree input VM // Only create entries for types supported by a tree input VM
if (!genericType.IsEnum && ProfileEditorService.RegisteredPropertyEditors.All(r => r.SupportedType != genericType)) if (!genericType.IsEnum && ProfileEditorService.RegisteredPropertyEditors.All(r => r.SupportedType != genericType))
return null; return null;

View File

@ -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>

View File

@ -96,11 +96,7 @@
</TreeView.ItemContainerStyle> </TreeView.ItemContainerStyle>
<TreeView.Resources> <TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type layerProperties:LayerPropertyGroupViewModel}" ItemsSource="{Binding Children}"> <HierarchicalDataTemplate DataType="{x:Type layerProperties:LayerPropertyGroupViewModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal"> <ContentControl s:View.Model="{Binding TreePropertyGroupViewModel}" />
<TextBlock Text="{Binding PropertyGroupDescription.Name}"
ToolTip="{Binding PropertyGroupDescription.Description}" Margin="5 0"
VerticalAlignment="Center" />
</StackPanel>
</HierarchicalDataTemplate> </HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type layerProperties:LayerPropertyViewModel}"> <DataTemplate DataType="{x:Type layerProperties:LayerPropertyViewModel}">
<ContentControl s:View.Model="{Binding TreePropertyBaseViewModel}" /> <ContentControl s:View.Model="{Binding TreePropertyBaseViewModel}" />

View File

@ -53,7 +53,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
case Core.Plugins.Abstract.Module _: case Core.Plugins.Abstract.Module _:
return PackIconKind.GearBox; return PackIconKind.GearBox;
case LayerBrushProvider _: case LayerBrushProvider _:
return PackIconKind.Brush; return PackIconKind.Brush;
case LayerEffectProvider _:
return PackIconKind.AutoAwesome;
} }
return PackIconKind.Plugin; return PackIconKind.Plugin;

View File

@ -30,6 +30,7 @@ namespace Artemis.UI.Services
{ {
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(BrushPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(BrushPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(ColorGradientPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(ColorGradientPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(EffectPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(FloatPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(FloatPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(IntPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(IntPropertyInputViewModel));
_profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKColorPropertyInputViewModel)); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKColorPropertyInputViewModel));

View File

@ -11,10 +11,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI", "Artemis.UI\Ar
{DCF7C321-95DC-4507-BB61-A7C5356E58EC} = {DCF7C321-95DC-4507-BB61-A7C5356E58EC} {DCF7C321-95DC-4507-BB61-A7C5356E58EC} = {DCF7C321-95DC-4507-BB61-A7C5356E58EC}
{E592F239-FAA0-4840-9C85-46E5867D06D5} = {E592F239-FAA0-4840-9C85-46E5867D06D5} {E592F239-FAA0-4840-9C85-46E5867D06D5} = {E592F239-FAA0-4840-9C85-46E5867D06D5}
{36C10640-A31F-4DEE-9F0E-9B9E3F12753D} = {36C10640-A31F-4DEE-9F0E-9B9E3F12753D} {36C10640-A31F-4DEE-9F0E-9B9E3F12753D} = {36C10640-A31F-4DEE-9F0E-9B9E3F12753D}
{62214042-667E-4B29-B64E-1A68CE6FE209} = {62214042-667E-4B29-B64E-1A68CE6FE209}
{0F288A66-6EB0-4589-8595-E33A3A3EAEA2} = {0F288A66-6EB0-4589-8595-E33A3A3EAEA2} {0F288A66-6EB0-4589-8595-E33A3A3EAEA2} = {0F288A66-6EB0-4589-8595-E33A3A3EAEA2}
{A46F278A-FC2C-4342-8455-994D957DDA03} = {A46F278A-FC2C-4342-8455-994D957DDA03} {A46F278A-FC2C-4342-8455-994D957DDA03} = {A46F278A-FC2C-4342-8455-994D957DDA03}
{26902C94-3EBC-4132-B7F0-FFCAB8E150DA} = {26902C94-3EBC-4132-B7F0-FFCAB8E150DA} {26902C94-3EBC-4132-B7F0-FFCAB8E150DA} = {26902C94-3EBC-4132-B7F0-FFCAB8E150DA}
{301C3AAA-9F79-46A5-9B9D-86F076C5BDD1} = {301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}
{7F4C7AB0-4C9B-452D-AFED-34544C903DEF} = {7F4C7AB0-4C9B-452D-AFED-34544C903DEF} {7F4C7AB0-4C9B-452D-AFED-34544C903DEF} = {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}
{235A45C7-24AD-4F47-B9D4-CD67E610A04D} = {235A45C7-24AD-4F47-B9D4-CD67E610A04D} {235A45C7-24AD-4F47-B9D4-CD67E610A04D} = {235A45C7-24AD-4F47-B9D4-CD67E610A04D}
{D004FEC9-0CF8-4828-B620-95DBA73201A3} = {D004FEC9-0CF8-4828-B620-95DBA73201A3} {D004FEC9-0CF8-4828-B620-95DBA73201A3} = {D004FEC9-0CF8-4828-B620-95DBA73201A3}
@ -69,6 +69,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{B258
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.Plugins.LayerBrushes.ColorRgbNet", "Plugins\Artemis.Plugins.LayerBrushes.ColorRgbNet\Artemis.Plugins.LayerBrushes.ColorRgbNet.csproj", "{301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.Plugins.LayerBrushes.ColorRgbNet", "Plugins\Artemis.Plugins.LayerBrushes.ColorRgbNet\Artemis.Plugins.LayerBrushes.ColorRgbNet.csproj", "{301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LayerEffects", "LayerEffects", "{2C1477DC-7A5C-4B65-85DB-1F16A18FB2EC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.LayerEffects.Filter", "Plugins\Artemis.Plugins.LayerEffects.Filter\Artemis.Plugins.LayerEffects.Filter.csproj", "{62214042-667E-4B29-B64E-1A68CE6FE209}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -237,6 +241,14 @@ Global
{301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}.Release|Any CPU.Build.0 = Release|Any CPU {301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}.Release|Any CPU.Build.0 = Release|Any CPU
{301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}.Release|x64.ActiveCfg = Release|Any CPU {301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}.Release|x64.ActiveCfg = Release|Any CPU
{301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}.Release|x64.Build.0 = Release|Any CPU {301C3AAA-9F79-46A5-9B9D-86F076C5BDD1}.Release|x64.Build.0 = Release|Any CPU
{62214042-667E-4B29-B64E-1A68CE6FE209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62214042-667E-4B29-B64E-1A68CE6FE209}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62214042-667E-4B29-B64E-1A68CE6FE209}.Debug|x64.ActiveCfg = Debug|Any CPU
{62214042-667E-4B29-B64E-1A68CE6FE209}.Debug|x64.Build.0 = Debug|Any CPU
{62214042-667E-4B29-B64E-1A68CE6FE209}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62214042-667E-4B29-B64E-1A68CE6FE209}.Release|Any CPU.Build.0 = Release|Any CPU
{62214042-667E-4B29-B64E-1A68CE6FE209}.Release|x64.ActiveCfg = Release|Any CPU
{62214042-667E-4B29-B64E-1A68CE6FE209}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -261,6 +273,8 @@ Global
{A311DC47-42A2-4DD4-B921-50FBF7A33F41} = {E830A02B-A7E5-4A6B-943F-76B0A542630C} {A311DC47-42A2-4DD4-B921-50FBF7A33F41} = {E830A02B-A7E5-4A6B-943F-76B0A542630C}
{B258A061-FA19-4835-8DC4-E9C3AE3664A0} = {E830A02B-A7E5-4A6B-943F-76B0A542630C} {B258A061-FA19-4835-8DC4-E9C3AE3664A0} = {E830A02B-A7E5-4A6B-943F-76B0A542630C}
{301C3AAA-9F79-46A5-9B9D-86F076C5BDD1} = {A311DC47-42A2-4DD4-B921-50FBF7A33F41} {301C3AAA-9F79-46A5-9B9D-86F076C5BDD1} = {A311DC47-42A2-4DD4-B921-50FBF7A33F41}
{2C1477DC-7A5C-4B65-85DB-1F16A18FB2EC} = {E830A02B-A7E5-4A6B-943F-76B0A542630C}
{62214042-667E-4B29-B64E-1A68CE6FE209} = {2C1477DC-7A5C-4B65-85DB-1F16A18FB2EC}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C203080A-4473-4CC2-844B-F552EA43D66A} SolutionGuid = {C203080A-4473-4CC2-844B-F552EA43D66A}

View File

@ -0,0 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<ShouldIncludeNativeSkiaSharp>false</ShouldIncludeNativeSkiaSharp>
<AssemblyTitle>Artemis.Plugins.LayerEffects.Filter</AssemblyTitle>
<Product>Artemis.Plugins.LayerEffects.Filter</Product>
<Copyright>Copyright © 2019</Copyright>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<UseWPF>true</UseWPF>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugType>full</DebugType>
<LangVersion>7</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<DebugType>pdbonly</DebugType>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Include="plugin.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="SkiaSharp" Version="1.68.3" />
<PackageReference Include="Stylet" Version="1.3.2" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Artemis.Core\Artemis.Core.csproj">
<Private>false</Private>
</ProjectReference>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(BuildingInsideVisualStudio)' == 'true'">
<Exec Command="echo Copying resources to plugin output directory&#xD;&#xA;XCOPY &quot;$(ProjectDir)Images&quot; &quot;$(TargetDir)Images&quot; /s /q /i /y&#xD;&#xA;XCOPY &quot;$(ProjectDir)Layouts&quot; &quot;$(TargetDir)Layouts&quot; /s /q /i /y&#xD;&#xA;echo Copying plugin to Artemis.UI output directory&#xD;&#xA;XCOPY &quot;$(TargetDir.TrimEnd('\'))&quot; &quot;$(SolutionDir)\Artemis.UI\$(OutDir)Plugins\$(ProjectName)&quot; /s /q /i /y" />
</Target>
</Project>

View File

@ -0,0 +1,29 @@
using Artemis.Core.Plugins.LayerEffect.Abstract;
using SkiaSharp;
namespace Artemis.Plugins.LayerEffects.Filter
{
public class FilterEffect : LayerEffect<FilterEffectProperties>
{
public override void EnableLayerEffect()
{
}
public override void DisableLayerEffect()
{
}
public override void Update(double deltaTime)
{
}
public override void PreProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint)
{
paint.ImageFilter = SKImageFilter.CreateBlur(Properties.BlurAmount.CurrentValue.Width, Properties.BlurAmount.CurrentValue.Height, paint.ImageFilter);
}
public override void PostProcess(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint)
{
}
}
}

View File

@ -0,0 +1,20 @@
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.Core.Models.Profile.LayerProperties.Types;
namespace Artemis.Plugins.LayerEffects.Filter
{
public class FilterEffectProperties : LayerPropertyGroup
{
[PropertyDescription(Description = "The amount of blur to apply")]
public SKSizeLayerProperty BlurAmount { get; set; }
protected override void PopulateDefaults()
{
}
protected override void OnPropertiesInitialized()
{
}
}
}

View File

@ -0,0 +1,16 @@
using Artemis.Core.Plugins.Abstract;
namespace Artemis.Plugins.LayerEffects.Filter
{
public class FilterEffectProvider : LayerEffectProvider
{
public override void EnablePlugin()
{
AddLayerEffectDescriptor<FilterEffect>("Filter", "A layer effect providing different types of filters", "ImageFilterFrames");
}
public override void DisablePlugin()
{
}
}
}

View File

@ -0,0 +1,7 @@
{
"Guid": "fca5b5d6-3f86-4ea7-a271-06ec3fc219e2",
"Name": "Filter layer effect",
"Description": "A layer effect providing different types of filters.",
"Version": "1.0.0.0",
"Main": "Artemis.Plugins.LayerEffects.Filter.dll"
}