Added support for displaying multiple screen overlays at the same time

This commit is contained in:
Blixibon 2021-09-20 22:38:49 -05:00
parent f278491d86
commit fc93d736ee
6 changed files with 216 additions and 2 deletions

View File

@ -48,6 +48,9 @@ protected:
int m_iCachedDesiredOverlay;
int m_iCurrentOverlay;
float m_flCurrentOverlayTime;
#ifdef MAPBASE
int m_iOverlayIndex;
#endif
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOverlay )
@ -56,6 +59,9 @@ IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOve
RecvPropFloat( RECVINFO( m_flStartTime ) ),
RecvPropInt( RECVINFO( m_iDesiredOverlay ) ),
RecvPropBool( RECVINFO( m_bIsActive ) ),
#ifdef MAPBASE
RecvPropInt( RECVINFO( m_iOverlayIndex ) ),
#endif
END_RECV_TABLE()
//-----------------------------------------------------------------------------
@ -77,7 +83,11 @@ void C_EnvScreenOverlay::PostDataUpdate( DataUpdateType_t updateType )
BaseClass::PostDataUpdate( updateType );
// If we have a start time now, start the overlays going
#ifdef MAPBASE
if ( m_bIsActive && m_flStartTime > 0 && (view->GetScreenOverlayMaterial() == NULL || (m_iOverlayIndex != -1 && view->GetIndexedScreenOverlayMaterial(m_iOverlayIndex) == NULL)) )
#else
if ( m_bIsActive && m_flStartTime > 0 && view->GetScreenOverlayMaterial() == NULL )
#endif
{
StartOverlays();
}
@ -111,7 +121,16 @@ void C_EnvScreenOverlay::StopOverlays( void )
if ( m_bWasActive && !m_bIsActive )
{
view->SetScreenOverlayMaterial( NULL );
#ifdef MAPBASE
if (m_iOverlayIndex != -1)
{
view->SetIndexedScreenOverlayMaterial( m_iOverlayIndex, NULL );
}
else
#endif
{
view->SetScreenOverlayMaterial( NULL );
}
}
}
@ -163,7 +182,16 @@ void C_EnvScreenOverlay::StartCurrentOverlay( void )
IMaterial *pMaterial = materials->FindMaterial( m_iszOverlayNames[m_iCurrentOverlay], TEXTURE_GROUP_CLIENT_EFFECTS, false );
if ( !IsErrorMaterial( pMaterial ) )
{
view->SetScreenOverlayMaterial( pMaterial );
#ifdef MAPBASE
if (m_iOverlayIndex != -1)
{
view->SetIndexedScreenOverlayMaterial( m_iOverlayIndex, pMaterial );
}
else
#endif
{
view->SetScreenOverlayMaterial( pMaterial );
}
}
else
{

View File

@ -115,6 +115,13 @@ public:
virtual void SetScreenOverlayMaterial( IMaterial *pMaterial ) = 0;
virtual IMaterial *GetScreenOverlayMaterial( ) = 0;
#ifdef MAPBASE
virtual void SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial ) = 0;
virtual IMaterial *GetIndexedScreenOverlayMaterial( int i ) = 0;
virtual void ResetIndexedScreenOverlays() = 0;
virtual int GetMaxIndexedScreenOverlays() const = 0;
#endif
virtual void WriteSaveGameScreenshot( const char *pFilename ) = 0;
virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded = false, bool bWriteVTF = false ) = 0;

View File

