Repository navigation
Plugin Game Settings Subsystem - #900
Cryotechnic wants to merge 21 commits into
Conversation
Expose `Progress` and `Status` on `IBackgroundActivity` and use them when wiring notification handlers in `BackgroundActivityManager`. This immediately initializes notification text/progress for already-running activities instead of waiting for the next event, preventing placeholder content from lingering.
Add a reusable speed-calculator reset helper in `ProgressBase` and use it in plugin install progress updates to avoid bogus speed deltas after state transitions. The wrapper now resets its download baseline when install state changes, computes per-tick bytes only from monotonic progress, and clears speed/time-left values appropriately. It also ensures completed installs report zero time left and clamp per-file progress to 100%.
Refactor GSP into a responsive multi-column layout while keeping informational sections full width
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. |
neon-nyan
left a comment
There was a problem hiding this comment.
Any changes to the BG-related so far. For the game settings related, still waiting for my game to be installed first.
| public sealed partial class PluginGameSettingsPage | ||
| { | ||
| private readonly GameSettingsExtension.GameSettingsContext _context; | ||
| private readonly TextBlock _statusText = new() |
There was a problem hiding this comment.
Bug: The _statusText TextBlock, intended for displaying plugin setting errors, is never added to the visual tree, so error messages are invisible to the user.
Severity: MEDIUM
Suggested Fix
The _statusText TextBlock should be added to a visible parent container within the page's XAML layout, such as a Grid or StackPanel. This will ensure that when its Text property is updated with an error message, it is rendered and becomes visible to the user.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location:
CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPages/PluginGameSettingsPage.cs#L31
Potential issue: In `PluginGameSettingsPage`, a `TextBlock` named `_statusText` is
instantiated to display error messages that occur when a plugin setting is changed.
However, this control is never added to the page's visual tree. When a user interacts
with a setting and the plugin's `_context.SetValue()` method throws an exception, the
`SetStatus(ex.Message, true)` method is called. This updates the `Text` property of
`_statusText`, but because the control is not rendered, the error message remains
invisible to the user, leading to silent failures.
Also affects:
CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPages/PluginGameSettingsPage.cs:279~296
| SwapChainPanelHelper.MediaPlayerCopyFrameUnsafe(_videoPlayerPtr, _canvasRenderTargetAsSurfacePtr); | ||
| drawingSessionPpv = SwapChainPanelHelper | ||
| .CanvasSessionDrawUnsafe(_canvasImageSourceNativePtr, | ||
| _canvasRenderTargetNativePtr, | ||
| _functionTableBeginDraw, | ||
| _functionTableDrawImage, | ||
| in _canvasRenderSize); | ||
| } | ||
| } | ||
| // Device lost error. If happened, reinitialize render target | ||
| catch (COMException comEx) when ((uint)comEx.HResult is 0x887A0005u or 0x802B0020u or 0x8899000Cu) |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
- Extract FFmpeg decoder checks into `RequiresFFmpegDecoder` and reuse it across codec detection and loader paths. - Treat 10-bit YUV420 (`AV_PIX_FMT_YUV420P10LE/BE`) as requiring FFmpeg, improving handling for High 10 H.264 backgrounds that Windows decoders may not support. - Tighten background reload behavior by comparing decoder mode before skipping reloads. - Layer setup now starts hidden, restores opacity after attach, and only sets a foreground overlay for video backgrounds.
- Improves `LayeredBackgroundImage` video initialization robustness by logging `MediaFailed` events, handling stale/invalid playback session size reads, and making render-target setup fail-safe with explicit success/failure returns. - Add proper native interface acquisition for DrawImageToRect, ensures acquired COM references are released correctly, detaches NaturalVideoSizeChanged on teardown, and clears frame player state during disposal to prevent leaks and stale callbacks.
- Improve LayeredBackgroundImage media handling to avoid race conditions and invalid state during video setup. - Render target initialization now fails safely and resets init state, FFmpeg source opening validates the active player before wiring it, and media-open flow now responds to natural size changes before creating the frame image. - Fix UI layering by hiding the foreground grid for static backgrounds (and restoring it for normal mode), and allows non-autoplay video to start when play was explicitly requested.
Use GameSettingsPageBase
|
|
||
| // -- Nullify _canvasImageSource so CanvasDevice and other dependencies are reinitialized too | ||
| Interlocked.Exchange(ref _canvasImageSource, null!); | ||
| InitializeRenderTarget(); | ||
| lock (_videoFrameRenderLock) | ||
| { | ||
| Interlocked.Exchange(ref _isBlockVideoFrameDraw, 1); | ||
| NullifyRenderTargetNativePointers(); | ||
| // Drop the image source only after invalidating its borrowed native pointer. | ||
| Interlocked.Exchange(ref _canvasImageSource, null!); | ||
| InitializeRenderTarget(); | ||
|
|
||
| // Try to unlock video draw progress (if a throw happened inside frame drawing routine) | ||
| Interlocked.Exchange(ref _isVideoFrameDrawInProgress, 0); | ||
| Interlocked.Exchange(ref _isVideoFrameDrawInProgress, 0); | ||
| } |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
+ Change CanvasVirtualImageSource -> CanvasImageSource + Simplify atomic check on the renderer state + Handle device lost and context lost catch correctly + Remove lock-based spin
| true); | ||
|
|
||
| _functionTableCopyFrameToVideoSurface(_videoPlayerPtr, _canvasRenderTargetAsSurfacePtr); | ||
| drawingSessionPpv = SwapChainPanelHelper | ||
| .CanvasSessionDrawUnsafe(_canvasImageSourceNativePtr, | ||
| _canvasRenderTargetNativePtr, | ||
| _functionTableBeginDraw, | ||
| _functionTableDrawImage, | ||
| in _canvasRenderSize); | ||
| } | ||
| // Device lost error. If happened, reinitialize render target | ||
| catch (COMException comEx) when ((uint)comEx.HResult is 0x887A0005u or 0x802B0020u or 0x8899000Cu) | ||
| { | ||
| DispatcherQueue.TryEnqueue(CanvasDevice_OnDeviceLost); | ||
| } | ||
| catch (COMException comEx) when ((uint)comEx.HResult is 0x88980801u) | ||
| { | ||
| // Try to unlock if any error caused by DCOMPOSITION_ERROR_SURFACE_NOT_BEING_RENDERED | ||
| Interlocked.Exchange(ref _isVideoFrameDrawInProgress, 0); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Logger.LogWriteLine($"[LayeredBackgroundImage::VideoPlayer_VideoFrameAvailableUnsafe|OtherThread] {ex}", | ||
| LogType.Error, | ||
| true); | ||
| } | ||
| finally | ||
| { | ||
| if (drawingSessionPpv != nint.Zero) | ||
| // Re-create the context and start redrawing. | ||
| _canvasImageSource?.Recreate(_canvasDevice); | ||
| goto StartDraw; | ||
| } |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
Still had issues with hard crash while trying to re-create the device context for the CanvasImageSource
|
|
||
| _functionTableCopyFrameToVideoSurface(_videoPlayerPtr, _canvasRenderTargetAsSurfacePtr); |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
The .Dispose() still require to be called from the UI thread
| try | ||
| { |
There was a problem hiding this comment.
Bug: The VideoPlayerSafe_OnVideoFrameAvailable method is missing the drawingSession?.DrawImage() call, causing the safe renderer fallback to display a blank video background.
Severity: HIGH
Suggested Fix
Restore the missing line drawingSession?.DrawImage(_canvasRenderTarget, _canvasRenderSize); in the VideoPlayerSafe_OnVideoFrameAvailable method, after the CreateDrawingSession call, to ensure the video frame is drawn to the canvas.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location:
CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage.Events.FrameRenderer.cs#L184-L185
Potential issue: In the `VideoPlayerSafe_OnVideoFrameAvailable` method, a refactoring
error resulted in the removal of the `drawingSession?.DrawImage()` call. The code now
correctly copies a video frame to the `_canvasRenderTarget` and creates a
`CanvasDrawingSession`, but it never draws the render target's content into the session.
Consequently, when the drawing session is disposed, it renders a blank, transparent
surface. This bug manifests when the application falls back to the 'safe' frame
renderer, causing the video background to be completely blank instead of displaying the
video.
Also affects:
CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage.Events.FrameRenderer.cs:211~219
Main Goal
Add declarative plugin-defined game settings support to Plugin.Core and render those settings in Collapse.
Also harden plugin integration by:
PR Status
Changelog