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

Core - Simplified and improved render scaling

This commit is contained in:
SpoinkyNL 2020-12-08 22:54:54 +01:00
parent 18359c443f
commit 186d012087
10 changed files with 63 additions and 99 deletions

View File

@ -1,5 +1,6 @@
using System.Text; using System.Text;
using RGB.NET.Core; using RGB.NET.Core;
using SkiaSharp;
namespace Artemis.Core namespace Artemis.Core
{ {
@ -20,4 +21,17 @@ namespace Artemis.Core
return builder.ToString(); return builder.ToString();
} }
} }
internal static class RgbRectangleExtensions
{
public static SKRect ToSKRect(this Rectangle rectangle)
{
return SKRect.Create(
(float) rectangle.Location.X,
(float) rectangle.Location.Y,
(float) rectangle.Size.Width,
(float) rectangle.Size.Height
);
}
}
} }

View File

@ -417,7 +417,7 @@ namespace Artemis.Core
{ {
SKPath path = new SKPath {FillType = SKPathFillType.Winding}; SKPath path = new SKPath {FillType = SKPathFillType.Winding};
foreach (ArtemisLed artemisLed in Leds) foreach (ArtemisLed artemisLed in Leds)
path.AddRect(artemisLed.AbsoluteRenderRectangle); path.AddRect(artemisLed.AbsoluteRectangle);
Path = path; Path = path;
} }

View File

@ -14,8 +14,8 @@ namespace Artemis.Core
/// </summary> /// </summary>
public class ArtemisDevice : CorePropertyChanged public class ArtemisDevice : CorePropertyChanged
{ {
private SKPath? _renderPath; private SKPath? _path;
private SKRect _renderRectangle; private SKRect _rectangle;
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface) internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface)
{ {
@ -58,21 +58,21 @@ namespace Artemis.Core
} }
/// <summary> /// <summary>
/// Gets the rectangle covering the device, sized to match the render scale /// Gets the rectangle covering the device
/// </summary> /// </summary>
public SKRect RenderRectangle public SKRect Rectangle
{ {
get => _renderRectangle; get => _rectangle;
private set => SetAndNotify(ref _renderRectangle, value); private set => SetAndNotify(ref _rectangle, value);
} }
/// <summary> /// <summary>
/// Gets the path surrounding the device, sized to match the render scale /// Gets the path surrounding the device
/// </summary> /// </summary>
public SKPath? RenderPath public SKPath? Path
{ {
get => _renderPath; get => _path;
private set => SetAndNotify(ref _renderPath, value); private set => SetAndNotify(ref _path, value);
} }
/// <summary> /// <summary>
@ -239,24 +239,18 @@ namespace Artemis.Core
internal void CalculateRenderProperties() internal void CalculateRenderProperties()
{ {
RenderRectangle = SKRect.Create( Rectangle = RgbDevice.DeviceRectangle.ToSKRect();
(RgbDevice.Location.X * Surface.Scale).RoundToInt(),
(RgbDevice.Location.Y * Surface.Scale).RoundToInt(),
(RgbDevice.DeviceRectangle.Size.Width * Surface.Scale).RoundToInt(),
(RgbDevice.DeviceRectangle.Size.Height * Surface.Scale).RoundToInt()
);
if (!Leds.Any()) if (!Leds.Any())
return; return;
foreach (ArtemisLed led in Leds) foreach (ArtemisLed led in Leds)
led.CalculateRenderRectangle(); led.CalculateRectangles();
SKPath path = new SKPath {FillType = SKPathFillType.Winding}; SKPath path = new SKPath {FillType = SKPathFillType.Winding};
foreach (ArtemisLed artemisLed in Leds) foreach (ArtemisLed artemisLed in Leds)
path.AddRect(artemisLed.AbsoluteRenderRectangle); path.AddRect(artemisLed.AbsoluteRectangle);
RenderPath = path; Path = path;
} }
#region Events #region Events

View File