@ -655,6 +655,57 @@ CON_COMMAND_F( r_screenoverlay, "Draw specified material as an overlay", FCVAR_C
}
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// The same as above, but using the new indexed overlays
//-----------------------------------------------------------------------------
CON_COMMAND_F( r_screenoverlay_indexed, "Draw specified material as an overlay in the specified index", FCVAR_CHEAT|FCVAR_SERVER_CAN_EXECUTE )
{
if( args.ArgC() == 3 )
{
int index = atoi( args[1] );
if (index < 0 || index >= MAX_SCREEN_OVERLAYS)
{
Warning( "r_screenoverlay_indexed: '%i' is out of range (should be 0-9)\n", index );
return;
}
if ( !Q_stricmp( "off", args[2] ) )
{
view->SetIndexedScreenOverlayMaterial( index, NULL );
}
else
{
IMaterial *pMaterial = materials->FindMaterial( args[2], TEXTURE_GROUP_OTHER, false );
if ( !IsErrorMaterial( pMaterial ) )
{
view->SetIndexedScreenOverlayMaterial( index, pMaterial );
}
else
{
view->SetIndexedScreenOverlayMaterial( index, NULL );
}
}
}
else if ( args.ArgC() == 2 )
{
int index = atoi( args[1] );
if (index < 0 || index >= MAX_SCREEN_OVERLAYS)
{
Warning( "r_screenoverlay_indexed: '%i' is out of range (should be 0-9)\n", index );
return;
}
IMaterial *pMaterial = view->GetIndexedScreenOverlayMaterial( index );
Warning( "r_screenoverlay_indexed %i: %s\n", index, pMaterial ? pMaterial->GetName() : "off" );
}
else
{
Warning( "Format: r_screenoverlay_indexed <index> <material> %s\n" );
}
}
#endif
// Used to verify frame syncing.
void CDebugViewRender::GenerateOverdrawForTesting()
{

View File

@ -1218,6 +1218,73 @@ IMaterial *CViewRender::GetScreenOverlayMaterial( )
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Sets the screen space effect material (can't be done during rendering)
//-----------------------------------------------------------------------------
void CViewRender::SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial )
{
if (i < 0 || i >= MAX_SCREEN_OVERLAYS)
return;
m_IndexedScreenOverlayMaterials[i].Init( pMaterial );
if (pMaterial == NULL)
{
// Check if we should set to false
int i;
for (i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
if (m_IndexedScreenOverlayMaterials[i] != NULL)
break;
}
if (i == MAX_SCREEN_OVERLAYS)
m_bUsingIndexedScreenOverlays = false;
}
else
{
m_bUsingIndexedScreenOverlays = true;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
IMaterial *CViewRender::GetIndexedScreenOverlayMaterial( int i )
{
if (i < 0 || i >= MAX_SCREEN_OVERLAYS)
return NULL;
return m_IndexedScreenOverlayMaterials[i];
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CViewRender::ResetIndexedScreenOverlays()
{
for (int i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
m_IndexedScreenOverlayMaterials[i].Init( NULL );
}
m_bUsingIndexedScreenOverlays = false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CViewRender::GetMaxIndexedScreenOverlays( ) const
{
return MAX_SCREEN_OVERLAYS;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Performs screen space effects, if any
//-----------------------------------------------------------------------------
@ -1254,6 +1321,44 @@ void CViewRender::PerformScreenOverlay( int x, int y, int w, int h )
render->ViewDrawFade( color, m_ScreenOverlayMaterial );
}
}
#ifdef MAPBASE
if (m_bUsingIndexedScreenOverlays)
{
for (int i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
if (!m_IndexedScreenOverlayMaterials[i])
continue;
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
if ( m_IndexedScreenOverlayMaterials[i]->NeedsFullFrameBufferTexture() )
{
// FIXME: check with multi/sub-rect renders. Should this be 0,0,w,h instead?
DrawScreenEffectMaterial( m_IndexedScreenOverlayMaterials[i], x, y, w, h );
}
else if ( m_IndexedScreenOverlayMaterials[i]->NeedsPowerOfTwoFrameBufferTexture() )
{
// First copy the FB off to the offscreen texture
UpdateRefractTexture( x, y, w, h, true );
// Now draw the entire screen using the material...
CMatRenderContextPtr pRenderContext( materials );
ITexture *pTexture = GetPowerOfTwoFrameBufferTexture( );
int sw = pTexture->GetActualWidth();
int sh = pTexture->GetActualHeight();
// Note - don't offset by x,y - already done by the viewport.
pRenderContext->DrawScreenSpaceRectangle( m_IndexedScreenOverlayMaterials[i], 0, 0, w, h,
0, 0, sw-1, sh-1, sw, sh );
}
else
{
byte color[4] = { 255, 255, 255, 255 };
render->ViewDrawFade( color, m_IndexedScreenOverlayMaterials[i] );
}
}
}
#endif
}
void CViewRender::DrawUnderwaterOverlay( void )

View File

@ -468,6 +468,13 @@ private:
IMaterial *GetScreenOverlayMaterial( );
void PerformScreenOverlay( int x, int y, int w, int h );
#ifdef MAPBASE
void SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial );
IMaterial *GetIndexedScreenOverlayMaterial( int i );
void ResetIndexedScreenOverlays();
int GetMaxIndexedScreenOverlays() const;
#endif
void DrawUnderwaterOverlay( void );
// Water-related methods
@ -511,6 +518,10 @@ private:
CMaterialReference m_TranslucentSingleColor;
CMaterialReference m_ModulateSingleColor;
CMaterialReference m_ScreenOverlayMaterial;
#ifdef MAPBASE
CMaterialReference m_IndexedScreenOverlayMaterials[MAX_SCREEN_OVERLAYS];
bool m_bUsingIndexedScreenOverlays;
#endif
CMaterialReference m_UnderWaterOverlayMaterial;
Vector m_vecLastFacing;

View File

@ -39,6 +39,9 @@ protected:
CNetworkVar( float, m_flStartTime );
CNetworkVar( int, m_iDesiredOverlay );
CNetworkVar( bool, m_bIsActive );
#ifdef MAPBASE
CNetworkVar( int, m_iOverlayIndex );
#endif
};
LINK_ENTITY_TO_CLASS( env_screenoverlay, CEnvScreenOverlay );
@ -74,6 +77,9 @@ BEGIN_DATADESC( CEnvScreenOverlay )
DEFINE_FIELD( m_iDesiredOverlay, FIELD_INTEGER ),
DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
DEFINE_FIELD( m_bIsActive, FIELD_BOOLEAN ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_iOverlayIndex, FIELD_INTEGER, "OverlayIndex" ),
#endif
DEFINE_INPUTFUNC( FIELD_VOID, "StartOverlays", InputStartOverlay ),
DEFINE_INPUTFUNC( FIELD_VOID, "StopOverlays", InputStopOverlay ),
@ -93,6 +99,9 @@ IMPLEMENT_SERVERCLASS_ST( CEnvScreenOverlay, DT_EnvScreenOverlay )
SendPropFloat( SENDINFO( m_flStartTime ), 32, SPROP_NOSCALE ),
SendPropInt( SENDINFO( m_iDesiredOverlay ), 5 ),
SendPropBool( SENDINFO( m_bIsActive ) ),
#ifdef MAPBASE
SendPropInt( SENDINFO( m_iOverlayIndex ), 5 ),
#endif
END_SEND_TABLE()
//-----------------------------------------------------------------------------
@ -103,6 +112,9 @@ CEnvScreenOverlay::CEnvScreenOverlay( void )
m_flStartTime = 0;
m_iDesiredOverlay = 0;
m_bIsActive = false;
#ifdef MAPBASE
m_iOverlayIndex = -1;
#endif
}
//-----------------------------------------------------------------------------