From 8e8c34f958722d6ef04740252f2a71c12cf36123 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sat, 31 Jul 2021 03:02:08 -0500 Subject: [PATCH] Added support for columns and images in outro env_credits and color overrides for both intro and outro env_credits --- sp/src/game/client/hl2/hud_credits.cpp | 331 ++++++++++++++++++++++++- 1 file changed, 323 insertions(+), 8 deletions(-) diff --git a/sp/src/game/client/hl2/hud_credits.cpp b/sp/src/game/client/hl2/hud_credits.cpp index 280e8a44..b9760712 100644 --- a/sp/src/game/client/hl2/hud_credits.cpp +++ b/sp/src/game/client/hl2/hud_credits.cpp @@ -32,6 +32,16 @@ struct creditname_t float flTimeAdd; float flTimeStart; int iSlot; + +#ifdef MAPBASE + // New credits stuff + + Color cColorOverride; + + // Images + int iImageID = -1; + float flImageScale = 1.0f; +#endif }; #define CREDITS_FILE "scripts/credits.txt" @@ -93,6 +103,10 @@ private: void DrawOutroCreditsName( void ); void DrawIntroCreditsName( void ); void DrawLogo( void ); +#ifdef MAPBASE + void DrawOutroCreditFont( const char *pCreditName, float flYPos, vgui::HFont hTFont, const Color &cColor, int iScreenWidth, int iDivisor = 2 ); + void DrawOutroCreditTexture( int iImageID, float flYPos, float flImageScale, const Color &cColor, int iScreenWidth, int iDivisor = 2 ); +#endif void PrepareLogo( float flTime ); void PrepareOutroCredits( void ); @@ -102,6 +116,10 @@ private: void PrepareLine( vgui::HFont hFont, char const *pchLine ); +#ifdef MAPBASE + int GetOrAllocateImageID( const char *szFileName ); +#endif + CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "Default" ); CPanelAnimationVar( Color, m_TextColor, "TextColor", "FgColor" ); @@ -110,7 +128,10 @@ private: float m_flScrollTime; float m_flSeparation; #ifdef MAPBASE - int m_iEndLines; + int m_iEndLines; + float m_flEndLinesFadeHoldTime; + bool m_bAllowColumns; + CUtlDict m_ImageDict; #endif float m_flFadeTime; bool m_bLastOneInPlace; @@ -202,6 +223,20 @@ void CHudCredits::Clear( void ) m_bLastOneInPlace = false; m_Alpha = m_TextColor[3]; m_iLogoState = LOGO_FADEOFF; + +#ifdef MAPBASE + if ( surface() ) + { + for (int i = m_ImageDict.Count()-1; i >= 0; i--) + { + if (m_ImageDict[i] != -1) + { + surface()->DestroyTextureID( m_ImageDict[i] ); + m_ImageDict.RemoveAt( i ); + } + } + } +#endif } //----------------------------------------------------------------------------- @@ -229,7 +264,11 @@ void CHudCredits::ReadNames( KeyValues *pKeyValue ) { creditname_t Credits; V_strcpy_safe( Credits.szCreditName, pKVNames->GetName() ); +#ifdef MAPBASE + V_strcpy_safe( Credits.szFontName, pKVNames->GetString( (const char *)NULL, "Default" ) ); +#else V_strcpy_safe( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) ); +#endif m_CreditsList.AddToTail( Credits ); pKVNames = pKVNames->GetNextKey(); @@ -248,6 +287,8 @@ void CHudCredits::ReadParams( KeyValues *pKeyValue ) m_flSeparation = pKeyValue->GetFloat( "separation", 5 ); #ifdef MAPBASE m_iEndLines = pKeyValue->GetInt( "endlines", 1 ); + m_flEndLinesFadeHoldTime = pKeyValue->GetFloat( "endlines_fadeholdtime", ( IsConsole() ? 2.0f : 10.0f ) ); // "360 certification requires that we not hold a static image too long." + m_bAllowColumns = pKeyValue->GetBool( "allow_columns", false ); #endif m_flFadeInTime = pKeyValue->GetFloat( "fadeintime", 1 ); @@ -301,9 +342,41 @@ void CHudCredits::DrawOutroCreditsName( void ) continue; vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" ); - vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName, true ); + vgui::HFont m_hTFont = INVALID_FONT; - int iFontTall = surface()->GetFontTall ( m_hTFont ); + int iFontTall = 1; + +#ifdef MAPBASE + if (pCredit->iImageID != -1) + { + // Get the size of the tallest image if there's multiple + int iFontWide; + if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" )) + { + CUtlStringList outStrings; + V_SplitString( pCredit->szCreditName, "\t", outStrings ); + FOR_EACH_VEC( outStrings, i ) + { + int iTempTall; + surface()->DrawGetTextureSize( GetOrAllocateImageID( outStrings[i] ), iFontWide, iTempTall ); + if (iTempTall > iFontTall) + iFontTall = iTempTall; + } + outStrings.PurgeAndDeleteElements(); + } + else + { + surface()->DrawGetTextureSize( GetOrAllocateImageID( pCredit->szCreditName ), iFontWide, iFontTall ); + } + + iFontTall = ((float)iFontTall * pCredit->flImageScale); + } + else +#endif + { + m_hTFont = vgui::scheme()->GetIScheme( scheme )->GetFont( pCredit->szFontName, true ); + iFontTall = surface()->GetFontTall( m_hTFont ); + } if ( pCredit->flYPos < -iFontTall || pCredit->flYPos > iTall ) { @@ -317,6 +390,9 @@ void CHudCredits::DrawOutroCreditsName( void ) Color cColor = m_TextColor; #ifdef MAPBASE + if (pCredit->cColorOverride.a() > 0) + cColor = pCredit->cColorOverride; + // Some lines should stick around and fade out if ( i >= m_CreditsList.Count()-m_iEndLines ) #else @@ -333,8 +409,12 @@ void CHudCredits::DrawOutroCreditsName( void ) { m_bLastOneInPlace = true; +#ifdef MAPBASE + m_flFadeTime = gpGlobals->curtime + m_flEndLinesFadeHoldTime; +#else // 360 certification requires that we not hold a static image too long. m_flFadeTime = gpGlobals->curtime + ( IsConsole() ? 2.0f : 10.0f ); +#endif } } else @@ -364,6 +444,50 @@ void CHudCredits::DrawOutroCreditsName( void ) if ( pCredit->bActive == false ) continue; +#ifdef MAPBASE + // Credits separated by tabs should appear divided + if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" )) + { + CUtlStringList outStrings; + V_SplitString( pCredit->szCreditName, "\t", outStrings ); + int iDivisor = 1 + outStrings.Count(); + if (pCredit->iImageID != -1) + { + FOR_EACH_VEC( outStrings, i ) + { + int iImageID = GetOrAllocateImageID( outStrings[i] ); + + // Center the image if needed + int iImageWide, iImageTall = 1; + surface()->DrawGetTextureSize( iImageID, iImageWide, iImageTall ); + if (iImageTall < iFontTall) + { + DrawOutroCreditTexture( iImageID, pCredit->flYPos + ((iFontTall * 0.5f) - (iImageTall * 0.5f)), pCredit->flImageScale, cColor, iWidth*(i + 1), iDivisor ); + } + else + { + DrawOutroCreditTexture( iImageID, pCredit->flYPos, pCredit->flImageScale, cColor, iWidth*(i + 1), iDivisor ); + } + } + } + else + { + FOR_EACH_VEC( outStrings, i ) + { + DrawOutroCreditFont( outStrings[i], pCredit->flYPos, m_hTFont, cColor, iWidth*(i + 1), iDivisor ); + } + } + outStrings.PurgeAndDeleteElements(); + } + else if (pCredit->iImageID != -1) + { + DrawOutroCreditTexture( pCredit->iImageID, pCredit->flYPos, pCredit->flImageScale, cColor, iWidth, 2 ); + } + else + { + DrawOutroCreditFont( pCredit->szCreditName, pCredit->flYPos, m_hTFont, cColor, iWidth, 2 ); + } +#else surface()->DrawSetTextFont( m_hTFont ); surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], cColor[3] ); @@ -382,9 +506,56 @@ void CHudCredits::DrawOutroCreditsName( void ) surface()->DrawSetTextPos( ( iWidth / 2 ) - ( iStringWidth / 2 ), pCredit->flYPos ); surface()->DrawUnicodeString( unicode ); +#endif } } +#ifdef MAPBASE +void CHudCredits::DrawOutroCreditFont( const char *pCreditName, float flYPos, vgui::HFont hTFont, const Color &cColor, int iScreenWidth, int iDivisor ) +{ + surface()->DrawSetTextFont( hTFont ); + surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], cColor[3] ); + + wchar_t unicode[256]; + + if ( pCreditName[0] == '#' ) + { + g_pVGuiLocalize->ConstructString( unicode, sizeof(unicode), g_pVGuiLocalize->Find(pCreditName), 0 ); + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode( pCreditName, unicode, sizeof( unicode ) ); + } + + int iStringWidth = GetStringPixelWidth( unicode, hTFont ); + + // ((iScreenWidth*iMultiplier) / iDivisor) + // When needed, just multiply iScreenWidth before sending to the function + surface()->DrawSetTextPos( (iScreenWidth / iDivisor) - (iStringWidth / 2), flYPos ); + surface()->DrawUnicodeString( unicode ); +} + +void CHudCredits::DrawOutroCreditTexture( int iImageID, float flYPos, float flImageScale, const Color &cColor, int iScreenWidth, int iDivisor ) +{ + int iImageWide, iImageTall; + surface()->DrawGetTextureSize( iImageID, iImageWide, iImageTall ); + + // Scale for resolution + flImageScale *= ((float)GetTall() / 900.0f); + + iImageWide = ((float)(iImageWide) * flImageScale); + iImageTall = ((float)(iImageTall) * flImageScale); + + iImageWide /= 2; + //iImageTall /= 2; + iScreenWidth /= iDivisor; + + surface()->DrawSetColor( cColor ); + surface()->DrawSetTexture( iImageID ); + surface()->DrawTexturedRect( iScreenWidth - iImageWide, flYPos, iScreenWidth + iImageWide, flYPos + iImageTall ); +} +#endif + void CHudCredits::DrawLogo( void ) { if( m_iLogoState == LOGO_FADEOFF ) @@ -551,7 +722,15 @@ void CHudCredits::DrawIntroCreditsName( void ) float localTime = gpGlobals->curtime - pCredit->flTimeStart; surface()->DrawSetTextFont( m_hTFont ); +#ifdef MAPBASE + Color cColor = m_cColor; + if (pCredit->cColorOverride.a() > 0) + cColor = pCredit->cColorOverride; + + surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], FadeBlend( m_flFadeInTime, m_flFadeOutTime, m_flFadeHoldTime + pCredit->flTimeAdd, localTime ) * cColor[3] ); +#else surface()->DrawSetTextColor( m_cColor[0], m_cColor[1], m_cColor[2], FadeBlend( m_flFadeInTime, m_flFadeOutTime, m_flFadeHoldTime + pCredit->flTimeAdd, localTime ) * m_cColor[3] ); +#endif wchar_t unicode[256]; g_pVGuiLocalize->ConvertANSIToUnicode( pCredit->szCreditName, unicode, sizeof( unicode ) ); @@ -693,16 +872,114 @@ void CHudCredits::PrepareOutroCredits( void ) continue; vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" ); - vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName, true ); - pCredit->flYPos = iHeight; - pCredit->bActive = false; +#ifdef MAPBASE + if (pCredit->szFontName[0] == '$') + { + if (V_strncmp( pCredit->szFontName + 1, "Image", 5 ) == 0) + { + if (pCredit->szFontName[6] == ';') + { + CUtlStringList outStrings; + V_SplitString( pCredit->szFontName, ";", outStrings ); + FOR_EACH_VEC( outStrings, i ) + { + switch (i) + { + // Get scale + case 1: + pCredit->flImageScale = atof( outStrings[i] ); + break; - iHeight += surface()->GetFontTall ( m_hTFont ) + m_flSeparation; + // Get color + case 2: + int tmp[4]; + UTIL_StringToIntArray( tmp, 4, outStrings[i] ); + pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] ); + break; + } + } + outStrings.PurgeAndDeleteElements(); + } - PrepareLine( m_hTFont, pCredit->szCreditName ); + // Get the size of the tallest image if there's multiple + int iFontWide, iFontTall = 1; + if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" )) + { + CUtlStringList outStrings; + V_SplitString( pCredit->szCreditName, "\t", outStrings ); + FOR_EACH_VEC( outStrings, i ) + { + pCredit->iImageID = GetOrAllocateImageID( outStrings[i] ); + + int iTempTall; + surface()->DrawGetTextureSize( pCredit->iImageID, iFontWide, iTempTall ); + if (iTempTall > iFontTall) + iFontTall = iTempTall; + } + outStrings.PurgeAndDeleteElements(); + } + else + { + pCredit->iImageID = GetOrAllocateImageID( pCredit->szCreditName ); + surface()->DrawGetTextureSize( pCredit->iImageID, iFontWide, iFontTall ); + } + + pCredit->flYPos = iHeight; + pCredit->bActive = false; + + iHeight += ((float)iFontTall * pCredit->flImageScale * ((float)GetTall() / 900.0f)) + m_flSeparation; + + Msg( "'%s' is image type (image scale is %f)\n", pCredit->szCreditName, pCredit->flImageScale ); + } + else + { + //Msg( "'%s' is not an image type\n", pCredit->szFontName + 1 ); + } + } + else +#endif + { +#ifdef MAPBASE + if (V_strstr( pCredit->szFontName, ";" )) + { + CUtlStringList outStrings; + V_SplitString( pCredit->szFontName, ";", outStrings ); + FOR_EACH_VEC( outStrings, i ) + { + switch (i) + { + // Get color + case 1: + int tmp[4]; + UTIL_StringToIntArray( tmp, 4, outStrings[i] ); + pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] ); + break; + } + } + + Q_strncpy( pCredit->szFontName, outStrings[0], sizeof( pCredit->szFontName ) ); + outStrings.PurgeAndDeleteElements(); + } +#endif + + vgui::HFont m_hTFont = vgui::scheme()->GetIScheme( scheme )->GetFont( pCredit->szFontName, true ); + + pCredit->flYPos = iHeight; + pCredit->bActive = false; + + iHeight += surface()->GetFontTall ( m_hTFont ) + m_flSeparation; + + PrepareLine( m_hTFont, pCredit->szCreditName ); + } } +#ifdef MAPBASE + // Check if the last line has a color override. If it does, use that as the alpha for the fadeout + if (m_CreditsList.Tail().cColorOverride.a() != 0) + m_Alpha = m_CreditsList.Tail().cColorOverride.a(); +#endif + SetActive( true ); g_iCreditsPixelHeight = iHeight; @@ -721,6 +998,29 @@ void CHudCredits::PrepareIntroCredits( void ) if ( pCredit == NULL ) continue; +#ifdef MAPBASE + if (V_strstr( pCredit->szFontName, ";" )) + { + CUtlStringList outStrings; + V_SplitString( pCredit->szFontName, ";", outStrings ); + FOR_EACH_VEC( outStrings, i ) + { + switch (i) + { + // Get color + case 1: + int tmp[4]; + UTIL_StringToIntArray( tmp, 4, outStrings[i] ); + pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] ); + break; + } + } + + Q_strncpy( pCredit->szFontName, outStrings[0], sizeof( pCredit->szFontName ) ); + outStrings.PurgeAndDeleteElements(); + } +#endif + vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" ); vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName ); @@ -749,6 +1049,21 @@ void CHudCredits::PrepareIntroCredits( void ) SetActive( true ); } +#ifdef MAPBASE +int CHudCredits::GetOrAllocateImageID( const char *szFileName ) +{ + int iIndex = m_ImageDict.Find( szFileName ); + if (iIndex == m_ImageDict.InvalidIndex()) + { + iIndex = surface()->CreateNewTextureID(); + m_ImageDict.Insert( szFileName, iIndex ); + surface()->DrawSetTextureFile( iIndex, szFileName, true, false ); + return iIndex; + } + return m_ImageDict[iIndex]; +} +#endif + void CHudCredits::MsgFunc_CreditsMsg( bf_read &msg ) { m_iCreditsType = msg.ReadByte();