@ -8,14 +8,14 @@ namespace Artemis.Core
/// </summary> /// </summary>
public class ArtemisLed : CorePropertyChanged public class ArtemisLed : CorePropertyChanged
{ {
private SKRect _absoluteRenderRectangle; private SKRect _absoluteRectangle;
private SKRect _renderRectangle; private SKRect _rectangle;
internal ArtemisLed(Led led, ArtemisDevice device) internal ArtemisLed(Led led, ArtemisDevice device)
{ {
RgbLed = led; RgbLed = led;
Device = device; Device = device;
CalculateRenderRectangle(); CalculateRectangles();
} }
/// <summary> /// <summary>
@ -29,38 +29,27 @@ namespace Artemis.Core
public ArtemisDevice Device { get; } public ArtemisDevice Device { get; }
/// <summary> /// <summary>
/// Gets the rectangle covering the LED, sized to match the render scale and positioned relative to the /// Gets the rectangle covering the LED positioned relative to the<see cref="Device" />
/// <see cref="Device" />
/// </summary> /// </summary>
public SKRect RenderRectangle public SKRect Rectangle
{ {
get => _renderRectangle; get => _rectangle;
private set => SetAndNotify(ref _renderRectangle, value); private set => SetAndNotify(ref _rectangle, value);
} }
/// <summary> /// <summary>
/// Gets the rectangle covering the LED, sized to match the render scale /// Gets the rectangle covering the LED
/// </summary> /// </summary>
public SKRect AbsoluteRenderRectangle public SKRect AbsoluteRectangle
{ {
get => _absoluteRenderRectangle; get => _absoluteRectangle;
private set => SetAndNotify(ref _absoluteRenderRectangle, value); private set => SetAndNotify(ref _absoluteRectangle, value);
} }
internal void CalculateRenderRectangle() internal void CalculateRectangles()
{ {
RenderRectangle = SKRect.Create( Rectangle = RgbLed.LedRectangle.ToSKRect();
(RgbLed.LedRectangle.Location.X * Device.Surface.Scale).RoundToInt(), AbsoluteRectangle = RgbLed.AbsoluteLedRectangle.ToSKRect();
(RgbLed.LedRectangle.Location.Y * Device.Surface.Scale).RoundToInt(),
(RgbLed.LedRectangle.Size.Width * Device.Surface.Scale).RoundToInt(),
(RgbLed.LedRectangle.Size.Height * Device.Surface.Scale).RoundToInt()
);
AbsoluteRenderRectangle = SKRect.Create(
(RgbLed.AbsoluteLedRectangle.Location.X * Device.Surface.Scale).RoundToInt(),
(RgbLed.AbsoluteLedRectangle.Location.Y * Device.Surface.Scale).RoundToInt(),
(RgbLed.AbsoluteLedRectangle.Size.Width * Device.Surface.Scale).RoundToInt(),
(RgbLed.AbsoluteLedRectangle.Size.Height * Device.Surface.Scale).RoundToInt()
);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -16,28 +16,25 @@ namespace Artemis.Core
private ReadOnlyDictionary<Led, ArtemisLed> _ledMap = new ReadOnlyDictionary<Led, ArtemisLed>(new Dictionary<Led, ArtemisLed>()); private ReadOnlyDictionary<Led, ArtemisLed> _ledMap = new ReadOnlyDictionary<Led, ArtemisLed>(new Dictionary<Led, ArtemisLed>());
private bool _isActive; private bool _isActive;
private string _name; private string _name;
private double _scale;
internal ArtemisSurface(RGBSurface rgbSurface, string name, double scale) internal ArtemisSurface(RGBSurface rgbSurface, string name)
{ {
SurfaceEntity = new SurfaceEntity {DeviceEntities = new List<DeviceEntity>()}; SurfaceEntity = new SurfaceEntity {DeviceEntities = new List<DeviceEntity>()};
EntityId = Guid.NewGuid(); EntityId = Guid.NewGuid();
RgbSurface = rgbSurface; RgbSurface = rgbSurface;
_name = name; _name = name;
_scale = scale;
_isActive = false; _isActive = false;
ApplyToEntity(); ApplyToEntity();
} }
internal ArtemisSurface(RGBSurface rgbSurface, SurfaceEntity surfaceEntity, double scale) internal ArtemisSurface(RGBSurface rgbSurface, SurfaceEntity surfaceEntity)
{ {
SurfaceEntity = surfaceEntity; SurfaceEntity = surfaceEntity;
EntityId = surfaceEntity.Id; EntityId = surfaceEntity.Id;
RgbSurface = rgbSurface; RgbSurface = rgbSurface;
_scale = scale;
_name = surfaceEntity.Name; _name = surfaceEntity.Name;
_isActive = surfaceEntity.IsActive; _isActive = surfaceEntity.IsActive;
} }
@ -47,15 +44,6 @@ namespace Artemis.Core
/// </summary> /// </summary>
public RGBSurface RgbSurface { get; } public RGBSurface RgbSurface { get; }
/// <summary>
/// Gets the scale at which this surface is rendered
/// </summary>
public double Scale
{
get => _scale;
private set => SetAndNotify(ref _scale, value);
}
/// <summary> /// <summary>
/// Gets the name of the surface /// Gets the name of the surface
/// </summary> /// </summary>
@ -96,19 +84,6 @@ namespace Artemis.Core
internal SurfaceEntity SurfaceEntity { get; set; } internal SurfaceEntity SurfaceEntity { get; set; }
internal Guid EntityId { get; set; } internal Guid EntityId { get; set; }
/// <summary>
/// Updates the scale of the surface
/// </summary>
/// <param name="value"></param>
public void UpdateScale(double value)
{
Scale = value;
foreach (ArtemisDevice device in Devices)
device.CalculateRenderProperties();
OnScaleChanged();
}
/// <summary> /// <summary>
/// Attempts to retrieve the <see cref="ArtemisLed" /> that corresponds the provided RGB.NET <see cref="Led" /> /// Attempts to retrieve the <see cref="ArtemisLed" /> that corresponds the provided RGB.NET <see cref="Led" />
/// </summary> /// </summary>

View File

@ -41,7 +41,7 @@ namespace Artemis.Core.LayerBrushes
pointsPath.AddPoly(new[] pointsPath.AddPoly(new[]
{ {
new SKPoint(0, 0), new SKPoint(0, 0),
new SKPoint(artemisLed.AbsoluteRenderRectangle.Left - Layer.Bounds.Left, artemisLed.AbsoluteRenderRectangle.Top - Layer.Bounds.Top) new SKPoint(artemisLed.AbsoluteRectangle.Left - Layer.Bounds.Left, artemisLed.AbsoluteRectangle.Top - Layer.Bounds.Top)
}); });
} }
@ -61,10 +61,10 @@ namespace Artemis.Core.LayerBrushes
ledPaint.Color = GetColor(artemisLed, renderPoint); ledPaint.Color = GetColor(artemisLed, renderPoint);
SKRect ledRectangle = SKRect.Create( SKRect ledRectangle = SKRect.Create(
artemisLed.AbsoluteRenderRectangle.Left - Layer.Bounds.Left, artemisLed.AbsoluteRectangle.Left - Layer.Bounds.Left,
artemisLed.AbsoluteRenderRectangle.Top - Layer.Bounds.Top, artemisLed.AbsoluteRectangle.Top - Layer.Bounds.Top,
artemisLed.AbsoluteRenderRectangle.Width, artemisLed.AbsoluteRectangle.Width,
artemisLed.AbsoluteRenderRectangle.Height artemisLed.AbsoluteRectangle.Height
); );
canvas.DrawRect(ledRectangle, ledPaint); canvas.DrawRect(ledRectangle, ledPaint);

View File

@ -27,13 +27,14 @@ namespace Artemis.Core.Services
private readonly Stopwatch _frameStopWatch; private readonly Stopwatch _frameStopWatch;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly PluginSetting<LogEventLevel> _loggingLevel; private readonly PluginSetting<LogEventLevel> _loggingLevel;
private readonly PluginSetting<double> _renderScale;
private readonly IPluginManagementService _pluginManagementService; private readonly IPluginManagementService _pluginManagementService;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly ISurfaceService _surfaceService; private readonly ISurfaceService _surfaceService;
private List<BaseDataModelExpansion> _dataModelExpansions = new List<BaseDataModelExpansion>(); private List<BaseDataModelExpansion> _dataModelExpansions = new List<BaseDataModelExpansion>();
private List<Module> _modules = new List<Module>(); private List<Module> _modules = new List<Module>();
// ReSharper disable UnusedParameter.Local - Storage migration and module service are injected early to ensure it runs before anything else // ReSharper disable UnusedParameter.Local - Storage migration and module service are injected early to ensure it runs before anything else
public CoreService(IKernel kernel, ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginManagementService pluginManagementService, public CoreService(IKernel kernel, ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginManagementService pluginManagementService,
IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService, IModuleService moduleService) IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService, IModuleService moduleService)
@ -47,6 +48,7 @@ namespace Artemis.Core.Services
_surfaceService = surfaceService; _surfaceService = surfaceService;
_profileService = profileService; _profileService = profileService;
_loggingLevel = settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Debug); _loggingLevel = settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Debug);
_renderScale = settingsService.GetSetting("Core.RenderScale", 0.5);
_frameStopWatch = new Stopwatch(); _frameStopWatch = new Stopwatch();
UpdatePluginCache(); UpdatePluginCache();
@ -185,6 +187,7 @@ namespace Artemis.Core.Services
// Render all active modules // Render all active modules
using SKCanvas canvas = new SKCanvas(_rgbService.BitmapBrush.Bitmap); using SKCanvas canvas = new SKCanvas(_rgbService.BitmapBrush.Bitmap);
canvas.Scale((float) _renderScale.Value);
canvas.Clear(new SKColor(0, 0, 0)); canvas.Clear(new SKColor(0, 0, 0));
if (!ModuleRenderingDisabled) if (!ModuleRenderingDisabled)
// While non-activated modules may be updated above if they expand the main data model, they may never render // While non-activated modules may be updated above if they expand the main data model, they may never render

