diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj
index de5d77946..ab3b4c4f5 100644
--- a/src/Artemis.Core/Artemis.Core.csproj
+++ b/src/Artemis.Core/Artemis.Core.csproj
@@ -160,7 +160,7 @@
-
+
@@ -194,6 +194,7 @@
+
diff --git a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs
index d88bb89b7..5267bd344 100644
--- a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs
+++ b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs
@@ -1,5 +1,4 @@
using System;
-using System.Drawing;
using Artemis.Core.RGB.NET;
using RGB.NET.Core;
@@ -7,13 +6,13 @@ namespace Artemis.Core.Events
{
public class FrameRenderedEventArgs : EventArgs
{
- public FrameRenderedEventArgs(GraphicsDecorator graphicsDecorator, RGBSurface rgbSurface)
+ public FrameRenderedEventArgs(BitmapBrush bitmapBrush, RGBSurface rgbSurface)
{
- GraphicsDecorator = graphicsDecorator;
+ BitmapBrush = bitmapBrush;
RgbSurface = rgbSurface;
}
-
- public GraphicsDecorator GraphicsDecorator { get; }
+
+ public BitmapBrush BitmapBrush { get; }
public RGBSurface RgbSurface { get; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Extensions/RgbColorExtensions.cs b/src/Artemis.Core/Extensions/RgbColorExtensions.cs
deleted file mode 100644
index e3dcef4c9..000000000
--- a/src/Artemis.Core/Extensions/RgbColorExtensions.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using RGB.NET.Core;
-using Color = System.Windows.Media.Color;
-
-namespace Artemis.Core.Extensions
-{
- public static class RgbColorExtensions
- {
- public static Color ToMediaColor(this global::RGB.NET.Core.Color color)
- {
- var (_, r, g, b) = color.GetRGBBytes();
- return Color.FromRgb(r, g, b);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.Core/Extensions/SKColorExtensions.cs b/src/Artemis.Core/Extensions/SKColorExtensions.cs
new file mode 100644
index 000000000..d7dfac717
--- /dev/null
+++ b/src/Artemis.Core/Extensions/SKColorExtensions.cs
@@ -0,0 +1,14 @@
+using RGB.NET.Core;
+using SkiaSharp;
+
+namespace Artemis.Core.Extensions
+{
+ // ReSharper disable once InconsistentNaming - I didn't come up with SKColor
+ public static class SKColorExtensions
+ {
+ public static Color ToRgbColor(this SKColor color)
+ {
+ return new Color(color.Alpha, color.Red, color.Green, color.Blue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/RGB.NET/BitmapBrush.cs b/src/Artemis.Core/RGB.NET/BitmapBrush.cs
new file mode 100644
index 000000000..7f8f3945f
--- /dev/null
+++ b/src/Artemis.Core/RGB.NET/BitmapBrush.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using Artemis.Core.Extensions;
+using RGB.NET.Core;
+using SkiaSharp;
+
+namespace Artemis.Core.RGB.NET
+{
+ public class BitmapBrush : AbstractDecoratable, IBrush, IDisposable
+ {
+ #region Constructors
+
+ public BitmapBrush(Scale scale)
+ {
+ 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 Dictionary();
+
+ public Scale Scale { get; set; }
+ public SKBitmap Bitmap { get; private set; }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ public virtual void PerformRender(Rectangle rectangle, IEnumerable renderTargets)
+ {
+ if (RenderedRectangle != rectangle || RenderedScale != Scale)
+ Bitmap = null;
+
+ if (renderTargets.Any())
+ {
+ var test = RGBSurface.Instance.SurfaceRectangle;
+ var width = renderTargets.Max(l => l.Led.AbsoluteLedRectangle.Location.X + l.Led.AbsoluteLedRectangle.Size.Width);
+ var height = renderTargets.Max(l => l.Led.AbsoluteLedRectangle.Location.Y + l.Led.AbsoluteLedRectangle.Size.Height);
+ }
+
+ RenderedRectangle = rectangle;
+ RenderedScale = Scale;
+ RenderedTargets.Clear();
+
+ if (Bitmap == null)
+ CreateBitmap(RenderedRectangle);
+
+ foreach (var renderTarget in renderTargets)
+ {
+ var scaledLocation = renderTarget.Point * Scale;
+ if (scaledLocation.X < Bitmap.Width && scaledLocation.Y < Bitmap.Height)
+ {
+ RenderedTargets[renderTarget] = Bitmap.GetPixel(RoundToInt(scaledLocation.X), RoundToInt(scaledLocation.Y)).ToRgbColor();
+ }
+ }
+ }
+
+ public Scale RenderedScale { get; private set; }
+
+ private void CreateBitmap(Rectangle rectangle)
+ {
+ var width = Math.Min((rectangle.Location.X + rectangle.Size.Width) * Scale.Horizontal, 4096);
+ var height = Math.Min((rectangle.Location.Y + rectangle.Size.Height) * Scale.Vertical, 4096);
+ Bitmap = new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt()));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private int RoundToInt(double number)
+ {
+ return (int) Math.Round(number, MidpointRounding.AwayFromZero);
+ }
+
+ ///
+ public virtual void PerformFinalize()
+ {
+ }
+
+ public void Dispose()
+ {
+ Bitmap?.Dispose();
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs b/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs
index f93cecb82..3cf61959b 100644
--- a/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs
+++ b/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs
@@ -22,7 +22,7 @@ namespace Artemis.Core.RGB.NET
var height = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.Y + l.AbsoluteLedRectangle.Size.Height) * scale, 4096);
Bitmap = new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt()));
}
-
+
public SKBitmap Bitmap { get; private set; }
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color)
diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs
index 606f5ccb3..9e0782079 100644
--- a/src/Artemis.Core/Services/CoreService.cs
+++ b/src/Artemis.Core/Services/CoreService.cs
@@ -89,14 +89,17 @@ namespace Artemis.Core.Services
module.Update(args.DeltaTime);
}
- // If there is no ready graphics decorator, skip the frame
- lock (_rgbService.GraphicsDecorator)
+ // If there is no ready bitmap brush, skip the frame
+ if (_rgbService.BitmapBrush == null)
+ return;
+
+ lock (_rgbService.BitmapBrush)
{
- if (_rgbService.GraphicsDecorator?.Bitmap == null)
+ if (_rgbService.BitmapBrush.Bitmap == null)
return;
// Render all active modules
- using (var canvas = new SKCanvas(_rgbService.GraphicsDecorator.Bitmap))
+ using (var canvas = new SKCanvas(_rgbService.BitmapBrush.Bitmap))
{
canvas.Clear(new SKColor(0, 0, 0));
lock (_modules)
@@ -117,7 +120,7 @@ namespace Artemis.Core.Services
private void SurfaceOnUpdated(UpdatedEventArgs args)
{
- OnFrameRendered(new FrameRenderedEventArgs(_rgbService.GraphicsDecorator, _rgbService.Surface));
+ OnFrameRendered(new FrameRenderedEventArgs(_rgbService.BitmapBrush, _rgbService.Surface));
}
protected virtual void OnFrameRendering(FrameRenderingEventArgs e)
diff --git a/src/Artemis.Core/Services/Interfaces/IRgbService.cs b/src/Artemis.Core/Services/Interfaces/IRgbService.cs
index ebf7298c0..1148bbaa1 100644
--- a/src/Artemis.Core/Services/Interfaces/IRgbService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IRgbService.cs
@@ -9,7 +9,7 @@ namespace Artemis.Core.Services.Interfaces
public interface IRgbService : IArtemisService
{
RGBSurface Surface { get; set; }
- GraphicsDecorator GraphicsDecorator { get; }
+ BitmapBrush BitmapBrush { get; }
IReadOnlyCollection LoadedDevices { get; }
void AddDeviceProvider(IRGBDeviceProvider deviceProvider);
@@ -25,6 +25,6 @@ namespace Artemis.Core.Services.Interfaces
///
event EventHandler DeviceReloaded;
- void UpdateGraphicsDecorator();
+ void UpdateSurfaceLedGroup();
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs
index fc2445c71..82040faaa 100644
--- a/src/Artemis.Core/Services/RgbService.cs
+++ b/src/Artemis.Core/Services/RgbService.cs
@@ -21,7 +21,7 @@ namespace Artemis.Core.Services
private readonly PluginSetting _renderScaleSetting;
private readonly PluginSetting _targetFrameRateSetting;
private readonly TimerUpdateTrigger _updateTrigger;
- private ListLedGroup _background;
+ private ListLedGroup _surfaceLedGroup;
internal RgbService(ILogger logger, ISettingsService settingsService)
{
@@ -30,7 +30,6 @@ namespace Artemis.Core.Services
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25);
Surface = RGBSurface.Instance;
- GraphicsDecorator = new GraphicsDecorator(new ListLedGroup(), 1);
// Let's throw these for now
Surface.Exception += SurfaceOnException;
@@ -44,7 +43,7 @@ namespace Artemis.Core.Services
///
public RGBSurface Surface { get; set; }
- public GraphicsDecorator GraphicsDecorator { get; private set; }
+ public BitmapBrush BitmapBrush { get; private set; }
public IReadOnlyCollection LoadedDevices => _loadedDevices.AsReadOnly();
@@ -57,7 +56,7 @@ namespace Artemis.Core.Services
_logger.Warning("RgbDevice provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
return;
}
-
+
foreach (var surfaceDevice in deviceProvider.Devices)
{
if (!_loadedDevices.Contains(surfaceDevice))
@@ -80,7 +79,7 @@ namespace Artemis.Core.Services
private void RenderScaleSettingOnSettingChanged(object sender, EventArgs e)
{
- UpdateGraphicsDecorator();
+ UpdateSurfaceLedGroup();
}
private void TargetFrameRateSettingOnSettingChanged(object sender, EventArgs e)
@@ -99,23 +98,28 @@ namespace Artemis.Core.Services
public event EventHandler DeviceLoaded;
public event EventHandler DeviceReloaded;
- public void UpdateGraphicsDecorator()
+ public void UpdateSurfaceLedGroup()
{
- lock (GraphicsDecorator)
+ if (_surfaceLedGroup == null)
{
- // Clean up the old background if present
- if (_background != null)
- {
- _background.Brush?.RemoveAllDecorators();
- _background.Detach();
- }
+ // Apply the application wide brush and decorator
+ BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value));
+ _surfaceLedGroup = new ListLedGroup(Surface.Leds) { Brush = BitmapBrush };
+ return;
+ }
+
+ lock (_surfaceLedGroup)
+ {
+ // Clean up the old background
+ _surfaceLedGroup.Detach();
// Apply the application wide brush and decorator
- _background = new ListLedGroup(Surface.Leds) {Brush = new SolidColorBrush(new Color(255, 255, 255, 255))};
- GraphicsDecorator = new GraphicsDecorator(_background, _renderScaleSetting.Value);
- _background.Brush.RemoveAllDecorators();
-
- _background.Brush.AddDecorator(GraphicsDecorator);
+ BitmapBrush.Scale = new Scale(_renderScaleSetting.Value);
+ _surfaceLedGroup = new ListLedGroup(Surface.Leds) { Brush = BitmapBrush };
+ }
+ lock (BitmapBrush)
+ {
+
}
}
diff --git a/src/Artemis.Core/Services/Storage/SurfaceService.cs b/src/Artemis.Core/Services/Storage/SurfaceService.cs
index f2a6e75b4..40704edf8 100644
--- a/src/Artemis.Core/Services/Storage/SurfaceService.cs
+++ b/src/Artemis.Core/Services/Storage/SurfaceService.cs
@@ -93,7 +93,7 @@ namespace Artemis.Core.Services.Storage
}
// Update the RGB service's graphics decorator to work with the new surface entity
- _rgbService.UpdateGraphicsDecorator();
+ _rgbService.UpdateSurfaceLedGroup();
OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurface));
}
@@ -111,7 +111,7 @@ namespace Artemis.Core.Services.Storage
}
_surfaceRepository.Save(surface.SurfaceEntity);
- _rgbService.UpdateGraphicsDecorator();
+ _rgbService.UpdateSurfaceLedGroup();
OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surface));
}
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml
index 5097631f3..0bd189dab 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml
@@ -22,6 +22,9 @@
+
+
+
diff --git a/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs b/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
index 7746d7f43..7063d8888 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
@@ -40,16 +40,16 @@ namespace Artemis.UI.Screens.Settings.Debug
{
Execute.PostToUIThread(() =>
{
- if (e.GraphicsDecorator.Bitmap == null)
+ if (e.BitmapBrush.Bitmap == null)
return;
if (!(CurrentFrame is WriteableBitmap writeableBitmap))
{
- CurrentFrame = e.GraphicsDecorator.Bitmap.ToWriteableBitmap();
+ CurrentFrame = e.BitmapBrush.Bitmap.ToWriteableBitmap();
return;
}
- using (var skiaImage = SKImage.FromPixels(e.GraphicsDecorator.Bitmap.PeekPixels()))
+ using (var skiaImage = SKImage.FromPixels(e.BitmapBrush.Bitmap.PeekPixels()))
{
var info = new SKImageInfo(skiaImage.Width, skiaImage.Height);
writeableBitmap.Lock();
diff --git a/src/Artemis.UI/Screens/Settings/SettingsView.xaml b/src/Artemis.UI/Screens/Settings/SettingsView.xaml
index 5c6de26a3..55d956ea7 100644
--- a/src/Artemis.UI/Screens/Settings/SettingsView.xaml
+++ b/src/Artemis.UI/Screens/Settings/SettingsView.xaml
@@ -5,8 +5,10 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:xaml="https://github.com/canton7/Stylet"
+ xmlns:settings="clr-namespace:Artemis.UI.Screens.Settings"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
- d:DataContext="{d:DesignInstance screens:SettingsViewModel}"
+ d:DataContext="{d:DesignInstance settings:SettingsViewModel}"
d:DesignHeight="600" d:DesignWidth="600">
@@ -16,71 +18,206 @@
-
-
- General
-
- General settings like start up with Windows etc.
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ General
+
+
+
+
+
+
+
+
+
+
+
+
+ Start up with Windows
+
+
+
+
+
+
- Render scale
-
+
+
+
+
+
+
+
+
+
+
+ Start up with Windows minimized
+
+
+
+
+
+
- Target framerate
-
-
+
+
+
+
+
+
+
+
+
+
+ Debugger
+
+ Use the debugger to see the raw image Artemis is rendering on the surface.
+
+
+
+
+
+
+
+
-
-
+
+ Rendering
+
+
+
+
+
+
+
+
+
+
+
+
+ Render scale
+
+ Sets the resolution Artemis renders at, higher scale means more CPU-usage, especially on large surfaces.
+
+
+
+
+
+
+
- Devices
-
- A list of devices and options to disable them
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ Target framerate
+
+ Sets the FPS Artemis tries to render at, higher FPS means more CPU-usage but smoother animations.
+
+
+
+
+
+
+
+
+
-
- Plugins
-
- A list of plugins and options to disable them
-
-
-
-
+
+
+
+ Below you view and manage your plugins. To find and install new plugins use the workshop (TODO).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Below you view and manage the devices that were detected by Artemis
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs
index 86e82a38e..83695cebf 100644
--- a/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs
@@ -1,4 +1,7 @@
-using Artemis.Core.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Artemis.Core.Services;
using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Settings.Debug;
@@ -34,10 +37,32 @@ namespace Artemis.UI.Screens.Settings
_deviceSettingsViewModelFactory = deviceSettingsViewModelFactory;
DeviceSettingsViewModels = new BindableCollection();
+
+ RenderScales = new List> {new Tuple("10%", 0.1)};
+ for (var i = 25; i <= 100; i += 25)
+ RenderScales.Add(new Tuple(i + "%", i / 100.0));
+
+ TargetFrameRates = new List>();
+ for (var i = 10; i <= 30; i += 5)
+ TargetFrameRates.Add(new Tuple(i + " FPS", i));
}
public BindableCollection DeviceSettingsViewModels { get; set; }
+ public List> RenderScales { get; set; }
+
+ public Tuple SelectedRenderScale
+ {
+ get => RenderScales.FirstOrDefault(s => Math.Abs(s.Item2 - RenderScale) < 0.01);
+ set => RenderScale = value.Item2;
+ }
+
+ public Tuple SelectedTargetFrameRate
+ {
+ get => TargetFrameRates.FirstOrDefault(t => Math.Abs(t.Item2 - TargetFrameRate) < 0.01);
+ set => TargetFrameRate = value.Item2;
+ }
+
public double RenderScale
{
get => _settingsService.GetSetting("Core.RenderScale", 1.0).Value;
@@ -48,6 +73,8 @@ namespace Artemis.UI.Screens.Settings
}
}
+ public List> TargetFrameRates { get; set; }
+
public int TargetFrameRate
{
get => _settingsService.GetSetting("Core.TargetFrameRate", 25).Value;
diff --git a/src/Artemis.UI/Screens/Splash/SplashView.xaml b/src/Artemis.UI/Screens/Splash/SplashView.xaml
index e26961e6f..4b41f103f 100644
--- a/src/Artemis.UI/Screens/Splash/SplashView.xaml
+++ b/src/Artemis.UI/Screens/Splash/SplashView.xaml
@@ -20,7 +20,7 @@
-
+
Artemis is initializing...