From e58c0f20bb059d4dc0515af14cbc5e119586b3c4 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 24 Feb 2021 00:45:31 +0100 Subject: [PATCH 1/8] Updated to work with the new RGB.NET rendering --- src/Artemis.Core/Artemis.Core.csproj | 6 - .../Events/FrameRenderedEventArgs.cs | 6 +- .../Models/Surface/ArtemisDevice.cs | 14 +- .../Plugins/LayerBrushes/RgbNetLayerBrush.cs | 1 - src/Artemis.Core/RGB.NET/ArtemisSampler.cs | 32 + src/Artemis.Core/RGB.NET/BitmapBrush.cs | 197 ----- src/Artemis.Core/RGB.NET/SKTexture.cs | 96 +++ src/Artemis.Core/Services/CoreService.cs | 53 +- src/Artemis.Core/Services/DeviceService.cs | 2 - .../Services/Interfaces/IRgbService.cs | 16 +- src/Artemis.Core/Services/RgbService.cs | 47 +- .../Storage/Models/SurfaceArrangement.cs | 4 +- .../Models/SurfaceArrangementConfiguration.cs | 8 +- .../Storage/Models/SurfaceArrangementType.cs | 12 +- .../Entities/Surface/DeviceEntity.cs | 14 +- .../Controls/DeviceVisualizerLed.cs | 1 + src/Artemis.UI/Artemis.UI.csproj | 716 +++++++++--------- .../Debug/Tabs/RenderDebugViewModel.cs | 8 +- .../Dialogs/SurfaceDeviceConfigViewModel.cs | 40 +- .../SurfaceDeviceConfigViewModelValidator.cs | 2 +- .../SurfaceDeviceDetectInputViewModel.cs | 2 - 21 files changed, 609 insertions(+), 668 deletions(-) create mode 100644 src/Artemis.Core/RGB.NET/ArtemisSampler.cs delete mode 100644 src/Artemis.Core/RGB.NET/BitmapBrush.cs create mode 100644 src/Artemis.Core/RGB.NET/SKTexture.cs diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index b13eae70e..cb65d532a 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -64,15 +64,9 @@ - - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Brushes.dll - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll - - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Groups.dll - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll diff --git a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs index 5911591d5..110f7279c 100644 --- a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs +++ b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs @@ -8,16 +8,16 @@ namespace Artemis.Core /// public class FrameRenderedEventArgs : EventArgs { - internal FrameRenderedEventArgs(BitmapBrush bitmapBrush, RGBSurface rgbSurface) + internal FrameRenderedEventArgs(SKTexture texture, RGBSurface rgbSurface) { - BitmapBrush = bitmapBrush; + Texture = texture; RgbSurface = rgbSurface; } /// /// Gets the bitmap brush used to render this frame /// - public BitmapBrush BitmapBrush { get; } + public SKTexture Texture { get; } /// /// Gets the RGB surface used to render this frame diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs index 90aee62a2..7db6d2ff1 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs @@ -106,7 +106,7 @@ namespace Artemis.Core /// /// Gets or sets the X-position of the device /// - public double X + public float X { get => DeviceEntity.X; set @@ -119,7 +119,7 @@ namespace Artemis.Core /// /// Gets or sets the Y-position of the device /// - public double Y + public float Y { get => DeviceEntity.Y; set @@ -132,7 +132,7 @@ namespace Artemis.Core /// /// Gets or sets the rotation of the device /// - public double Rotation + public float Rotation { get => DeviceEntity.Rotation; set @@ -145,7 +145,7 @@ namespace Artemis.Core /// /// Gets or sets the scale of the device /// - public double Scale + public float Scale { get => DeviceEntity.Scale; set @@ -171,7 +171,7 @@ namespace Artemis.Core /// /// Gets or sets the scale of the red color component used for calibration /// - public double RedScale + public float RedScale { get => DeviceEntity.RedScale; set @@ -184,7 +184,7 @@ namespace Artemis.Core /// /// Gets or sets the scale of the green color component used for calibration /// - public double GreenScale + public float GreenScale { get => DeviceEntity.GreenScale; set @@ -197,7 +197,7 @@ namespace Artemis.Core /// /// Gets or sets the scale of the blue color component used for calibration /// - public double BlueScale + public float BlueScale { get => DeviceEntity.BlueScale; set diff --git a/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs index 6424b4f06..e52e06c13 100644 --- a/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs @@ -4,7 +4,6 @@ using System.Linq; using Artemis.Core.Services; using Ninject; using RGB.NET.Core; -using RGB.NET.Groups; using SkiaSharp; namespace Artemis.Core.LayerBrushes diff --git a/src/Artemis.Core/RGB.NET/ArtemisSampler.cs b/src/Artemis.Core/RGB.NET/ArtemisSampler.cs new file mode 100644 index 000000000..307dcc252 --- /dev/null +++ b/src/Artemis.Core/RGB.NET/ArtemisSampler.cs @@ -0,0 +1,32 @@ +using System; +using RGB.NET.Core; + +namespace Artemis.Core +{ + public class ArtemisSampler : ISampler + { + #region Methods + + /// + public Color SampleColor(SamplerInfo info) + { + int count = info.Width * info.Height; + if (count == 0) return Color.Transparent; + + ReadOnlySpan data = info.Data; + + uint r = 0, g = 0, b = 0; + for (int i = 0; i < data.Length; i += 4) + { + r += data[i]; + g += data[i + 1]; + b += data[i + 2]; + } + + float divisor = count * byte.MaxValue; + return new Color(r / divisor, g / divisor, b / divisor); + } + + #endregion + } +} diff --git a/src/Artemis.Core/RGB.NET/BitmapBrush.cs b/src/Artemis.Core/RGB.NET/BitmapBrush.cs deleted file mode 100644 index 11021f317..000000000 --- a/src/Artemis.Core/RGB.NET/BitmapBrush.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System; -using System.Collections.Generic; -using Artemis.Core.Services; -using RGB.NET.Core; -using SkiaSharp; - -namespace Artemis.Core -{ - /// - /// The RGB.NET brush Artemis uses to map the SkiaSharp bitmap to LEDs - /// - public sealed class BitmapBrush : AbstractDecoratable, IBrush, IDisposable - { - private readonly object _disposeLock; - private readonly PluginSetting _sampleSizeSetting; - private readonly IRgbService _rgbService; - - #region Constructors - - internal BitmapBrush(Scale scale, PluginSetting sampleSizeSetting, IRgbService rgbService) - { - _disposeLock = new object(); - _sampleSizeSetting = sampleSizeSetting; - _rgbService = rgbService; - Scale = scale; - } - - #endregion - - #region Properties & Fields - - /// - public bool IsEnabled { get; set; } = true; - - /// - public BrushCalculationMode BrushCalculationMode { get; set; } = BrushCalculationMode.Absolute; - - /// - public double Brightness { get; set; } - - /// - public double Opacity { get; set; } - - /// - public IList ColorCorrections { get; } = new List(); - - /// - public Rectangle RenderedRectangle { get; private set; } - - /// - public Dictionary RenderedTargets { get; } = new(); - - /// - /// Gets or sets the desired scale of the bitmap brush - /// - public Scale Scale { get; set; } - - /// - /// Gets the last rendered scale of the bitmap brush - /// - public Scale RenderedScale { get; private set; } - - /// - /// Gets the bitmap used to sample the brush - /// - public SKBitmap? Bitmap { get; private set; } - - #endregion - - #region Methods - - /// - public void PerformRender(Rectangle rectangle, IEnumerable renderTargets) - { - lock (_disposeLock) - { - // Can happen during surface change - if (IsDisposed) - return; - - if (RenderedRectangle != rectangle || RenderedScale != Scale) - Bitmap = null; - - RenderedRectangle = rectangle; - RenderedScale = Scale; - RenderedTargets.Clear(); - - if (Bitmap == null) - CreateBitmap(RenderedRectangle); - - if (_sampleSizeSetting.Value == 1) - TakeCenter(renderTargets); - else - TakeSamples(renderTargets); - } - } - - private void TakeCenter(IEnumerable renderTargets) - { - if (Bitmap == null) - return; - - foreach (BrushRenderTarget renderTarget in renderTargets) - { - Point scaledLocation = renderTarget.Point * Scale; - if (scaledLocation.X < Bitmap.Width && scaledLocation.Y < Bitmap.Height) - { - Color pixel = Bitmap.GetPixel(scaledLocation.X.RoundToInt(), scaledLocation.Y.RoundToInt()).ToRgbColor(); - ArtemisDevice? artemisDevice = _rgbService.GetLed(renderTarget.Led)?.Device; - if (artemisDevice != null) - pixel = pixel.MultiplyRGB(artemisDevice.RedScale, artemisDevice.GreenScale, artemisDevice.BlueScale); - RenderedTargets[renderTarget] = pixel; - } - } - } - - private void TakeSamples(IEnumerable renderTargets) - { - if (Bitmap == null) - return; - - int sampleSize = _sampleSizeSetting.Value; - int sampleDepth = Math.Sqrt(sampleSize).RoundToInt(); - - int bitmapWidth = Bitmap.Width; - int bitmapHeight = Bitmap.Height; - - using SKPixmap pixmap = Bitmap.PeekPixels(); - foreach (BrushRenderTarget renderTarget in renderTargets) - { - // SKRect has all the good stuff we need - int left = (int) ((renderTarget.Rectangle.Location.X + 4) * Scale.Horizontal); - int top = (int) ((renderTarget.Rectangle.Location.Y + 4) * Scale.Vertical); - int width = (int) ((renderTarget.Rectangle.Size.Width - 8) * Scale.Horizontal); - int height = (int) ((renderTarget.Rectangle.Size.Height - 8) * Scale.Vertical); - - int verticalSteps = height / (sampleDepth - 1); - int horizontalSteps = width / (sampleDepth - 1); - - int a = 0, r = 0, g = 0, b = 0; - for (int horizontalStep = 0; horizontalStep < sampleDepth; horizontalStep++) - { - for (int verticalStep = 0; verticalStep < sampleDepth; verticalStep++) - { - int x = left + horizontalSteps * horizontalStep; - int y = top + verticalSteps * verticalStep; - if (x < 0 || x >= bitmapWidth || y < 0 || y >= bitmapHeight) - continue; - - SKColor color = pixmap.GetPixelColor(x, y); - a += color.Alpha; - r += color.Red; - g += color.Green; - b += color.Blue; - - // Uncomment to view the sample pixels in the debugger, need a checkbox in the actual debugger but this was a quickie - // Bitmap.SetPixel(x, y, new SKColor(0, 255, 0)); - } - } - - Color pixel = new(a / sampleSize, r / sampleSize, g / sampleSize, b / sampleSize); - - ArtemisDevice? artemisDevice = _rgbService.GetLed(renderTarget.Led)?.Device; - if (artemisDevice is not null) - pixel = pixel.MultiplyRGB(artemisDevice.RedScale, artemisDevice.GreenScale, artemisDevice.BlueScale); - - RenderedTargets[renderTarget] = pixel; - } - } - - private void CreateBitmap(Rectangle rectangle) - { - double width = Math.Min((rectangle.Location.X + rectangle.Size.Width) * Scale.Horizontal, 4096); - double height = Math.Min((rectangle.Location.Y + rectangle.Size.Height) * Scale.Vertical, 4096); - Bitmap = new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt(), SKColorType.Rgb888x)); - } - - /// - public void PerformFinalize() - { - } - - /// - public void Dispose() - { - lock (_disposeLock) - { - Bitmap?.Dispose(); - IsDisposed = true; - } - } - - internal bool IsDisposed { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/src/Artemis.Core/RGB.NET/SKTexture.cs b/src/Artemis.Core/RGB.NET/SKTexture.cs new file mode 100644 index 000000000..3be5905a2 --- /dev/null +++ b/src/Artemis.Core/RGB.NET/SKTexture.cs @@ -0,0 +1,96 @@ +using System; +using System.Buffers; +using RGB.NET.Core; +using SkiaSharp; + +namespace Artemis.Core +{ + public sealed class SKTexture : ITexture + { + #region Constants + + private const int STACK_ALLOC_LIMIT = 1024; + + #endregion + + #region Properties & Fields + + private readonly SKBitmap _bitmap; + private readonly int _stride; + + public SKBitmap Bitmap => _bitmap; + + public Size Size { get; } + + public ISampler Sampler { get; set; } = new ArtemisSampler(); + + public Color this[in Point point] + { + get + { + int x = (Size.Width * point.X.Clamp(0, 1)).RoundToInt(); + int y = (Size.Height * point.Y.Clamp(0, 1)).RoundToInt(); + return _bitmap.GetPixel(x, y).ToRgbColor(); + } + } + + public Color this[in Rectangle rectangle] + { + get + { + int x = (Size.Width * rectangle.Location.X.Clamp(0, 1)).RoundToInt(); + int y = (Size.Height * rectangle.Location.Y.Clamp(0, 1)).RoundToInt(); + int width = (Size.Width * rectangle.Size.Width.Clamp(0, 1)).RoundToInt(); + int height = (Size.Height * rectangle.Size.Height.Clamp(0, 1)).RoundToInt(); + + int bufferSize = width * height * 4; + if (bufferSize <= STACK_ALLOC_LIMIT) + { + Span buffer = stackalloc byte[bufferSize]; + GetRegionData(x, y, width, height, buffer); + return Sampler.SampleColor(new SamplerInfo(width, height, buffer)); + } + else + { + byte[] rent = ArrayPool.Shared.Rent(bufferSize); + Span buffer = new Span(rent).Slice(0, bufferSize); + GetRegionData(x, y, width, height, buffer); + Color color = Sampler.SampleColor(new SamplerInfo(width, height, buffer)); + ArrayPool.Shared.Return(rent); + + return color; + } + } + } + + #endregion + + #region Constructors + + public SKTexture(SKBitmap bitmap) + { + this._bitmap = bitmap; + + Size = new Size(bitmap.Width, bitmap.Height); + _stride = bitmap.Width; + } + + #endregion + + #region Methods + + private void GetRegionData(int x, int y, int width, int height, in Span buffer) + { + int width4 = width * 4; + ReadOnlySpan data = _bitmap.GetPixelSpan(); + for (int i = 0; i < height; i++) + { + ReadOnlySpan dataSlice = data.Slice((((y + i) * _stride) + x) * 4, width4); + Span destination = buffer.Slice(i * width4, width4); + dataSlice.CopyTo(destination); + } + } + + #endregion + } +} diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index ff820f4cb..e4e0a460d 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -1,16 +1,13 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Artemis.Core.DataModelExpansions; using Artemis.Core.Ninject; -using Artemis.Core.Services.Core; using Artemis.Storage; using HidSharp; -using Newtonsoft.Json; using Ninject; using RGB.NET.Core; using Serilog; @@ -38,6 +35,8 @@ namespace Artemis.Core.Services private List _dataModelExpansions = new(); private DateTime _lastExceptionLog; private List _modules = new(); + private SKBitmap? _bitmap; + private readonly object _bitmapLock = new(); // ReSharper disable UnusedParameter.Local public CoreService(IKernel kernel, @@ -66,11 +65,14 @@ namespace Artemis.Core.Services _rgbService.Surface.Updating += SurfaceOnUpdating; _rgbService.Surface.Updated += SurfaceOnUpdated; + _rgbService.Surface.SurfaceLayoutChanged += SurfaceOnSurfaceLayoutChanged; _loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel(); + _renderScale.SettingChanged += RenderScaleSettingChanged; _pluginManagementService.PluginFeatureEnabled += (sender, args) => UpdatePluginCache(); _pluginManagementService.PluginFeatureDisabled += (sender, args) => UpdatePluginCache(); } + // ReSharper restore UnusedParameter.Local public TimeSpan FrameTime { get; private set; } @@ -169,8 +171,8 @@ namespace Artemis.Core.Services string[] parts = argument.Split('='); if (parts.Length == 2 && Enum.TryParse(typeof(LogEventLevel), parts[1], true, out object? logLevelArgument)) { - _logger.Information("Setting logging level to {loggingLevel} from startup argument", (LogEventLevel) logLevelArgument!); - LoggerProvider.LoggingLevelSwitch.MinimumLevel = (LogEventLevel) logLevelArgument; + _logger.Information("Setting logging level to {loggingLevel} from startup argument", (LogEventLevel)logLevelArgument!); + LoggerProvider.LoggingLevelSwitch.MinimumLevel = (LogEventLevel)logLevelArgument; } else { @@ -214,23 +216,22 @@ namespace Artemis.Core.Services foreach (Module module in modules) module.InternalUpdate(args.DeltaTime); - // If there is no ready bitmap brush, skip the frame - if (_rgbService.BitmapBrush == null) - return; - - lock (_rgbService.BitmapBrush) + lock (_bitmapLock) { - if (_rgbService.BitmapBrush.Bitmap == null) - return; + if (_bitmap == null) + { + _bitmap = CreateBitmap(); + _rgbService.UpdateTexture(_bitmap); + } // Render all active modules - using SKCanvas canvas = new(_rgbService.BitmapBrush.Bitmap); - canvas.Scale((float) _renderScale.Value); + using SKCanvas canvas = new(_bitmap); + canvas.Scale((float)_renderScale.Value); canvas.Clear(new SKColor(0, 0, 0)); if (!ModuleRenderingDisabled) // While non-activated modules may be updated above if they expand the main data model, they may never render foreach (Module module in modules.Where(m => m.IsActivated)) - module.InternalRender(args.DeltaTime, canvas, _rgbService.BitmapBrush.Bitmap.Info); + module.InternalRender(args.DeltaTime, canvas, _bitmap.Info); OnFrameRendering(new FrameRenderingEventArgs(canvas, args.DeltaTime, _rgbService.Surface)); } @@ -248,6 +249,26 @@ namespace Artemis.Core.Services } } + private SKBitmap CreateBitmap() + { + float width = MathF.Min(_rgbService.Surface.Boundary.Size.Width * (float)_renderScale.Value, 4096); + float height = MathF.Min(_rgbService.Surface.Boundary.Size.Height * (float)_renderScale.Value, 4096); + return new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt(), SKColorType.Rgb888x)); + } + + private void InvalidateBitmap() + { + + lock (_bitmapLock) + { + _bitmap?.Dispose(); + _bitmap = null; + } + } + + private void SurfaceOnSurfaceLayoutChanged(SurfaceLayoutChangedEventArgs args) => InvalidateBitmap(); + private void RenderScaleSettingChanged(object? sender, EventArgs e) => InvalidateBitmap(); + private void LogUpdateExceptions() { // Only log update exceptions every 10 seconds to avoid spamming the logs @@ -271,7 +292,7 @@ namespace Artemis.Core.Services if (_rgbService.IsRenderPaused) return; - OnFrameRendered(new FrameRenderedEventArgs(_rgbService.BitmapBrush!, _rgbService.Surface)); + OnFrameRendered(new FrameRenderedEventArgs(_rgbService.Texture!, _rgbService.Surface)); } #region Events diff --git a/src/Artemis.Core/Services/DeviceService.cs b/src/Artemis.Core/Services/DeviceService.cs index 032c0db53..46f8bdc52 100644 --- a/src/Artemis.Core/Services/DeviceService.cs +++ b/src/Artemis.Core/Services/DeviceService.cs @@ -1,8 +1,6 @@ using System.Linq; using System.Threading.Tasks; -using RGB.NET.Brushes; using RGB.NET.Core; -using RGB.NET.Groups; namespace Artemis.Core.Services { diff --git a/src/Artemis.Core/Services/Interfaces/IRgbService.cs b/src/Artemis.Core/Services/Interfaces/IRgbService.cs index 838f15ff8..d478d8a00 100644 --- a/src/Artemis.Core/Services/Interfaces/IRgbService.cs +++ b/src/Artemis.Core/Services/Interfaces/IRgbService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using RGB.NET.Core; +using SkiaSharp; namespace Artemis.Core.Services { @@ -31,9 +32,14 @@ namespace Artemis.Core.Services RGBSurface Surface { get; set; } /// - /// Gets the bitmap brush used to convert the rendered frame to LED-colors + /// Gets the texture brush used to convert the rendered frame to LED-colors /// - BitmapBrush? BitmapBrush { get; } + TextureBrush TextureBrush { get; } + + /// + /// Gets the texture used to convert the rendered frame to LED-colors + /// + SKTexture? Texture { get; } /// /// Gets the update trigger that drives the render loop @@ -45,6 +51,12 @@ namespace Artemis.Core.Services /// bool IsRenderPaused { get; set; } + /// + /// Recreates the Texture to use the given + /// + /// + void UpdateTexture(SKBitmap bitmap); + /// /// Adds the given device provider to the /// diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs index 3cec517d6..5ca291db6 100644 --- a/src/Artemis.Core/Services/RgbService.cs +++ b/src/Artemis.Core/Services/RgbService.cs @@ -7,8 +7,8 @@ using Artemis.Core.Services.Models; using Artemis.Storage.Entities.Surface; using Artemis.Storage.Repositories.Interfaces; using RGB.NET.Core; -using RGB.NET.Groups; using Serilog; +using SkiaSharp; namespace Artemis.Core.Services { @@ -24,7 +24,6 @@ namespace Artemis.Core.Services private readonly ILogger _logger; private readonly IPluginManagementService _pluginManagementService; private readonly IDeviceRepository _deviceRepository; - private readonly PluginSetting _renderScaleSetting; private readonly PluginSetting _targetFrameRateSetting; private readonly PluginSetting _sampleSizeSetting; private ListLedGroup? _surfaceLedGroup; @@ -35,7 +34,6 @@ namespace Artemis.Core.Services _logger = logger; _pluginManagementService = pluginManagementService; _deviceRepository = deviceRepository; - _renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.5); _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25); _sampleSizeSetting = settingsService.GetSetting("Core.SampleSize", 1); @@ -43,13 +41,13 @@ namespace Artemis.Core.Services // Let's throw these for now Surface.Exception += SurfaceOnException; - _renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged; + Surface.SurfaceLayoutChanged += SurfaceOnLayoutChanged; _targetFrameRateSetting.SettingChanged += TargetFrameRateSettingOnSettingChanged; _enabledDevices = new List(); _devices = new List(); _ledMap = new Dictionary(); - UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value}; + UpdateTrigger = new TimerUpdateTrigger { UpdateFrequency = 1.0 / _targetFrameRateSetting.Value }; Surface.RegisterUpdateTrigger(UpdateTrigger); } @@ -61,7 +59,8 @@ namespace Artemis.Core.Services public RGBSurface Surface { get; set; } public TimerUpdateTrigger UpdateTrigger { get; } - public BitmapBrush? BitmapBrush { get; private set; } + public TextureBrush TextureBrush { get; private set; } = new(ITexture.Empty) { CalculationMode = RenderMode.Absolute }; + public SKTexture? Texture { get; private set; } public bool IsRenderPaused { get; set; } @@ -104,7 +103,7 @@ namespace Artemis.Core.Services finally { _modifyingProviders = false; - UpdateBitmapBrush(); + UpdateLedGroup(); } } } @@ -132,12 +131,20 @@ namespace Artemis.Core.Services finally { _modifyingProviders = false; - UpdateBitmapBrush(); + UpdateLedGroup(); } } } - private void UpdateBitmapBrush() + public void UpdateTexture(SKBitmap bitmap) + { + Texture = new SKTexture(bitmap); + TextureBrush.Texture = Texture; + } + + private void SurfaceOnLayoutChanged(SurfaceLayoutChangedEventArgs args) => UpdateLedGroup(); + + private void UpdateLedGroup() { lock (_devices) { @@ -146,11 +153,9 @@ namespace Artemis.Core.Services _ledMap = new Dictionary(_devices.SelectMany(d => d.Leds).ToDictionary(l => l.RgbLed)); - if (_surfaceLedGroup == null || BitmapBrush == null) + if (_surfaceLedGroup == null) { - // Apply the application wide brush and decorator - BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value), _sampleSizeSetting, this); - _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) {Brush = BitmapBrush}; + _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) { Brush = TextureBrush }; OnLedsChanged(); return; } @@ -161,8 +166,7 @@ namespace Artemis.Core.Services _surfaceLedGroup.Detach(Surface); // Apply the application wide brush and decorator - BitmapBrush.Scale = new Scale(_renderScaleSetting.Value); - _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) {Brush = BitmapBrush}; + _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) { Brush = TextureBrush }; OnLedsChanged(); } } @@ -234,10 +238,8 @@ namespace Artemis.Core.Services public void ApplyDeviceLayout(ArtemisDevice device, ArtemisLayout layout, bool createMissingLeds, bool removeExessiveLeds) { device.ApplyLayout(layout, createMissingLeds, removeExessiveLeds); - // Applying layouts can affect LEDs, update LED group - UpdateBitmapBrush(); } - + public ArtemisDevice? GetDevice(IRGBDevice rgbDevice) { return _devices.FirstOrDefault(d => d.RgbDevice == rgbDevice); @@ -259,7 +261,6 @@ namespace Artemis.Core.Services device.ApplyToEntity(); _deviceRepository.Save(device.DeviceEntity); - UpdateBitmapBrush(); OnDeviceAdded(new DeviceEventArgs(device)); } @@ -273,7 +274,6 @@ namespace Artemis.Core.Services device.ApplyToEntity(); _deviceRepository.Save(device.DeviceEntity); - UpdateBitmapBrush(); OnDeviceRemoved(new DeviceEventArgs(device)); } @@ -298,7 +298,6 @@ namespace Artemis.Core.Services if (device.IsEnabled) _enabledDevices.Remove(device); - UpdateBitmapBrush(); OnDeviceRemoved(new DeviceEventArgs(device)); } @@ -349,12 +348,6 @@ namespace Artemis.Core.Services #region Event handlers - private void RenderScaleSettingOnSettingChanged(object? sender, EventArgs e) - { - // The surface hasn't changed so we can safely reuse it - UpdateBitmapBrush(); - } - private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e) { UpdateTrigger.UpdateFrequency = 1.0 / _targetFrameRateSetting.Value; diff --git a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs index ca0d1ce60..245bd7621 100644 --- a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs +++ b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs @@ -90,8 +90,8 @@ namespace Artemis.Core.Services.Models surfaceArrangementType.Arrange(devices); // See if we need to move the surface to keep X and Y values positive - double x = devices.Min(d => d.RgbDevice.Location.X); - double y = devices.Min(d => d.RgbDevice.Location.Y); + float x = devices.Min(d => d.RgbDevice.Location.X); + float y = devices.Min(d => d.RgbDevice.Location.Y); if (x < 0) { foreach (ArtemisDevice surfaceDevice in devices) diff --git a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs index a3ada512d..d21e4378a 100644 --- a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs +++ b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs @@ -52,11 +52,11 @@ namespace Artemis.Core.Services.Models if (stackVertically) { artemisDevice.X = previous.X; - artemisDevice.Y = previous.RgbDevice.Location.Y + previous.RgbDevice.Size.Height + MarginTop / 2.0; + artemisDevice.Y = previous.RgbDevice.Location.Y + previous.RgbDevice.Size.Height + MarginTop / 2f; } else { - artemisDevice.X = previous.RgbDevice.Location.X + previous.RgbDevice.Size.Width + MarginLeft / 2.0; + artemisDevice.X = previous.RgbDevice.Location.X + previous.RgbDevice.Size.Width + MarginLeft / 2f; artemisDevice.Y = previous.Y; } } @@ -66,7 +66,7 @@ namespace Artemis.Core.Services.Models { HorizontalArrangementPosition.Left => startPoint.X - artemisDevice.RgbDevice.Size.Width - MarginRight, HorizontalArrangementPosition.Right => startPoint.X + MarginLeft, - HorizontalArrangementPosition.Center => startPoint.X - artemisDevice.RgbDevice.Size.Width / 2, + HorizontalArrangementPosition.Center => startPoint.X - artemisDevice.RgbDevice.Size.Width / 2f, HorizontalArrangementPosition.Equal => startPoint.X, _ => artemisDevice.X }; @@ -74,7 +74,7 @@ namespace Artemis.Core.Services.Models { VerticalArrangementPosition.Top => startPoint.Y - artemisDevice.RgbDevice.Size.Height - MarginBottom, VerticalArrangementPosition.Bottom => startPoint.Y + MarginTop, - VerticalArrangementPosition.Center => startPoint.Y - artemisDevice.RgbDevice.Size.Height / 2, + VerticalArrangementPosition.Center => startPoint.Y - artemisDevice.RgbDevice.Size.Height / 2f, VerticalArrangementPosition.Equal => startPoint.Y, _ => artemisDevice.X }; diff --git a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementType.cs b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementType.cs index 6a2c4f185..5f25fe5f2 100644 --- a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementType.cs +++ b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementType.cs @@ -62,18 +62,18 @@ namespace Artemis.Core.Services.Models if (!devices.Any()) return new Point(); - double x = horizontalPosition switch + float x = horizontalPosition switch { - HorizontalArrangementPosition.Left => devices.Min(d => d.RgbDevice.Location.X) - (AppliedConfiguration?.MarginLeft ?? 0.0), - HorizontalArrangementPosition.Right => devices.Max(d => d.RgbDevice.Location.X + d.RgbDevice.Size.Width) + (AppliedConfiguration?.MarginRight ?? 0.0), + HorizontalArrangementPosition.Left => devices.Min(d => d.RgbDevice.Location.X) - (AppliedConfiguration?.MarginLeft ?? 0.0f), + HorizontalArrangementPosition.Right => devices.Max(d => d.RgbDevice.Location.X + d.RgbDevice.Size.Width) + (AppliedConfiguration?.MarginRight ?? 0.0f), HorizontalArrangementPosition.Center => devices.First().RgbDevice.Boundary.Center.X, HorizontalArrangementPosition.Equal => devices.First().RgbDevice.Location.X, _ => throw new ArgumentOutOfRangeException(nameof(horizontalPosition), horizontalPosition, null) }; - double y = verticalPosition switch + float y = verticalPosition switch { - VerticalArrangementPosition.Top => devices.Min(d => d.RgbDevice.Location.Y) - (AppliedConfiguration?.MarginTop ?? 0.0), - VerticalArrangementPosition.Bottom => devices.Max(d => d.RgbDevice.Location.Y + d.RgbDevice.Size.Height) + (AppliedConfiguration?.MarginBottom ?? 0.0), + VerticalArrangementPosition.Top => devices.Min(d => d.RgbDevice.Location.Y) - (AppliedConfiguration?.MarginTop ?? 0.0f), + VerticalArrangementPosition.Bottom => devices.Max(d => d.RgbDevice.Location.Y + d.RgbDevice.Size.Height) + (AppliedConfiguration?.MarginBottom ?? 0.0f), VerticalArrangementPosition.Center => devices.First().RgbDevice.Boundary.Center.Y, VerticalArrangementPosition.Equal => devices.First().RgbDevice.Location.Y, _ => throw new ArgumentOutOfRangeException(nameof(verticalPosition), verticalPosition, null) diff --git a/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs b/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs index 670cec969..258902d5e 100644 --- a/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs +++ b/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs @@ -10,14 +10,14 @@ namespace Artemis.Storage.Entities.Surface } public string Id { get; set; } - public double X { get; set; } - public double Y { get; set; } - public double Rotation { get; set; } - public double Scale { get; set; } + public float X { get; set; } + public float Y { get; set; } + public float Rotation { get; set; } + public float Scale { get; set; } public int ZIndex { get; set; } - public double RedScale { get; set; } - public double GreenScale { get; set; } - public double BlueScale { get; set; } + public float RedScale { get; set; } + public float GreenScale { get; set; } + public float BlueScale { get; set; } public bool IsEnabled { get; set; } public int PhysicalLayout { get; set; } diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs index c3ba1fd6a..498932b35 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs @@ -6,6 +6,7 @@ using System.Windows.Media.Imaging; using Artemis.Core; using RGB.NET.Core; using Color = System.Windows.Media.Color; +using SolidColorBrush = System.Windows.Media.SolidColorBrush; namespace Artemis.UI.Shared { diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index a78e9658a..7ec6d7c41 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -1,364 +1,358 @@  - - WinExe - net5.0-windows - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - true - Artemis - Artemis - en-US - Provides advanced unified lighting across many different brands RGB peripherals - Copyright © Robert Beekman - 2021 - 2.0.0.0 - bin\$(Platform)\$(Configuration)\ - true - x64 - windows - - - x64 - + + WinExe + net5.0-windows + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + Artemis + Artemis + en-US + Provides advanced unified lighting across many different brands RGB peripherals + Copyright © Robert Beekman - 2021 + 2.0.0.0 + bin\$(Platform)\$(Configuration)\ + true + x64 + windows + + + x64 + - - Resources\Images\Logo\logo-512.ico - - - - 2.0.0.0 - 2.0.0 - - - 2.0-{chash:6} - true - true - true - v[0-9]* - true - git - true - - - - - - - false - - - - - - - - - - - - - - - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Brushes.dll - - - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll - - - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Groups.dll - - - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll - - - - - - ResXFileCodeGenerator - Designer - Resources.Designer.cs - - - - - true - - - true - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - True - True - Settings.settings - - - - - PreserveNewest - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - Designer - - - Designer - - - Designer - - - Designer - - - Designer - - - Designer - - - $(DefaultXamlRuntime) - - + + Resources\Images\Logo\logo-512.ico + + + + 2.0.0.0 + 2.0.0 + + + 2.0-{chash:6} + true + true + true + v[0-9]* + true + git + true + + + + + + + false + + + + + + + + + + + + + + + ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll + + + ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll + + + + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + + + true + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + Designer + + + Designer + + + Designer + + + Designer + + + Designer + + + Designer + + + $(DefaultXamlRuntime) + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Settings/Debug/Tabs/RenderDebugViewModel.cs b/src/Artemis.UI/Screens/Settings/Debug/Tabs/RenderDebugViewModel.cs index 437284ed4..2d5fc3572 100644 --- a/src/Artemis.UI/Screens/Settings/Debug/Tabs/RenderDebugViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/Debug/Tabs/RenderDebugViewModel.cs @@ -52,22 +52,22 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs { Execute.PostToUIThread(() => { - if (e.BitmapBrush?.Bitmap == null || e.BitmapBrush.Bitmap.Pixels.Length == 0) + if (e.Texture.Bitmap.Pixels.Length == 0) return; - SKImageInfo bitmapInfo = e.BitmapBrush.Bitmap.Info; + SKImageInfo bitmapInfo = e.Texture.Bitmap.Info; if (!(CurrentFrame is WriteableBitmap writeableBitmap) || writeableBitmap.Width != bitmapInfo.Width || writeableBitmap.Height != bitmapInfo.Height) { - CurrentFrame = e.BitmapBrush.Bitmap.ToWriteableBitmap(); + CurrentFrame = e.Texture.Bitmap.ToWriteableBitmap(); return; } try { - using (SKImage skiaImage = SKImage.FromPixels(e.BitmapBrush.Bitmap.PeekPixels())) + using (SKImage skiaImage = SKImage.FromPixels(e.Texture.Bitmap.PeekPixels())) { SKImageInfo info = new(skiaImage.Width, skiaImage.Height); writeableBitmap.Lock(); diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigViewModel.cs b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigViewModel.cs index ad06f0ca0..ea52a5867 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigViewModel.cs +++ b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigViewModel.cs @@ -17,16 +17,16 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs private readonly ICoreService _coreService; private readonly IRgbService _rgbService; private readonly IMessageService _messageService; - private readonly double _initialRedScale; - private readonly double _initialGreenScale; - private readonly double _initialBlueScale; + private readonly float _initialRedScale; + private readonly float _initialGreenScale; + private readonly float _initialBlueScale; private int _rotation; - private double _scale; + private float _scale; private int _x; private int _y; - private double _redScale; - private double _greenScale; - private double _blueScale; + private float _redScale; + private float _greenScale; + private float _blueScale; private SKColor _currentColor; private bool _displayOnDevices; @@ -46,9 +46,9 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs Y = (int) Device.Y; Scale = Device.Scale; Rotation = (int) Device.Rotation; - RedScale = Device.RedScale * 100d; - GreenScale = Device.GreenScale * 100d; - BlueScale = Device.BlueScale * 100d; + RedScale = Device.RedScale * 100f; + GreenScale = Device.GreenScale * 100f; + BlueScale = Device.BlueScale * 100f; //we need to store the initial values to be able to restore them when the user clicks "Cancel" _initialRedScale = Device.RedScale; _initialGreenScale = Device.GreenScale; @@ -79,7 +79,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs set => SetAndNotify(ref _y, value); } - public double Scale + public float Scale { get => _scale; set => SetAndNotify(ref _scale, value); @@ -91,19 +91,19 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs set => SetAndNotify(ref _rotation, value); } - public double RedScale + public float RedScale { get => _redScale; set => SetAndNotify(ref _redScale, value); } - public double GreenScale + public float GreenScale { get => _greenScale; set => SetAndNotify(ref _greenScale, value); } - public double BlueScale + public float BlueScale { get => _blueScale; set => SetAndNotify(ref _blueScale, value); @@ -134,9 +134,9 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs Device.Y = Y; Device.Scale = Scale; Device.Rotation = Rotation; - Device.RedScale = RedScale / 100d; - Device.GreenScale = GreenScale / 100d; - Device.BlueScale = BlueScale / 100d; + Device.RedScale = RedScale / 100f; + Device.GreenScale = GreenScale / 100f; + Device.BlueScale = BlueScale / 100f; _coreService.ModuleRenderingDisabled = false; Session.Close(true); @@ -144,9 +144,9 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs public void ApplyScaling() { - Device.RedScale = RedScale / 100d; - Device.GreenScale = GreenScale / 100d; - Device.BlueScale = BlueScale / 100d; + Device.RedScale = RedScale / 100f; + Device.GreenScale = GreenScale / 100f; + Device.BlueScale = BlueScale / 100f; } public void BrowseCustomLayout(object sender, MouseEventArgs e) diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigViewModelValidator.cs b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigViewModelValidator.cs index 764bb36db..188ace180 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigViewModelValidator.cs +++ b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigViewModelValidator.cs @@ -10,7 +10,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs RuleFor(m => m.Y).GreaterThanOrEqualTo(0).WithMessage("Y-coordinate must be 0 or greater"); - RuleFor(m => m.Scale).GreaterThanOrEqualTo(0.2).WithMessage("Scale must be 0.2 or greater"); + RuleFor(m => m.Scale).GreaterThanOrEqualTo(0.2f).WithMessage("Scale must be 0.2 or greater"); RuleFor(m => m.Rotation).GreaterThanOrEqualTo(0).WithMessage("Rotation must be 0 or greater"); RuleFor(m => m.Rotation).LessThanOrEqualTo(359).WithMessage("Rotation must be 359 or less"); diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceDetectInputViewModel.cs b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceDetectInputViewModel.cs index 07f04fce9..4168c5b00 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceDetectInputViewModel.cs +++ b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceDetectInputViewModel.cs @@ -4,9 +4,7 @@ using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.Shared.Services; using MaterialDesignThemes.Wpf; -using RGB.NET.Brushes; using RGB.NET.Core; -using RGB.NET.Groups; namespace Artemis.UI.Screens.SurfaceEditor.Dialogs { From 62497fa18886e992897f6b510b09959edbd94a1f Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Wed, 24 Feb 2021 13:05:50 +0100 Subject: [PATCH 2/8] Updated to use a simpler texture --- src/Artemis.Core/Artemis.Core.csproj | 3 + src/Artemis.Core/RGB.NET/ArtemisSampler.cs | 32 ---------- src/Artemis.Core/RGB.NET/SKTexture.cs | 72 ++-------------------- 3 files changed, 9 insertions(+), 98 deletions(-) delete mode 100644 src/Artemis.Core/RGB.NET/ArtemisSampler.cs diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index cb65d532a..bcbc79521 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -70,6 +70,9 @@ ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll + + ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Presets.dll + diff --git a/src/Artemis.Core/RGB.NET/ArtemisSampler.cs b/src/Artemis.Core/RGB.NET/ArtemisSampler.cs deleted file mode 100644 index 307dcc252..000000000 --- a/src/Artemis.Core/RGB.NET/ArtemisSampler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using RGB.NET.Core; - -namespace Artemis.Core -{ - public class ArtemisSampler : ISampler - { - #region Methods - - /// - public Color SampleColor(SamplerInfo info) - { - int count = info.Width * info.Height; - if (count == 0) return Color.Transparent; - - ReadOnlySpan data = info.Data; - - uint r = 0, g = 0, b = 0; - for (int i = 0; i < data.Length; i += 4) - { - r += data[i]; - g += data[i + 1]; - b += data[i + 2]; - } - - float divisor = count * byte.MaxValue; - return new Color(r / divisor, g / divisor, b / divisor); - } - - #endregion - } -} diff --git a/src/Artemis.Core/RGB.NET/SKTexture.cs b/src/Artemis.Core/RGB.NET/SKTexture.cs index 3be5905a2..367faab76 100644 --- a/src/Artemis.Core/RGB.NET/SKTexture.cs +++ b/src/Artemis.Core/RGB.NET/SKTexture.cs @@ -1,95 +1,35 @@ using System; -using System.Buffers; using RGB.NET.Core; +using RGB.NET.Presets.Textures.Sampler; using SkiaSharp; namespace Artemis.Core { - public sealed class SKTexture : ITexture + public sealed class SKTexture : PixelTexture { - #region Constants - - private const int STACK_ALLOC_LIMIT = 1024; - - #endregion - #region Properties & Fields private readonly SKBitmap _bitmap; - private readonly int _stride; - public SKBitmap Bitmap => _bitmap; - public Size Size { get; } - - public ISampler Sampler { get; set; } = new ArtemisSampler(); - - public Color this[in Point point] - { - get - { - int x = (Size.Width * point.X.Clamp(0, 1)).RoundToInt(); - int y = (Size.Height * point.Y.Clamp(0, 1)).RoundToInt(); - return _bitmap.GetPixel(x, y).ToRgbColor(); - } - } - - public Color this[in Rectangle rectangle] - { - get - { - int x = (Size.Width * rectangle.Location.X.Clamp(0, 1)).RoundToInt(); - int y = (Size.Height * rectangle.Location.Y.Clamp(0, 1)).RoundToInt(); - int width = (Size.Width * rectangle.Size.Width.Clamp(0, 1)).RoundToInt(); - int height = (Size.Height * rectangle.Size.Height.Clamp(0, 1)).RoundToInt(); - - int bufferSize = width * height * 4; - if (bufferSize <= STACK_ALLOC_LIMIT) - { - Span buffer = stackalloc byte[bufferSize]; - GetRegionData(x, y, width, height, buffer); - return Sampler.SampleColor(new SamplerInfo(width, height, buffer)); - } - else - { - byte[] rent = ArrayPool.Shared.Rent(bufferSize); - Span buffer = new Span(rent).Slice(0, bufferSize); - GetRegionData(x, y, width, height, buffer); - Color color = Sampler.SampleColor(new SamplerInfo(width, height, buffer)); - ArrayPool.Shared.Return(rent); - - return color; - } - } - } + protected override ReadOnlySpan Data => _bitmap.GetPixelSpan(); #endregion #region Constructors public SKTexture(SKBitmap bitmap) + : base(bitmap.Width, bitmap.Height, 4, new AverageByteSampler()) { this._bitmap = bitmap; - - Size = new Size(bitmap.Width, bitmap.Height); - _stride = bitmap.Width; } #endregion #region Methods - private void GetRegionData(int x, int y, int width, int height, in Span buffer) - { - int width4 = width * 4; - ReadOnlySpan data = _bitmap.GetPixelSpan(); - for (int i = 0; i < height; i++) - { - ReadOnlySpan dataSlice = data.Slice((((y + i) * _stride) + x) * 4, width4); - Span destination = buffer.Slice(i * width4, width4); - dataSlice.CopyTo(destination); - } - } + /// + protected override Color GetColor(ReadOnlySpan pixel) => new(pixel[0], pixel[1], pixel[2]); #endregion } From 154c1393c2203b02f7a09464f34806a80b190771 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 24 Feb 2021 21:07:01 +0100 Subject: [PATCH 3/8] CSPROJ - Formatting --- src/Artemis.UI/Artemis.UI.csproj | 710 +++++++++++++++---------------- 1 file changed, 355 insertions(+), 355 deletions(-) diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 7ec6d7c41..a22295ddd 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -1,358 +1,358 @@  - - WinExe - net5.0-windows - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - true - Artemis - Artemis - en-US - Provides advanced unified lighting across many different brands RGB peripherals - Copyright © Robert Beekman - 2021 - 2.0.0.0 - bin\$(Platform)\$(Configuration)\ - true - x64 - windows - - - x64 - + + WinExe + net5.0-windows + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + Artemis + Artemis + en-US + Provides advanced unified lighting across many different brands RGB peripherals + Copyright © Robert Beekman - 2021 + 2.0.0.0 + bin\$(Platform)\$(Configuration)\ + true + x64 + windows + + + x64 + - - Resources\Images\Logo\logo-512.ico - - - - 2.0.0.0 - 2.0.0 - - - 2.0-{chash:6} - true - true - true - v[0-9]* - true - git - true - - - - - - - false - - - - - - - - - - - - - - - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll - - - ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll - - - - - - ResXFileCodeGenerator - Designer - Resources.Designer.cs - - - - - true - - - true - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - True - True - Settings.settings - - - - - PreserveNewest - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - Designer - - - Designer - - - Designer - - - Designer - - - Designer - - - Designer - - - $(DefaultXamlRuntime) - - + + Resources\Images\Logo\logo-512.ico + + + + 2.0.0.0 + 2.0.0 + + + 2.0-{chash:6} + true + true + true + v[0-9]* + true + git + true + + + + + + + false + + + + + + + + + + + + + + + ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll + + + ..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll + + + + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + + + true + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + Designer + + + Designer + + + Designer + + + Designer + + + Designer + + + Designer + + + $(DefaultXamlRuntime) + + \ No newline at end of file From 528d082e62d756b0f04987ca0dd660f17af48b39 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 24 Feb 2021 21:30:50 +0100 Subject: [PATCH 4/8] UI - Removed now unused sample size setting --- src/Artemis.Core/Services/RgbService.cs | 2 - .../Tabs/General/GeneralSettingsTabView.xaml | 21 --------- .../General/GeneralSettingsTabViewModel.cs | 43 +++++-------------- 3 files changed, 10 insertions(+), 56 deletions(-) diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs index 5ca291db6..459f140e7 100644 --- a/src/Artemis.Core/Services/RgbService.cs +++ b/src/Artemis.Core/Services/RgbService.cs @@ -25,7 +25,6 @@ namespace Artemis.Core.Services private readonly IPluginManagementService _pluginManagementService; private readonly IDeviceRepository _deviceRepository; private readonly PluginSetting _targetFrameRateSetting; - private readonly PluginSetting _sampleSizeSetting; private ListLedGroup? _surfaceLedGroup; private bool _modifyingProviders; @@ -35,7 +34,6 @@ namespace Artemis.Core.Services _pluginManagementService = pluginManagementService; _deviceRepository = deviceRepository; _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25); - _sampleSizeSetting = settingsService.GetSetting("Core.SampleSize", 1); Surface = new RGBSurface(); diff --git a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml index 9f0564084..6aef820f3 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml +++ b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml @@ -347,27 +347,6 @@ - - - - - - - - - - - - - LED sample size - - Sets the amount of samples that is taken to determine each LEDs color. This means a LED can be semi off if it is not completely covered by a color. - - - - - - diff --git a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs index 21a54084c..a84a3281e 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs @@ -3,11 +3,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Net.Mime; +using System.Security.Principal; using System.Threading.Tasks; -using System.Windows; using System.Xml.Linq; -using System.Xml.XPath; using Artemis.Core; using Artemis.Core.LayerBrushes; using Artemis.Core.Services; @@ -16,7 +14,6 @@ using Artemis.UI.Screens.StartupWizard; using Artemis.UI.Services; using Artemis.UI.Shared; using Artemis.UI.Shared.Services; -using MaterialDesignThemes.Wpf; using Ninject; using Serilog.Events; using Stylet; @@ -26,17 +23,16 @@ namespace Artemis.UI.Screens.Settings.Tabs.General public class GeneralSettingsTabViewModel : Screen { private readonly IDebugService _debugService; - private readonly IKernel _kernel; - private readonly IWindowManager _windowManager; + private readonly PluginSetting _defaultLayerBrushDescriptor; private readonly IDialogService _dialogService; + private readonly IKernel _kernel; + private readonly IMessageService _messageService; private readonly ISettingsService _settingsService; private readonly IUpdateService _updateService; - private readonly IMessageService _messageService; - private List> _renderScales; - private List _sampleSizes; - private List> _targetFrameRates; - private readonly PluginSetting _defaultLayerBrushDescriptor; + private readonly IWindowManager _windowManager; private bool _canOfferUpdatesIfFound = true; + private List> _renderScales; + private List> _targetFrameRates; public GeneralSettingsTabViewModel( IKernel kernel, @@ -68,9 +64,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.General for (int i = 10; i <= 30; i += 5) TargetFrameRates.Add(new Tuple(i + " FPS", i)); - // Anything else is kinda broken right now - SampleSizes = new List {1, 9}; - List layerBrushProviders = pluginManagementService.GetFeaturesOfType(); LayerBrushDescriptors = new BindableCollection(layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors)); @@ -111,12 +104,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.General set => SetAndNotify(ref _renderScales, value); } - public List SampleSizes - { - get => _sampleSizes; - set => SetAndNotify(ref _sampleSizes, value); - } - public bool StartWithWindows { get => _settingsService.GetSetting("UI.AutoRun", false).Value; @@ -239,16 +226,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.General } } - public int SampleSize - { - get => _settingsService.GetSetting("Core.SampleSize", 1).Value; - set - { - _settingsService.GetSetting("Core.SampleSize", 1).Value = value; - _settingsService.GetSetting("Core.SampleSize", 1).Save(); - } - } - public PluginSetting WebServerPortSetting { get; } public bool CanOfferUpdatesIfFound @@ -320,7 +297,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.General File.Delete(autoRunFile); // TODO: Don't do anything if running a development build, only auto-run release builds - + // Create or remove the task if necessary try { @@ -363,13 +340,13 @@ namespace Artemis.UI.Screens.Settings.Tabs.General task.Descendants().First(d => d.Name.LocalName == "RegistrationInfo").Descendants().First(d => d.Name.LocalName == "Date") .SetValue(DateTime.Now); task.Descendants().First(d => d.Name.LocalName == "RegistrationInfo").Descendants().First(d => d.Name.LocalName == "Author") - .SetValue(System.Security.Principal.WindowsIdentity.GetCurrent().Name); + .SetValue(WindowsIdentity.GetCurrent().Name); task.Descendants().First(d => d.Name.LocalName == "Triggers").Descendants().First(d => d.Name.LocalName == "LogonTrigger").Descendants().First(d => d.Name.LocalName == "Delay") .SetValue(TimeSpan.FromSeconds(AutoRunDelay)); task.Descendants().First(d => d.Name.LocalName == "Principals").Descendants().First(d => d.Name.LocalName == "Principal").Descendants().First(d => d.Name.LocalName == "UserId") - .SetValue(System.Security.Principal.WindowsIdentity.GetCurrent().User.Value); + .SetValue(WindowsIdentity.GetCurrent().User.Value); task.Descendants().First(d => d.Name.LocalName == "Actions").Descendants().First(d => d.Name.LocalName == "Exec").Descendants().First(d => d.Name.LocalName == "WorkingDirectory") .SetValue(Constants.ApplicationFolder); From 2e859bc84c1b50cc059bc3e5fe48343de301f222 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Thu, 25 Feb 2021 00:30:25 +0100 Subject: [PATCH 5/8] Small RGB.NET update --- src/Artemis.Core/RGB.NET/SKTexture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Artemis.Core/RGB.NET/SKTexture.cs b/src/Artemis.Core/RGB.NET/SKTexture.cs index 367faab76..04992f3e7 100644 --- a/src/Artemis.Core/RGB.NET/SKTexture.cs +++ b/src/Artemis.Core/RGB.NET/SKTexture.cs @@ -29,7 +29,7 @@ namespace Artemis.Core #region Methods /// - protected override Color GetColor(ReadOnlySpan pixel) => new(pixel[0], pixel[1], pixel[2]); + protected override Color GetColor(in ReadOnlySpan pixel) => new(pixel[0], pixel[1], pixel[2]); #endregion } From 1ea2e2bee7deb1a9a8f6ac762b75c420554b8d3a Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 25 Feb 2021 19:58:40 +0100 Subject: [PATCH 6/8] Devices - Ported color correction code to RGB.NET --- .../Events/FrameRenderedEventArgs.cs | 2 +- .../Models/Surface/ArtemisDevice.cs | 7 +++- src/Artemis.Core/Models/Surface/ArtemisLed.cs | 11 +----- src/Artemis.Core/RGB.NET/SKTexture.cs | 37 ++++++++++++------- .../RGB.NET/ScaleColorCorrection.cs | 19 ++++++++++ .../Controls/DeviceVisualizerLed.cs | 9 ++--- 6 files changed, 55 insertions(+), 30 deletions(-) create mode 100644 src/Artemis.Core/RGB.NET/ScaleColorCorrection.cs diff --git a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs index 110f7279c..65c0c18e9 100644 --- a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs +++ b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs @@ -15,7 +15,7 @@ namespace Artemis.Core } /// - /// Gets the bitmap brush used to render this frame + /// Gets the texture used to render this frame /// public SKTexture Texture { get; } diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs index 7db6d2ff1..661130160 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs @@ -340,18 +340,20 @@ namespace Artemis.Core DeviceEntity.InputIdentifiers.Clear(); foreach (ArtemisDeviceInputIdentifier identifier in InputIdentifiers) + { DeviceEntity.InputIdentifiers.Add(new DeviceInputIdentifierEntity { InputProvider = identifier.InputProvider, Identifier = identifier.Identifier }); + } } internal void ApplyToRgbDevice() { RgbDevice.Rotation = DeviceEntity.Rotation; RgbDevice.Scale = DeviceEntity.Scale; - + // Workaround for device rotation not applying if (DeviceEntity.X == 0 && DeviceEntity.Y == 0) RgbDevice.Location = new Point(1, 1); @@ -361,6 +363,9 @@ namespace Artemis.Core foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers) InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier)); + if (!RgbDevice.ColorCorrections.Any()) + RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this)); + CalculateRenderProperties(); OnDeviceUpdated(); } diff --git a/src/Artemis.Core/Models/Surface/ArtemisLed.cs b/src/Artemis.Core/Models/Surface/ArtemisLed.cs index eaf06b73a..473757f76 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisLed.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisLed.cs @@ -53,16 +53,7 @@ namespace Artemis.Core { return RgbLed.ToString(); } - - /// - /// Gets the color of this led, reverting the correction done to the parent device - /// - /// - public Color GetOriginalColor() - { - return RgbLed.Color.DivideRGB(Device.RedScale, Device.GreenScale, Device.BlueScale); - } - + internal void CalculateRectangles() { Rectangle = RgbLed.Boundary.ToSKRect(); diff --git a/src/Artemis.Core/RGB.NET/SKTexture.cs b/src/Artemis.Core/RGB.NET/SKTexture.cs index 04992f3e7..45d039203 100644 --- a/src/Artemis.Core/RGB.NET/SKTexture.cs +++ b/src/Artemis.Core/RGB.NET/SKTexture.cs @@ -5,23 +5,17 @@ using SkiaSharp; namespace Artemis.Core { + /// + /// Represents a SkiaSharp-based RGB.NET PixelTexture + /// public sealed class SKTexture : PixelTexture { - #region Properties & Fields - - private readonly SKBitmap _bitmap; - public SKBitmap Bitmap => _bitmap; - - protected override ReadOnlySpan Data => _bitmap.GetPixelSpan(); - - #endregion - #region Constructors - public SKTexture(SKBitmap bitmap) + internal SKTexture(SKBitmap bitmap) : base(bitmap.Width, bitmap.Height, 4, new AverageByteSampler()) { - this._bitmap = bitmap; + Bitmap = bitmap; } #endregion @@ -29,8 +23,25 @@ namespace Artemis.Core #region Methods /// - protected override Color GetColor(in ReadOnlySpan pixel) => new(pixel[0], pixel[1], pixel[2]); + protected override Color GetColor(in ReadOnlySpan pixel) + { + return new(pixel[0], pixel[1], pixel[2]); + } + + #endregion + + #region Properties & Fields + + /// + /// Gets the SKBitmap backing this texture + /// + public SKBitmap Bitmap { get; } + + /// + /// Gets the color data in RGB format + /// + protected override ReadOnlySpan Data => Bitmap.GetPixelSpan(); #endregion } -} +} \ No newline at end of file diff --git a/src/Artemis.Core/RGB.NET/ScaleColorCorrection.cs b/src/Artemis.Core/RGB.NET/ScaleColorCorrection.cs new file mode 100644 index 000000000..8cd7dd1f5 --- /dev/null +++ b/src/Artemis.Core/RGB.NET/ScaleColorCorrection.cs @@ -0,0 +1,19 @@ +using RGB.NET.Core; + +namespace Artemis.Core +{ + internal class ScaleColorCorrection : IColorCorrection + { + private readonly ArtemisDevice _device; + + public ScaleColorCorrection(ArtemisDevice device) + { + _device = device; + } + + public void ApplyTo(ref Color color) + { + color = color.MultiplyRGB(_device.RedScale, _device.GreenScale, _device.BlueScale); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs index 498932b35..1e96549a9 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs @@ -27,7 +27,7 @@ namespace Artemis.UI.Shared if (Led.Layout?.Image != null && File.Exists(Led.Layout.Image.LocalPath)) LedImage = new BitmapImage(Led.Layout.Image); - + CreateLedGeometry(); } @@ -44,10 +44,9 @@ namespace Artemis.UI.Shared _renderColorBrush ??= new SolidColorBrush(); - RGB.NET.Core.Color originalColor = Led.GetOriginalColor(); - byte r = originalColor.GetR(); - byte g = originalColor.GetG(); - byte b = originalColor.GetB(); + byte r = Led.RgbLed.Color.GetR(); + byte g = Led.RgbLed.Color.GetG(); + byte b = Led.RgbLed.Color.GetB(); _renderColor.A = isDimmed ? 100 : 255; _renderColor.R = r; From 5bcba8a4a58fe663709c47035a0098c50f8452b3 Mon Sep 17 00:00:00 2001 From: Robert Date: Fri, 5 Mar 2021 16:18:12 +0100 Subject: [PATCH 7/8] Device properties - Changed doubles to floats for RGB.NET update --- .../Tabs/DevicePropertiesTabViewModel.cs | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs b/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs index 42fffa621..4de139698 100644 --- a/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs @@ -16,16 +16,16 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs private readonly ICoreService _coreService; private readonly IMessageService _messageService; private readonly IRgbService _rgbService; - private double _blueScale; + private float _blueScale; private SKColor _currentColor; private bool _displayOnDevices; - private double _greenScale; - private double _initialBlueScale; - private double _initialGreenScale; - private double _initialRedScale; - private double _redScale; + private float _greenScale; + private float _initialBlueScale; + private float _initialGreenScale; + private float _initialRedScale; + private float _redScale; private int _rotation; - private double _scale; + private float _scale; private int _x; private int _y; @@ -57,7 +57,7 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs set => SetAndNotify(ref _y, value); } - public double Scale + public float Scale { get => _scale; set => SetAndNotify(ref _scale, value); @@ -69,19 +69,19 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs set => SetAndNotify(ref _rotation, value); } - public double RedScale + public float RedScale { get => _redScale; set => SetAndNotify(ref _redScale, value); } - public double GreenScale + public float GreenScale { get => _greenScale; set => SetAndNotify(ref _greenScale, value); } - public double BlueScale + public float BlueScale { get => _blueScale; set => SetAndNotify(ref _blueScale, value); @@ -101,9 +101,9 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs public void ApplyScaling() { - Device.RedScale = RedScale / 100d; - Device.GreenScale = GreenScale / 100d; - Device.BlueScale = BlueScale / 100d; + Device.RedScale = RedScale / 100f; + Device.GreenScale = GreenScale / 100f; + Device.BlueScale = BlueScale / 100f; } public void BrowseCustomLayout(object sender, MouseEventArgs e) @@ -139,9 +139,9 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs Device.Y = Y; Device.Scale = Scale; Device.Rotation = Rotation; - Device.RedScale = RedScale / 100d; - Device.GreenScale = GreenScale / 100d; - Device.BlueScale = BlueScale / 100d; + Device.RedScale = RedScale / 100f; + Device.GreenScale = GreenScale / 100f; + Device.BlueScale = BlueScale / 100f; _coreService.ModuleRenderingDisabled = false; } @@ -159,9 +159,9 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs Y = (int) Device.Y; Scale = Device.Scale; Rotation = (int) Device.Rotation; - RedScale = Device.RedScale * 100d; - GreenScale = Device.GreenScale * 100d; - BlueScale = Device.BlueScale * 100d; + RedScale = Device.RedScale * 100f; + GreenScale = Device.GreenScale * 100f; + BlueScale = Device.BlueScale * 100f; //we need to store the initial values to be able to restore them when the user clicks "Cancel" _initialRedScale = Device.RedScale; _initialGreenScale = Device.GreenScale; From 4b914718e6f2ac0737a43b93db386ffdf70a5b08 Mon Sep 17 00:00:00 2001 From: Robert Date: Sat, 6 Mar 2021 00:07:40 +0100 Subject: [PATCH 8/8] Further RGB.NET updates --- src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs | 4 ++-- src/Artemis.Core/RGB.NET/SKTexture.cs | 8 +++++++- src/Artemis.Core/Services/CoreService.cs | 2 -- src/Artemis.Core/Services/DeviceService.cs | 2 +- src/Artemis.Core/Services/RgbService.cs | 5 ++++- .../Dialogs/SurfaceDeviceDetectInputViewModel.cs | 2 +- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs index e52e06c13..843321c99 100644 --- a/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs @@ -49,7 +49,7 @@ namespace Artemis.Core.LayerBrushes LedGroup.ZIndex = 1; List missingLeds = Layer.Leds.Where(l => !LedGroup.ContainsLed(l.RgbLed)).Select(l => l.RgbLed).ToList(); - List extraLeds = LedGroup.GetLeds().Where(l => Layer.Leds.All(layerLed => layerLed.RgbLed != l)).ToList(); + List extraLeds = LedGroup.Where(l => Layer.Leds.All(layerLed => layerLed.RgbLed != l)).ToList(); LedGroup.AddLeds(missingLeds); LedGroup.RemoveLeds(extraLeds); LedGroup.Brush = GetBrush(); @@ -78,7 +78,7 @@ namespace Artemis.Core.LayerBrushes throw new ArtemisCoreException("Cannot dispose RGB.NET layer brush because RgbService is not set"); Layer.RenderPropertiesUpdated -= LayerOnRenderPropertiesUpdated; - LedGroup?.Detach(RgbService.Surface); + LedGroup?.Detach(); LedGroup = null; } diff --git a/src/Artemis.Core/RGB.NET/SKTexture.cs b/src/Artemis.Core/RGB.NET/SKTexture.cs index 45d039203..59f8d0558 100644 --- a/src/Artemis.Core/RGB.NET/SKTexture.cs +++ b/src/Artemis.Core/RGB.NET/SKTexture.cs @@ -8,7 +8,7 @@ namespace Artemis.Core /// /// Represents a SkiaSharp-based RGB.NET PixelTexture /// - public sealed class SKTexture : PixelTexture + public sealed class SKTexture : PixelTexture, IDisposable { #region Constructors @@ -42,6 +42,12 @@ namespace Artemis.Core /// protected override ReadOnlySpan Data => Bitmap.GetPixelSpan(); + /// + public void Dispose() + { + Bitmap.Dispose(); + } + #endregion } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index e4e0a460d..19b9b6210 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -258,10 +258,8 @@ namespace Artemis.Core.Services private void InvalidateBitmap() { - lock (_bitmapLock) { - _bitmap?.Dispose(); _bitmap = null; } } diff --git a/src/Artemis.Core/Services/DeviceService.cs b/src/Artemis.Core/Services/DeviceService.cs index 46f8bdc52..68329ac77 100644 --- a/src/Artemis.Core/Services/DeviceService.cs +++ b/src/Artemis.Core/Services/DeviceService.cs @@ -31,7 +31,7 @@ namespace Artemis.Core.Services Task.Run(async () => { await Task.Delay(200); - ledGroup.Detach(_rgbService.Surface); + ledGroup.Detach(); if (blinkCount < 5) { diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs index f29cda2e9..30e359658 100644 --- a/src/Artemis.Core/Services/RgbService.cs +++ b/src/Artemis.Core/Services/RgbService.cs @@ -136,8 +136,11 @@ namespace Artemis.Core.Services public void UpdateTexture(SKBitmap bitmap) { + SKTexture? oldTexture = Texture; Texture = new SKTexture(bitmap); TextureBrush.Texture = Texture; + + oldTexture?.Dispose(); } private void SurfaceOnLayoutChanged(SurfaceLayoutChangedEventArgs args) => UpdateLedGroup(); @@ -161,7 +164,7 @@ namespace Artemis.Core.Services lock (_surfaceLedGroup) { // Clean up the old background - _surfaceLedGroup.Detach(Surface); + _surfaceLedGroup.Detach(); // Apply the application wide brush and decorator _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) { Brush = TextureBrush }; diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceDetectInputViewModel.cs b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceDetectInputViewModel.cs index 4168c5b00..cd35e79f1 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceDetectInputViewModel.cs +++ b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceDetectInputViewModel.cs @@ -43,7 +43,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs { base.OnDialogClosed(sender, e); _inputService.DeviceIdentified -= InputServiceOnDeviceIdentified; - _ledGroup.Detach(_rgbService.Surface); + _ledGroup.Detach(); } private void InputServiceOnDeviceIdentified(object sender, EventArgs e)