mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 11:56:30 +00:00
Layers - Allow the clip render mode to stretch if really needed
Core - Include the canvas' SKImageInfo in render calls
This commit is contained in:
1 parent
1853f87c61
commit
1a0d5dafd1
13 files changed
+107
-64
No files matched your search
@@ -55,11 +55,11 @@ namespace Artemis.Core.Models.Profile
|
||||
profileElement.Update(deltaTime);
|
||||
}
|
||||
|
||||
public override void Render(double deltaTime, SKCanvas canvas)
|
||||
public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
|
||||
{
|
||||
// Folders don't render but their children do
|
||||
foreach (var profileElement in Children)
|
||||
profileElement.Render(deltaTime, canvas);
|
||||
profileElement.Render(deltaTime, canvas, canvasInfo);
|
||||
}
|
||||
|
||||
public Folder AddFolder(string name)
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Artemis.Core.Models.Profile
|
||||
/// </summary>
|
||||
public SKPath Path
|
||||
{
|
||||
get => _path;
|
||||
get => _path != null ? new SKPath(_path) : null;
|
||||
private set
|
||||
{
|
||||
_path = value;
|
||||
@@ -231,7 +231,7 @@ namespace Artemis.Core.Models.Profile
|
||||
LayerBrush?.Update(deltaTime);
|
||||
}
|
||||
|
||||
public override void Render(double deltaTime, SKCanvas canvas)
|
||||
public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
|
||||
{
|
||||
if (Path == null || LayerShape?.Path == null)
|
||||
return;
|
||||
@@ -247,10 +247,10 @@ namespace Artemis.Core.Models.Profile
|
||||
switch (FillTypeProperty.CurrentValue)
|
||||
{
|
||||
case LayerFillType.Stretch:
|
||||
StretchRender(canvas, paint);
|
||||
StretchRender(canvas, canvasInfo, paint);
|
||||
break;
|
||||
case LayerFillType.Clip:
|
||||
ClipRender(canvas, paint, true);
|
||||
ClipRender(canvas, canvasInfo, paint);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
@@ -260,7 +260,7 @@ namespace Artemis.Core.Models.Profile
|
||||
canvas.Restore();
|
||||
}
|
||||
|
||||
private void StretchRender(SKCanvas canvas, SKPaint paint)
|
||||
private void StretchRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint)
|
||||
{
|
||||
// Apply transformations
|
||||
var sizeProperty = ScaleProperty.CurrentValue;
|
||||
@@ -278,10 +278,10 @@ namespace Artemis.Core.Models.Profile
|
||||
canvas.Scale(sizeProperty.Width / 100f, sizeProperty.Height / 100f, anchorPosition.X, anchorPosition.Y);
|
||||
canvas.Translate(x, y);
|
||||
|
||||
LayerBrush?.Render(canvas, new SKPath(LayerShape.Path), paint);
|
||||
LayerBrush?.Render(canvas, canvasInfo, new SKPath(LayerShape.Path), paint);
|
||||
}
|
||||
|
||||
private void ClipRender(SKCanvas canvas, SKPaint paint, bool rotatePath)
|
||||
private void ClipRender(SKCanvas canvas, SKImageInfo canvasInfo, SKPaint paint)
|
||||
{
|
||||
// Apply transformations
|
||||
var sizeProperty = ScaleProperty.CurrentValue;
|
||||
@@ -303,10 +303,17 @@ namespace Artemis.Core.Models.Profile
|
||||
canvas.RotateDegrees(rotationProperty, anchorPosition.X, anchorPosition.Y);
|
||||
canvas.Translate(x, y);
|
||||
|
||||
// Render the entire layer, the clip will ensure the shape is matched
|
||||
// Render the layer in the largest required bounds, this still creates stretching in some situations
|
||||
// but the only alternative I see right now is always forcing brushes to render on the entire canvas
|
||||
var boundsRect = new SKRect(
|
||||
Math.Min(clipPath.Bounds.Left - x, Bounds.Left - x),
|
||||
Math.Min(clipPath.Bounds.Top - y, Bounds.Top - y),
|
||||
Math.Max(clipPath.Bounds.Right - x, Bounds.Right - x),
|
||||
Math.Max(clipPath.Bounds.Bottom - y, Bounds.Bottom - y)
|
||||
);
|
||||
var renderPath = new SKPath();
|
||||
renderPath.AddRect(Path.Bounds);
|
||||
LayerBrush?.Render(canvas, renderPath, paint);
|
||||
renderPath.AddRect(boundsRect);
|
||||
LayerBrush?.Render(canvas, canvasInfo, renderPath, paint);
|
||||
}
|
||||
|
||||
internal void CalculateRenderProperties()
|
||||
@@ -332,7 +339,7 @@ namespace Artemis.Core.Models.Profile
|
||||
OnRenderPropertiesUpdated();
|
||||
}
|
||||
|
||||
private SKPoint GetLayerAnchorPosition()
|
||||
internal SKPoint GetLayerAnchorPosition()
|
||||
{
|
||||
var positionProperty = PositionProperty.CurrentValue;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Artemis.Core.Models.Profile
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(double deltaTime, SKCanvas canvas)
|
||||
public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
@@ -65,7 +65,7 @@ namespace Artemis.Core.Models.Profile
|
||||
throw new ArtemisCoreException($"Cannot render inactive profile: {this}");
|
||||
|
||||
foreach (var profileElement in Children)
|
||||
profileElement.Render(deltaTime, canvas);
|
||||
profileElement.Render(deltaTime, canvas, canvasInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Artemis.Core.Models.Profile
|
||||
/// <summary>
|
||||
/// Renders the element
|
||||
/// </summary>
|
||||
public abstract void Render(double deltaTime, SKCanvas canvas);
|
||||
public abstract void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo);
|
||||
|
||||
public List<Folder> GetAllFolders()
|
||||
{
|
||||
|
||||
@@ -44,7 +44,8 @@ namespace Artemis.Core.Plugins.Abstract
|
||||
/// <param name="deltaTime">Time since the last render</param>
|
||||
/// <param name="surface">The RGB Surface to render to</param>
|
||||
/// <param name="canvas"></param>
|
||||
public abstract void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas);
|
||||
/// <param name="canvasInfo"></param>
|
||||
public abstract void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the module's view model is being show, return view models here to create tabs for them
|
||||
|
||||
@@ -31,12 +31,12 @@ namespace Artemis.Core.Plugins.Abstract
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas)
|
||||
public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// Render the profile
|
||||
ActiveProfile?.Render(deltaTime, canvas);
|
||||
ActiveProfile?.Render(deltaTime, canvas, canvasInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,10 @@ namespace Artemis.Core.Plugins.LayerBrush
|
||||
/// <para>Called during rendering, in the order configured on the layer</para>
|
||||
/// </summary>
|
||||
/// <param name="canvas">The layer canvas</param>
|
||||
/// <param name="canvasInfo"></param>
|
||||
/// <param name="path">The path to be filled, represents the shape</param>
|
||||
/// <param name="paint">The paint to be used to fill the shape</param>
|
||||
public virtual void Render(SKCanvas canvas, SKPath path, SKPaint paint)
|
||||
public virtual void Render(SKCanvas canvas, SKImageInfo canvasInfo, SKPath path, SKPaint paint)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -86,32 +86,28 @@ namespace Artemis.Core.RGB.NET
|
||||
var sampleSize = _sampleSizeSetting.Value;
|
||||
var sampleDepth = Math.Sqrt(sampleSize).RoundToInt();
|
||||
|
||||
var bitmapWidth = Bitmap.Width;
|
||||
var bitmapHeight = Bitmap.Height;
|
||||
|
||||
foreach (var renderTarget in renderTargets)
|
||||
{
|
||||
// SKRect has all the good stuff we need
|
||||
var rect = SKRect.Create(
|
||||
(float) ((renderTarget.Rectangle.Location.X + 4) * Scale.Horizontal),
|
||||
(float) ((renderTarget.Rectangle.Location.Y + 4) * Scale.Vertical),
|
||||
(float) ((renderTarget.Rectangle.Size.Width - 8) * Scale.Horizontal),
|
||||
(float) ((renderTarget.Rectangle.Size.Height - 8) * Scale.Vertical)
|
||||
);
|
||||
var left = (int) ((renderTarget.Rectangle.Location.X + 4) * Scale.Horizontal);
|
||||
var top = (int) ((renderTarget.Rectangle.Location.Y + 4) * Scale.Vertical);
|
||||
var width = (int) ((renderTarget.Rectangle.Size.Width - 8) * Scale.Horizontal);
|
||||
var height = (int) ((renderTarget.Rectangle.Size.Height - 8) * Scale.Vertical);
|
||||
|
||||
var verticalSteps = rect.Height / (sampleDepth - 1);
|
||||
var horizontalSteps = rect.Width / (sampleDepth - 1);
|
||||
var verticalSteps = height / (sampleDepth - 1);
|
||||
var horizontalSteps = width / (sampleDepth - 1);
|
||||
|
||||
var a = 0;
|
||||
var r = 0;
|
||||
var g = 0;
|
||||
var b = 0;
|
||||
|
||||
// TODO: Compare this with LINQ, might be quicker and cleaner
|
||||
int a = 0, r = 0, g = 0, b = 0;
|
||||
for (var horizontalStep = 0; horizontalStep < sampleDepth; horizontalStep++)
|
||||
{
|
||||
for (var verticalStep = 0; verticalStep < sampleDepth; verticalStep++)
|
||||
{
|
||||
var x = (rect.Left + horizontalSteps * horizontalStep).RoundToInt();
|
||||
var y = (rect.Top + verticalSteps * verticalStep).RoundToInt();
|
||||
if (x < 0 || x > Bitmap.Width || y < 0 || y > Bitmap.Height)
|
||||
var x = left + horizontalSteps * horizontalStep;
|
||||
var y = top + verticalSteps * verticalStep;
|
||||
if (x < 0 || x > bitmapWidth || y < 0 || y > bitmapHeight)
|
||||
continue;
|
||||
|
||||
var color = Bitmap.GetPixel(x, y);
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace Artemis.Core.Services
|
||||
lock (_modules)
|
||||
{
|
||||
foreach (var module in _modules)
|
||||
module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas);
|
||||
module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas, _rgbService.BitmapBrush.Bitmap.Info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,24 @@ namespace Artemis.Core.Services.Interfaces
|
||||
{
|
||||
public interface IRgbService : IArtemisService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the RGB surface rendering is performed on
|
||||
/// </summary>
|
||||
RGBSurface Surface { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bitmap brush used to convert the rendered frame to LED-colors
|
||||
/// </summary>
|
||||
BitmapBrush BitmapBrush { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scale the frames are rendered on, a scale of 1.0 means 1 pixel = 1mm
|
||||
/// </summary>
|
||||
double RenderScale { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all loaded RGB devices
|
||||
/// </summary>
|
||||
IReadOnlyCollection<IRGBDevice> LoadedDevices { get; }
|
||||
|
||||
void AddDeviceProvider(IRGBDeviceProvider deviceProvider);
|
||||
|
||||
@@ -48,6 +48,8 @@ namespace Artemis.Core.Services
|
||||
|
||||
public IReadOnlyCollection<IRGBDevice> LoadedDevices => _loadedDevices.AsReadOnly();
|
||||
|
||||
public double RenderScale => _renderScaleSetting.Value;
|
||||
|
||||
public void AddDeviceProvider(IRGBDeviceProvider deviceProvider)
|
||||
{
|
||||
Surface.LoadDevices(deviceProvider);
|
||||
|
||||
Reference in new issue
Block a user