mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 10:54:55 +08:00
change opacity effect rendering method
This commit is contained in:
@@ -18,18 +18,12 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.MarqueeText" Version="0.1.230830" />
|
||||
<PackageReference
|
||||
Include="CommunityToolkit.Labs.WinUI.OpacityMaskView"
|
||||
Version="0.1.250513-build.2126"
|
||||
/>
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.OpacityMaskView" Version="0.1.250513-build.2126" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Behaviors" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.2.250402" />
|
||||
<PackageReference
|
||||
Include="CommunityToolkit.WinUI.Controls.SettingsControls"
|
||||
Version="8.2.250402"
|
||||
/>
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Helpers" Version="8.2.250402" />
|
||||
@@ -46,7 +40,7 @@
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.6" />
|
||||
<PackageReference Include="TagLibSharp" Version="2.3.0" />
|
||||
<PackageReference Include="Ude.NetStandard" Version="1.2.0" />
|
||||
<PackageReference Include="WinUIEx" Version="2.5.1" />
|
||||
<PackageReference Include="WinUIEx" Version="2.6.0" />
|
||||
<PackageReference Include="z440.atl.core" Version="6.26.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
#region Enums
|
||||
|
||||
/// <summary>
|
||||
/// Defines the LineMaskType
|
||||
/// </summary>
|
||||
public enum LineRenderingType
|
||||
{
|
||||
UntilCurrentChar,
|
||||
|
||||
/// <summary>
|
||||
/// Current char only
|
||||
/// </summary>
|
||||
CurrentCharOnly,
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
#region Enums
|
||||
|
||||
/// <summary>
|
||||
/// Defines the LyricsGlowEffectScope
|
||||
/// </summary>
|
||||
public enum LyricsGlowEffectScope
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the WholeLyrics
|
||||
/// </summary>
|
||||
WholeLyrics,
|
||||
|
||||
/// <summary>
|
||||
/// Defines the CurrentLine
|
||||
/// </summary>
|
||||
CurrentLine,
|
||||
|
||||
/// <summary>
|
||||
/// Defines the CurrentChar
|
||||
/// </summary>
|
||||
CurrentChar,
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
namespace BetterLyrics.WinUI3.Enums
|
||||
{
|
||||
#region Enums
|
||||
|
||||
/// <summary>
|
||||
/// Defines the LyricsHighlightType
|
||||
/// </summary>
|
||||
public enum LyricsHighlightType
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the LineByLine
|
||||
/// </summary>
|
||||
LineByLine,
|
||||
|
||||
/// <summary>
|
||||
/// Defines the CharByChar
|
||||
/// </summary>
|
||||
CharByChar,
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Microsoft.Graphics.Canvas.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
@@ -14,6 +15,8 @@ namespace BetterLyrics.WinUI3.Models
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public CanvasTextLayout? CanvasTextLayout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CenterPosition
|
||||
/// </summary>
|
||||
@@ -80,32 +83,5 @@ namespace BetterLyrics.WinUI3.Models
|
||||
public string Text { get; set; } = "";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The Clone
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="LyricsLine"/></returns>
|
||||
public LyricsLine Clone()
|
||||
{
|
||||
return new LyricsLine
|
||||
{
|
||||
Text = this.Text,
|
||||
CharTimings = this.CharTimings,
|
||||
StartMs = this.StartMs,
|
||||
EndMs = this.EndMs,
|
||||
PlayingState = this.PlayingState,
|
||||
EnteringProgress = this.EnteringProgress,
|
||||
ExitingProgress = this.ExitingProgress,
|
||||
PlayingProgress = this.PlayingProgress,
|
||||
Position = this.Position,
|
||||
CenterPosition = this.CenterPosition,
|
||||
Scale = this.Scale,
|
||||
Opacity = this.Opacity,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
<canvas:CanvasAnimatedControl
|
||||
x:Name="LyricsCanvas"
|
||||
Draw="LyricsCanvas_Draw"
|
||||
Loaded="LyricsCanvas_Loaded"
|
||||
Update="LyricsCanvas_Update" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System.Diagnostics;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System.Diagnostics;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
@@ -56,16 +56,6 @@ namespace BetterLyrics.WinUI3.Renderer
|
||||
ViewModel.Draw(sender, args.DrawingSession);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The LyricsCanvas_Loaded
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender<see cref="object"/></param>
|
||||
/// <param name="e">The e<see cref="RoutedEventArgs"/></param>
|
||||
private void LyricsCanvas_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.RequestRelayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The LyricsCanvas_Update
|
||||
/// </summary>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System.Collections.Generic;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using Microsoft.UI.Text;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System.Collections.Generic;
|
||||
using Windows.UI.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services
|
||||
@@ -111,7 +111,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsGlowEffectScope
|
||||
/// </summary>
|
||||
LyricsGlowEffectScope LyricsGlowEffectScope { get; set; }
|
||||
LineRenderingType LyricsGlowEffectScope { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsLineSpacingFactor
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -10,6 +7,9 @@ using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using ATL;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.FileProperties;
|
||||
|
||||
@@ -232,11 +232,11 @@ namespace BetterLyrics.WinUI3.Services
|
||||
for (int j = 0; j <= b.Length; j++)
|
||||
d[0, j] = j;
|
||||
for (int i = 1; i <= a.Length; i++)
|
||||
for (int j = 1; j <= b.Length; j++)
|
||||
d[i, j] = Math.Min(
|
||||
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
|
||||
d[i - 1, j - 1] + (a[i - 1] == b[j - 1] ? 0 : 1)
|
||||
);
|
||||
for (int j = 1; j <= b.Length; j++)
|
||||
d[i, j] = Math.Min(
|
||||
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
|
||||
d[i - 1, j - 1] + (a[i - 1] == b[j - 1] ? 0 : 1)
|
||||
);
|
||||
return d[a.Length, b.Length];
|
||||
}
|
||||
|
||||
@@ -340,7 +340,8 @@ namespace BetterLyrics.WinUI3.Services
|
||||
if (FuzzyMatch(Path.GetFileNameWithoutExtension(file), title, artist))
|
||||
{
|
||||
//Track track = new(file);
|
||||
//var plain = track.Lyrics.UnsynchronizedLyrics;
|
||||
//var test1 = track.Lyrics.SynchronizedLyrics;
|
||||
//var test2 = track.Lyrics.UnsynchronizedLyrics;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Serialization;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services
|
||||
@@ -202,7 +202,7 @@ namespace BetterLyrics.WinUI3.Services
|
||||
SetDefault(LyricsLineSpacingFactorKey, 0.5f);
|
||||
SetDefault(LyricsVerticalEdgeOpacityKey, 0);
|
||||
SetDefault(IsLyricsGlowEffectEnabledKey, true);
|
||||
SetDefault(LyricsGlowEffectScopeKey, (int)LyricsGlowEffectScope.CurrentChar);
|
||||
SetDefault(LyricsGlowEffectScopeKey, (int)LineRenderingType.CurrentCharOnly);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -212,52 +212,92 @@ namespace BetterLyrics.WinUI3.Services
|
||||
/// <summary>
|
||||
/// Gets or sets the AutoStartWindowType
|
||||
/// </summary>
|
||||
public AutoStartWindowType AutoStartWindowType { get => (AutoStartWindowType)GetValue<int>(AutoStartWindowTypeKey); set => SetValue(AutoStartWindowTypeKey, (int)value); }
|
||||
public AutoStartWindowType AutoStartWindowType
|
||||
{
|
||||
get => (AutoStartWindowType)GetValue<int>(AutoStartWindowTypeKey);
|
||||
set => SetValue(AutoStartWindowTypeKey, (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the BackdropType
|
||||
/// </summary>
|
||||
public BackdropType BackdropType { get => (BackdropType)GetValue<int>(BackdropTypeKey); set => SetValue(BackdropTypeKey, (int)value); }
|
||||
public BackdropType BackdropType
|
||||
{
|
||||
get => (BackdropType)GetValue<int>(BackdropTypeKey);
|
||||
set => SetValue(BackdropTypeKey, (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CoverImageRadius
|
||||
/// </summary>
|
||||
public int CoverImageRadius { get => GetValue<int>(CoverImageRadiusKey); set => SetValue(CoverImageRadiusKey, value); }
|
||||
public int CoverImageRadius
|
||||
{
|
||||
get => GetValue<int>(CoverImageRadiusKey);
|
||||
set => SetValue(CoverImageRadiusKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CoverOverlayBlurAmount
|
||||
/// </summary>
|
||||
public int CoverOverlayBlurAmount { get => GetValue<int>(CoverOverlayBlurAmountKey); set => SetValue(CoverOverlayBlurAmountKey, value); }
|
||||
public int CoverOverlayBlurAmount
|
||||
{
|
||||
get => GetValue<int>(CoverOverlayBlurAmountKey);
|
||||
set => SetValue(CoverOverlayBlurAmountKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CoverOverlayOpacity
|
||||
/// </summary>
|
||||
public int CoverOverlayOpacity { get => GetValue<int>(CoverOverlayOpacityKey); set => SetValue(CoverOverlayOpacityKey, value); }
|
||||
public int CoverOverlayOpacity
|
||||
{
|
||||
get => GetValue<int>(CoverOverlayOpacityKey);
|
||||
set => SetValue(CoverOverlayOpacityKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsCoverOverlayEnabled
|
||||
/// </summary>
|
||||
public bool IsCoverOverlayEnabled { get => GetValue<bool>(IsCoverOverlayEnabledKey); set => SetValue(IsCoverOverlayEnabledKey, value); }
|
||||
public bool IsCoverOverlayEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsCoverOverlayEnabledKey);
|
||||
set => SetValue(IsCoverOverlayEnabledKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsDynamicCoverOverlayEnabled
|
||||
/// </summary>
|
||||
public bool IsDynamicCoverOverlayEnabled { get => GetValue<bool>(IsDynamicCoverOverlayEnabledKey); set => SetValue(IsDynamicCoverOverlayEnabledKey, value); }
|
||||
public bool IsDynamicCoverOverlayEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsDynamicCoverOverlayEnabledKey);
|
||||
set => SetValue(IsDynamicCoverOverlayEnabledKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsFirstRun
|
||||
/// </summary>
|
||||
public bool IsFirstRun { get => GetValue<bool>(IsFirstRunKey); set => SetValue(IsFirstRunKey, value); }
|
||||
public bool IsFirstRun
|
||||
{
|
||||
get => GetValue<bool>(IsFirstRunKey);
|
||||
set => SetValue(IsFirstRunKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IsLyricsGlowEffectEnabled
|
||||
/// </summary>
|
||||
public bool IsLyricsGlowEffectEnabled { get => GetValue<bool>(IsLyricsGlowEffectEnabledKey); set => SetValue(IsLyricsGlowEffectEnabledKey, value); }
|
||||
public bool IsLyricsGlowEffectEnabled
|
||||
{
|
||||
get => GetValue<bool>(IsLyricsGlowEffectEnabledKey);
|
||||
set => SetValue(IsLyricsGlowEffectEnabledKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Language
|
||||
/// </summary>
|
||||
public Language Language { get => (Language)GetValue<int>(LanguageKey); set => SetValue(LanguageKey, (int)value); }
|
||||
public Language Language
|
||||
{
|
||||
get => (Language)GetValue<int>(LanguageKey);
|
||||
set => SetValue(LanguageKey, (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LocalLyricsFolders
|
||||
@@ -268,7 +308,8 @@ namespace BetterLyrics.WinUI3.Services
|
||||
System.Text.Json.JsonSerializer.Deserialize(
|
||||
GetValue<string>(LocalLyricsFoldersKey) ?? "[]",
|
||||
SourceGenerationContext.Default.ListLocalLyricsFolder
|
||||
)!; set =>
|
||||
)!;
|
||||
set =>
|
||||
SetValue(
|
||||
LocalLyricsFoldersKey,
|
||||
System.Text.Json.JsonSerializer.Serialize(
|
||||
@@ -281,37 +322,65 @@ namespace BetterLyrics.WinUI3.Services
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsAlignmentType
|
||||
/// </summary>
|
||||
public LyricsAlignmentType LyricsAlignmentType { get => (LyricsAlignmentType)GetValue<int>(LyricsAlignmentTypeKey); set => SetValue(LyricsAlignmentTypeKey, (int)value); }
|
||||
public LyricsAlignmentType LyricsAlignmentType
|
||||
{
|
||||
get => (LyricsAlignmentType)GetValue<int>(LyricsAlignmentTypeKey);
|
||||
set => SetValue(LyricsAlignmentTypeKey, (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsBlurAmount
|
||||
/// </summary>
|
||||
public int LyricsBlurAmount { get => GetValue<int>(LyricsBlurAmountKey); set => SetValue(LyricsBlurAmountKey, value); }
|
||||
public int LyricsBlurAmount
|
||||
{
|
||||
get => GetValue<int>(LyricsBlurAmountKey);
|
||||
set => SetValue(LyricsBlurAmountKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsFontColorType
|
||||
/// </summary>
|
||||
public LyricsFontColorType LyricsFontColorType { get => (LyricsFontColorType)GetValue<int>(LyricsFontColorTypeKey); set => SetValue(LyricsFontColorTypeKey, (int)value); }
|
||||
public LyricsFontColorType LyricsFontColorType
|
||||
{
|
||||
get => (LyricsFontColorType)GetValue<int>(LyricsFontColorTypeKey);
|
||||
set => SetValue(LyricsFontColorTypeKey, (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsFontSize
|
||||
/// </summary>
|
||||
public int LyricsFontSize { get => GetValue<int>(LyricsFontSizeKey); set => SetValue(LyricsFontSizeKey, value); }
|
||||
public int LyricsFontSize
|
||||
{
|
||||
get => GetValue<int>(LyricsFontSizeKey);
|
||||
set => SetValue(LyricsFontSizeKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsFontWeight
|
||||
/// </summary>
|
||||
public LyricsFontWeight LyricsFontWeight { get => (LyricsFontWeight)GetValue<int>(LyricsFontWeightKey); set => SetValue(LyricsFontWeightKey, (int)value); }
|
||||
public LyricsFontWeight LyricsFontWeight
|
||||
{
|
||||
get => (LyricsFontWeight)GetValue<int>(LyricsFontWeightKey);
|
||||
set => SetValue(LyricsFontWeightKey, (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsGlowEffectScope
|
||||
/// </summary>
|
||||
public LyricsGlowEffectScope LyricsGlowEffectScope { get => (LyricsGlowEffectScope)GetValue<int>(LyricsGlowEffectScopeKey); set => SetValue(LyricsGlowEffectScopeKey, (int)value); }
|
||||
public LineRenderingType LyricsGlowEffectScope
|
||||
{
|
||||
get => (LineRenderingType)GetValue<int>(LyricsGlowEffectScopeKey);
|
||||
set => SetValue(LyricsGlowEffectScopeKey, (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsLineSpacingFactor
|
||||
/// </summary>
|
||||
public float LyricsLineSpacingFactor { get => GetValue<float>(LyricsLineSpacingFactorKey); set => SetValue(LyricsLineSpacingFactorKey, value); }
|
||||
public float LyricsLineSpacingFactor
|
||||
{
|
||||
get => GetValue<float>(LyricsLineSpacingFactorKey);
|
||||
set => SetValue(LyricsLineSpacingFactorKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsSearchProvidersInfo
|
||||
@@ -322,7 +391,8 @@ namespace BetterLyrics.WinUI3.Services
|
||||
System.Text.Json.JsonSerializer.Deserialize(
|
||||
GetValue<string>(LyricsSearchProvidersInfoKey) ?? "[]",
|
||||
SourceGenerationContext.Default.ListLyricsSearchProviderInfo
|
||||
)!; set =>
|
||||
)!;
|
||||
set =>
|
||||
SetValue(
|
||||
LyricsSearchProvidersInfoKey,
|
||||
System.Text.Json.JsonSerializer.Serialize(
|
||||
@@ -335,17 +405,29 @@ namespace BetterLyrics.WinUI3.Services
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsVerticalEdgeOpacity
|
||||
/// </summary>
|
||||
public int LyricsVerticalEdgeOpacity { get => GetValue<int>(LyricsVerticalEdgeOpacityKey); set => SetValue(LyricsVerticalEdgeOpacityKey, value); }
|
||||
public int LyricsVerticalEdgeOpacity
|
||||
{
|
||||
get => GetValue<int>(LyricsVerticalEdgeOpacityKey);
|
||||
set => SetValue(LyricsVerticalEdgeOpacityKey, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ThemeType
|
||||
/// </summary>
|
||||
public ElementTheme ThemeType { get => (ElementTheme)GetValue<int>(ThemeTypeKey); set => SetValue(ThemeTypeKey, (int)value); }
|
||||
public ElementTheme ThemeType
|
||||
{
|
||||
get => (ElementTheme)GetValue<int>(ThemeTypeKey);
|
||||
set => SetValue(ThemeTypeKey, (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the TitleBarType
|
||||
/// </summary>
|
||||
public TitleBarType TitleBarType { get => (TitleBarType)GetValue<int>(TitleBarTypeKey); set => SetValue(TitleBarTypeKey, (int)value); }
|
||||
public TitleBarType TitleBarType
|
||||
{
|
||||
get => (TitleBarType)GetValue<int>(TitleBarTypeKey);
|
||||
set => SetValue(TitleBarTypeKey, (int)value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
// 2025/6/23 by Zhe Fang
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using BetterInAppLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
@@ -16,12 +22,7 @@ using Microsoft.Graphics.Canvas.Text;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.UI;
|
||||
@@ -43,7 +44,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
IRecipient<PropertyChangedMessage<LyricsAlignmentType>>,
|
||||
IRecipient<PropertyChangedMessage<ElementTheme>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsFontWeight>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsGlowEffectScope>>,
|
||||
IRecipient<PropertyChangedMessage<LineRenderingType>>,
|
||||
IRecipient<PropertyChangedMessage<ObservableCollection<LyricsSearchProviderInfo>>>,
|
||||
IRecipient<PropertyChangedMessage<ObservableCollection<LocalLyricsFolder>>>
|
||||
{
|
||||
@@ -130,7 +131,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// <summary>
|
||||
/// Defines the _lyricsGlowEffectAmount
|
||||
/// </summary>
|
||||
private readonly float _lyricsGlowEffectAmount = 6f;
|
||||
private readonly float _lyricsGlowEffectAmount = 8f;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the _musicSearchService
|
||||
@@ -145,7 +146,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// <summary>
|
||||
/// Defines the _rightMargin
|
||||
/// </summary>
|
||||
private readonly double _rightMargin = 36;
|
||||
private readonly float _rightMargin = 36f;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the _topMargin
|
||||
@@ -202,11 +203,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// </summary>
|
||||
private Color _lightFontColor = Colors.White;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the _lyricsForGlowEffect
|
||||
/// </summary>
|
||||
private List<LyricsLine>? _lyricsForGlowEffect = [];
|
||||
|
||||
/// <summary>
|
||||
/// Defines the _multiLangLyrics
|
||||
/// </summary>
|
||||
@@ -277,7 +273,10 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_playbackService.SongInfoChanged += PlaybackService_SongInfoChanged;
|
||||
_playbackService.PositionChanged += PlaybackService_PositionChanged;
|
||||
|
||||
RefreshPlaybackInfo();
|
||||
_isPlaying = _playbackService.IsPlaying;
|
||||
SongInfo = _playbackService.SongInfo;
|
||||
TotalTime = _playbackService.Position;
|
||||
|
||||
UpdateFontColor();
|
||||
}
|
||||
|
||||
@@ -356,7 +355,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsGlowEffectScope
|
||||
/// </summary>
|
||||
public LyricsGlowEffectScope LyricsGlowEffectScope { get; set; }
|
||||
public LineRenderingType LyricsGlowEffectScope { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsLineSpacingFactor
|
||||
@@ -430,86 +429,19 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
break;
|
||||
case LyricsDisplayType.LyricsOnly:
|
||||
case LyricsDisplayType.SplitView:
|
||||
DrawLyrics(
|
||||
control,
|
||||
lyricsDs,
|
||||
_multiLangLyrics.SafeGet(_langIndex),
|
||||
_defaultOpacity,
|
||||
LyricsHighlightType.LineByLine
|
||||
);
|
||||
DrawLyrics(control, lyricsDs, LineRenderingType.UntilCurrentChar);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Lyrics layer with opacity modification (used for glow effect)
|
||||
using var modifiedLyrics = new CanvasCommandList(control);
|
||||
using (var modifiedLyricsDs = modifiedLyrics.CreateDrawingSession())
|
||||
{
|
||||
if (IsLyricsGlowEffectEnabled)
|
||||
{
|
||||
switch (DisplayType)
|
||||
{
|
||||
case LyricsDisplayType.AlbumArtOnly:
|
||||
case LyricsDisplayType.PlaceholderOnly:
|
||||
break;
|
||||
case LyricsDisplayType.LyricsOnly:
|
||||
case LyricsDisplayType.SplitView:
|
||||
switch (LyricsGlowEffectScope)
|
||||
{
|
||||
case LyricsGlowEffectScope.WholeLyrics:
|
||||
modifiedLyricsDs.DrawImage(lyrics);
|
||||
break;
|
||||
case LyricsGlowEffectScope.CurrentLine:
|
||||
DrawLyrics(
|
||||
control,
|
||||
modifiedLyricsDs,
|
||||
_lyricsForGlowEffect,
|
||||
0,
|
||||
LyricsHighlightType.LineByLine
|
||||
);
|
||||
break;
|
||||
case LyricsGlowEffectScope.CurrentChar:
|
||||
DrawLyrics(
|
||||
control,
|
||||
modifiedLyricsDs,
|
||||
_lyricsForGlowEffect,
|
||||
0,
|
||||
LyricsHighlightType.CharByChar
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using var glowedLyrics = new CanvasCommandList(control);
|
||||
using (var glowedLyricsDs = glowedLyrics.CreateDrawingSession())
|
||||
{
|
||||
glowedLyricsDs.DrawImage(
|
||||
new ShadowEffect
|
||||
{
|
||||
Source = modifiedLyrics,
|
||||
BlurAmount = _lyricsGlowEffectAmount,
|
||||
ShadowColor = _fontColor,
|
||||
Optimization = EffectOptimization.Quality,
|
||||
}
|
||||
);
|
||||
glowedLyricsDs.DrawImage(lyrics);
|
||||
}
|
||||
|
||||
// Mock gradient blurred lyrics layer
|
||||
using var blurredLyrics = new CanvasCommandList(control);
|
||||
using var blurredLyricsDs = blurredLyrics.CreateDrawingSession();
|
||||
if (LyricsBlurAmount == 0)
|
||||
{
|
||||
blurredLyricsDs.DrawImage(glowedLyrics);
|
||||
blurredLyricsDs.DrawImage(lyrics);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -519,7 +451,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
using var halfBlurredLyrics = new GaussianBlurEffect
|
||||
{
|
||||
Source = glowedLyrics,
|
||||
Source = lyrics,
|
||||
BlurAmount = (float)(LyricsBlurAmount * (1 - i / (0.5 - step))),
|
||||
Optimization = EffectOptimization.Quality,
|
||||
BorderMode = EffectBorderMode.Soft,
|
||||
@@ -800,11 +732,14 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// The Receive
|
||||
/// </summary>
|
||||
/// <param name="message">The message<see cref="PropertyChangedMessage{LyricsGlowEffectScope}"/></param>
|
||||
public void Receive(PropertyChangedMessage<LyricsGlowEffectScope> message)
|
||||
public void Receive(PropertyChangedMessage<LineRenderingType> message)
|
||||
{
|
||||
if (message.Sender is LyricsSettingsControlViewModel)
|
||||
{
|
||||
if (message.PropertyName == nameof(LyricsSettingsControlViewModel.LyricsGlowEffectScope))
|
||||
if (
|
||||
message.PropertyName
|
||||
== nameof(LyricsSettingsControlViewModel.LyricsGlowEffectScope)
|
||||
)
|
||||
{
|
||||
LyricsGlowEffectScope = message.NewValue;
|
||||
}
|
||||
@@ -827,24 +762,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The RefreshPlaybackInfo
|
||||
/// </summary>
|
||||
public void RefreshPlaybackInfo()
|
||||
{
|
||||
_isPlaying = _playbackService.IsPlaying;
|
||||
SongInfo = _playbackService.SongInfo;
|
||||
TotalTime = _playbackService.Position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The RequestRelayout
|
||||
/// </summary>
|
||||
public void RequestRelayout()
|
||||
{
|
||||
_isRelayoutNeeded = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Update
|
||||
/// </summary>
|
||||
@@ -887,30 +804,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_isRelayoutNeeded = false;
|
||||
}
|
||||
|
||||
UpdateLinesProps(_multiLangLyrics.SafeGet(_langIndex), _defaultOpacity);
|
||||
UpdateLinesProps();
|
||||
UpdateCanvasYScrollOffset(control);
|
||||
|
||||
if (IsLyricsGlowEffectEnabled)
|
||||
{
|
||||
// Deep copy lyrics lines for glow effect
|
||||
_lyricsForGlowEffect = _multiLangLyrics
|
||||
.SafeGet(_langIndex)
|
||||
?.Select(line => line.Clone())
|
||||
.ToList();
|
||||
switch (LyricsGlowEffectScope)
|
||||
{
|
||||
case LyricsGlowEffectScope.WholeLyrics:
|
||||
break;
|
||||
case LyricsGlowEffectScope.CurrentLine:
|
||||
UpdateLinesProps(_lyricsForGlowEffect, 0);
|
||||
break;
|
||||
case LyricsGlowEffectScope.CurrentChar:
|
||||
UpdateLinesProps(_lyricsForGlowEffect, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1078,42 +973,49 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// </summary>
|
||||
/// <param name="control">The control<see cref="ICanvasAnimatedControl"/></param>
|
||||
/// <param name="ds">The ds<see cref="CanvasDrawingSession"/></param>
|
||||
/// <param name="source">The source<see cref="List{LyricsLine}?"/></param>
|
||||
/// <param name="defaultOpacity">The defaultOpacity<see cref="float"/></param>
|
||||
/// <param name="currentLineHighlightType">The currentLineHighlightType<see cref="LyricsHighlightType"/></param>
|
||||
private void DrawLyrics(
|
||||
ICanvasAnimatedControl control,
|
||||
CanvasDrawingSession ds,
|
||||
List<LyricsLine>? source,
|
||||
float defaultOpacity,
|
||||
LyricsHighlightType currentLineHighlightType
|
||||
LineRenderingType currentLineHighlightType
|
||||
)
|
||||
{
|
||||
var (displayStartLineIndex, displayEndLineIndex) =
|
||||
GetVisibleLyricsLineIndexBoundaries();
|
||||
|
||||
for (
|
||||
int i = displayStartLineIndex;
|
||||
source?.Count > 0 && i >= 0 && i < source?.Count && i <= displayEndLineIndex;
|
||||
i++
|
||||
)
|
||||
var currentPlayingLineIndex = GetCurrentPlayingLineIndex();
|
||||
|
||||
for (int i = displayStartLineIndex; i <= displayEndLineIndex; i++)
|
||||
{
|
||||
var line = source?[i];
|
||||
var line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i);
|
||||
|
||||
using var textLayout = new CanvasTextLayout(
|
||||
control,
|
||||
line?.Text,
|
||||
_textFormat,
|
||||
(float)_limitedLineWidthTransition.Value,
|
||||
(float)control.Size.Height
|
||||
);
|
||||
if (line == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float progressPerChar = 1f / line.Text.Length;
|
||||
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 + (float)textLayout.LayoutBounds.Height / 2;
|
||||
float centerY = position.Y + layoutHeight / 2;
|
||||
|
||||
// X offset for alignment, used for rectangle mask
|
||||
float maskXOffset = 0f;
|
||||
|
||||
switch (LyricsAlignmentType)
|
||||
{
|
||||
@@ -1123,103 +1025,265 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
case LyricsAlignmentType.Center:
|
||||
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Center;
|
||||
centerX += (float)_limitedLineWidthTransition.Value / 2;
|
||||
maskXOffset = (_limitedLineWidthTransition.Value - layoutWidth) / 2;
|
||||
break;
|
||||
case LyricsAlignmentType.Right:
|
||||
textLayout.HorizontalAlignment = CanvasHorizontalAlignment.Right;
|
||||
centerX += (float)_limitedLineWidthTransition.Value;
|
||||
maskXOffset = _limitedLineWidthTransition.Value - layoutWidth;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int startIndex = 0;
|
||||
|
||||
// Set brush
|
||||
for (int j = 0; j < textLayout.LineCount; j++)
|
||||
{
|
||||
int count = textLayout.LineMetrics[j].CharacterCount;
|
||||
var regions = textLayout.GetCharacterRegions(startIndex, count);
|
||||
float subLinePlayingProgress = Math.Clamp(
|
||||
(line.PlayingProgress * line.Text.Length - startIndex) / count,
|
||||
0,
|
||||
1
|
||||
);
|
||||
|
||||
float startX = (float)(regions[0].LayoutBounds.Left + position.X);
|
||||
float endX = (float)(regions[^1].LayoutBounds.Right + position.X);
|
||||
|
||||
if (currentLineHighlightType == LyricsHighlightType.LineByLine)
|
||||
{
|
||||
float[] pos =
|
||||
[
|
||||
0,
|
||||
subLinePlayingProgress * (1 + progressPerChar) - progressPerChar,
|
||||
subLinePlayingProgress * (1 + progressPerChar),
|
||||
1.5f,
|
||||
];
|
||||
float[] opacity =
|
||||
[
|
||||
line.Opacity,
|
||||
line.Opacity,
|
||||
defaultOpacity,
|
||||
defaultOpacity,
|
||||
];
|
||||
|
||||
using var brush = GetHorizontalFillBrush(
|
||||
control,
|
||||
pos,
|
||||
opacity,
|
||||
startX,
|
||||
endX
|
||||
);
|
||||
textLayout.SetBrush(startIndex, count, brush);
|
||||
}
|
||||
else if (currentLineHighlightType == LyricsHighlightType.CharByChar)
|
||||
{
|
||||
float[] pos =
|
||||
[
|
||||
subLinePlayingProgress * (1 + progressPerChar) - 3 * progressPerChar,
|
||||
subLinePlayingProgress * (1 + progressPerChar) - progressPerChar,
|
||||
subLinePlayingProgress * (1 + progressPerChar),
|
||||
1.5f,
|
||||
];
|
||||
float[] opacity =
|
||||
[
|
||||
defaultOpacity,
|
||||
line.Opacity,
|
||||
defaultOpacity,
|
||||
defaultOpacity,
|
||||
];
|
||||
|
||||
using var brush = GetHorizontalFillBrush(
|
||||
control,
|
||||
pos,
|
||||
opacity,
|
||||
startX,
|
||||
endX
|
||||
);
|
||||
textLayout.SetBrush(startIndex, count, brush);
|
||||
}
|
||||
|
||||
startIndex += count;
|
||||
}
|
||||
float offsetToLeft =
|
||||
(float)control.Size.Width - _rightMargin - _limitedLineWidthTransition.Value;
|
||||
|
||||
// Scale
|
||||
ds.Transform =
|
||||
Matrix3x2.CreateScale(line.Scale, new Vector2(centerX, centerY))
|
||||
* Matrix3x2.CreateTranslation(
|
||||
(float)(
|
||||
control.Size.Width - _rightMargin - _limitedLineWidthTransition.Value
|
||||
),
|
||||
offsetToLeft,
|
||||
_canvasYScrollTransition.Value + (float)(control.Size.Height / 2)
|
||||
);
|
||||
|
||||
ds.DrawTextLayout(textLayout, position, Colors.Transparent);
|
||||
// Create the original lyrics line
|
||||
using var pureLyricsLine = new CanvasCommandList(control);
|
||||
using (var pureLyricsLineDs = pureLyricsLine.CreateDrawingSession())
|
||||
{
|
||||
pureLyricsLineDs.DrawTextLayout(textLayout, position, _fontColor);
|
||||
}
|
||||
|
||||
// Create and draw glow (shadow) effect
|
||||
if (IsLyricsGlowEffectEnabled)
|
||||
{
|
||||
ds.DrawImage(
|
||||
new ShadowEffect
|
||||
{
|
||||
Source = new AlphaMaskEffect
|
||||
{
|
||||
Source = pureLyricsLine,
|
||||
AlphaMask = CreateLineMask(
|
||||
control,
|
||||
line,
|
||||
LyricsGlowEffectScope,
|
||||
false
|
||||
),
|
||||
},
|
||||
BlurAmount = _lyricsGlowEffectAmount,
|
||||
ShadowColor = _fontColor,
|
||||
Optimization = EffectOptimization.Quality,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Create and draw highlight (opacity changed) effect
|
||||
ds.DrawImage(
|
||||
new AlphaMaskEffect
|
||||
{
|
||||
Source = pureLyricsLine,
|
||||
AlphaMask = CreateLineMask(
|
||||
control,
|
||||
line,
|
||||
LineRenderingType.UntilCurrentChar,
|
||||
true
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
// Reset scale
|
||||
ds.Transform = Matrix3x2.Identity;
|
||||
}
|
||||
}
|
||||
|
||||
private CanvasCommandList CreateLineMask(
|
||||
ICanvasAnimatedControl control,
|
||||
LyricsLine line,
|
||||
LineRenderingType lineMaskType,
|
||||
bool isUnhighlightedAreaVisible
|
||||
)
|
||||
{
|
||||
var alphaMask = new CanvasCommandList(control);
|
||||
|
||||
var textLayout = line.CanvasTextLayout;
|
||||
if (textLayout == null)
|
||||
{
|
||||
return alphaMask;
|
||||
}
|
||||
|
||||
using (var ds = alphaMask.CreateDrawingSession())
|
||||
{
|
||||
// Current playing char index
|
||||
int charIndex = (int)(line.PlayingProgress * line.Text.Length);
|
||||
int totalCharCountBefore = 0;
|
||||
foreach (var lineMatrix in textLayout.LineMetrics)
|
||||
{
|
||||
int lineCharCount = lineMatrix.CharacterCount;
|
||||
|
||||
var region = textLayout
|
||||
.GetCharacterRegions(totalCharCountBefore, lineCharCount)
|
||||
.FirstOrDefault();
|
||||
|
||||
var lineWidth = region.LayoutBounds.Width;
|
||||
var lineHeight = region.LayoutBounds.Height;
|
||||
|
||||
var lineLeft = (float)region.LayoutBounds.X;
|
||||
var lineTop = (float)region.LayoutBounds.Y + line.Position.Y;
|
||||
var lineRight = lineLeft + lineWidth;
|
||||
|
||||
if (
|
||||
totalCharCountBefore <= charIndex
|
||||
&& charIndex < totalCharCountBefore + lineCharCount
|
||||
)
|
||||
{
|
||||
var currentRegion = textLayout
|
||||
.GetCharacterRegions(charIndex, 1)
|
||||
.FirstOrDefault();
|
||||
var charPlayingProgress =
|
||||
line.PlayingProgress * line.Text.Length - charIndex;
|
||||
|
||||
// 确保小于右边距
|
||||
float fadeSpacing = 18f;
|
||||
|
||||
float currentCharWidth = (float)currentRegion.LayoutBounds.Width;
|
||||
|
||||
float currentPlayingX = 0f;
|
||||
|
||||
// 行首行尾增加 fadeSpacing 以完成完整的淡入淡出效果
|
||||
if (region.LayoutBounds.Left == currentRegion.LayoutBounds.Left)
|
||||
{
|
||||
currentCharWidth += fadeSpacing;
|
||||
currentPlayingX =
|
||||
lineLeft - fadeSpacing + currentCharWidth * charPlayingProgress;
|
||||
}
|
||||
else if (region.LayoutBounds.Right == currentRegion.LayoutBounds.Right)
|
||||
{
|
||||
currentCharWidth += fadeSpacing;
|
||||
currentPlayingX =
|
||||
(float)currentRegion.LayoutBounds.Left
|
||||
+ currentCharWidth * charPlayingProgress;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentPlayingX =
|
||||
(float)currentRegion.LayoutBounds.Left
|
||||
+ currentCharWidth * charPlayingProgress;
|
||||
}
|
||||
|
||||
float beforeFadeInX = lineLeft - fadeSpacing * 2;
|
||||
|
||||
float beforePlayingOpacity = lineMaskType switch
|
||||
{
|
||||
LineRenderingType.UntilCurrentChar => line.Opacity,
|
||||
LineRenderingType.CurrentCharOnly => isUnhighlightedAreaVisible
|
||||
? _defaultOpacity
|
||||
: 0,
|
||||
_ => line.Opacity,
|
||||
};
|
||||
|
||||
// 画当前字符淡入之前部分(已播放)
|
||||
ds?.FillRectangle(
|
||||
new Rect(
|
||||
beforeFadeInX,
|
||||
lineTop,
|
||||
currentPlayingX - fadeSpacing - beforeFadeInX,
|
||||
lineHeight
|
||||
),
|
||||
Color.FromArgb((byte)(255 * beforePlayingOpacity), 200, 0, 0)
|
||||
);
|
||||
|
||||
float fadeInStartX = currentPlayingX - fadeSpacing;
|
||||
float fadeInEndX = currentPlayingX;
|
||||
|
||||
// 画正处在高亮字符之前 fadeSpaing 距离的渐变部分(淡入)
|
||||
ds?.FillRectangle(
|
||||
new Rect(fadeInStartX, lineTop, fadeSpacing, lineHeight),
|
||||
GetHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, beforePlayingOpacity), (1f, line.Opacity)],
|
||||
fadeInStartX,
|
||||
fadeInEndX
|
||||
)
|
||||
);
|
||||
|
||||
float afterPlayingOpacity = isUnhighlightedAreaVisible
|
||||
? _defaultOpacity
|
||||
: 0;
|
||||
|
||||
float fadeOutStartX = currentPlayingX;
|
||||
float fadeOutEndX = fadeOutStartX + fadeSpacing;
|
||||
|
||||
// 画正处在高亮之后 fadeSpaing 距离的渐变部分(淡出)
|
||||
ds?.FillRectangle(
|
||||
new Rect(fadeOutStartX, lineTop, fadeSpacing, lineHeight),
|
||||
GetHorizontalFillBrush(
|
||||
control,
|
||||
[(0f, line.Opacity), (1f, afterPlayingOpacity)],
|
||||
fadeOutStartX,
|
||||
fadeOutEndX
|
||||
)
|
||||
);
|
||||
|
||||
// 画渐变之后透明度为 _defaultOpacity 的部分(未播放)
|
||||
ds?.FillRectangle(
|
||||
new Rect(
|
||||
fadeOutEndX,
|
||||
lineTop,
|
||||
lineRight + fadeSpacing * 2 - fadeOutEndX,
|
||||
lineHeight
|
||||
),
|
||||
Color.FromArgb((byte)(255 * afterPlayingOpacity), 0, 200, 0)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (charIndex < totalCharCountBefore)
|
||||
{
|
||||
// 当前子行未播放
|
||||
float opacity = isUnhighlightedAreaVisible ? _defaultOpacity : 0;
|
||||
ds?.FillRectangle(
|
||||
new Rect(lineLeft, lineTop, lineWidth, lineHeight),
|
||||
Color.FromArgb((byte)(255 * opacity), 0, 200, 0)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 当前子行已完全播放
|
||||
float opacity = lineMaskType switch
|
||||
{
|
||||
LineRenderingType.UntilCurrentChar => line.Opacity,
|
||||
LineRenderingType.CurrentCharOnly => _defaultOpacity,
|
||||
_ => line.Opacity,
|
||||
};
|
||||
if (!isUnhighlightedAreaVisible)
|
||||
{
|
||||
switch (lineMaskType)
|
||||
{
|
||||
case LineRenderingType.UntilCurrentChar:
|
||||
opacity *=
|
||||
(line.Opacity - _defaultOpacity)
|
||||
/ (_highlightedOpacity - _defaultOpacity);
|
||||
break;
|
||||
case LineRenderingType.CurrentCharOnly:
|
||||
opacity = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ds?.FillRectangle(
|
||||
new Rect(lineLeft, lineTop, lineWidth, lineHeight),
|
||||
Color.FromArgb((byte)(255 * opacity), 200, 0, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
totalCharCountBefore += lineCharCount;
|
||||
}
|
||||
}
|
||||
|
||||
return alphaMask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GetCurrentPlayingLineIndex
|
||||
/// </summary>
|
||||
@@ -1250,8 +1314,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// <returns>The <see cref="CanvasLinearGradientBrush"/></returns>
|
||||
private CanvasLinearGradientBrush GetHorizontalFillBrush(
|
||||
ICanvasAnimatedControl control,
|
||||
float[] stopPosition,
|
||||
float[] stopOpacity,
|
||||
List<(float position, float opacity)> stops,
|
||||
float startX,
|
||||
float endX
|
||||
)
|
||||
@@ -1262,28 +1325,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
return new CanvasLinearGradientBrush(
|
||||
control,
|
||||
[
|
||||
new()
|
||||
stops
|
||||
.Select(stops => new CanvasGradientStop
|
||||
{
|
||||
Position = stopPosition[0],
|
||||
Color = Color.FromArgb((byte)(255 * stopOpacity[0]), r, g, b),
|
||||
},
|
||||
new()
|
||||
{
|
||||
Position = stopPosition[1],
|
||||
Color = Color.FromArgb((byte)(255 * stopOpacity[1]), r, g, b),
|
||||
},
|
||||
new()
|
||||
{
|
||||
Position = stopPosition[2],
|
||||
Color = Color.FromArgb((byte)(255 * stopOpacity[2]), r, g, b),
|
||||
},
|
||||
new()
|
||||
{
|
||||
Position = stopPosition[3],
|
||||
Color = Color.FromArgb((byte)(255 * stopOpacity[3]), r, g, b),
|
||||
},
|
||||
]
|
||||
Position = stops.position,
|
||||
Color = Color.FromArgb((byte)(stops.opacity * 255), r, g, b),
|
||||
})
|
||||
.ToArray()
|
||||
)
|
||||
{
|
||||
StartPoint = new Vector2(startX, 0),
|
||||
@@ -1488,20 +1536,27 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.CanvasTextLayout != null)
|
||||
{
|
||||
line.CanvasTextLayout.Dispose();
|
||||
line.CanvasTextLayout = null;
|
||||
}
|
||||
|
||||
// Calculate layout bounds
|
||||
using var textLayout = new CanvasTextLayout(
|
||||
line.CanvasTextLayout = new CanvasTextLayout(
|
||||
control,
|
||||
line.Text,
|
||||
_textFormat,
|
||||
(float)_limitedLineWidthTransition.Value,
|
||||
(float)control.Size.Height
|
||||
);
|
||||
|
||||
line.Position = new Vector2(0, y);
|
||||
|
||||
y +=
|
||||
(float)textLayout.LayoutBounds.Height
|
||||
/ textLayout.LineCount
|
||||
* (textLayout.LineCount + LyricsLineSpacingFactor);
|
||||
(float)line.CanvasTextLayout.LayoutBounds.Height
|
||||
/ line.CanvasTextLayout.LineCount
|
||||
* (line.CanvasTextLayout.LineCount + LyricsLineSpacingFactor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1512,10 +1567,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private void UpdateCanvasYScrollOffset(ICanvasAnimatedControl control)
|
||||
{
|
||||
var currentPlayingLineIndex = GetCurrentPlayingLineIndex();
|
||||
if (currentPlayingLineIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var (startLineIndex, endLineIndex) = GetMaxLyricsLineIndexBoundaries();
|
||||
|
||||
@@ -1527,21 +1578,15 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
// Set _scrollOffsetY
|
||||
LyricsLine? currentPlayingLine = _multiLangLyrics
|
||||
.SafeGet(_langIndex)
|
||||
?[currentPlayingLineIndex];
|
||||
?.SafeGet(currentPlayingLineIndex);
|
||||
|
||||
if (currentPlayingLine == null)
|
||||
var playingTextLayout = currentPlayingLine?.CanvasTextLayout;
|
||||
|
||||
if (currentPlayingLine == null || playingTextLayout == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var playingTextLayout = new CanvasTextLayout(
|
||||
control,
|
||||
currentPlayingLine.Text,
|
||||
_textFormat,
|
||||
(float)_limitedLineWidthTransition.Value,
|
||||
(float)control.Size.Height
|
||||
);
|
||||
|
||||
float targetYScrollOffset =
|
||||
(float?)(
|
||||
-currentPlayingLine.Position.Y
|
||||
@@ -1566,18 +1611,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
var line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i);
|
||||
|
||||
if (line == null)
|
||||
if (line == null || line.CanvasTextLayout == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using var textLayout = new CanvasTextLayout(
|
||||
control,
|
||||
line?.Text,
|
||||
_textFormat,
|
||||
(float)_limitedLineWidthTransition.Value,
|
||||
(float)control.Size.Height
|
||||
);
|
||||
var textLayout = line.CanvasTextLayout;
|
||||
|
||||
if (
|
||||
_canvasYScrollTransition.Value
|
||||
@@ -1662,7 +1701,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
/// </summary>
|
||||
/// <param name="source">The source<see cref="List{LyricsLine}?"/></param>
|
||||
/// <param name="defaultOpacity">The defaultOpacity<see cref="float"/></param>
|
||||
private void UpdateLinesProps(List<LyricsLine>? source, float defaultOpacity)
|
||||
private void UpdateLinesProps()
|
||||
{
|
||||
var (startLineIndex, endLineIndex) = GetMaxLyricsLineIndexBoundaries();
|
||||
|
||||
@@ -1670,7 +1709,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
for (int i = startLineIndex; i <= endLineIndex; i++)
|
||||
{
|
||||
var line = source?.SafeGet(i);
|
||||
var line = _multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i);
|
||||
|
||||
if (line == null)
|
||||
{
|
||||
@@ -1684,7 +1723,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
if (i + 1 <= endLineIndex)
|
||||
{
|
||||
lineExitingDurationMs = Math.Min(
|
||||
source?[i + 1].DurationMs ?? 0,
|
||||
_multiLangLyrics.SafeGet(_langIndex)?.SafeGet(i + 1)?.DurationMs ?? 0,
|
||||
lineExitingDurationMs
|
||||
);
|
||||
}
|
||||
@@ -1696,7 +1735,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
bool lineExiting = false;
|
||||
|
||||
float scale = _defaultScale;
|
||||
float opacity = defaultOpacity;
|
||||
float opacity = _defaultOpacity;
|
||||
|
||||
float playProgress = 0;
|
||||
|
||||
@@ -1718,8 +1757,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_defaultScale
|
||||
+ (_highlightedScale - _defaultScale) * (float)lineEnteringProgress;
|
||||
opacity =
|
||||
defaultOpacity
|
||||
+ (_highlightedOpacity - defaultOpacity) * (float)lineEnteringProgress;
|
||||
_defaultOpacity
|
||||
+ (_highlightedOpacity - _defaultOpacity) * (float)lineEnteringProgress;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1739,7 +1778,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
- (_highlightedScale - _defaultScale) * (float)lineExitingProgress;
|
||||
opacity =
|
||||
_highlightedOpacity
|
||||
- (_highlightedOpacity - defaultOpacity)
|
||||
- (_highlightedOpacity - _defaultOpacity)
|
||||
* (float)lineExitingProgress;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace BetterInAppLyrics.WinUI3.ViewModels
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial LyricsGlowEffectScope LyricsGlowEffectScope { get; set; }
|
||||
public partial LineRenderingType LyricsGlowEffectScope { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LyricsLineSpacingFactor
|
||||
@@ -162,8 +162,8 @@ namespace BetterInAppLyrics.WinUI3.ViewModels
|
||||
/// <summary>
|
||||
/// The OnLyricsGlowEffectScopeChanged
|
||||
/// </summary>
|
||||
/// <param name="value">The value<see cref="LyricsGlowEffectScope"/></param>
|
||||
partial void OnLyricsGlowEffectScopeChanged(LyricsGlowEffectScope value)
|
||||
/// <param name="value">The value<see tef="LyricsGlowEffectScope"/></param>
|
||||
partial void OnLyricsGlowEffectScopeChanged(LineRenderingType value)
|
||||
{
|
||||
_settingsService?.LyricsGlowEffectScope = value;
|
||||
}
|
||||
|
||||
@@ -450,7 +450,6 @@
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageLyricsGlowEffectScope" IsEnabled="{x:Bind LyricsSettingsControlViewModel.IsLyricsGlowEffectEnabled, Mode=OneWay}">
|
||||
<ComboBox SelectedIndex="{x:Bind LyricsSettingsControlViewModel.LyricsGlowEffectScope, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsGlowEffectScopeWholeLyrics" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsGlowEffectScopeCurrentLine" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLyricsGlowEffectScopeCurrentChar" />
|
||||
</ComboBox>
|
||||
|
||||
Reference in New Issue
Block a user