Skip to content

refactor(loadscreen): Refactor the single player load screen to use TheDisplay for intro video playback#2273

Open
Mauller wants to merge 2 commits intoTheSuperHackers:mainfrom
Mauller:Mauller/refactor-loadscreen-video-playback
Open

refactor(loadscreen): Refactor the single player load screen to use TheDisplay for intro video playback#2273
Mauller wants to merge 2 commits intoTheSuperHackers:mainfrom
Mauller:Mauller/refactor-loadscreen-video-playback

Conversation

@Mauller
Copy link

@Mauller Mauller commented Feb 8, 2026

Merge with rebase

This breaks out changes from #2053 that involve the refactoring of the video playback.

I split this into two commits, one with the changes to TheDisplay for adding extra functionality, the second is the load screen refactor changes.

The other changes will come along after for video scaling options and for disabling the custom overlay during video playback.


  • Replicate in generals

@Mauller Mauller self-assigned this Feb 8, 2026
@Mauller Mauller added Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Refactor Edits the code with insignificant behavior changes, is never user facing labels Feb 8, 2026
}

// if the display has a movie playing then we need to draw the displays video buffer
if (TheDisplay->isMoviePlaying())
Copy link
Author

@Mauller Mauller Feb 8, 2026

Choose a reason for hiding this comment

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

This is added in addition to the original drawing functionality as some screens still use the original method, such as the challenge load screen.

The challenge load screen does something more complex with it's video handling and needs looking at seperate from this change.

@greptile-apps
Copy link

greptile-apps bot commented Feb 8, 2026

Greptile Overview

Greptile Summary

Refactored SinglePlayerLoadScreen to use TheDisplay->playMovie() for video playback instead of manually managing VideoBuffer and VideoStreamInterface objects. This simplifies the code by delegating video resource management to the display layer.

Key changes:

  • Removed m_videoBuffer and m_videoStream member variables from SinglePlayerLoadScreen
  • Replaced manual video stream opening, buffer allocation, frame decompression, and rendering with TheDisplay->playMovie(), isMoviePlaying(), and stopMovie() calls
  • Added new overloaded drawVideoBuffer() and drawScaledVideoBuffer() methods without parameters that use internal display buffers
  • Updated W3DGameWindow to automatically render TheDisplay's video buffer when a movie is playing
  • Removed progress bar updates during video playback (previously updated based on frame count)

Note: Progress bar animation during video playback was removed as part of this refactoring. Verify this aligns with the intended user experience.

Confidence Score: 4/5

  • This PR is safe to merge with one minor consideration about user experience
  • The refactoring is well-structured and delegates video playback to the display layer as intended. The code properly removes the old video buffer management and uses the new TheDisplay API. However, the progress bar update logic during video playback was removed, which may affect user experience by removing visual feedback during loading. This should be verified as intentional.
  • LoadScreen.cpp should be verified to ensure progress bar removal during video playback was intentional

Important Files Changed

Filename Overview
GeneralsMD/Code/GameEngine/Include/GameClient/LoadScreen.h Removed m_videoBuffer and m_videoStream member variables from SinglePlayerLoadScreen class as video playback is now managed by TheDisplay
GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp Refactored SinglePlayerLoadScreen to use TheDisplay->playMovie() instead of manual video buffer management; removed progress bar updates during video playback
GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/W3DGameWindow.cpp Added code to draw TheDisplay's video buffer when a movie is playing via isMoviePlaying() check

Sequence Diagram

sequenceDiagram
    participant SP as SinglePlayerLoadScreen
    participant Display as TheDisplay
    participant WM as TheWindowManager
    participant GW as W3DGameWindow
    participant KB as TheKeyboard
    
    Note over SP: init() called
    SP->>Display: playMovie(movieLabel)
    Note over Display: Starts internal video stream<br/>and buffer management
    
    loop while isMoviePlaying()
        opt ESC key pressed
            KB->>SP: KEY_ESC detected
            SP->>SP: break loop
        end
        SP->>WM: update()
        SP->>Display: update()
        SP->>Display: draw()
        Display->>GW: W3DGameWinDefaultDraw()
        GW->>Display: isMoviePlaying() check
        GW->>Display: drawVideoBuffer(coords)
        Note over GW: Draws internal video buffer<br/>to window coordinates
    end
    
    SP->>Display: stopMovie()
    Note over Display: Cleans up internal<br/>video resources
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 502 to 522
@@ -548,51 +515,23 @@ void SinglePlayerLoadScreen::init( GameInfo *game )

