Skip to content

Commit

Permalink
调整播放器操作逻辑,避免关闭Flyout时暂停视频 (#939)
Browse files Browse the repository at this point in the history
* Update

* 调整播放器操作逻辑,避免关闭Flyout时暂停视频
  • Loading branch information
Richasy authored Dec 8, 2024
1 parent 4ee00b6 commit c69168e
Show file tree
Hide file tree
Showing 10 changed files with 248 additions and 23 deletions.
4 changes: 2 additions & 2 deletions Bili.Copilot.sln
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,8 @@ Global
{91A1C2B5-D3DD-47A6-8EEA-642C42096A49}.Release|x86.Build.0 = Release|Any CPU
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|ARM64.Build.0 = Debug|Any CPU
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|ARM64.ActiveCfg = Debug|ARM64
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|ARM64.Build.0 = Debug|ARM64
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|x64.ActiveCfg = Debug|x64
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|x64.Build.0 = Debug|x64
{50BC1CC1-7508-4F61-A4A7-0E8EF4426B51}.Debug|x86.ActiveCfg = Debug|Any CPU
Expand Down
17 changes: 13 additions & 4 deletions src/Desktop/BiliCopilot.UI/BiliCopilot.UI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
<Content Remove="Assets\DashAudioWithoutVideoTemplate.xml" />
<Content Remove="Assets\DashVideoTemplate.xml" />
<Content Remove="Assets\DashVideoWithoutAudioTemplate.xml" />
<Content Remove="Assets\ffmpeg\ffmpeg.exe" />
<Content Remove="Assets\ffmpeg\arm64\ffmpeg.exe" />
<Content Remove="Assets\ffmpeg\x64\ffmpeg.exe" />
<Content Remove="Assets\libmpv\arm64\libmpv-2.dll" />
<Content Remove="Assets\libmpv\x64\libmpv-2.dll" />
<Content Remove="Assets\WebPlayer.js" />
Expand Down Expand Up @@ -375,6 +376,7 @@
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" />
<PackageReference Include="ComputeSharp.D2D1.WinUI" />
<PackageReference Include="FluentIcons.WinUI" />
<PackageReference Include="H.NotifyIcon.WinUI" />
<PackageReference Include="HtmlAgilityPack" />
Expand Down Expand Up @@ -1063,6 +1065,16 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x64'">
<None Update="Assets\ffmpeg\x64\ffmpeg.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'ARM64'">
<None Update="Assets\ffmpeg\arm64\ffmpeg.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x64'">
<None Update="Assets\BBDown\x64\BBDown.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand Down Expand Up @@ -1325,9 +1337,6 @@
<None Update="Assets\DashVideoWithoutAudioTemplate.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Assets\ffmpeg\ffmpeg.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Assets\WebPlayer.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public sealed partial class BiliPlayer
private StackPanel _notificationContainer;
private LoadingWidget _loadingWidget;
private EmptyHolder _failedHolder;
private MenuFlyout _contextFlyout;

/// <summary>
/// 注入弹幕控件创建函数.
Expand Down Expand Up @@ -102,13 +103,13 @@ private void CreateOverlayContainer()
Icon = new FluentIcons.WinUI.SymbolIcon { Symbol = FluentIcons.Common.Symbol.ArrowClockwise },
});

_contextFlyout = contextFlyout;
_interactionControl = new Rectangle
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Fill = new SolidColorBrush(Colors.Transparent),
Visibility = ViewModel?.IsExternalPlayer ?? false ? Visibility.Collapsed : Visibility.Visible,
ContextFlyout = contextFlyout,
};
HookInteractionControlEvents();
rootGrid.Children.Add(_interactionControl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using BiliCopilot.UI.Toolkits;
using BiliCopilot.UI.ViewModels.Core;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Input;

namespace BiliCopilot.UI.Controls.Core;
Expand Down Expand Up @@ -163,15 +164,6 @@ private void RestoreCursor()
}
}

private void OnInteractionControlContextRequested(UIElement sender, ContextRequestedEventArgs args)
{
if (_isHolding)
{
args.Handled = true;
sender.ContextFlyout?.Hide();
}
}

