From 5e345fed7c70790a24e5bc4711719909b34b40a1 Mon Sep 17 00:00:00 2001 From: Robert Date: Sat, 17 Apr 2021 10:22:33 +0200 Subject: [PATCH] UI - Decreased device visualizer CPU usage Keyframes - Snap to closest 50 ms while Ctrl is held down --- src/Artemis.Core/MVVM/CorePropertyChanged.cs | 2 + .../Models/Surface/ArtemisDevice.cs | 83 +++++++++++-------- .../Surface/ArtemisDeviceInputIdentifier.cs | 25 ++---- .../Controls/DeviceVisualizer.cs | 7 +- .../Controls/DeviceVisualizerLed.cs | 11 ++- .../BrushPropertyInputViewModel.cs | 2 +- .../Timeline/TimelineViewModel.cs | 3 + .../Plugins/PluginSettingsWindowView.xaml | 2 +- 8 files changed, 73 insertions(+), 62 deletions(-) diff --git a/src/Artemis.Core/MVVM/CorePropertyChanged.cs b/src/Artemis.Core/MVVM/CorePropertyChanged.cs index fb1d84497..06db7bd0b 100644 --- a/src/Artemis.Core/MVVM/CorePropertyChanged.cs +++ b/src/Artemis.Core/MVVM/CorePropertyChanged.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using System.Runtime.CompilerServices; +using Artemis.Core.Properties; namespace Artemis.Core { @@ -44,6 +45,7 @@ namespace Artemis.Core /// . /// /// true if the value was changed, false if the existing value matched the desired value. + [NotifyPropertyChangedInvocator] protected virtual bool SetAndNotify(ref T storage, T value, [CallerMemberName] string propertyName = null) { if (!RequiresUpdate(ref storage, value)) return false; diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs index a8ae3a17d..ca1ae6094 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs @@ -109,6 +109,9 @@ namespace Artemis.Core /// public List InputIdentifiers { get; } + /// + /// Gets a list of input mappings configured on the device + /// public Dictionary InputMappings { get; } /// @@ -288,7 +291,10 @@ namespace Artemis.Core /// Attempts to retrieve the that corresponds the provided RGB.NET /// /// The RGB.NET to find the corresponding for - /// If , LEDs mapped to different LEDs are taken into consideration + /// + /// If , LEDs mapped to different LEDs + /// are taken into consideration + /// /// If found, the corresponding ; otherwise . public ArtemisLed? GetLed(Led led, bool applyInputMapping) { @@ -299,7 +305,10 @@ namespace Artemis.Core /// Attempts to retrieve the that corresponds the provided RGB.NET /// /// The RGB.NET to find the corresponding for - /// If , LEDs mapped to different LEDs are taken into consideration + /// + /// If , LEDs mapped to different LEDs + /// are taken into consideration + /// /// If found, the corresponding ; otherwise . public ArtemisLed? GetLed(LedId ledId, bool applyInputMapping) { @@ -329,12 +338,31 @@ namespace Artemis.Core return fileName; } + /// + /// Occurs when the underlying RGB.NET device was updated + /// + public event EventHandler? DeviceUpdated; + + /// + /// Invokes the event + /// + protected virtual void OnDeviceUpdated() + { + DeviceUpdated?.Invoke(this, EventArgs.Empty); + } + /// /// Applies the provided layout to the device /// /// The layout to apply - /// A boolean indicating whether to add missing LEDs defined in the layout but missing on the device - /// A boolean indicating whether to remove excess LEDs present in the device but missing in the layout + /// + /// A boolean indicating whether to add missing LEDs defined in the layout but missing on + /// the device + /// + /// + /// A boolean indicating whether to remove excess LEDs present in the device but missing + /// in the layout + /// internal void ApplyLayout(ArtemisLayout layout, bool createMissingLeds, bool removeExcessiveLeds) { if (createMissingLeds && !DeviceProvider.CreateMissingLedsSupported) @@ -355,21 +383,6 @@ namespace Artemis.Core OnDeviceUpdated(); } - private void UpdateLeds() - { - Leds = RgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly(); - LedIds = new ReadOnlyDictionary(Leds.ToDictionary(l => l.RgbLed.Id, l => l)); - - InputMappings.Clear(); - foreach (InputMappingEntity deviceEntityInputMapping in DeviceEntity.InputMappings) - { - ArtemisLed? original = Leds.FirstOrDefault(l => l.RgbLed.Id == (LedId) deviceEntityInputMapping.OriginalLedId); - ArtemisLed? mapped = Leds.FirstOrDefault(l => l.RgbLed.Id == (LedId) deviceEntityInputMapping.MappedLedId); - if (original != null && mapped != null) - InputMappings.Add(original, mapped); - } - } - internal void ApplyToEntity() { // Other properties are computed @@ -427,6 +440,21 @@ namespace Artemis.Core Path = path; } + private void UpdateLeds() + { + Leds = RgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly(); + LedIds = new ReadOnlyDictionary(Leds.ToDictionary(l => l.RgbLed.Id, l => l)); + + InputMappings.Clear(); + foreach (InputMappingEntity deviceEntityInputMapping in DeviceEntity.InputMappings) + { + ArtemisLed? original = Leds.FirstOrDefault(l => l.RgbLed.Id == (LedId) deviceEntityInputMapping.OriginalLedId); + ArtemisLed? mapped = Leds.FirstOrDefault(l => l.RgbLed.Id == (LedId) deviceEntityInputMapping.MappedLedId); + if (original != null && mapped != null) + InputMappings.Add(original, mapped); + } + } + private void ApplyKeyboardLayout() { if (RgbDevice.DeviceInfo.DeviceType != RGBDeviceType.Keyboard) @@ -443,22 +471,5 @@ namespace Artemis.Core else LogicalLayout = DeviceEntity.LogicalLayout; } - - #region Events - - /// - /// Occurs when the underlying RGB.NET device was updated - /// - public event EventHandler? DeviceUpdated; - - /// - /// Invokes the event - /// - protected virtual void OnDeviceUpdated() - { - DeviceUpdated?.Invoke(this, EventArgs.Empty); - } - - #endregion } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Surface/ArtemisDeviceInputIdentifier.cs b/src/Artemis.Core/Models/Surface/ArtemisDeviceInputIdentifier.cs index 3eab18dff..fb05e25b7 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisDeviceInputIdentifier.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisDeviceInputIdentifier.cs @@ -1,17 +1,18 @@ -using Artemis.Core.Services; -using RGB.NET.Core; - -namespace Artemis.Core +namespace Artemis.Core { /// - /// Represents a device input identifier used by a specific to identify the device + /// Represents a device input identifier used by a specific to identify the + /// device /// public class ArtemisDeviceInputIdentifier { /// /// Creates a new instance of the class /// - /// The full type and namespace of the this identifier is used by + /// + /// The full type and namespace of the this identifier is + /// used by + /// /// A value used to identify the device internal ArtemisDeviceInputIdentifier(string inputProvider, object identifier) { @@ -29,16 +30,4 @@ namespace Artemis.Core /// public object Identifier { get; set; } } - - public class ArtemisDeviceInputMapping - { - public ArtemisLed OriginalLed { get; } - public ArtemisLed MappedLed { get; } - - internal ArtemisDeviceInputMapping(ArtemisLed originalLed, ArtemisLed mappedLed) - { - OriginalLed = originalLed; - MappedLed = mappedLed; - } - } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs index 6dce06e42..fb3b77506 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs @@ -330,14 +330,15 @@ namespace Artemis.UI.Shared private void Render() { - DrawingContext drawingContext = _backingStore.Open(); + DrawingContext drawingContext = _backingStore.Append(); + // DrawingContext drawingContext = _backingStore.Open(); if (HighlightedLeds != null && HighlightedLeds.Any()) foreach (DeviceVisualizerLed deviceVisualizerLed in _deviceVisualizerLeds) - deviceVisualizerLed.RenderColor(drawingContext, !HighlightedLeds.Contains(deviceVisualizerLed.Led)); + deviceVisualizerLed.RenderColor(_backingStore, drawingContext, !HighlightedLeds.Contains(deviceVisualizerLed.Led)); else foreach (DeviceVisualizerLed deviceVisualizerLed in _deviceVisualizerLeds) - deviceVisualizerLed.RenderColor(drawingContext, false); + deviceVisualizerLed.RenderColor(_backingStore, drawingContext, false); drawingContext.Close(); } diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs index 3845a31a4..45dc4ac41 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs @@ -14,9 +14,10 @@ namespace Artemis.UI.Shared { private const byte Dimmed = 100; private const byte NonDimmed = 255; + private GeometryDrawing? _geometryDrawing; + private Color _renderColor; private SolidColorBrush? _renderColorBrush; - private Color _renderColor; public DeviceVisualizerLed(ArtemisLed led) { @@ -40,12 +41,13 @@ namespace Artemis.UI.Shared public BitmapImage? LedImage { get; set; } public Geometry? DisplayGeometry { get; private set; } - public void RenderColor(DrawingContext drawingContext, bool isDimmed) + public void RenderColor(DrawingGroup backingStore, DrawingContext drawingContext, bool isDimmed) { if (DisplayGeometry == null) return; _renderColorBrush ??= new SolidColorBrush(); + _geometryDrawing ??= new GeometryDrawing(_renderColorBrush, null, new RectangleGeometry(LedRect)); byte r = Led.RgbLed.Color.GetR(); byte g = Led.RgbLed.Color.GetG(); @@ -56,7 +58,10 @@ namespace Artemis.UI.Shared _renderColor.G = g; _renderColor.B = b; _renderColorBrush.Color = _renderColor; - drawingContext.DrawRectangle(_renderColorBrush, null, LedRect); + + + if (!backingStore.Children.Contains(_geometryDrawing)) + backingStore.Children.Add(_geometryDrawing); } public void RenderImage(DrawingContext drawingContext) diff --git a/src/Artemis.UI/DefaultTypes/PropertyInput/BrushPropertyInputViewModel.cs b/src/Artemis.UI/DefaultTypes/PropertyInput/BrushPropertyInputViewModel.cs index c356cfc60..bafcc7f30 100644 --- a/src/Artemis.UI/DefaultTypes/PropertyInput/BrushPropertyInputViewModel.cs +++ b/src/Artemis.UI/DefaultTypes/PropertyInput/BrushPropertyInputViewModel.cs @@ -55,7 +55,7 @@ namespace Artemis.UI.DefaultTypes.PropertyInput Execute.PostToUIThread(async () => { await Task.Delay(400); - _dialogService.ShowDialogAt("LayerProperties", new Dictionary {{"layerBrush", layer.LayerBrush}}); + await _dialogService.ShowDialogAt("LayerProperties", new Dictionary {{"layerBrush", layer.LayerBrush}}); }); } } diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs index eb3f728a8..b6aaf3612 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs @@ -322,6 +322,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline false, keyframeViewModels.Where(k => k != sourceKeyframeViewModel).Select(k => k.Position).ToList() ); + // If holding down control, round to the closest 50ms + else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) + cursorTime = TimeSpan.FromMilliseconds(Math.Round(cursorTime.TotalMilliseconds / 50.0) * 50.0); sourceKeyframeViewModel.UpdatePosition(cursorTime); diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml index a05dd93df..0d1655136 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml +++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml @@ -9,7 +9,7 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" mc:Ignorable="d" - Title="Plugin configuration" + Title="Plugin Configuration | Artemis" Background="{DynamicResource MaterialDesignPaper}" FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto" UseLayoutRounding="True"