garrysmod icon indicating copy to clipboard operation
garrysmod copied to clipboard

'Seamless' Singleplayer level transitions

Open DarthTealc opened this issue 4 months ago • 6 comments

Suggestion

'Seamless' level transitions for singleplayer's Source Engine level transitions, showing the freeze frame just like in the original games.

Demos

https://github.com/user-attachments/assets/38debb33-d0d9-494a-801c-ad84e5403c7e

https://github.com/user-attachments/assets/17b0492a-6832-413d-9444-6a060e00584c

HL2's d1_trainstation_02 to d1_trainstation_03 & Portal's testchmb_a_01 to testchmb_a_02

Required for functionality

The PR code would need these before merging.

  • The loading panel needs its :OnActivate() function to be given a parameter :OnActivate( transition ), which is true when the player's singleplayer game experiences a changelevel2/trigger_changelevel. This is similar to https://wiki.facepunch.com/gmod/game.MapLoadType
  • Menu-state needs a function engine.GetLastFrame(), which returns a material of the final frame rendered prior to loading, excluding the hud/vgui/etc.
How the demo gameplay works without that functionality
  • To work around :OnActivate( transition ) not currently being provided that flag - transition = true was added.
  • To work around engine.GetLastFrame() not currently existing - A specific texture is updated every PreDrawHUD clientside, which stops getting updated when rendering stops and is therefore frozen at the final frame, and in menustate a dummy GetLastFrame() returns a material of that texture.

DarthTealc avatar Dec 08 '25 00:12 DarthTealc

you can draw a level transition LOADING panel near identical to vanilla hl2 with

        local panelH = h * 0.0667
        local panelW = panelH * 2.625
        local panelX = (w - panelW) / 2
        local panelY = (h - panelH) / 2
        local cornerRadius = math.max( 8, math.floor( panelH * 0.15 ) )
        
        -- Panel background with rounded corners
        draw.RoundedBox( cornerRadius, panelX, panelY, panelW, panelH, Color( 0, 0, 0, 76 ) )
        
        -- Loading text
        surface.SetFont( "HudDefault" )
        local text = "LOADING"
        local tw, th = surface.GetTextSize( text )
        surface.SetTextColor( 255, 255, 255, 255 )
        surface.SetTextPos( panelX + (panelW - tw) / 2, panelY + (panelH - th) / 2 )
        surface.DrawText( text )

you can have localised text with the already existing #GameUI_LoadingGame

Xenthio avatar Dec 10 '25 05:12 Xenthio

Thanks @Xenthio - added and confirmed it matches HL2's dimensions/position

This PR in Gmod @ 1920x1080 image

Half Life 2 anniversary edition @ 1920x1080 image

DarthTealc avatar Dec 11 '25 12:12 DarthTealc

Thanks @Xenthio - added and confirmed it matches HL2's dimensions/position

This PR in Gmod @ 1920x1080 image

Half Life 2 anniversary edition @ 1920x1080 image

the text should appear identical to pre anniversary edition half-life 2

Xenthio avatar Dec 11 '25 21:12 Xenthio

Confirmed, the text matches pre-anniversary perfectly. via "steam_legacy" branch.

(Animated) alternating between HL2 and Gmod

Half Life 2 pre-Anniversary "steam_legacy" @ 1920x1080 HL2 screenshot

DarthTealc avatar Dec 12 '25 05:12 DarthTealc

Maybe you might want to separate the loading bubble to avoid this PR becoming stuck. I am not sure if Rubat would like this given that loading bubble had been removed from GMod a long time ago. I like that bubble change, though.

Grocel avatar Dec 14 '25 01:12 Grocel

The bubble commit can be reverted during merge without impacting the rest of the PR. Rubat can decide. If kept, it only shows on singleplayer's Source level transitions, doesn't show on any other loading type.

DarthTealc avatar Dec 14 '25 09:12 DarthTealc