Skip to content

Plugin Game Settings Subsystem - #900

Open
Cryotechnic wants to merge 21 commits into
mainfrom
plugin
Open

Cryotechnic wants to merge 21 commits into
mainfrom
plugin

Conversation

@Cryotechnic

@Cryotechnic Cryotechnic commented Aug 18, 2026 •

Copy link
Copy Markdown
Member

Main Goal

Add declarative plugin-defined game settings support to Plugin.Core and render those settings in Collapse.
Also harden plugin integration by:

  • Keeping the game-log callback alive throughout asynchronous game sessions.
  • Hydrating background notifications from an already-running activity’s current progress and status.
  • Correcting Wuthering Waves preload progress totals.

PR Status

  • Overall Status: Complete
  • Commits: Complete
  • Synced to base (Collapse:main): Yes
  • Build status: x64 Debug build passed
  • Crashing: None reported
  • Bugs found caused by PR: 0 reported

Changelog

  • [New] Add declarative plugin-defined game settings support to Plugin.Core and render those settings in Collapse.
  • [Fix] Keep the game-log callback alive throughout asynchronous game sessions.
  • [Fix] Initialize background notifications using the running activity’s current progress and status.
  • [Fix] Correct Wuthering Waves preload progress totals.
  • [Fix] Harden callback lifetimes and native-resource cleanup in plugin integration and background rendering.

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
@socket-security

socket-security Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

@socket-security

socket-security Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

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.

View full report

@Cryotechnic
Cryotechnic marked this pull request as ready for review September 30, 2026 16:30
@Cryotechnic Cryotechnic changed the title [DRAFT] Plugin Game Settings Subsystem Plugin Game Settings Subsystem Sep 30, 2026

@neon-nyan neon-nyan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any changes to the BG-related so far. For the game settings related, still waiting for my game to be installed first.

Comment thread CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPages/PluginGameSettingsPage.cs Outdated
public sealed partial class PluginGameSettingsPage
{
private readonly GameSettingsExtension.GameSettingsContext _context;
private readonly TextBlock _statusText = new()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment on lines 117 to 127
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.

bagusnl and others added 11 commits October 1, 2026 10:02
- 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
Comment on lines +280 to +290

// -- 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.

+ Change CanvasVirtualImageSource -> CanvasImageSource
+ Simplify atomic check on the renderer state
+ Handle device lost and context lost catch correctly
+ Remove lock-based spin
Comment on lines +129 to +134
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.

Still had issues with hard crash while trying to re-create the device context for the CanvasImageSource
Comment on lines +103 to +104

_functionTableCopyFrameToVideoSurface(_videoPlayerPtr, _canvasRenderTargetAsSurfacePtr);

This comment was marked as outdated.

The .Dispose() still require to be called from the UI thread
Comment on lines +184 to +185
try
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants