mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 19:24:55 +08:00
涉及文件修改说明: - 接口层:ISettingsService.cs新增CoverAcrylicEffectAmount属性 - 服务层:SettingsService.cs实现亚克力效果参数存储 - 视图模型:LyricsRendererViewModel系列文件新增噪点贴图处理逻辑 - 设置页面:新增CoverAcrylicEffectAmount绑定属性及通知机制 - 字符串资源:新增多语言支持(en-US, ja-JP, ko-KR, zh-CN, zh-TW) - XAML界面:SettingsPage.xaml新增调节滑块控件 Signed-off-by: Ivand <littlehider@gmail.com>
595 lines
25 KiB
C#
595 lines
25 KiB
C#
using BetterLyrics.WinUI3.Enums;
|
|
using BetterLyrics.WinUI3.Helper;
|
|
using Microsoft.Graphics.Canvas;
|
|
using Microsoft.Graphics.Canvas.Brushes;
|
|
using Microsoft.Graphics.Canvas.Effects;
|
|
using Microsoft.Graphics.Canvas.Geometry;
|
|
using Microsoft.Graphics.Canvas.Text;
|
|
using Microsoft.Graphics.Canvas.UI.Xaml;
|
|
using Microsoft.UI;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using Windows.Foundation;
|
|
using Windows.Graphics.Effects;
|
|
using Windows.UI;
|
|
|
|
namespace BetterLyrics.WinUI3.ViewModels
|
|
{
|
|
public partial class LyricsRendererViewModel
|
|
{
|
|
public void Draw(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
|
{
|
|
// Blurred lyrics layer
|
|
using var blurredLyrics = new CanvasCommandList(control);
|
|
using (var blurredLyricsDs = blurredLyrics.CreateDrawingSession())
|
|
{
|
|
DrawBlurredLyrics(control, blurredLyricsDs);
|
|
}
|
|
|
|
if (_lastAlbumArtSwBitmap != null && _lastAlbumArtCanvasBitmap == null)
|
|
{
|
|
_lastAlbumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _lastAlbumArtSwBitmap);
|
|
}
|
|
if (_albumArtSwBitmap != null && _albumArtCanvasBitmap == null)
|
|
{
|
|
_albumArtCanvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(control, _albumArtSwBitmap);
|
|
}
|
|
|
|
using var combined = new CanvasCommandList(control);
|
|
using var combinedDs = combined.CreateDrawingSession();
|
|
|
|
if (_isDockMode)
|
|
{
|
|
DrawImmersiveBackground(control, combinedDs, 0f);
|
|
}
|
|
else if (_isDesktopMode)
|
|
{
|
|
DrawImmersiveBackground(control, combinedDs, 0f);
|
|
}
|
|
else
|
|
{
|
|
DrawAlbumArtBackground(control, combinedDs);
|
|
}
|
|
|
|
combinedDs.DrawImage(blurredLyrics);
|
|
|
|
ds.DrawImage(combined);
|
|
|
|
DrawAlbumArt(control, ds);
|
|
DrawTitleAndArtist(control, ds);
|
|
|
|
if (_isDebugOverlayEnabled)
|
|
{
|
|
var currentPlayingLine = _lyricsDataArr
|
|
.ElementAtOrDefault(_langIndex)
|
|
?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
|
|
|
if (currentPlayingLine != null)
|
|
{
|
|
GetLinePlayingProgress(
|
|
_playingLineIndex,
|
|
out int charStartIndex,
|
|
out int charLength,
|
|
out float charProgress
|
|
);
|
|
|
|
ds.DrawText(
|
|
$"[DEBUG]\n" +
|
|
$"Cur playing {_playingLineIndex}, char start idx {charStartIndex}, length {charLength}, prog {charProgress}\n" +
|
|
$"Visible lines [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n" +
|
|
$"Cur time {TotalTime + _positionOffset}\n" +
|
|
$"Lang size {_lyricsDataArr.Count}\n" +
|
|
$"Song duration {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}",
|
|
new Vector2(10, 10),
|
|
ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White
|
|
);
|
|
|
|
//for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++)
|
|
//{
|
|
// LyricsLine? line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i);
|
|
// if (line != null)
|
|
// {
|
|
// ds.DrawText(
|
|
// $"[{i}] {line.OriginalText} {line.HighlightOpacityTransition.Value}",
|
|
// new Vector2(10, 30 + (i - _startVisibleLineIndex) * 20),
|
|
// ThemeTypeSent == ElementTheme.Light ? Colors.Black : Colors.White
|
|
// );
|
|
// }
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawBackgroundImgae(ICanvasAnimatedControl control, CanvasDrawingSession ds, CanvasBitmap canvasBitmap, float opacity)
|
|
{
|
|
float imageWidth = (float)canvasBitmap.Size.Width;
|
|
float imageHeight = (float)canvasBitmap.Size.Height;
|
|
|
|
float targetSize = MathF.Sqrt(MathF.Pow(_canvasWidth, 2) + MathF.Pow(_canvasHeight, 2)) * 1.4f;
|
|
float scaleFactor = targetSize / MathF.Min(imageWidth, imageHeight);
|
|
|
|
float x = _canvasWidth / 2 - imageWidth * scaleFactor / 2;
|
|
float y = _canvasHeight / 2 - imageHeight * scaleFactor / 2;
|
|
|
|
// Original source: https://zhuanlan.zhihu.com/p/37178216
|
|
float gain = _lyricsBgBrightnessTransition.Value;
|
|
|
|
float whiteX = 1 - 0.5f * gain;
|
|
float whiteY = 0.5f + 0.5f * gain;
|
|
float blackX = 0.5f - 0.5f * gain;
|
|
float blackY = 0 + 0.5f * gain;
|
|
|
|
ds.DrawImage(new OpacityEffect
|
|
{
|
|
Source = new BrightnessEffect
|
|
{
|
|
Source = new ScaleEffect
|
|
{
|
|
Scale = new Vector2(scaleFactor),
|
|
Source = canvasBitmap,
|
|
},
|
|
WhitePoint = new Vector2(whiteX, whiteY),
|
|
BlackPoint = new Vector2(blackX, blackY),
|
|
},
|
|
Opacity = opacity,
|
|
}, new Vector2(x, y));
|
|
}
|
|
|
|
private void DrawForegroundImgae(ICanvasAnimatedControl control, CanvasDrawingSession ds, CanvasBitmap canvasBitmap, float opacity)
|
|
{
|
|
if (opacity == 0) return;
|
|
|
|
float imageWidth = (float)canvasBitmap.Size.Width;
|
|
float imageHeight = (float)canvasBitmap.Size.Height;
|
|
|
|
float scaleFactor = _albumArtSize / Math.Min(imageWidth, imageHeight);
|
|
if (scaleFactor < 0.01f) return;
|
|
|
|
float cornerRadius = _albumArtCornerRadius / 100f * _albumArtSize / 2;
|
|
|
|
using var cornerRadiusMask = new CanvasCommandList(control.Device);
|
|
using var cornerRadiusMaskDs = cornerRadiusMask.CreateDrawingSession();
|
|
cornerRadiusMaskDs.FillRoundedRectangle(
|
|
new Rect(0, 0, imageWidth * scaleFactor, imageHeight * scaleFactor),
|
|
cornerRadius, cornerRadius, Colors.White
|
|
);
|
|
|
|
ds.DrawImage(new OpacityEffect
|
|
{
|
|
Source = new AlphaMaskEffect
|
|
{
|
|
Source = new ScaleEffect
|
|
{
|
|
Scale = new Vector2(scaleFactor),
|
|
Source = canvasBitmap,
|
|
},
|
|
AlphaMask = cornerRadiusMask,
|
|
},
|
|
Opacity = opacity,
|
|
}, new Vector2(_albumArtXTransition.Value, _albumArtY)
|
|
);
|
|
}
|
|
|
|
private void DrawAlbumArtBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
|
{
|
|
ds.Transform = Matrix3x2.CreateRotation(_rotateAngle, control.Size.ToVector2() * 0.5f);
|
|
|
|
using var overlappedCovers = new CanvasCommandList(control.Device);
|
|
using var overlappedCoversDs = overlappedCovers.CreateDrawingSession();
|
|
|
|
if (_lastAlbumArtCanvasBitmap != null)
|
|
{
|
|
DrawBackgroundImgae(control, overlappedCoversDs, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
|
}
|
|
if (_albumArtCanvasBitmap != null)
|
|
{
|
|
DrawBackgroundImgae(control, overlappedCoversDs, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
|
}
|
|
|
|
IGraphicsEffectSource blurredCover = new GaussianBlurEffect
|
|
{
|
|
BlurAmount = _albumArtBgBlurAmount,
|
|
Source = overlappedCovers,
|
|
BorderMode = EffectBorderMode.Soft,
|
|
Optimization = EffectOptimization.Speed,
|
|
};
|
|
|
|
// 应用亚克力噪点效果
|
|
// TODO: 没有写_coverAcrylicNoiseCanvasBitmap加载的代码
|
|
if (_coverAcrylicEffectAmount > 0 && _coverAcrylicNoiseCanvasBitmap != null)
|
|
{
|
|
blurredCover = new BlendEffect
|
|
{
|
|
Mode = BlendEffectMode.SoftLight,
|
|
Background = blurredCover,
|
|
Foreground = new OpacityEffect
|
|
{
|
|
Source = _coverAcrylicNoiseCanvasBitmap,
|
|
Opacity = _coverAcrylicEffectAmount / 100f,
|
|
},
|
|
};
|
|
}
|
|
|
|
var coverOverlayEffect = new OpacityEffect
|
|
{
|
|
Opacity = _albumArtBgOpacity / 100f,
|
|
Source = blurredCover,
|
|
};
|
|
ds.DrawImage(coverOverlayEffect);
|
|
|
|
ds.Transform = Matrix3x2.Identity;
|
|
}
|
|
|
|
private void DrawAlbumArt(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
|
{
|
|
using var albumArt = new CanvasCommandList(control.Device);
|
|
using var albumArtDs = albumArt.CreateDrawingSession();
|
|
if (_albumArtCanvasBitmap != null)
|
|
{
|
|
DrawForegroundImgae(control, albumArtDs, _albumArtCanvasBitmap, _albumArtBgTransition.Value);
|
|
}
|
|
if (_lastAlbumArtCanvasBitmap != null)
|
|
{
|
|
DrawForegroundImgae(control, albumArtDs, _lastAlbumArtCanvasBitmap, 1 - _albumArtBgTransition.Value);
|
|
}
|
|
|
|
using var opacity = new CanvasCommandList(control.Device);
|
|
using var opacityDs = opacity.CreateDrawingSession();
|
|
opacityDs.DrawImage(new GaussianBlurEffect
|
|
{
|
|
Source = albumArt,
|
|
BlurAmount = 12f,
|
|
Optimization = EffectOptimization.Quality,
|
|
});
|
|
opacityDs.DrawImage(albumArt);
|
|
|
|
ds.DrawImage(new OpacityEffect
|
|
{
|
|
Source = opacity,
|
|
Opacity = _albumArtOpacityTransition.Value
|
|
});
|
|
}
|
|
|
|
private void DrawTitleAndArtist(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
|
{
|
|
if (_lastSongTitle != null || _lastSongArtist != null)
|
|
{
|
|
DrawSingleTitleAndArtist(control, ds, _lastSongTitle, _lastSongArtist, 1 - _songInfoOpacityTransition.Value);
|
|
}
|
|
if (_songTitle != null || _songArtist != null)
|
|
{
|
|
DrawSingleTitleAndArtist(control, ds, _songTitle, _songArtist, _songInfoOpacityTransition.Value);
|
|
}
|
|
}
|
|
|
|
private void DrawSingleTitleAndArtist(ICanvasAnimatedControl control, CanvasDrawingSession ds, string? title, string? artist, float opacity)
|
|
{
|
|
CanvasTextLayout titleLayout = new(
|
|
control, title ?? string.Empty,
|
|
_titleTextFormat, _albumArtSize, _canvasHeight
|
|
);
|
|
CanvasTextLayout artistLayout = new(
|
|
control, artist ?? string.Empty,
|
|
_artistTextFormat, _albumArtSize, _canvasHeight
|
|
);
|
|
ds.DrawTextLayout(
|
|
titleLayout,
|
|
new Vector2(_albumArtXTransition.Value, _titleY),
|
|
_bgFontColor.WithAlpha((byte)(_albumArtOpacityTransition.Value * 255 * opacity)));
|
|
ds.DrawTextLayout(
|
|
artistLayout,
|
|
new Vector2(_albumArtXTransition.Value, _titleY + (float)titleLayout.LayoutBounds.Height),
|
|
_bgFontColor.WithAlpha((byte)(_albumArtOpacityTransition.Value * 128 * opacity)));
|
|
}
|
|
|
|
private void DrawBlurredLyrics(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
|
{
|
|
var currentPlayingLine = _lyricsDataArr
|
|
.ElementAtOrDefault(_langIndex)
|
|
?.LyricsLines.ElementAtOrDefault(_playingLineIndex);
|
|
|
|
if (currentPlayingLine == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = _startVisibleLineIndex; i <= _endVisibleLineIndex; i++)
|
|
{
|
|
var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i);
|
|
if (line == null) continue;
|
|
|
|
var textLayout = line.CanvasTextLayout;
|
|
if (textLayout == null) continue;
|
|
|
|
var position = new Vector2(line.Position.X, line.Position.Y);
|
|
|
|
float layoutWidth = (float)textLayout.LayoutBounds.Width;
|
|
float layoutHeight = (float)textLayout.LayoutBounds.Height;
|
|
|
|
if (layoutWidth <= 0 || layoutHeight <= 0) continue;
|
|
|
|
float centerX = position.X;
|
|
float centerY = position.Y + layoutHeight / 2;
|
|
|
|
switch (_lyricsAlignmentType)
|
|
{
|
|
case TextAlignmentType.Left:
|
|
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Left;
|
|
break;
|
|
case TextAlignmentType.Center:
|
|
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Center;
|
|
centerX += _maxLyricsWidth / 2;
|
|
break;
|
|
case TextAlignmentType.Right:
|
|
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Right;
|
|
centerX += _maxLyricsWidth;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
float xOffset = _lyricsXTransition.Value;
|
|
float yOffset = _canvasYScrollTransition.Value + _canvasHeight / 2;
|
|
|
|
// 组合变换:缩放 -> 旋转 -> 平移
|
|
ds.Transform =
|
|
Matrix3x2.CreateScale(line.ScaleTransition.Value, new Vector2(centerX, centerY))
|
|
* Matrix3x2.CreateRotation(line.AngleTransition.Value, currentPlayingLine.Position)
|
|
* Matrix3x2.CreateTranslation(xOffset, yOffset);
|
|
|
|
// Create the background lyrics line with stroke and fill
|
|
using var bgLyrics = new CanvasCommandList(control.Device);
|
|
using var bgLyricsDs = bgLyrics.CreateDrawingSession();
|
|
|
|
// Create the foreground lyrics line with stroke and fill
|
|
using var fgLyrics = new CanvasCommandList(control.Device);
|
|
using var fgLyricsDs = fgLyrics.CreateDrawingSession();
|
|
|
|
// 创建文字几何体
|
|
using var textGeometry = CanvasGeometry.CreateText(textLayout);
|
|
if (_isDesktopMode)
|
|
{
|
|
bgLyricsDs.DrawGeometry(textGeometry, position, _strokeFontColor, _lyricsFontStrokeWidth); // 背景描边
|
|
fgLyricsDs.DrawGeometry(textGeometry, position, _strokeFontColor, _lyricsFontStrokeWidth); // 前景描边
|
|
}
|
|
|
|
bgLyricsDs.FillGeometry(textGeometry, position, _bgFontColor); // 背景填充
|
|
fgLyricsDs.FillGeometry(textGeometry, position, _fgFontColor); // 前景填充
|
|
|
|
using var combined = new CanvasCommandList(control.Device);
|
|
using var combinedDs = combined.CreateDrawingSession();
|
|
|
|
// Mock gradient blurred lyrics layer
|
|
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
|
|
// Current line will not be blurred
|
|
combinedDs.DrawImage(
|
|
new GaussianBlurEffect
|
|
{
|
|
Source = new OpacityEffect { Source = bgLyrics, Opacity = line.OpacityTransition.Value * _lyricsOpacityTransition.Value },
|
|
BlurAmount = line.BlurAmountTransition.Value,
|
|
Optimization = EffectOptimization.Quality,
|
|
BorderMode = EffectBorderMode.Soft,
|
|
}
|
|
);
|
|
|
|
if (line.HighlightOpacityTransition.Value != 0)
|
|
{
|
|
// 再叠加高亮行歌词层(前景歌词层)
|
|
using var mask = new CanvasCommandList(control.Device);
|
|
using var maskDs = mask.CreateDrawingSession();
|
|
|
|
using var highlightMask = new CanvasCommandList(control.Device);
|
|
using var highlightMaskDs = highlightMask.CreateDrawingSession();
|
|
|
|
if (i == _playingLineIndex)
|
|
{
|
|
GetLinePlayingProgress(
|
|
i,
|
|
out int charStartIndex,
|
|
out int charLength,
|
|
out float charProgress
|
|
);
|
|
var regions = textLayout.GetCharacterRegions(0, charStartIndex);
|
|
var highlightRegion = textLayout
|
|
.GetCharacterRegions(charStartIndex, charLength)
|
|
.FirstOrDefault();
|
|
if (regions.Length > 0)
|
|
{
|
|
// Draw the mask for the current line
|
|
for (int j = 0; j < regions.Length; j++)
|
|
{
|
|
var region = regions[j];
|
|
var rect = new Rect(
|
|
region.LayoutBounds.X,
|
|
region.LayoutBounds.Y + position.Y,
|
|
region.LayoutBounds.Width,
|
|
region.LayoutBounds.Height
|
|
);
|
|
maskDs.FillRectangle(rect, Color.FromArgb(255, 128, 128, 128));
|
|
}
|
|
}
|
|
|
|
float highlightTotalWidth = (float)highlightRegion.LayoutBounds.Width;
|
|
// Draw the highlight for the current character
|
|
float highlightWidth = highlightTotalWidth * charProgress;
|
|
|
|
float fadingWidth = (float)highlightRegion.LayoutBounds.Height / 2;
|
|
|
|
// Rects
|
|
var highlightRect = new Rect(
|
|
highlightRegion.LayoutBounds.X,
|
|
highlightRegion.LayoutBounds.Y + position.Y,
|
|
highlightWidth,
|
|
highlightRegion.LayoutBounds.Height
|
|
);
|
|
|
|
var fadeInRect = new Rect(
|
|
highlightRect.Right - fadingWidth,
|
|
highlightRegion.LayoutBounds.Y + position.Y,
|
|
fadingWidth,
|
|
highlightRegion.LayoutBounds.Height
|
|
);
|
|
var fadeOutRect = new Rect(
|
|
highlightRect.Right,
|
|
highlightRegion.LayoutBounds.Y + position.Y,
|
|
fadingWidth,
|
|
highlightRegion.LayoutBounds.Height
|
|
);
|
|
|
|
// Brushes
|
|
using var fadeInBrush = GetHorizontalFillBrush(
|
|
control,
|
|
[(0f, 0f), (1f, 1f)],
|
|
(float)highlightRect.Right - fadingWidth,
|
|
fadingWidth
|
|
);
|
|
using var fadeOutBrush = GetHorizontalFillBrush(
|
|
control,
|
|
[(0f, 1f), (1f, 0f)],
|
|
(float)highlightRect.Right,
|
|
fadingWidth
|
|
);
|
|
|
|
maskDs.FillRectangle(highlightRect, Color.FromArgb(255, 128, 128, 128));
|
|
maskDs.FillRectangle(fadeOutRect, fadeOutBrush);
|
|
|
|
highlightMaskDs.FillRectangle(fadeInRect, fadeInBrush);
|
|
highlightMaskDs.FillRectangle(fadeOutRect, fadeOutBrush);
|
|
}
|
|
else
|
|
{
|
|
float height = 0f;
|
|
//var regions = textLayout.GetCharacterRegions(0, string.Join("", line.LyricsChars.Select(x => x.Text)).Length);
|
|
var regions = textLayout.GetCharacterRegions(0, line.OriginalText.Length);
|
|
if (regions.Length > 0)
|
|
{
|
|
height = (float)regions[^1].LayoutBounds.Bottom - (float)regions[0].LayoutBounds.Top;
|
|
}
|
|
|
|
maskDs.FillRectangle(
|
|
new Rect(
|
|
textLayout.LayoutBounds.X,
|
|
position.Y,
|
|
textLayout.LayoutBounds.Width,
|
|
height
|
|
),
|
|
Colors.White
|
|
);
|
|
}
|
|
|
|
using var opacityEffect = new OpacityEffect
|
|
{
|
|
Source = new BlendEffect
|
|
{
|
|
Background = _isLyricsGlowEffectEnabled
|
|
? new GaussianBlurEffect
|
|
{
|
|
Source = new AlphaMaskEffect
|
|
{
|
|
Source = fgLyrics,
|
|
AlphaMask = _lyricsGlowEffectScope switch
|
|
{
|
|
LineRenderingType.CurrentChar => highlightMask,
|
|
LineRenderingType.LineStartToCurrentChar => mask,
|
|
LineRenderingType.CurrentLine => fgLyrics,
|
|
_ => mask,
|
|
},
|
|
},
|
|
BlurAmount = _lyricsGlowEffectAmount,
|
|
Optimization = EffectOptimization.Quality,
|
|
}
|
|
: new CanvasCommandList(control.Device),
|
|
Foreground = new AlphaMaskEffect
|
|
{
|
|
Source = fgLyrics,
|
|
AlphaMask = _lyricsHighlightScope switch
|
|
{
|
|
LineRenderingType.CurrentChar => highlightMask,
|
|
LineRenderingType.LineStartToCurrentChar => mask,
|
|
LineRenderingType.CurrentLine => fgLyrics,
|
|
_ => mask,
|
|
},
|
|
},
|
|
},
|
|
Opacity = line.HighlightOpacityTransition.Value * _lyricsOpacityTransition.Value,
|
|
};
|
|
|
|
combinedDs.DrawImage(opacityEffect);
|
|
|
|
if (i == _playingLineIndex)
|
|
{
|
|
if (_isLyricsFloatAnimationEnabled)
|
|
{
|
|
ds.DrawImage(new DisplacementMapEffect
|
|
{
|
|
Source = combined,
|
|
Displacement = mask,
|
|
XChannelSelect = EffectChannelSelect.Red,
|
|
YChannelSelect = EffectChannelSelect.Alpha,
|
|
Amount = 1f
|
|
});
|
|
}
|
|
else
|
|
{
|
|
ds.DrawImage(combined);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ds.DrawImage(combined);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ds.DrawImage(combined);
|
|
}
|
|
|
|
// Reset scale
|
|
ds.Transform = Matrix3x2.Identity;
|
|
}
|
|
}
|
|
|
|
private void DrawImmersiveBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds, float radius)
|
|
{
|
|
CanvasCommandList list = new(control.Device);
|
|
using var listDs = list.CreateDrawingSession();
|
|
listDs.FillRoundedRectangle(
|
|
new Rect(0, 0, _canvasWidth, _canvasHeight),
|
|
radius,
|
|
radius,
|
|
_immersiveBgTransition.Value
|
|
);
|
|
ds.DrawImage(new OpacityEffect
|
|
{
|
|
Source = list,
|
|
Opacity = _immersiveBgOpacityTransition.Value
|
|
});
|
|
}
|
|
|
|
private CanvasLinearGradientBrush GetHorizontalFillBrush(
|
|
ICanvasAnimatedControl control,
|
|
List<(float position, float opacity)> stops,
|
|
float startX,
|
|
float width
|
|
)
|
|
{
|
|
return new CanvasLinearGradientBrush(
|
|
control,
|
|
stops
|
|
.Select(stops => new CanvasGradientStop
|
|
{
|
|
Position = stops.position,
|
|
Color = Color.FromArgb((byte)(stops.opacity * 255), 128, 128, 128),
|
|
})
|
|
.ToArray()
|
|
)
|
|
{
|
|
StartPoint = new Vector2(startX, 0),
|
|
EndPoint = new Vector2(startX + width, 0),
|
|
};
|
|
}
|
|
}
|
|
}
|