private void OnInteractionControlManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
_manipulationVolume = 0;
Expand Down Expand Up @@ -270,14 +262,25 @@ private void OnRootPointerCanceled(object sender, PointerRoutedEventArgs e)

private void OnRootPointerPressed(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
var point = e.GetCurrentPoint((UIElement)sender);
if (point.Properties.PointerUpdateKind == PointerUpdateKind.RightButtonPressed)
{
var options = new FlyoutShowOptions
{
Position = point.Position,
};
_contextFlyout.ShowAt(_interactionControl, options);
return;
}

_isPointerHasPressed = true;
if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse || e.Pointer.PointerDeviceType == PointerDeviceType.Touch)
{
_lastPressedTime = DateTimeOffset.Now;
}

if (ViewModel is IslandPlayerViewModel)
{
var point = e.GetCurrentPoint((UIElement)sender);
if (point.Properties.IsXButton1Pressed || point.Properties.IsXButton2Pressed)
{
if (ViewModel.IsFullScreen || ViewModel.IsFullWindow || ViewModel.IsCompactOverlay)
Expand Down Expand Up @@ -324,6 +327,12 @@ private void OnRootPointerMoved(object sender, PointerRoutedEventArgs e)

private void OnRootPointerReleased(object sender, PointerRoutedEventArgs e)
{
if (_isPointerHasPressed != true || e.GetCurrentPoint((UIElement)sender).Properties.PointerUpdateKind == PointerUpdateKind.RightButtonReleased)
{
return;
}

_isPointerHasPressed = default;
_lastPressedTime = default;
_lastRightArrowPressedTime = default;
if (_isHolding)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public sealed partial class BiliPlayer : PlayerControlBase
private PlayerManipulationType _manipulationType = PlayerManipulationType.None;
private DateTimeOffset? _lastPressedTime;
private DateTimeOffset? _lastRightArrowPressedTime;
private bool? _isPointerHasPressed;

/// <summary>
/// Initializes a new instance of the <see cref="BiliPlayer"/> class.
Expand Down Expand Up @@ -201,7 +202,6 @@ private void HookInteractionControlEvents()
_interactionControl.ManipulationStarted += OnInteractionControlManipulationStarted;
_interactionControl.ManipulationDelta += OnInteractionControlManipulationDelta;
_interactionControl.ManipulationCompleted += OnInteractionControlManipulationCompleted;
_interactionControl.ContextRequested += OnInteractionControlContextRequested;
}

private void UnhookInteractionControlEvents()
Expand All @@ -212,7 +212,6 @@ private void UnhookInteractionControlEvents()
_interactionControl.ManipulationStarted -= OnInteractionControlManipulationStarted;
_interactionControl.ManipulationDelta -= OnInteractionControlManipulationDelta;
_interactionControl.ManipulationCompleted -= OnInteractionControlManipulationCompleted;
_interactionControl.ContextRequested -= OnInteractionControlContextRequested;
}
}

Expand Down
206 changes: 206 additions & 0 deletions src/Desktop/BiliCopilot.UI/Extensions/BlurCanvasEffect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
// Copyright (c) Bili Copilot. All rights reserved.

// 源自 https://learn.microsoft.com/zh-cn/windows/apps/develop/win2d/custom-effects#custom-effects-in-c-using-computesharp
using System.Numerics;
using ComputeSharp;
using ComputeSharp.D2D1;
using ComputeSharp.D2D1.WinUI;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.UI;
using Windows.Graphics.Effects;
using Windows.UI;

namespace Richasy.WinUI.Share.Effects;