TheGameEngine->serviceWindowsOS();

if(!m_videoStream->isFrameReady())
{
Sleep(1);
continue;
}

m_videoStream->frameDecompress();
m_videoStream->frameRender(m_videoBuffer);

// PULLED FROM THE MISSION DISK
// moveWindows( m_videoStream->frameIndex());

m_videoStream->frameNext();

if(m_videoBuffer)
m_loadScreen->winGetInstanceData()->setVideoBuffer(m_videoBuffer);
if(m_videoStream->frameIndex() % progressUpdateCount == 0)
{
shiftedPercent++;
if(shiftedPercent >0)
shiftedPercent = 0;
Int percent = (shiftedPercent + FRAME_FUDGE_ADD)/1.3;
UnicodeString per;
per.format(L"%d%%",percent);
TheMouse->setCursorTooltip(UnicodeString::TheEmptyString);
GadgetProgressBarSetProgress(m_progressBar, percent);
GadgetStaticTextSetText(m_percent, per);

}
TheWindowManager->update();

// redraw all views, update the GUI
TheWindowManager->update();
TheDisplay->update();
TheDisplay->draw();
}
Copy link

Choose a reason for hiding this comment

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

Progress bar update logic was removed during video playback. The old implementation updated the progress bar based on video frame count, but now the loop only checks isMoviePlaying() without updating any visual progress indicator. Check whether this removal was intentional.

Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
Line: 502:522

Comment:
Progress bar update logic was removed during video playback. The old implementation updated the progress bar based on video frame count, but now the loop only checks `isMoviePlaying()` without updating any visual progress indicator. Check whether this removal was intentional.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Author

Choose a reason for hiding this comment

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

The removal was intentional as the progress bar handling was already considered a hack and added nothing to the video playback

Copy link

Choose a reason for hiding this comment

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

It actually does show a loading bar at the bottom. Seen in USA 01 Mission Load Screen:

Image

Copy link
Author

@Mauller Mauller Feb 13, 2026

Choose a reason for hiding this comment

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

It actually does show a loading bar at the bottom. Seen in USA 01 Mission Load Screen:

Image

i know, i removed the loading bar since it doesn't really add anything and the code behind it functioning for showing the video playback is hacky. The portion of the bar that progresses while the video plays back is a small 1/20 th of the bars overall length. So seems better to just use it to report loading progress.

The window it is part of also has to be hidden when rescaled videos are played otherwise it shows behind the video.

Copy link

Choose a reason for hiding this comment

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

I think the purpose of the loading bar is to show how long the video will play? Would be good to keep it.

Copy link
Author

Choose a reason for hiding this comment

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

I think the purpose of the loading bar is to show how long the video will play? Would be good to keep it.

I can check it again but i am sure the video doesn't fill the bar during playback, it only fills a tiny portion at the beginning and the rest is filled when the rest of the game data is loading.

Copy link

Choose a reason for hiding this comment

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

If that is the case, maybe we fix the loading bar. It should be possible to calculate the loading progress because the video length is known.

Copy link

@xezon xezon left a comment

Choose a reason for hiding this comment

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

Does the loading bar in videos still work?

@Mauller
Copy link
Author

Mauller commented Feb 13, 2026

Does the loading bar in videos still work?

No i removed the video playback being part of the loading bar since the code behind it is hacky and it didn't add anything to the playback.
The window the bar is part of also needs hiding when rescaled videos are played otherwise the stretched background image shows behind the video.

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

Labels

Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker Refactor Edits the code with insignificant behavior changes, is never user facing ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants