UI - Many misc fixes I can't remember

Profile editor - Removed layer outline, increasing performance by a lot
Device visualizer - Streamlined custom
Device providers - Added debug device provider
ASUS - Added Maximus X Hero thanks @copystring
Plugin core - Added PerLedLayerBrush
Noise layer - Converted to PerLedLayerBrush, increasing performance and quality
This commit is contained in:
SpoinkyNL committed 2020-08-02 00:20:25 +02:00
1 parent f36049a0e1
commit 29489fe7b3
29 files changed
+767 -277

No files matched your search

@@ -65,7 +65,7 @@ namespace Artemis.UI.Ninject.Factories
public interface IProfileLayerVmFactory : IVmFactory
{
ProfileLayerViewModel Create(Layer layer);
ProfileLayerViewModel Create(Layer layer, ProfileViewModel profileViewModel);
}
public interface IVisualizationToolVmFactory : IVmFactory
@@ -104,43 +104,45 @@
</Button.ContextMenu>
</Button>
<!-- Right side property if type is dynamic -->
<Button Grid.Row="0"
Grid.Column="3"
Background="{DynamicResource PrimaryHueMidBrush}"
BorderBrush="{DynamicResource PrimaryHueMidBrush}"
Style="{StaticResource DisplayConditionButton}"
ToolTip="{Binding SelectedRightSideProperty.DisplayPropertyPath}"
Click="PropertyButton_OnClick"
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding RightSideDataModel.Children}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Header" Value="{Binding PropertyDescription.Name}" />
<Setter Property="ToolTip" Value="{Binding PropertyDescription.Description}" />
<Setter Property="Command" Value="{Binding Data.SelectRightPropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" />
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>
<Grid>
<TextBlock Text="{Binding SelectedRightSideProperty.PropertyDescription.Name}"
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="« Select a property »"
FontStyle="Italic"
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
</Grid>
</Button>
<Grid Grid.Row="0"
Grid.Column="3"
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
<materialDesign:Transitioner SelectedIndex="{Binding RightSideTransitionIndex}" DefaultTransitionOrigin="0.5, 0.5" Margin="3 -4">
Visibility="{Binding SelectedOperator.SupportsRightSide, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<!-- Right side property if type is dynamic -->
<Button Background="{DynamicResource PrimaryHueMidBrush}"
BorderBrush="{DynamicResource PrimaryHueMidBrush}"
Style="{StaticResource DisplayConditionButton}"
ToolTip="{Binding SelectedRightSideProperty.DisplayPropertyPath}"
Click="PropertyButton_OnClick"
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding RightSideDataModel.Children}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Header" Value="{Binding PropertyDescription.Name}" />
<Setter Property="ToolTip" Value="{Binding PropertyDescription.Description}" />
<Setter Property="Command" Value="{Binding Data.SelectRightPropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" />
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>
<Grid>
<TextBlock Text="{Binding SelectedRightSideProperty.PropertyDescription.Name}"
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="« Select a property »"
FontStyle="Italic"
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
</Grid>
</Button>
<!-- Right side property if type is static -->
<materialDesign:Transitioner SelectedIndex="{Binding RightSideTransitionIndex}"
DefaultTransitionOrigin="0.5, 0.5"
Margin="3 -4"
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
<Button Style="{StaticResource DisplayConditionButton}"
Background="{DynamicResource PrimaryHueMidBrush}"
BorderBrush="{DynamicResource PrimaryHueMidBrush}"
@@ -151,8 +153,8 @@
<StackPanel Visibility="{Binding RightStaticValue, Converter={StaticResource NullToVisibilityConverter}}" Orientation="Horizontal">
<TextBlock FontWeight="Light"
Text="{Binding SelectedLeftSideProperty.PropertyDescription.Prefix}"
Visibility="{Binding SelectedLeftSideProperty.PropertyDescription.Prefix, Converter={StaticResource NullToVisibilityConverter}}"/>
<TextBlock Text="{Binding RightStaticValue}"/>
Visibility="{Binding SelectedLeftSideProperty.PropertyDescription.Prefix, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="{Binding RightStaticValue}" />
<TextBlock FontWeight="Light"
Text="{Binding SelectedLeftSideProperty.PropertyDescription.Affix}"
Visibility="{Binding SelectedLeftSideProperty.PropertyDescription.Affix, Converter={StaticResource NullToVisibilityConverter}}" />
@@ -102,8 +102,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public Layer SelectedLayer => SelectedProfileElement as Layer;
public Folder SelectedFolder => SelectedProfileElement as Folder;
public BindableCollection<LayerPropertyGroupViewModel> LayerPropertyGroups
{
get => _layerPropertyGroups;
@@ -197,7 +197,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
LoadWorkspaceSettings();
_profileEditorService.StopRegularRender();
Module.ActiveProfileChanged += ModuleOnActiveProfileChanged;
Task.Run(LoadProfiles);
Execute.PostToUIThread(LoadProfiles);
base.OnInitialActivate();
}
@@ -262,23 +262,20 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
profiles.Add(activeProfile);
// Populate the UI collection
Execute.PostToUIThread(() =>
Profiles.AddRange(profiles.Except(Profiles).ToList());
Profiles.RemoveRange(Profiles.Except(profiles).ToList());
var index = 0;
foreach (var profile in Profiles.OrderBy(p => p.Name).ToList())
{
Profiles.AddRange(profiles.Except(Profiles).ToList());
Profiles.RemoveRange(Profiles.Except(profiles).ToList());
var index = 0;
foreach (var profile in Profiles.OrderBy(p => p.Name).ToList())
{
Profiles.Move(Profiles.IndexOf(profile), index);
index++;
}
Profiles.Move(Profiles.IndexOf(profile), index);
index++;
}
SelectedProfile = activeProfile;
if (_profileEditorService.SelectedProfile != activeProfile)
_profileEditorService.ChangeSelectedProfile(activeProfile);
if (!activeProfile.IsActivated)
_profileService.ActivateProfile(Module, activeProfile);
});
SelectedProfile = activeProfile;
if (_profileEditorService.SelectedProfile != activeProfile)
_profileEditorService.ChangeSelectedProfile(activeProfile);
if (!activeProfile.IsActivated)
_profileService.ActivateProfile(Module, activeProfile);
}
}
}
@@ -16,8 +16,7 @@
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="Gray" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="(Path.StrokeThickness)" To="0.5" Duration="0:0:0.5" />
<ColorAnimation Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="#99808080" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
@@ -25,7 +24,6 @@
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="{StaticResource Accent700}" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="(Path.StrokeThickness)" To="1" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
@@ -38,14 +36,14 @@
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Path.Opacity)" To="0" Duration="0:0:0.5" />
<ColorAnimation Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="#A7A7A7" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Path.Opacity)" To="1" Duration="0:0:0.5" />
<ColorAnimation Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="#00A7A7A7" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
@@ -54,21 +52,10 @@
</Style>
</UserControl.Resources>
<Canvas>
<!-- The part of the layer's shape that falls outside the layer -->
<Path Data="{Binding ShapeGeometry, Mode=OneWay}"
StrokeThickness="0.5"
Style="{StaticResource SelectedShapeStyle}">
<Path Data="{Binding ShapeGeometry, Mode=OneWay}" StrokeThickness="{Binding StrokeThickness}" Style="{StaticResource SelectedShapeStyle}">
<Path.Stroke>
<SolidColorBrush Color="{StaticResource Primary700}" />
</Path.Stroke>
</Path>
<Path Data="{Binding LayerGeometry, Mode=OneWay}"
ClipToBounds="False"
Stroke="#A7A7A7"
StrokeThickness="1"
StrokeLineJoin="Round"
x:Name="LayerPath"
Style="{StaticResource SelectedLayerStyle}" />
</Canvas>
</UserControl>
@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
@@ -10,7 +11,6 @@ using Artemis.Core.Models.Surface;
using Artemis.UI.Extensions;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared.Services.Interfaces;
using RGB.NET.Core;
using Stylet;
using Rectangle = Artemis.Core.Models.Profile.LayerShapes.Rectangle;
@@ -20,52 +20,35 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{
private readonly ILayerEditorService _layerEditorService;
private readonly IProfileEditorService _profileEditorService;
private Geometry _layerGeometry;
private Geometry _opacityGeometry;
private Geometry _shapeGeometry;
private RenderTargetBitmap _layerGeometryBitmap;
private Rect _viewportRectangle;
private readonly ProfileViewModel _profileViewModel;
private bool _isSelected;
private Geometry _shapeGeometry;
private Rect _viewportRectangle;
public ProfileLayerViewModel(Layer layer, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService)
public ProfileLayerViewModel(Layer layer, ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService)
{
_profileViewModel = profileViewModel;
_profileEditorService = profileEditorService;
_layerEditorService = layerEditorService;
Layer = layer;
Update();
Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated;
_profileEditorService.ProfileElementSelected += OnProfileElementSelected;
_profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated;
_profileEditorService.ProfilePreviewUpdated += ProfileEditorServiceOnProfilePreviewUpdated;
_profileViewModel.PanZoomViewModel.PropertyChanged += PanZoomViewModelOnPropertyChanged;
}
public Layer Layer { get; }
public Geometry LayerGeometry
{
get => _layerGeometry;
set => SetAndNotify(ref _layerGeometry, value);
}
public Geometry OpacityGeometry
{
get => _opacityGeometry;
set => SetAndNotify(ref _opacityGeometry, value);
}
public Geometry ShapeGeometry
{
get => _shapeGeometry;
set => SetAndNotify(ref _shapeGeometry, value);
}
public RenderTargetBitmap LayerGeometryBitmap
{
get => _layerGeometryBitmap;
set => SetAndNotify(ref _layerGeometryBitmap, value);
}
public Rect ViewportRectangle
{
get => _viewportRectangle;
@@ -76,12 +59,36 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
}
}
public double StrokeThickness
{
get
{
if (IsSelected)
return Math.Max(2 / _profileViewModel.PanZoomViewModel.Zoom, 1);
return Math.Max(2 / _profileViewModel.PanZoomViewModel.Zoom, 1) / 2;
}
}
public double LayerStrokeThickness
{
get
{
if (IsSelected)
return StrokeThickness / 2;
return StrokeThickness;
}
}
public Thickness LayerPosition => new Thickness(ViewportRectangle.Left, ViewportRectangle.Top, 0, 0);
public bool IsSelected
{
get => _isSelected;
set => SetAndNotify(ref _isSelected, value);
set
{
if (!SetAndNotify(ref _isSelected, value)) return;
NotifyOfPropertyChange(nameof(StrokeThickness));
}
}
protected override void Dispose(bool disposing)
@@ -92,84 +99,29 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
_profileEditorService.ProfileElementSelected -= OnProfileElementSelected;
_profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated;
_profileEditorService.ProfilePreviewUpdated -= ProfileEditorServiceOnProfilePreviewUpdated;
_profileViewModel.PanZoomViewModel.PropertyChanged -= PanZoomViewModelOnPropertyChanged;
}
base.Dispose(disposing);
}
private void PanZoomViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(_profileViewModel.PanZoomViewModel.Zoom))
{
NotifyOfPropertyChange(nameof(StrokeThickness));
NotifyOfPropertyChange(nameof(LayerStrokeThickness));
}
}
private void Update()
{
IsSelected = _profileEditorService.SelectedProfileElement == Layer;
CreateLayerGeometry();
CreateShapeGeometry();
CreateViewportRectangle();
}
private void CreateLayerGeometry()
{
Execute.OnUIThread(() =>
{
if (!Layer.Leds.Any())
{
LayerGeometry = Geometry.Empty;
OpacityGeometry = Geometry.Empty;
ViewportRectangle = Rect.Empty;
return;
}
var group = new GeometryGroup();
group.FillRule = FillRule.Nonzero;
foreach (var led in Layer.Leds)
{
Geometry geometry;
switch (led.RgbLed.Shape)
{
case Shape.Custom:
if (led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
geometry = CreateCustomGeometry(led, 2);
else
geometry = CreateCustomGeometry(led, 1);
break;
case Shape.Rectangle:
geometry = CreateRectangleGeometry(led);
break;
case Shape.Circle:
geometry = CreateCircleGeometry(led);
break;
default:
throw new ArgumentOutOfRangeException();
}
group.Children.Add(geometry);
}
var layerGeometry = group.GetOutlinedPathGeometry();
var opacityGeometry = Geometry.Combine(Geometry.Empty, layerGeometry, GeometryCombineMode.Exclude, new TranslateTransform());
LayerGeometry = layerGeometry;
OpacityGeometry = opacityGeometry;
// Render the store as a bitmap
var drawingImage = new DrawingImage(new GeometryDrawing(new SolidColorBrush(Colors.Black), null, LayerGeometry));
var image = new Image {Source = drawingImage};
var bitmap = new RenderTargetBitmap(
(int) (LayerGeometry.Bounds.Width * 2.5),
(int) (LayerGeometry.Bounds.Height * 2.5),
96,
96,
PixelFormats.Pbgra32
);
image.Arrange(new Rect(0, 0, bitmap.Width, bitmap.Height));
bitmap.Render(image);
bitmap.Freeze();
LayerGeometryBitmap = bitmap;
});
}
private void CreateShapeGeometry()
{
if (Layer.LayerShape == null || !Layer.Leds.Any())
@@ -213,21 +165,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
private Geometry CreateRectangleGeometry(ArtemisLed led)
{
var rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
rect.Inflate(1, 1);
return new RectangleGeometry(rect);
}
private Geometry CreateCircleGeometry(ArtemisLed led)
{
var rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
rect.Inflate(1, 1);
return new EllipseGeometry(rect);
}
private Geometry CreateCustomGeometry(ArtemisLed led, double deflateAmount)
{
var rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
rect.Inflate(1, 1);
try
{
var geometry = Geometry.Combine(
@@ -218,26 +218,28 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
private void ApplyActiveProfile()
{
Execute.PostToUIThread(() =>
var layerViewModels = CanvasViewModels.Where(vm => vm is ProfileLayerViewModel).Cast<ProfileLayerViewModel>().ToList();
var layers = _profileEditorService.SelectedProfile?.GetAllLayers() ?? new List<Layer>();
// Add new layers missing a VM
foreach (var layer in layers)
{
var layerViewModels = CanvasViewModels.Where(vm => vm is ProfileLayerViewModel).Cast<ProfileLayerViewModel>().ToList();
var layers = _profileEditorService.SelectedProfile?.GetAllLayers() ?? new List<Layer>();
if (layerViewModels.All(vm => vm.Layer != layer))
CanvasViewModels.Add(_profileLayerVmFactory.Create(layer, this));
}
// Add new layers missing a VM
foreach (var layer in layers)
{
if (layerViewModels.All(vm => vm.Layer != layer))
CanvasViewModels.Add(_profileLayerVmFactory.Create(layer));
}
// Remove layers that no longer exist
var toRemove = layerViewModels.Where(vm => !layers.Contains(vm.Layer));
foreach (var profileLayerViewModel in toRemove)
{
profileLayerViewModel.Dispose();
CanvasViewModels.Remove(profileLayerViewModel);
}
}
// Remove layers that no longer exist
var toRemove = layerViewModels.Where(vm => !layers.Contains(vm.Layer));
foreach (var profileLayerViewModel in toRemove)
{
profileLayerViewModel.Dispose();
CanvasViewModels.Remove(profileLayerViewModel);
}
});
protected override void OnActivate()
{
ApplyActiveProfile();
}
private void ApplySurfaceConfiguration(ArtemisSurface surface)
@@ -49,7 +49,7 @@
<Grid Margin="10, 10, 10, 10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
@@ -59,8 +59,7 @@
Please note that having this window open can have a performance impact on your system.
</TextBlock>
<controls:DeviceVisualizer Grid.Row="1" Device="{Binding Device}" HighlightedLeds="{Binding SelectedLeds}" HorizontalAlignment="Center"
Height="320" Width="800" ShowColors="True" />
<controls:DeviceVisualizer Grid.Row="1" Device="{Binding Device}" HighlightedLeds="{Binding SelectedLeds}" HorizontalAlignment="Center" MaxHeight="500" ShowColors="True" />
<Expander Grid.Row="2" Width="800" VerticalAlignment="Center" Header="Device properties">
<StackPanel Orientation="Horizontal">
@@ -12,6 +12,14 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
{
Icon = icon;
ActiveItem = configurationViewModel;
ActiveItem.Closed += ActiveItemOnClosed;
}
private void ActiveItemOnClosed(object? sender, CloseEventArgs e)
{
ActiveItem.Closed -= ActiveItemOnClosed;
RequestClose();
}
}
}