/// <summary>
/// 图像表面模糊的效果.
/// </summary>
public sealed partial class BlurCanvasEffect : CanvasEffect
{
private static readonly CanvasEffectNode<BorderEffect> _borderNode = new();
private static readonly CanvasEffectNode<ScaleEffect> _scaleNode = new();
private static readonly CanvasEffectNode<GaussianBlurEffect> _gaussianBlurNode = new();
private static readonly CanvasEffectNode<TintEffect> _tintNode = new();
private static readonly CanvasEffectNode<PixelShaderEffect<CrossFadeShader>> _crossFadeNode = new();
private static readonly CanvasEffectNode<PixelShaderEffect<NoiseShader>> _noiseNode = new();
private static readonly CanvasEffectNode<BlendEffect> _blendNode = new();

private IGraphicsEffectSource _source;
private float _blurAmount;
private Color _tintColor = Colors.White;
private int _crossfadeVerticalOffset;
private int _crossfadeVerticalLength;
private Rect _sourceRectangle;
private Rect _destinationRectangle;

/// <summary>
/// 图像源.
/// </summary>
public IGraphicsEffectSource Source
{
get => _source;
set => SetPropertyAndInvalidateEffectGraph(ref _source, value);
}

/// <summary>
/// 模糊强度.
/// </summary>
public float BlurAmount
{
get => _blurAmount;
set => SetPropertyAndInvalidateEffectGraph(ref _blurAmount, value);
}

/// <summary>
/// 模糊表面颜色.
/// </summary>
public Color TintColor
{
get => _tintColor;
set => SetPropertyAndInvalidateEffectGraph(ref _tintColor, value);
}

/// <summary>
/// 交错偏移.
/// </summary>
public int CrossfadeVerticalOffset
{
get => _crossfadeVerticalOffset;
set => SetPropertyAndInvalidateEffectGraph(ref _crossfadeVerticalOffset, value);
}

/// <summary>
/// 交错长度.
/// </summary>
public int CrossfadeVerticalLength
{
get => _crossfadeVerticalLength;
set => SetPropertyAndInvalidateEffectGraph(ref _crossfadeVerticalLength, value);
}

/// <summary>
/// 源矩形.
/// </summary>
public Rect SourceRectangle
{
get => _sourceRectangle;
set => SetPropertyAndInvalidateEffectGraph(ref _sourceRectangle, value);
}

/// <summary>
/// 目标矩形.
/// </summary>
public Rect DestinationRectangle
{
get => _destinationRectangle;
set => SetPropertyAndInvalidateEffectGraph(ref _destinationRectangle, value);
}

/// <inheritdoc/>
protected override void BuildEffectGraph(CanvasEffectGraph effectGraph)
{
BorderEffect borderEffect = new() { ExtendY = Microsoft.Graphics.Canvas.CanvasEdgeBehavior.Mirror };
ScaleEffect scaleEffect = new();
GaussianBlurEffect gaussianBlurEffect = new() { Optimization = EffectOptimization.Speed, BorderMode = EffectBorderMode.Hard };
TintEffect tintEffect = new();
BlendEffect blendEffect = new() { Mode = BlendEffectMode.Luminosity };
PremultiplyEffect noisePremultiplyEffect = new();
PremultiplyEffect finalPremultiplyEffect = new();
UnPremultiplyEffect unPremultiplyEffect1 = new();
UnPremultiplyEffect unPremultiplyEffect2 = new();
PixelShaderEffect<CrossFadeShader> crossFadeEffect = new();
PixelShaderEffect<NoiseShader> noiseEffect = new();

scaleEffect.Source = borderEffect;
gaussianBlurEffect.Source = scaleEffect;
tintEffect.Source = gaussianBlurEffect;
noisePremultiplyEffect.Source = noiseEffect;
blendEffect.Foreground = noisePremultiplyEffect;
blendEffect.Background = tintEffect;
unPremultiplyEffect1.Source = scaleEffect;
unPremultiplyEffect2.Source = blendEffect;
crossFadeEffect.Sources[0] = unPremultiplyEffect1;
crossFadeEffect.Sources[1] = unPremultiplyEffect2;
finalPremultiplyEffect.Source = crossFadeEffect;

effectGraph.RegisterNode(_noiseNode, noiseEffect);
effectGraph.RegisterNode(_borderNode, borderEffect);
effectGraph.RegisterNode(_scaleNode, scaleEffect);
effectGraph.RegisterNode(_gaussianBlurNode, gaussianBlurEffect);
effectGraph.RegisterNode(_tintNode, tintEffect);
effectGraph.RegisterNode(_blendNode, blendEffect);
effectGraph.RegisterNode(_crossFadeNode, crossFadeEffect);
effectGraph.RegisterNode(finalPremultiplyEffect);
effectGraph.RegisterNode(unPremultiplyEffect1);
effectGraph.RegisterNode(unPremultiplyEffect2);
}

/// <inheritdoc/>
protected override void ConfigureEffectGraph(CanvasEffectGraph effectGraph)
{
effectGraph.GetNode(_noiseNode).ConstantBuffer = new NoiseShader(0.1f);
effectGraph.GetNode(_borderNode).Source = _source;
effectGraph.GetNode(_scaleNode).Scale = new Vector2((float)_destinationRectangle.Width / (float)_sourceRectangle.Width);
effectGraph.GetNode(_gaussianBlurNode).BlurAmount = _blurAmount;
effectGraph.GetNode(_tintNode).Color = _tintColor;
effectGraph.GetNode(_crossFadeNode).ConstantBuffer = new CrossFadeShader(_crossfadeVerticalOffset, _crossfadeVerticalLength);
effectGraph.SetOutputNode(_crossFadeNode);
}
}

