mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Profile editor - Added effect renaming
Core - Fixed effect loading Core - Fixed some effects not applying on per-LED brushes
This commit is contained in:
parent
2bf36fbf20
commit
cd8656cb0d
3
src/.idea/.idea.Artemis/.idea/avalonia.xml
generated
3
src/.idea/.idea.Artemis/.idea/avalonia.xml
generated
@ -18,9 +18,12 @@
|
||||
<entry key="Artemis.UI/DefaultTypes/PropertyInput/ColorGradientPropertyInputView.axaml" value="Artemis.UI.Windows/Artemis.UI.Windows.csproj" />
|
||||
<entry key="Artemis.UI/Screens/ProfileEditor/Panels/Properties/Dialogs/AddEffectView.axaml" value="Artemis.UI.Windows/Artemis.UI.Windows.csproj" />
|
||||
<entry key="Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertiesView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||
<entry key="Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||
<entry key="Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/SidebarCategoryEditView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||
<entry key="Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupView.axaml" value="Artemis.UI.Windows/Artemis.UI.Windows.csproj" />
|
||||
<entry key="Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreePropertyView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||
<entry key="Artemis.UI/Screens/Settings/Tabs/GeneralTabView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||
<entry key="Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||
<entry key="Avalonia/Artemis.UI/Screens/Debugger/Tabs/Render/RenderDebugView.axaml" value="Avalonia/Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||
<entry key="Avalonia/Artemis.UI/Styles/Artemis.axaml" value="Avalonia/Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||
</map>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Artemis.Core.JsonConverters;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Core.Services.Core;
|
||||
@ -14,6 +15,11 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// The Artemis.Core assembly
|
||||
/// </summary>
|
||||
public static readonly Assembly CoreAssembly = typeof(Constants).Assembly;
|
||||
|
||||
/// <summary>
|
||||
/// The full path to the Artemis application folder
|
||||
/// </summary>
|
||||
|
||||
@ -627,13 +627,12 @@ namespace Artemis.Core
|
||||
if (LayerBrush == null)
|
||||
throw new ArtemisCoreException("The layer is not yet ready for rendering");
|
||||
|
||||
using SKAutoCanvasRestore _ = new(canvas);
|
||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
||||
{
|
||||
if (!baseLayerEffect.Suspended)
|
||||
baseLayerEffect.InternalPreProcess(canvas, bounds, layerPaint);
|
||||
}
|
||||
|
||||
using SKAutoCanvasRestore _ = new(canvas);
|
||||
canvas.ClipPath(renderPath);
|
||||
|
||||
// Restore the blend mode before doing the actual render
|
||||
|
||||
@ -35,7 +35,6 @@ namespace Artemis.Core.LayerBrushes
|
||||
canvas.SetMatrix(canvas.TotalMatrix.PreConcat(Layer.GetTransformMatrix(true, false, false, true).Invert()));
|
||||
|
||||
using SKPath pointsPath = new();
|
||||
using SKPaint ledPaint = new();
|
||||
foreach (ArtemisLed artemisLed in Layer.Leds)
|
||||
{
|
||||
pointsPath.AddPoly(new[]
|
||||
@ -61,7 +60,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
continue;
|
||||
|
||||
// Let the brush determine the color
|
||||
ledPaint.Color = GetColor(artemisLed, renderPoint);
|
||||
paint.Color = GetColor(artemisLed, renderPoint);
|
||||
|
||||
SKRect ledRectangle = SKRect.Create(
|
||||
artemisLed.AbsoluteRectangle.Left - Layer.Bounds.Left,
|
||||
@ -70,7 +69,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
artemisLed.AbsoluteRectangle.Height
|
||||
);
|
||||
|
||||
canvas.DrawRect(ledRectangle, ledPaint);
|
||||
canvas.DrawRect(ledRectangle, paint);
|
||||
}
|
||||
}, "Failed to render");
|
||||
}
|
||||
|
||||
@ -222,8 +222,8 @@ namespace Artemis.Core.LayerEffects
|
||||
/// <inheritdoc />
|
||||
public void Load()
|
||||
{
|
||||
Name = LayerEffectEntity.Name;
|
||||
HasBeenRenamed = LayerEffectEntity.HasBeenRenamed;
|
||||
Name = HasBeenRenamed ? LayerEffectEntity.Name : Descriptor.DisplayName;
|
||||
Order = LayerEffectEntity.Order;
|
||||
}
|
||||
|
||||
|
||||
@ -87,6 +87,7 @@ public class LayerEffectDescriptor
|
||||
else
|
||||
{
|
||||
effect.LayerEffectEntity = new LayerEffectEntity();
|
||||
effect.Name = DisplayName;
|
||||
effect.Initialize();
|
||||
effect.Save();
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ namespace Artemis.Core
|
||||
{
|
||||
lock (Registrations)
|
||||
{
|
||||
return Registrations.FirstOrDefault(d => d.PluginFeature.Id == providerId && d.LayerEffectDescriptor.LayerEffectType?.Name == typeName);
|
||||
return Registrations.FirstOrDefault(d => d.PluginFeature.Id == providerId && d.LayerEffectDescriptor.LayerEffectType?.FullName == typeName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.LayerEffects;
|
||||
|
||||
namespace Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a profile editor command that can be used to remove a layer effect from a profile element.
|
||||
/// </summary>
|
||||
public class RemoveLayerEffect : IProfileEditorCommand, IDisposable
|
||||
{
|
||||
private readonly RenderProfileElement _renderProfileElement;
|
||||
private readonly BaseLayerEffect _layerEffect;
|
||||
private bool _executed;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="RemoveLayerEffect"/> class.
|
||||
/// </summary>
|
||||
public RemoveLayerEffect(BaseLayerEffect layerEffect)
|
||||
{
|
||||
_renderProfileElement = layerEffect.ProfileElement;
|
||||
_layerEffect = layerEffect;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DisplayName => "Remove layer effect";
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Execute()
|
||||
{
|
||||
_renderProfileElement.RemoveLayerEffect(_layerEffect);
|
||||
_executed = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Undo()
|
||||
{
|
||||
_renderProfileElement.AddLayerEffect(_layerEffect);
|
||||
_executed = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
if (_executed)
|
||||
_layerEffect.Dispose();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.LayerEffects;
|
||||
|
||||
namespace Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a profile editor command that can be used to rename a layer effect
|
||||
/// </summary>
|
||||
public class RenameLayerEffect : IProfileEditorCommand
|
||||
{
|
||||
private readonly BaseLayerEffect _layerEffect;
|
||||
private readonly string _name;
|
||||
private readonly string _oldName;
|
||||
private readonly bool _wasRenamed;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="RenameLayerEffect"/> class.
|
||||
/// </summary>
|
||||
public RenameLayerEffect(BaseLayerEffect layerEffect, string name)
|
||||
{
|
||||
_layerEffect = layerEffect;
|
||||
_name = name;
|
||||
_oldName = layerEffect.Name;
|
||||
_wasRenamed = layerEffect.HasBeenRenamed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DisplayName => "Rename layer effect";
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Execute()
|
||||
{
|
||||
_layerEffect.Name = _name;
|
||||
_layerEffect.HasBeenRenamed = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Undo()
|
||||
{
|
||||
_layerEffect.Name = _oldName;
|
||||
_layerEffect.HasBeenRenamed = _wasRenamed;
|
||||
}
|
||||
}
|
||||
@ -68,6 +68,14 @@
|
||||
<Compile Update="Screens\VisualScripting\NodeScriptWindowView.axaml.cs">
|
||||
<DependentUpon>NodeScriptWindowView.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Screens\ProfileEditor\Panels\Properties\Tree\ContentDialogs\LayerEffectRenameView.axaml.cs">
|
||||
<DependentUpon>LayerEffectRenameView.axaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Screens\ProfileEditor\Panels\Properties\Tree\ContentDialogs\SidebarCategoryEditView.axaml.cs">
|
||||
<DependentUpon>SidebarCategoryEditView.axaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AvaloniaXaml Update="DefaultTypes\PropertyInput\StringPropertyInputView.axaml">
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Artemis.Core;
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.PropertyInput;
|
||||
using ReactiveUI;
|
||||
@ -14,17 +15,17 @@ public class SKPointPropertyInputViewModel : PropertyInputViewModel<SKPoint>
|
||||
{
|
||||
if (LayerProperty.PropertyDescription.MinInputValue.IsNumber())
|
||||
{
|
||||
this.ValidationRule(vm => vm.X, i => i >= (float) LayerProperty.PropertyDescription.MinInputValue,
|
||||
this.ValidationRule(vm => vm.X, i => i >= Convert.ToSingle(LayerProperty.PropertyDescription.MinInputValue),
|
||||
$"X must be equal to or greater than {LayerProperty.PropertyDescription.MinInputValue}.");
|
||||
this.ValidationRule(vm => vm.Y, i => i >= (float) LayerProperty.PropertyDescription.MinInputValue,
|
||||
this.ValidationRule(vm => vm.Y, i => i >= Convert.ToSingle(LayerProperty.PropertyDescription.MinInputValue),
|
||||
$"Y must be equal to or greater than {LayerProperty.PropertyDescription.MinInputValue}.");
|
||||
}
|
||||
|
||||
if (LayerProperty.PropertyDescription.MaxInputValue.IsNumber())
|
||||
{
|
||||
this.ValidationRule(vm => vm.X, i => i <= (float) LayerProperty.PropertyDescription.MaxInputValue,
|
||||
this.ValidationRule(vm => vm.X, i => i <= Convert.ToSingle(LayerProperty.PropertyDescription.MaxInputValue),
|
||||
$"X must be equal to or smaller than {LayerProperty.PropertyDescription.MaxInputValue}.");
|
||||
this.ValidationRule(vm => vm.Y, i => i <= (float) LayerProperty.PropertyDescription.MaxInputValue,
|
||||
this.ValidationRule(vm => vm.Y, i => i <= Convert.ToSingle(LayerProperty.PropertyDescription.MaxInputValue),
|
||||
$"Y must be equal to or smaller than {LayerProperty.PropertyDescription.MaxInputValue}.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Artemis.Core;
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.PropertyInput;
|
||||
using ReactiveUI;
|
||||
@ -16,17 +17,17 @@ public class SKSizePropertyInputViewModel : PropertyInputViewModel<SKSize>
|
||||
{
|
||||
if (LayerProperty.PropertyDescription.MinInputValue.IsNumber())
|
||||
{
|
||||
this.ValidationRule(vm => vm.Width, i => i >= (float) LayerProperty.PropertyDescription.MinInputValue,
|
||||
this.ValidationRule(vm => vm.Width, i => i >= Convert.ToSingle(LayerProperty.PropertyDescription.MinInputValue),
|
||||
$"Width must be equal to or greater than {LayerProperty.PropertyDescription.MinInputValue}.");
|
||||
this.ValidationRule(vm => vm.Height, i => i >= (float) LayerProperty.PropertyDescription.MinInputValue,
|
||||
this.ValidationRule(vm => vm.Height, i => i >= Convert.ToSingle(LayerProperty.PropertyDescription.MinInputValue),
|
||||
$"Height must be equal to or greater than {LayerProperty.PropertyDescription.MinInputValue}.");
|
||||
}
|
||||
|
||||
if (LayerProperty.PropertyDescription.MaxInputValue.IsNumber())
|
||||
{
|
||||
this.ValidationRule(vm => vm.Width, i => i <= (float) LayerProperty.PropertyDescription.MaxInputValue,
|
||||
this.ValidationRule(vm => vm.Width, i => i <= Convert.ToSingle(LayerProperty.PropertyDescription.MaxInputValue),
|
||||
$"Width must be equal to or smaller than {LayerProperty.PropertyDescription.MaxInputValue}.");
|
||||
this.ValidationRule(vm => vm.Height, i => i <= (float) LayerProperty.PropertyDescription.MaxInputValue,
|
||||
this.ValidationRule(vm => vm.Height, i => i <= Convert.ToSingle(LayerProperty.PropertyDescription.MaxInputValue),
|
||||
$"Height must be equal to or smaller than {LayerProperty.PropertyDescription.MaxInputValue}.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +117,8 @@ public class PropertyGroupViewModel : ViewModelBase, IDisposable
|
||||
{
|
||||
// Get all properties and property groups and create VMs for them
|
||||
// The group has methods for getting this without reflection but then we lose the order of the properties as they are defined on the group
|
||||
foreach (PropertyInfo propertyInfo in LayerPropertyGroup.GetType().GetProperties())
|
||||
// Sorting is done to ensure properties defined by the Core (such as on layers) are always on top.
|
||||
foreach (PropertyInfo propertyInfo in LayerPropertyGroup.GetType().GetProperties().OrderBy(p => p.DeclaringType?.Assembly != Constants.CoreAssembly))
|
||||
{
|
||||
if (Attribute.IsDefined(propertyInfo, typeof(LayerPropertyIgnoreAttribute)))
|
||||
continue;
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:contentDialogs="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs.LayerEffectRenameView"
|
||||
x:DataType="contentDialogs:LayerEffectRenameViewModel">
|
||||
<StackPanel>
|
||||
<StackPanel.KeyBindings>
|
||||
<KeyBinding Gesture="Enter" Command="{CompiledBinding Confirm}" />
|
||||
</StackPanel.KeyBindings>
|
||||
<TextBox Name="NameTextBox" Text="{CompiledBinding LayerEffectName}" Watermark="Layer effect name"/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@ -0,0 +1,35 @@
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.UI.Shared.Extensions;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Threading;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs;
|
||||
|
||||
public class LayerEffectRenameView : ReactiveUserControl<LayerEffectRenameViewModel>
|
||||
{
|
||||
public LayerEffectRenameView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(_ =>
|
||||
{
|
||||
this.ClearAllDataValidationErrors();
|
||||
Dispatcher.UIThread.Post(DelayedAutoFocus);
|
||||
});
|
||||
}
|
||||
|
||||
private async void DelayedAutoFocus()
|
||||
{
|
||||
// Don't ask
|
||||
await Task.Delay(200);
|
||||
this.Get<TextBox>("NameTextBox").SelectAll();
|
||||
this.Get<TextBox>("NameTextBox").Focus();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
using System.Reactive;
|
||||
using Artemis.Core.LayerEffects;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs
|
||||
{
|
||||
public class LayerEffectRenameViewModel : ContentDialogViewModelBase
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly BaseLayerEffect _layerEffect;
|
||||
private string? _layerEffectName;
|
||||
|
||||
public LayerEffectRenameViewModel(IProfileEditorService profileEditorService, BaseLayerEffect layerEffect)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_layerEffect = layerEffect;
|
||||
_layerEffectName = layerEffect.Name;
|
||||
|
||||
Confirm = ReactiveCommand.Create(ExecuteConfirm, ValidationContext.Valid);
|
||||
this.ValidationRule(vm => vm.LayerEffectName, categoryName => !string.IsNullOrWhiteSpace(categoryName), "You must specify a valid name");
|
||||
}
|
||||
|
||||
public string? LayerEffectName
|
||||
{
|
||||
get => _layerEffectName;
|
||||
set => this.RaiseAndSetIfChanged(ref _layerEffectName, value);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> Confirm { get; }
|
||||
|
||||
private void ExecuteConfirm()
|
||||
{
|
||||
if (LayerEffectName == null)
|
||||
return;
|
||||
|
||||
_profileEditorService.ExecuteCommand(new RenameLayerEffect(_layerEffect, LayerEffectName));
|
||||
ContentDialog?.Hide(ContentDialogResult.Primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,8 @@
|
||||
xmlns:properties="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.TreeGroupView">
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.TreeGroupView"
|
||||
x:DataType="viewModel:TreeGroupViewModel">
|
||||
<UserControl.Resources>
|
||||
<converters:PropertyTreeMarginConverter x:Key="PropertyTreeMarginConverter" Length="20" />
|
||||
<sharedConverters:EnumToBooleanConverter x:Key="EnumBoolConverter" />
|
||||
@ -26,8 +27,8 @@
|
||||
Height="29">
|
||||
<Grid Margin="{Binding Converter={StaticResource PropertyTreeMarginConverter}}" ColumnDefinitions="19,*">
|
||||
|
||||
<avalonia:MaterialIcon Classes.chevron-collapsed="{Binding !PropertyGroupViewModel.IsExpanded}"
|
||||
IsVisible="{Binding PropertyGroupViewModel.HasChildren}"
|
||||
<avalonia:MaterialIcon Classes.chevron-collapsed="{CompiledBinding !PropertyGroupViewModel.IsExpanded}"
|
||||
IsVisible="{CompiledBinding PropertyGroupViewModel.HasChildren}"
|
||||
Kind="ChevronDown"
|
||||
Grid.Column="0"
|
||||
Margin="5 0"
|
||||
@ -42,59 +43,59 @@
|
||||
|
||||
<StackPanel Grid.Column="1">
|
||||
<!-- Type: None -->
|
||||
<TextBlock Text="{Binding LayerPropertyGroup.GroupDescription.Name}"
|
||||
ToolTip.Tip="{Binding LayerPropertyGroup.GroupDescription.Description}"
|
||||
<TextBlock Text="{CompiledBinding LayerPropertyGroup.GroupDescription.Name}"
|
||||
ToolTip.Tip="{CompiledBinding LayerPropertyGroup.GroupDescription.Description}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="3 5 0 5"
|
||||
IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.None}}" />
|
||||
IsVisible="{CompiledBinding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.None}}" />
|
||||
|
||||
<!-- Type: General -->
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="0 5"
|
||||
IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.General}}">
|
||||
IsVisible="{CompiledBinding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.General}}">
|
||||
<avalonia:MaterialIcon Kind="HammerWrench" Margin="0 0 5 0" />
|
||||
<TextBlock ToolTip.Tip="{Binding LayerPropertyGroup.GroupDescription.Description}">General</TextBlock>
|
||||
<TextBlock ToolTip.Tip="{CompiledBinding LayerPropertyGroup.GroupDescription.Description}">General</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Type: Transform -->
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="0 5"
|
||||
IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.Transform}}">
|
||||
IsVisible="{CompiledBinding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.Transform}}">
|
||||
<avalonia:MaterialIcon Kind="TransitConnectionVariant" Margin="0 0 5 0" />
|
||||
<TextBlock ToolTip.Tip="{Binding LayerPropertyGroup.GroupDescription.Description}">Transform</TextBlock>
|
||||
<TextBlock ToolTip.Tip="{CompiledBinding LayerPropertyGroup.GroupDescription.Description}">Transform</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Type: LayerBrushRoot -->
|
||||
<Grid IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerBrushRoot}}"
|
||||
<Grid IsVisible="{CompiledBinding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerBrushRoot}}"
|
||||
Height="29"
|
||||
ColumnDefinitions="Auto,Auto,Auto,*">
|
||||
<shared:ArtemisIcon Grid.Column="0"
|
||||
Icon="{Binding LayerBrush.Descriptor.Icon}"
|
||||
Icon="{CompiledBinding LayerBrush.Descriptor.Icon}"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="0 0 5 0" />
|
||||
<TextBlock Grid.Column="1"
|
||||
ToolTip.Tip="{Binding LayerBrush.Descriptor.Description}"
|
||||
ToolTip.Tip="{CompiledBinding LayerBrush.Descriptor.Description}"
|
||||
Margin="0 5 5 0">
|
||||
Brush -
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding LayerBrush.Descriptor.DisplayName}"
|
||||
ToolTip.Tip="{Binding LayerBrush.Descriptor.Description}"
|
||||
Text="{CompiledBinding LayerBrush.Descriptor.DisplayName}"
|
||||
ToolTip.Tip="{CompiledBinding LayerBrush.Descriptor.Description}"
|
||||
Margin="0 5 0 0" />
|
||||
|
||||
<StackPanel Grid.Column="3"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{Binding LayerBrush.ConfigurationDialog, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
IsVisible="{CompiledBinding LayerBrush.ConfigurationDialog, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock VerticalAlignment="Center">Extra options available!</TextBlock>
|
||||
<avalonia:MaterialIcon Kind="ChevronRight" VerticalAlignment="Center">
|
||||
<avalonia:MaterialIcon.RenderTransform>
|
||||
<TranslateTransform X="0" />
|
||||
</avalonia:MaterialIcon.RenderTransform>
|
||||
</avalonia:MaterialIcon>
|
||||
<Button Classes="icon-button" ToolTip.Tip="Open brush settings" Width="24" Height="24" HorizontalAlignment="Right" Command="{Binding OpenBrushSettings}">
|
||||
<Button Classes="icon-button" ToolTip.Tip="Open brush settings" Width="24" Height="24" HorizontalAlignment="Right" Command="{CompiledBinding OpenBrushSettings}">
|
||||
<avalonia:MaterialIcon Kind="Settings" Height="16" Width="16" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
@ -102,61 +103,45 @@
|
||||
</Grid>
|
||||
|
||||
<!-- Type: LayerEffectRoot -->
|
||||
<Grid IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerEffectRoot}}"
|
||||
<Grid IsVisible="{CompiledBinding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerEffectRoot}}"
|
||||
Height="29"
|
||||
ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto">
|
||||
<shared:ArtemisIcon
|
||||
Grid.Column="0"
|
||||
Cursor="SizeNorthSouth"
|
||||
Icon="{Binding LayerEffect.Descriptor.Icon}"
|
||||
Icon="{CompiledBinding LayerEffect.Descriptor.Icon}"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="0 0 5 0"
|
||||
Background="Transparent" />
|
||||
<TextBlock Grid.Column="1" ToolTip.Tip="{Binding LayerEffect.Descriptor.Description}" Margin="0 5 0 0">
|
||||
<TextBlock Grid.Column="1" ToolTip.Tip="{CompiledBinding LayerEffect.Descriptor.Description}" Margin="0 5 0 0">
|
||||
Effect
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="2"
|
||||
ToolTip.Tip="{Binding LayerEffect.Descriptor.Description}"
|
||||
ToolTip.Tip="{CompiledBinding LayerEffect.Descriptor.Description}"
|
||||
Margin="3 5">
|
||||
-
|
||||
</TextBlock>
|
||||
|
||||
<!-- Show either the descriptors display name or, if set, the effect name -->
|
||||
<TextBlock Grid.Column="3"
|
||||
Text="{Binding LayerEffect.Descriptor.DisplayName}"
|
||||
ToolTip.Tip="{Binding LayerEffect.Descriptor.Description}"
|
||||
Text="{CompiledBinding LayerEffect.Descriptor.DisplayName}"
|
||||
ToolTip.Tip="{CompiledBinding LayerEffect.Descriptor.Description}"
|
||||
Margin="0 5"
|
||||
IsVisible="{Binding !LayerEffect.Name, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||
IsVisible="{CompiledBinding !LayerEffect.HasBeenRenamed}" />
|
||||
<TextBlock Grid.Column="4"
|
||||
Text="{Binding LayerEffect.Name}"
|
||||
ToolTip.Tip="{Binding LayerEffect.Descriptor.Description}"
|
||||
Text="{CompiledBinding LayerEffect.Name}"
|
||||
ToolTip.Tip="{CompiledBinding LayerEffect.Descriptor.Description}"
|
||||
Margin="0 5"
|
||||
IsVisible="{Binding LayerEffect.Name, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||
IsVisible="{CompiledBinding LayerEffect.HasBeenRenamed}" />
|
||||
|
||||
<StackPanel Grid.Column="5" Orientation="Horizontal" Spacing="2">
|
||||
<Button Classes="icon-button"
|
||||
ToolTip.Tip="Toggle suspended state"
|
||||
Width="24"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding SuspendedToggled}">
|
||||
<avalonia:MaterialIcon Kind="EyeOff" Height="16" Width="16" IsVisible="True" />
|
||||
</Button>
|
||||
<Button Classes="icon-button"
|
||||
ToolTip.Tip="Toggle suspended state"
|
||||
Width="24"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding SuspendedToggled}">
|
||||
<avalonia:MaterialIcon Kind="Eye" Height="16" Width="16" IsVisible="True" />
|
||||
</Button>
|
||||
<Button Classes="icon-button"
|
||||
ToolTip.Tip="Rename"
|
||||
Width="24"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding RenameEffect}">
|
||||
Command="{CompiledBinding RenameEffect}">
|
||||
<avalonia:MaterialIcon Kind="RenameBox" Height="16" Width="16" />
|
||||
</Button>
|
||||
<Button Classes="icon-button"
|
||||
@ -164,8 +149,8 @@
|
||||
Width="24"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding OpenEffectSettings}"
|
||||
IsVisible="{Binding LayerEffect.ConfigurationDialog, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
Command="{CompiledBinding OpenEffectSettings}"
|
||||
IsVisible="{CompiledBinding LayerEffect.ConfigurationDialog, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<avalonia:MaterialIcon Kind="Settings" Height="16" Width="16" />
|
||||
</Button>
|
||||
<Button Classes="icon-button"
|
||||
@ -173,7 +158,7 @@
|
||||
Width="24"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding DeleteEffect}">
|
||||
Command="{CompiledBinding DeleteEffect}">
|
||||
<avalonia:MaterialIcon Kind="TrashCan" Height="16" Width="16" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
@ -186,15 +171,15 @@
|
||||
Do not bind directly to the PropertyGroupViewModel.Children collection
|
||||
Instead use a reference provided by the VM that is null when collapsed, virtualization for noobs
|
||||
-->
|
||||
<ItemsControl Items="{Binding Children}"
|
||||
IsVisible="{Binding PropertyGroupViewModel.IsExpanded}"
|
||||
<ItemsControl Items="{CompiledBinding Children}"
|
||||
IsVisible="{CompiledBinding PropertyGroupViewModel.IsExpanded}"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ItemsControl.DataTemplates>
|
||||
<DataTemplate DataType="properties:PropertyGroupViewModel">
|
||||
<ContentControl Content="{Binding TreeGroupViewModel}" IsVisible="{Binding IsVisible}" />
|
||||
<ContentControl Content="{CompiledBinding TreeGroupViewModel}" IsVisible="{CompiledBinding IsVisible}" />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="properties:PropertyViewModel">
|
||||
<ContentControl Content="{Binding TreePropertyViewModel}" IsVisible="{Binding IsVisible}" />
|
||||
<ContentControl Content="{CompiledBinding TreePropertyViewModel}" IsVisible="{CompiledBinding IsVisible}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.DataTemplates>
|
||||
</ItemsControl>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
@ -8,12 +9,15 @@ using Artemis.Core;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Artemis.Core.LayerEffects;
|
||||
using Artemis.UI.Exceptions;
|
||||
using Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs;
|
||||
using Artemis.UI.Screens.ProfileEditor.Properties.Windows;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.LayerBrushes;
|
||||
using Artemis.UI.Shared.LayerEffects;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Builders;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using Ninject;
|
||||
using Ninject.Parameters;
|
||||
using ReactiveUI;
|
||||
@ -41,19 +45,25 @@ public class TreeGroupViewModel : ActivatableViewModelBase
|
||||
});
|
||||
|
||||
// TODO: Update ProfileElementPropertyGroupViewModel visibility on change (can remove the sub on line 41 as well then)
|
||||
OpenBrushSettings = ReactiveCommand.CreateFromTask(ExecuteOpenBrushSettings);
|
||||
OpenEffectSettings = ReactiveCommand.CreateFromTask(ExecuteOpenEffectSettings);
|
||||
RenameEffect = ReactiveCommand.CreateFromTask(ExecuteRenameEffect);
|
||||
DeleteEffect = ReactiveCommand.Create(ExecuteDeleteEffect);
|
||||
}
|
||||
|
||||
|
||||
public PropertyGroupViewModel PropertyGroupViewModel { get; }
|
||||
public LayerPropertyGroup LayerPropertyGroup => PropertyGroupViewModel.LayerPropertyGroup;
|
||||
public BaseLayerBrush? LayerBrush => PropertyGroupViewModel.LayerBrush;
|
||||
public BaseLayerEffect? LayerEffect => PropertyGroupViewModel.LayerEffect;
|
||||
|
||||
public ObservableCollection<ViewModelBase>? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null;
|
||||
|
||||
public LayerPropertyGroupType GroupType { get; private set; }
|
||||
public ObservableCollection<ViewModelBase>? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null;
|
||||
|
||||
public ReactiveCommand<Unit, Unit> OpenBrushSettings { get; }
|
||||
public ReactiveCommand<Unit, Unit> OpenEffectSettings { get; }
|
||||
public ReactiveCommand<Unit, Unit> RenameEffect { get; }
|
||||
public ReactiveCommand<Unit, Unit> DeleteEffect { get; }
|
||||
|
||||
public async Task OpenBrushSettings()
|
||||
private async Task ExecuteOpenBrushSettings()
|
||||
{
|
||||
if (LayerBrush?.ConfigurationDialog is not LayerBrushConfigurationDialog configurationViewModel)
|
||||
return;
|
||||
@ -83,7 +93,7 @@ public class TreeGroupViewModel : ActivatableViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
public async Task OpenEffectSettings()
|
||||
private async Task ExecuteOpenEffectSettings()
|
||||
{
|
||||
if (LayerEffect?.ConfigurationDialog is not LayerEffectConfigurationDialog configurationViewModel)
|
||||
return;
|
||||
@ -113,14 +123,26 @@ public class TreeGroupViewModel : ActivatableViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RenameEffect()
|
||||
private async Task ExecuteRenameEffect()
|
||||
{
|
||||
await _windowService.ShowConfirmContentDialog("Not yet implemented", "Try again later :p");
|
||||
if (LayerEffect == null)
|
||||
return;
|
||||
|
||||
await _windowService.CreateContentDialog()
|
||||
.WithTitle("Rename layer effect")
|
||||
.WithViewModel(out LayerEffectRenameViewModel vm, ("layerEffect", LayerEffect))
|
||||
.HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Confirm))
|
||||
.WithCloseButtonText("Cancel")
|
||||
.WithDefaultButton(ContentDialogButton.Primary)
|
||||
.ShowAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteEffect()
|
||||
private void ExecuteDeleteEffect()
|
||||
{
|
||||
await _windowService.ShowConfirmContentDialog("Not yet implemented", "Try again later :p");
|
||||
if (LayerEffect == null)
|
||||
return;
|
||||
|
||||
_profileEditorService.ExecuteCommand(new RemoveLayerEffect(LayerEffect));
|
||||
}
|
||||
|
||||
public double GetDepth()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user