View File

@ -17,6 +17,8 @@ namespace Artemis.Core.Services.Models
MarginTop = margin; MarginTop = margin;
MarginRight = margin; MarginRight = margin;
MarginBottom = margin; MarginBottom = margin;
SurfaceArrangement = null!;
} }

View File

@ -15,26 +15,23 @@ namespace Artemis.Core.Services
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IPluginManagementService _pluginManagementService; private readonly IPluginManagementService _pluginManagementService;
private readonly PluginSetting<double> _renderScaleSetting;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly List<ArtemisSurface> _surfaceConfigurations; private readonly List<ArtemisSurface> _surfaceConfigurations;
private readonly ISurfaceRepository _surfaceRepository; private readonly ISurfaceRepository _surfaceRepository;
public SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, IPluginManagementService pluginManagementService, ISettingsService settingsService) public SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, IPluginManagementService pluginManagementService)
{ {
_logger = logger; _logger = logger;
_surfaceRepository = surfaceRepository; _surfaceRepository = surfaceRepository;
_rgbService = rgbService; _rgbService = rgbService;
_pluginManagementService = pluginManagementService; _pluginManagementService = pluginManagementService;
_surfaceConfigurations = new List<ArtemisSurface>(); _surfaceConfigurations = new List<ArtemisSurface>();
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.5);
// LoadFromRepository is guaranteed to set the ActiveSurface // LoadFromRepository is guaranteed to set the ActiveSurface
ActiveSurface = null!; ActiveSurface = null!;
LoadFromRepository(); LoadFromRepository();
_rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded; _rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded;
_renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged;
} }
public ArtemisSurface ActiveSurface { get; private set; } public ArtemisSurface ActiveSurface { get; private set; }
@ -43,7 +40,7 @@ namespace Artemis.Core.Services
public ArtemisSurface CreateSurfaceConfiguration(string name) public ArtemisSurface CreateSurfaceConfiguration(string name)
{ {
// Create a blank config // Create a blank config
ArtemisSurface configuration = new ArtemisSurface(_rgbService.Surface, name, _renderScaleSetting.Value); ArtemisSurface configuration = new ArtemisSurface(_rgbService.Surface, name);
// Add all current devices // Add all current devices
foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices) foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices)
@ -133,7 +130,7 @@ namespace Artemis.Core.Services
foreach (SurfaceEntity surfaceEntity in configs) foreach (SurfaceEntity surfaceEntity in configs)
{ {
// Create the surface entity // Create the surface entity
ArtemisSurface surfaceConfiguration = new ArtemisSurface(_rgbService.Surface, surfaceEntity, _renderScaleSetting.Value); ArtemisSurface surfaceConfiguration = new ArtemisSurface(_rgbService.Surface, surfaceEntity);
foreach (DeviceEntity position in surfaceEntity.DeviceEntities) foreach (DeviceEntity position in surfaceEntity.DeviceEntities)
{ {
IRGBDevice? device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier); IRGBDevice? device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
@ -225,15 +222,6 @@ namespace Artemis.Core.Services
UpdateSurfaceConfiguration(ActiveSurface, true); UpdateSurfaceConfiguration(ActiveSurface, true);
} }
private void RenderScaleSettingOnSettingChanged(object? sender, EventArgs e)
{
foreach (ArtemisSurface surfaceConfiguration in SurfaceConfigurations)
{
surfaceConfiguration.UpdateScale(_renderScaleSetting.Value);
OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surfaceConfiguration));
}
}
#endregion #endregion
#region Events #region Events

View File

@ -22,12 +22,11 @@ namespace Artemis.UI.Services
public Rect GetLayerBounds(Layer layer) public Rect GetLayerBounds(Layer layer)
{ {
// Adjust the render rectangle for the difference in render scale // Adjust the render rectangle for the difference in render scale
double renderScale = _settingsService.GetSetting("Core.RenderScale", 0.5).Value;
return new Rect( return new Rect(
layer.Bounds.Left / renderScale * 1, layer.Bounds.Left,
layer.Bounds.Top / renderScale * 1, layer.Bounds.Top,
Math.Max(0, layer.Bounds.Width / renderScale * 1), Math.Max(0, layer.Bounds.Width),
Math.Max(0, layer.Bounds.Height / renderScale * 1) Math.Max(0, layer.Bounds.Height)
); );
} }