/// <summary>
/// 噪声着色器.
/// </summary>
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader40)]
[D2DGeneratedPixelShaderDescriptor]
public readonly partial struct NoiseShader(float amount) : ID2D1PixelShader
{
/// <inheritdoc/>
public float4 Execute()
{
var position = (int2)D2D.GetScenePosition().XY;
var hash = Hlsl.Frac(Hlsl.Sin(Hlsl.Dot(position, new float2(41, 289))) * 45758.5453f);
var alpha = Hlsl.Lerp(0, amount, hash);
return new(0, 0, 0, alpha);
}
}

/// <summary>
/// 交错着色器.
/// </summary>
[D2DInputCount(2)]
[D2DInputSimple(0)]
[D2DInputSimple(1)]
[D2DInputDescription(0, D2D1Filter.MinMagMipPoint)]
[D2DInputDescription(1, D2D1Filter.MinMagMipPoint)]
[D2DPixelOptions(D2D1PixelOptions.TrivialSampling)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader40)]
[D2DGeneratedPixelShaderDescriptor]
public readonly partial struct CrossFadeShader : ID2D1PixelShader
{
private readonly int _offsetStartY;
private readonly int _offsetLengthY;

/// <summary>
/// Initializes a new instance of the <see cref="CrossFadeShader"/> struct.
/// </summary>
public CrossFadeShader(int offsetStartY, int offsetLengthY)
{
_offsetStartY = offsetStartY;
_offsetLengthY = offsetLengthY;
}

/// <inheritdoc/>
public float4 Execute()
{
var offsetY = (int)D2D.GetScenePosition().Y;
var factor = Hlsl.Saturate((offsetY - _offsetStartY) / (float)_offsetLengthY);
var easing = Hlsl.Sin(factor * 1.57f);
var blend = Hlsl.Lerp(D2D.GetInput(0).XYZ, D2D.GetInput(1).XYZ, easing);

return new(blend, 1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private async Task InitializeExternalAsync()
var bbdownFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/BBDown/{identifier}/BBDown.exe")).AsTask();
BBDownPath = bbdownFile.Path;

var ffmpegFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/ffmpeg/ffmpeg.exe")).AsTask();
var ffmpegFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/ffmpeg/{identifier}/ffmpeg.exe")).AsTask();
FFmpegPath = ffmpegFile.Path;
}

Expand Down
1 change: 1 addition & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.241112-preview1" />
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.Media" Version="8.0.240109" />
<PackageVersion Include="ComputeSharp.D2D1.WinUI" Version="3.1.0-preview2" />
<PackageVersion Include="FluentIcons.WinUI" Version="1.1.266" />
<PackageVersion Include="Flurl.Http" Version="4.0.2" />
<PackageVersion Include="Google.Protobuf" Version="3.27.2" />
Expand Down
2 changes: 1 addition & 1 deletion src/Libs/WinUI.Share
2 changes: 1 addition & 1 deletion src/Libs/mpv-winui

0 comments on commit c69168e

Please sign in to comment.