You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1292 lines
35 KiB
1292 lines
35 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
|
|
#include "cbase.h" |
|
|
|
#include "ienginevgui.h" |
|
#include <vgui_controls/ScrollBarSlider.h> |
|
#include "vgui/ILocalize.h" |
|
#include "vgui/ISurface.h" |
|
#include "vgui/IInput.h" |
|
#include "tf_controls.h" |
|
#include "vgui_controls/TextImage.h" |
|
#include "vgui_controls/PropertyPage.h" |
|
#include "econ_item_system.h" |
|
#include "iachievementmgr.h" |
|
#include <vgui_controls/ListPanel.h> |
|
#include <vgui_controls/PanelListPanel.h> |
|
#include <vgui_controls/Label.h> |
|
#include <vgui_controls/Button.h> |
|
#include <vgui_controls/MessageBox.h> |
|
#include <vgui_controls/CheckButton.h> |
|
#include <vgui_controls/ComboBox.h> |
|
#include <vgui_controls/TextEntry.h> |
|
#include <../common/GameUI/cvarslider.h> |
|
#include "filesystem.h" |
|
|
|
using namespace vgui; |
|
|
|
wchar_t* LocalizeNumberWithToken( const char* pszLocToken, int nValue ) |
|
{ |
|
static wchar_t wszOutString[ 128 ]; |
|
wchar_t wszCount[ 16 ]; |
|
_snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", nValue ); |
|
const wchar_t *wpszFormat = g_pVGuiLocalize->Find( pszLocToken ); |
|
g_pVGuiLocalize->ConstructString_safe( wszOutString, wpszFormat, 1, wszCount ); |
|
|
|
return wszOutString; |
|
} |
|
|
|
DECLARE_BUILD_FACTORY( CExCheckButton ); |
|
DECLARE_BUILD_FACTORY( CTFFooter ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Xbox-specific panel that displays button icons text labels |
|
//----------------------------------------------------------------------------- |
|
CTFFooter::CTFFooter( Panel *parent, const char *panelName ) : BaseClass( parent, panelName ) |
|
{ |
|
SetVisible( true ); |
|
SetAlpha( 0 ); |
|
|
|
m_nButtonGap = 32; |
|
m_ButtonPinRight = 100; |
|
m_FooterTall = 80; |
|
|
|
m_ButtonOffsetFromTop = 0; |
|
m_ButtonSeparator = 4; |
|
m_TextAdjust = 0; |
|
|
|
m_bPaintBackground = false; |
|
m_bCenterHorizontal = true; |
|
|
|
m_szButtonFont[0] = '\0'; |
|
m_szTextFont[0] = '\0'; |
|
m_szFGColor[0] = '\0'; |
|
m_szBGColor[0] = '\0'; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFFooter::~CTFFooter() |
|
{ |
|
ClearButtons(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFooter::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
m_hButtonFont = pScheme->GetFont( ( m_szButtonFont[0] != '\0' ) ? m_szButtonFont : "GameUIButtons" ); |
|
m_hTextFont = pScheme->GetFont( ( m_szTextFont[0] != '\0' ) ? m_szTextFont : "MenuLarge" ); |
|
|
|
SetFgColor( pScheme->GetColor( m_szFGColor, Color( 255, 255, 255, 255 ) ) ); |
|
SetBgColor( pScheme->GetColor( m_szBGColor, Color( 0, 0, 0, 255 ) ) ); |
|
|
|
int x, y, w, h; |
|
GetParent()->GetBounds( x, y, w, h ); |
|
SetBounds( x, h - m_FooterTall, w, m_FooterTall ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFooter::ApplySettings( KeyValues *inResourceData ) |
|
{ |
|
BaseClass::ApplySettings( inResourceData ); |
|
|
|
// gap between hints |
|
m_nButtonGap = inResourceData->GetInt( "buttongap", 32 ); |
|
m_ButtonPinRight = inResourceData->GetInt( "button_pin_right", 100 ); |
|
m_FooterTall = inResourceData->GetInt( "tall", 80 ); |
|
m_ButtonOffsetFromTop = inResourceData->GetInt( "buttonoffsety", 0 ); |
|
m_ButtonSeparator = inResourceData->GetInt( "button_separator", 4 ); |
|
m_TextAdjust = inResourceData->GetInt( "textadjust", 0 ); |
|
|
|
m_bCenterHorizontal = ( inResourceData->GetInt( "center", 1 ) == 1 ); |
|
m_bPaintBackground = ( inResourceData->GetInt( "paintbackground", 0 ) == 1 ); |
|
|
|
// fonts for text and button |
|
Q_strncpy( m_szTextFont, inResourceData->GetString( "fonttext", "MenuLarge" ), sizeof( m_szTextFont ) ); |
|
Q_strncpy( m_szButtonFont, inResourceData->GetString( "fontbutton", "GameUIButtons" ), sizeof( m_szButtonFont ) ); |
|
|
|
// fg and bg colors |
|
Q_strncpy( m_szFGColor, inResourceData->GetString( "fgcolor", "White" ), sizeof( m_szFGColor ) ); |
|
Q_strncpy( m_szBGColor, inResourceData->GetString( "bgcolor", "Black" ), sizeof( m_szBGColor ) ); |
|
|
|
// clear the buttons because we're going to re-add them here |
|
ClearButtons(); |
|
|
|
for ( KeyValues *pButton = inResourceData->GetFirstSubKey(); pButton != NULL; pButton = pButton->GetNextKey() ) |
|
{ |
|
const char *pNameButton = pButton->GetName(); |
|
|
|
if ( !Q_stricmp( pNameButton, "button" ) ) |
|
{ |
|
// Add a button to the footer |
|
const char *pName = pButton->GetString( "name", "NULL" ); |
|
const char *pText = pButton->GetString( "text", "NULL" ); |
|
const char *pIcon = pButton->GetString( "icon", "NULL" ); |
|
AddNewButtonLabel( pName, pText, pIcon ); |
|
} |
|
} |
|
|
|
InvalidateLayout( false, true ); // force ApplySchemeSettings to run |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFooter::AddNewButtonLabel( const char *name, const char *text, const char *icon ) |
|
{ |
|
FooterButton_t *button = new FooterButton_t; |
|
|
|
button->bVisible = true; |
|
Q_strncpy( button->name, name, sizeof( button->name ) ); |
|
|
|
// Button icons are a single character |
|
wchar_t *pIcon = g_pVGuiLocalize->Find( icon ); |
|
if ( pIcon ) |
|
{ |
|
button->icon[0] = pIcon[0]; |
|
button->icon[1] = '\0'; |
|
} |
|
else |
|
{ |
|
button->icon[0] = '\0'; |
|
} |
|
|
|
// Set the help text |
|
wchar_t *pText = g_pVGuiLocalize->Find( text ); |
|
if ( pText ) |
|
{ |
|
wcsncpy( button->text, pText, wcslen( pText ) + 1 ); |
|
} |
|
else |
|
{ |
|
button->text[0] = '\0'; |
|
} |
|
|
|
m_Buttons.AddToTail( button ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFooter::ShowButtonLabel( const char *name, bool show ) |
|
{ |
|
for ( int i = 0; i < m_Buttons.Count(); ++i ) |
|
{ |
|
if ( !Q_stricmp( m_Buttons[ i ]->name, name ) ) |
|
{ |
|
m_Buttons[ i ]->bVisible = show; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFooter::PaintBackground( void ) |
|
{ |
|
if ( !m_bPaintBackground ) |
|
return; |
|
|
|
BaseClass::PaintBackground(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFooter::Paint( void ) |
|
{ |
|
// inset from right edge |
|
int wide = GetWide(); |
|
|
|
// center the text within the button |
|
int buttonHeight = vgui::surface()->GetFontTall( m_hButtonFont ); |
|
int fontHeight = vgui::surface()->GetFontTall( m_hTextFont ); |
|
int textY = ( buttonHeight - fontHeight )/2 + m_TextAdjust; |
|
|
|
if ( textY < 0 ) |
|
{ |
|
textY = 0; |
|
} |
|
|
|
int y = m_ButtonOffsetFromTop; |
|
|
|
if ( !m_bCenterHorizontal ) |
|
{ |
|
// draw the buttons, right to left |
|
int x = wide - m_ButtonPinRight; |
|
|
|
vgui::Label label( this, "temp", L"" ); |
|
for ( int i = m_Buttons.Count() - 1 ; i >= 0 ; --i ) |
|
{ |
|
FooterButton_t *pButton = m_Buttons[i]; |
|
if ( !pButton->bVisible ) |
|
continue; |
|
|
|
// Get the string length |
|
label.SetFont( m_hTextFont ); |
|
label.SetText( pButton->text ); |
|
label.SizeToContents(); |
|
|
|
int iTextWidth = label.GetWide(); |
|
|
|
if ( iTextWidth == 0 ) |
|
x += m_nButtonGap; // There's no text, so remove the gap between buttons |
|
else |
|
x -= iTextWidth; |
|
|
|
// Draw the string |
|
vgui::surface()->DrawSetTextFont( m_hTextFont ); |
|
vgui::surface()->DrawSetTextColor( GetFgColor() ); |
|
vgui::surface()->DrawSetTextPos( x, y + textY ); |
|
vgui::surface()->DrawPrintText( pButton->text, wcslen( pButton->text ) ); |
|
|
|
// Draw the button |
|
// back up button width and a little extra to leave a gap between button and text |
|
x -= ( vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] ) + m_ButtonSeparator ); |
|
vgui::surface()->DrawSetTextFont( m_hButtonFont ); |
|
vgui::surface()->DrawSetTextColor( 255, 255, 255, 255 ); |
|
vgui::surface()->DrawSetTextPos( x, y ); |
|
vgui::surface()->DrawPrintText( pButton->icon, 1 ); |
|
|
|
// back up to next string |
|
x -= m_nButtonGap; |
|
} |
|
} |
|
else |
|
{ |
|
// center the buttons (as a group) |
|
int x = wide / 2; |
|
int totalWidth = 0; |
|
int i = 0; |
|
int nButtonCount = 0; |
|
|
|
vgui::Label label( this, "temp", L"" ); |
|
|
|
// need to loop through and figure out how wide our buttons and text are (with gaps between) so we can offset from the center |
|
for ( i = 0; i < m_Buttons.Count(); ++i ) |
|
{ |
|
FooterButton_t *pButton = m_Buttons[i]; |
|
|
|
if ( !pButton->bVisible ) |
|
continue; |
|
|
|
// Get the string length |
|
label.SetFont( m_hTextFont ); |
|
label.SetText( pButton->text ); |
|
label.SizeToContents(); |
|
|
|
totalWidth += vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] ); |
|
totalWidth += m_ButtonSeparator; |
|
totalWidth += label.GetWide(); |
|
|
|
nButtonCount++; // keep track of how many active buttons we'll be drawing |
|
} |
|
|
|
totalWidth += ( nButtonCount - 1 ) * m_nButtonGap; // add in the gaps between the buttons |
|
x -= ( totalWidth / 2 ); |
|
|
|
for ( i = 0; i < m_Buttons.Count(); ++i ) |
|
{ |
|
FooterButton_t *pButton = m_Buttons[i]; |
|
|
|
if ( !pButton->bVisible ) |
|
continue; |
|
|
|
// Get the string length |
|
label.SetFont( m_hTextFont ); |
|
label.SetText( pButton->text ); |
|
label.SizeToContents(); |
|
|
|
int iTextWidth = label.GetWide(); |
|
|
|
// Draw the icon |
|
vgui::surface()->DrawSetTextFont( m_hButtonFont ); |
|
vgui::surface()->DrawSetTextColor( 255, 255, 255, 255 ); |
|
vgui::surface()->DrawSetTextPos( x, y ); |
|
vgui::surface()->DrawPrintText( pButton->icon, 1 ); |
|
x += vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] ) + m_ButtonSeparator; |
|
|
|
// Draw the string |
|
vgui::surface()->DrawSetTextFont( m_hTextFont ); |
|
vgui::surface()->DrawSetTextColor( GetFgColor() ); |
|
vgui::surface()->DrawSetTextPos( x, y + textY ); |
|
vgui::surface()->DrawPrintText( pButton->text, wcslen( pButton->text ) ); |
|
|
|
x += iTextWidth + m_nButtonGap; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFooter::ClearButtons( void ) |
|
{ |
|
m_Buttons.PurgeAndDeleteElements(); |
|
} |
|
|
|
#define OPTIONS_DIR "cfg" |
|
#define DEFAULT_OPTIONS_FILE OPTIONS_DIR "/user_default.scr" |
|
#define OPTIONS_FILE OPTIONS_DIR "/user.scr" |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CTFAdvancedOptionsDialog::CTFAdvancedOptionsDialog(vgui::Panel *parent) : BaseClass(NULL, "TFAdvancedOptionsDialog") |
|
{ |
|
// Need to use the clientscheme (we're not parented to a clientscheme'd panel) |
|
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme"); |
|
SetScheme(scheme); |
|
SetProportional( true ); |
|
|
|
m_pListPanel = new vgui::PanelListPanel( this, "PanelListPanel" ); |
|
|
|
m_pList = NULL; |
|
|
|
m_pToolTip = new CTFTextToolTip( this ); |
|
m_pToolTipEmbeddedPanel = new vgui::EditablePanel( this, "TooltipPanel" ); |
|
m_pToolTipEmbeddedPanel->SetKeyBoardInputEnabled( false ); |
|
m_pToolTipEmbeddedPanel->SetMouseInputEnabled( false ); |
|
m_pToolTip->SetEmbeddedPanel( m_pToolTipEmbeddedPanel ); |
|
m_pToolTip->SetTooltipDelay( 0 ); |
|
|
|
m_pDescription = new CInfoDescription(); |
|
m_pDescription->InitFromFile( DEFAULT_OPTIONS_FILE ); |
|
m_pDescription->InitFromFile( OPTIONS_FILE, false ); |
|
m_pDescription->TransferCurrentValues( NULL ); |
|
|
|
// MoveToCenterOfScreen(); |
|
// SetSizeable( false ); |
|
// SetDeleteSelfOnClose( true ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Destructor |
|
//----------------------------------------------------------------------------- |
|
CTFAdvancedOptionsDialog::~CTFAdvancedOptionsDialog() |
|
{ |
|
delete m_pDescription; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
LoadControlSettings("resource/ui/TFAdvancedOptionsDialog.res"); |
|
m_pListPanel->SetFirstColumnWidth( 0 ); |
|
|
|
CreateControls(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::ApplySettings( KeyValues *inResourceData ) |
|
{ |
|
BaseClass::ApplySettings( inResourceData ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::OnClose() |
|
{ |
|
BaseClass::OnClose(); |
|
|
|
TFModalStack()->PopModal( this ); |
|
MarkForDeletion(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *command - |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::OnCommand( const char *command ) |
|
{ |
|
if ( !stricmp( command, "Ok" ) ) |
|
{ |
|
// OnApplyChanges(); |
|
SaveValues(); |
|
OnClose(); |
|
return; |
|
} |
|
else if ( !stricmp( command, "Close" ) ) |
|
{ |
|
OnClose(); |
|
return; |
|
} |
|
|
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
void CTFAdvancedOptionsDialog::OnKeyCodeTyped(KeyCode code) |
|
{ |
|
// force ourselves to be closed if the escape key it pressed |
|
if ( code == KEY_ESCAPE ) |
|
{ |
|
OnClose(); |
|
} |
|
else |
|
{ |
|
BaseClass::OnKeyCodeTyped(code); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::OnKeyCodePressed(KeyCode code) |
|
{ |
|
// force ourselves to be closed if the escape key it pressed |
|
if ( GetBaseButtonCode( code ) == KEY_XBUTTON_B || GetBaseButtonCode( code ) == STEAMCONTROLLER_B || GetBaseButtonCode( code ) == STEAMCONTROLLER_START ) |
|
{ |
|
OnClose(); |
|
} |
|
else |
|
{ |
|
BaseClass::OnKeyCodePressed(code); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::GatherCurrentValues() |
|
{ |
|
if ( !m_pDescription ) |
|
return; |
|
|
|
// OK |
|
CheckButton *pBox; |
|
TextEntry *pEdit; |
|
ComboBox *pCombo; |
|
CCvarSlider *pSlider; |
|
|
|
mpcontrol_t *pList; |
|
|
|
CScriptObject *pObj; |
|
CScriptListItem *pItem; |
|
|
|
char szValue[256]; |
|
char strValue[ 256 ]; |
|
|
|
pList = m_pList; |
|
while ( pList ) |
|
{ |
|
pObj = pList->pScrObj; |
|
|
|
if ( pObj->type == O_CATEGORY ) |
|
{ |
|
pList = pList->next; |
|
continue; |
|
} |
|
|
|
if ( !pList->pControl ) |
|
{ |
|
pObj->SetCurValue( pObj->defValue ); |
|
pList = pList->next; |
|
continue; |
|
} |
|
|
|
switch ( pObj->type ) |
|
{ |
|
case O_BOOL: |
|
pBox = (CheckButton *)pList->pControl; |
|
sprintf( szValue, "%s", pBox->IsSelected() ? "1" : "0" ); |
|
break; |
|
case O_NUMBER: |
|
pEdit = ( TextEntry * )pList->pControl; |
|
pEdit->GetText( strValue, sizeof( strValue ) ); |
|
sprintf( szValue, "%s", strValue ); |
|
break; |
|
case O_STRING: |
|
pEdit = ( TextEntry * )pList->pControl; |
|
pEdit->GetText( strValue, sizeof( strValue ) ); |
|
sprintf( szValue, "%s", strValue ); |
|
break; |
|
case O_LIST: |
|
{ |
|
pCombo = (ComboBox *)pList->pControl; |
|
// pCombo->GetText( strValue, sizeof( strValue ) ); |
|
int activeItem = pCombo->GetActiveItem(); |
|
|
|
pItem = pObj->pListItems; |
|
// int n = (int)pObj->fdefValue; |
|
|
|
while ( pItem ) |
|
{ |
|
if (!activeItem--) |
|
break; |
|
|
|
pItem = pItem->pNext; |
|
} |
|
|
|
if ( pItem ) |
|
{ |
|
sprintf( szValue, "%s", pItem->szValue ); |
|
} |
|
else // Couln't find index |
|
{ |
|
//assert(!("Couldn't find string in list, using default value")); |
|
sprintf( szValue, "%s", pObj->defValue ); |
|
} |
|
break; |
|
} |
|
case O_SLIDER: |
|
pSlider = ( CCvarSlider * )pList->pControl; |
|
sprintf( szValue, "%.2f", pSlider->GetSliderValue() ); |
|
break; |
|
} |
|
|
|
// Remove double quotes and % characters |
|
UTIL_StripInvalidCharacters( szValue, sizeof(szValue) ); |
|
|
|
V_strcpy_safe( strValue, szValue ); |
|
|
|
pObj->SetCurValue( strValue ); |
|
|
|
pList = pList->next; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::CreateControls() |
|
{ |
|
DestroyControls(); |
|
|
|
// Go through desciption creating controls |
|
CScriptObject *pObj; |
|
|
|
pObj = m_pDescription->pObjList; |
|
|
|
// Build out the clan dropdown |
|
CScriptObject *pClanObj = m_pDescription->FindObject( "cl_clanid" ); |
|
ISteamFriends *pFriends = steamapicontext->SteamFriends(); |
|
if ( pFriends && pClanObj ) |
|
{ |
|
pClanObj->RemoveAndDeleteAllItems(); |
|
int iGroupCount = pFriends->GetClanCount(); |
|
pClanObj->AddItem( new CScriptListItem( "#Cstrike_ClanTag_None", "0" ) ); |
|
for ( int k = 0; k < iGroupCount; ++ k ) |
|
{ |
|
CSteamID clanID = pFriends->GetClanByIndex( k ); |
|
const char *pName = pFriends->GetClanName( clanID ); |
|
const char *pTag = pFriends->GetClanTag( clanID ); |
|
|
|
char id[12]; |
|
Q_snprintf( id, sizeof( id ), "%d", clanID.GetAccountID() ); |
|
pClanObj->AddItem( new CScriptListItem( CFmtStr( "%s (%s)", pTag, pName ), id ) ); |
|
} |
|
} |
|
|
|
mpcontrol_t *pCtrl; |
|
|
|
CheckButton *pBox; |
|
TextEntry *pEdit; |
|
ComboBox *pCombo; |
|
CCvarSlider *pSlider; |
|
CScriptListItem *pListItem; |
|
|
|
Panel *objParent = m_pListPanel; |
|
|
|
IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); |
|
vgui::HFont hTextFont = pScheme->GetFont( "HudFontSmallestBold", true ); |
|
Color tanDark = pScheme->GetColor( "TanDark", Color(255,0,0,255) ); |
|
|
|
while ( pObj ) |
|
{ |
|
if ( pObj->type == O_OBSOLETE ) |
|
{ |
|
pObj = pObj->pNext; |
|
continue; |
|
} |
|
|
|
pCtrl = new mpcontrol_t( objParent, "mpcontrol_t" ); |
|
pCtrl->type = pObj->type; |
|
|
|
// Force it to invalidate scheme now, so we can change color afterwards and have it persist |
|
pCtrl->InvalidateLayout( true, true ); |
|
|
|
switch ( pCtrl->type ) |
|
{ |
|
case O_BOOL: |
|
pBox = new CheckButton( pCtrl, "DescCheckButton", pObj->prompt ); |
|
pBox->SetSelected( pObj->fdefValue != 0.0f ? true : false ); |
|
|
|
pCtrl->pControl = (Panel *)pBox; |
|
pBox->SetFont( hTextFont ); |
|
|
|
pBox->InvalidateLayout( true, true ); |
|
|
|
// This is utterly fucking retarded. |
|
pBox->SetFgColor( tanDark ); |
|
pBox->SetDefaultColor( tanDark, pBox->GetBgColor() ); |
|
pBox->SetArmedColor( tanDark, pBox->GetBgColor() ); |
|
pBox->SetDepressedColor( tanDark, pBox->GetBgColor() ); |
|
pBox->SetSelectedColor( tanDark, pBox->GetBgColor() ); |
|
pBox->SetHighlightColor( tanDark ); |
|
pBox->GetCheckImage()->SetColor( tanDark ); |
|
break; |
|
case O_STRING: |
|
case O_NUMBER: |
|
pEdit = new TextEntry( pCtrl, "DescTextEntry"); |
|
pEdit->InsertString(pObj->defValue); |
|
pCtrl->pControl = (Panel *)pEdit; |
|
pEdit->SetFont( hTextFont ); |
|
|
|
pEdit->InvalidateLayout( true, true ); |
|
pEdit->SetBgColor( Color(0,0,0,255) ); |
|
break; |
|
case O_LIST: |
|
{ |
|
pCombo = new ComboBox( pCtrl, "DescComboBox", 5, false ); |
|
|
|
// track which row matches the current value |
|
int iRow = -1; |
|
int iCount = 0; |
|
pListItem = pObj->pListItems; |
|
while ( pListItem ) |
|
{ |
|
if ( iRow == -1 && !Q_stricmp( pListItem->szValue, pObj->curValue ) ) |
|
iRow = iCount; |
|
|
|
pCombo->AddItem( pListItem->szItemText, NULL ); |
|
pListItem = pListItem->pNext; |
|
++iCount; |
|
} |
|
|
|
|
|
pCombo->ActivateItemByRow( iRow ); |
|
|
|
pCtrl->pControl = (Panel *)pCombo; |
|
pCombo->SetFont( hTextFont ); |
|
} |
|
break; |
|
case O_SLIDER: |
|
pSlider = new CCvarSlider( pCtrl, "DescSlider", "Test", pObj->fMin, pObj->fMax, pObj->cvarname, false ); |
|
pCtrl->pControl = (Panel *)pSlider; |
|
break; |
|
case O_CATEGORY: |
|
pCtrl->SetBorder( pScheme->GetBorder("OptionsCategoryBorder") ); |
|
break; |
|
default: |
|
break; |
|
} |
|
|
|
if ( pCtrl->type != O_BOOL ) |
|
{ |
|
pCtrl->pPrompt = new vgui::Label( pCtrl, "DescLabel", "" ); |
|
pCtrl->pPrompt->SetContentAlignment( vgui::Label::a_west ); |
|
pCtrl->pPrompt->SetTextInset( 5, 0 ); |
|
pCtrl->pPrompt->SetText( pObj->prompt ); |
|
pCtrl->pPrompt->SetFont( hTextFont ); |
|
|
|
pCtrl->pPrompt->InvalidateLayout( true, true ); |
|
|
|
if ( pCtrl->type == O_CATEGORY ) |
|
{ |
|
pCtrl->pPrompt->SetFont( pScheme->GetFont( "HudFontSmallBold", true ) ); |
|
pCtrl->pPrompt->SetFgColor( pScheme->GetColor( "TanLight", Color(255,0,0,255) ) ); |
|
} |
|
else |
|
{ |
|
pCtrl->pPrompt->SetFgColor( tanDark ); |
|
} |
|
} |
|
|
|
pCtrl->pScrObj = pObj; |
|
|
|
switch ( pCtrl->type ) |
|
{ |
|
case O_BOOL: |
|
case O_STRING: |
|
case O_NUMBER: |
|
case O_LIST: |
|
case O_CATEGORY: |
|
pCtrl->SetSize( m_iControlW, m_iControlH ); |
|
break; |
|
case O_SLIDER: |
|
pCtrl->SetSize( m_iSliderW, m_iSliderH ); |
|
break; |
|
default: |
|
break; |
|
} |
|
|
|
// Hook up the tooltip, if the entry has one |
|
if ( pObj->tooltip && pObj->tooltip[0] ) |
|
{ |
|
if ( pCtrl->pPrompt ) |
|
{ |
|
pCtrl->pPrompt->SetTooltip( m_pToolTip, pObj->tooltip ); |
|
} |
|
else |
|
{ |
|
pCtrl->SetTooltip( m_pToolTip, pObj->tooltip ); |
|
pCtrl->pControl->SetTooltip( m_pToolTip, pObj->tooltip ); |
|
} |
|
} |
|
|
|
m_pListPanel->AddItem( NULL, pCtrl ); |
|
|
|
// Link it in |
|
if ( !m_pList ) |
|
{ |
|
m_pList = pCtrl; |
|
pCtrl->next = NULL; |
|
} |
|
else |
|
{ |
|
mpcontrol_t *p; |
|
p = m_pList; |
|
while ( p ) |
|
{ |
|
if ( !p->next ) |
|
{ |
|
p->next = pCtrl; |
|
pCtrl->next = NULL; |
|
break; |
|
} |
|
p = p->next; |
|
} |
|
} |
|
|
|
pObj = pObj->pNext; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::DestroyControls() |
|
{ |
|
mpcontrol_t *p, *n; |
|
|
|
p = m_pList; |
|
while ( p ) |
|
{ |
|
n = p->next; |
|
// |
|
if ( p->pControl ) |
|
{ |
|
p->pControl->MarkForDeletion(); |
|
p->pControl = NULL; |
|
} |
|
if ( p->pPrompt ) |
|
{ |
|
p->pPrompt->MarkForDeletion(); |
|
p->pPrompt = NULL; |
|
} |
|
delete p; |
|
p = n; |
|
} |
|
|
|
m_pList = NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::SaveValues() |
|
{ |
|
// Get the values from the controls: |
|
GatherCurrentValues(); |
|
|
|
// Create the game.cfg file |
|
if ( m_pDescription ) |
|
{ |
|
FileHandle_t fp; |
|
|
|
// Add settings to config.cfg |
|
m_pDescription->WriteToConfig(); |
|
|
|
g_pFullFileSystem->CreateDirHierarchy( OPTIONS_DIR ); |
|
fp = g_pFullFileSystem->Open( OPTIONS_FILE, "wb" ); |
|
if ( fp ) |
|
{ |
|
m_pDescription->WriteToScriptFile( fp ); |
|
g_pFullFileSystem->Close( fp ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFAdvancedOptionsDialog::Deploy( void ) |
|
{ |
|
SetVisible( true ); |
|
MakePopup(); |
|
MoveToFront(); |
|
SetKeyBoardInputEnabled(true); |
|
SetMouseInputEnabled(true); |
|
TFModalStack()->PushModal( this ); |
|
|
|
// Center it, keeping requested size |
|
int x, y, ww, wt, wide, tall; |
|
vgui::surface()->GetWorkspaceBounds( x, y, ww, wt ); |
|
GetSize(wide, tall); |
|
SetPos(x + ((ww - wide) / 2), y + ((wt - tall) / 2)); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFTextToolTip::PerformLayout() |
|
{ |
|
if ( !ShouldLayout() ) |
|
return; |
|
|
|
_isDirty = false; |
|
|
|
// Resize our text labels to fit. |
|
int iW = m_pEmbeddedPanel->GetWide(); |
|
int iH = 0; |
|
for (int i = 0; i < m_pEmbeddedPanel->GetChildCount(); i++) |
|
{ |
|
vgui::Label *pLabel = dynamic_cast<vgui::Label*>( m_pEmbeddedPanel->GetChild(i) ); |
|
if ( !pLabel ) |
|
continue; |
|
|
|
// Only checking to see if we have any text |
|
char szTmp[2]; |
|
pLabel->GetText( szTmp, sizeof(szTmp) ); |
|
if ( !szTmp[0] ) |
|
continue; |
|
|
|
int iLX, iLY; |
|
pLabel->GetPos( iLX, iLY ); |
|
|
|
int iMaxWidth = m_pEmbeddedPanel->GetWide() - (iLX * 2); |
|
pLabel->GetTextImage()->ResizeImageToContentMaxWidth( iMaxWidth ); |
|
pLabel->SizeToContents(); |
|
pLabel->SetWide( iMaxWidth ); |
|
pLabel->InvalidateLayout(true); |
|
|
|
int iX, iY; |
|
pLabel->GetPos( iX, iY ); |
|
iW = MAX( iW, ( pLabel->GetWide() + (iX * 2) ) ); |
|
|
|
if ( iH == 0 ) |
|
{ |
|
iH += MAX( iH, pLabel->GetTall() + (iY * 2) ); |
|
} |
|
else |
|
{ |
|
iH += MAX( iH, pLabel->GetTall() ); |
|
} |
|
} |
|
m_pEmbeddedPanel->SetSize( m_pEmbeddedPanel->GetWide(), iH ); |
|
|
|
m_pEmbeddedPanel->SetVisible(true); |
|
|
|
PositionWindow( m_pEmbeddedPanel ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFTextToolTip::PositionWindow( Panel *pTipPanel ) |
|
{ |
|
int iTipW, iTipH; |
|
pTipPanel->GetSize( iTipW, iTipH ); |
|
|
|
int cursorX, cursorY; |
|
input()->GetCursorPos(cursorX, cursorY); |
|
|
|
int px, py, wide, tall; |
|
ipanel()->GetAbsPos( m_pEmbeddedPanel->GetParent()->GetVPanel(), px, py ); |
|
m_pEmbeddedPanel->GetParent()->GetSize(wide, tall); |
|
|
|
if ( !m_pEmbeddedPanel->IsPopup() ) |
|
{ |
|
// Move the cursor into our parent space |
|
cursorX -= px; |
|
cursorY -= py; |
|
} |
|
|
|
if (wide - iTipW > cursorX) |
|
{ |
|
cursorY += 20; |
|
// menu hanging right |
|
if (tall - iTipH > cursorY) |
|
{ |
|
// menu hanging down |
|
pTipPanel->SetPos(cursorX, cursorY); |
|
} |
|
else |
|
{ |
|
// menu hanging up |
|
pTipPanel->SetPos(cursorX, cursorY - iTipH - 20); |
|
} |
|
} |
|
else |
|
{ |
|
// menu hanging left |
|
if (tall - iTipH > cursorY) |
|
{ |
|
// menu hanging down |
|
pTipPanel->SetPos( Max( 0, cursorX - iTipW ), cursorY); |
|
} |
|
else |
|
{ |
|
// menu hanging up |
|
pTipPanel->SetPos( Max( 0, cursorX - iTipW ), cursorY - iTipH - 20 ); |
|
} |
|
} |
|
} |
|
|
|
static vgui::DHANDLE<CTFAdvancedOptionsDialog> g_pTFAdvancedOptionsDialog; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Callback to open the game menus |
|
//----------------------------------------------------------------------------- |
|
void CL_OpenTFAdvancedOptionsDialog( const CCommand &args ) |
|
{ |
|
if ( g_pTFAdvancedOptionsDialog.Get() == NULL ) |
|
{ |
|
g_pTFAdvancedOptionsDialog = vgui::SETUP_PANEL( new CTFAdvancedOptionsDialog( NULL ) ); |
|
} |
|
|
|
g_pTFAdvancedOptionsDialog->Deploy(); |
|
} |
|
|
|
// the console commands |
|
static ConCommand opentf2options( "opentf2options", &CL_OpenTFAdvancedOptionsDialog, "Displays the TF2 Advanced Options dialog." ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: A scroll bar that can have specified width |
|
//----------------------------------------------------------------------------- |
|
class CExScrollBar : public ScrollBar |
|
{ |
|
DECLARE_CLASS_SIMPLE( CExScrollBar, ScrollBar ); |
|
public: |
|
|
|
CExScrollBar( Panel *parent, const char *name, bool bVertical ) |
|
: ScrollBar( parent, name, bVertical ) |
|
{} |
|
|
|
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE |
|
{ |
|
// Deliberately skip ScrollBar |
|
Panel::ApplySchemeSettings( pScheme ); |
|
} |
|
}; |
|
|
|
DECLARE_BUILD_FACTORY( CExScrollingEditablePanel ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CExScrollingEditablePanel::CExScrollingEditablePanel( Panel *pParent, const char *pszName ) |
|
: EditablePanel( pParent, pszName ) |
|
, m_nLastScrollValue( 0 ) |
|
, m_bUseMouseWheelToScroll( true ) |
|
{ |
|
m_pScrollBar = new CExScrollBar( this, "ScrollBar", true ); |
|
m_pScrollBar->AddActionSignalTarget( this ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CExScrollingEditablePanel::~CExScrollingEditablePanel() |
|
{} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CExScrollingEditablePanel::ApplySettings( KeyValues *inResourceData ) |
|
{ |
|
BaseClass::ApplySettings( inResourceData ); |
|
|
|
KeyValues *pScrollbarKV = inResourceData->FindKey( "Scrollbar" ); |
|
if ( pScrollbarKV ) |
|
{ |
|
m_pScrollBar->ApplySettings( pScrollbarKV ); |
|
} |
|
|
|
m_bUseMouseWheelToScroll = inResourceData->GetBool( "allow_mouse_wheel_to_scroll", true ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CExScrollingEditablePanel::OnSizeChanged( int newWide, int newTall ) |
|
{ |
|
BaseClass::OnSizeChanged( newWide, newTall ); |
|
|
|
int nDelta = m_nLastScrollValue; |
|
// Go through all our children and move them BACK into position |
|
int nNumChildren = GetChildCount(); |
|
for ( int i=0; i < nNumChildren; ++i ) |
|
{ |
|
Panel* pChild = GetChild( i ); |
|
|
|
if ( pChild == m_pScrollBar ) |
|
continue; |
|
|
|
EditablePanel* pEditableChild = dynamic_cast< EditablePanel* >( pChild ); |
|
if ( pEditableChild && pEditableChild->ShouldSkipAutoResize() ) |
|
continue; |
|
|
|
int x,y; |
|
pChild->GetPos( x, y ); |
|
|
|
pChild->SetPos( x, y - nDelta ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CExScrollingEditablePanel::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
int nFurthestY = 0; |
|
|
|
// Go through all our children and find the lowest point on the lowest child |
|
// that we'd need to scroll to |
|
int nNumChildren = GetChildCount(); |
|
for ( int i=0; i < nNumChildren; ++i ) |
|
{ |
|
Panel* pChild = GetChild( i ); |
|
|
|
if ( pChild == m_pScrollBar ) |
|
continue; |
|
|
|
int x,y,wide,tall; |
|
pChild->GetBounds( x, y, wide, tall ); |
|
|
|
// Offset by our scroll value |
|
y += m_nLastScrollValue; |
|
|
|
if ( m_bRestrictWidth ) |
|
{ |
|
int nMaxWide = Min( x + wide, GetWide() - m_pScrollBar->GetWide() ); |
|
pChild->SetWide( nMaxWide - x ); |
|
} |
|
|
|
nFurthestY = Max( y + tall, nFurthestY ); |
|
} |
|
|
|
int nMaxRange = nFurthestY + m_iBottomBuffer; |
|
m_pScrollBar->SetRange( 0, nMaxRange ); |
|
m_pScrollBar->SetRangeWindow( GetTall() ); |
|
|
|
OnScrollBarSliderMoved(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Called when the scroll bar moves |
|
//----------------------------------------------------------------------------- |
|
void CExScrollingEditablePanel::OnScrollBarSliderMoved() |
|
{ |
|
// Figure out how far they just scrolled |
|
int nScrollAmount = m_pScrollBar->GetValue(); |
|
int nDelta = nScrollAmount - m_nLastScrollValue; |
|
|
|
if ( nDelta == 0 ) |
|
return; |
|
|
|
ShiftChildren( nDelta ); |
|
|
|
m_nLastScrollValue = nScrollAmount; |
|
} |
|
|
|
void CExScrollingEditablePanel::ShiftChildren( int nDistance ) |
|
{ |
|
// Go through all our children and move them |
|
int nNumChildren = GetChildCount(); |
|
for ( int i=0; i < nNumChildren; ++i ) |
|
{ |
|
Panel* pChild = GetChild( i ); |
|
|
|
if ( pChild == m_pScrollBar ) |
|
continue; |
|
|
|
int x,y; |
|
pChild->GetPos( x, y ); |
|
|
|
pChild->SetPos( x, y - nDistance ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// respond to mouse wheel events |
|
//----------------------------------------------------------------------------- |
|
void CExScrollingEditablePanel::OnMouseWheeled( int delta ) |
|
{ |
|
if ( !m_bUseMouseWheelToScroll ) |
|
{ |
|
BaseClass::OnMouseWheeled( delta ); |
|
return; |
|
} |
|
|
|
int val = m_pScrollBar->GetValue(); |
|
val -= ( delta * m_iScrollStep ); |
|
m_pScrollBar->SetValue( val ); |
|
} |
|
|
|
DECLARE_BUILD_FACTORY( CScrollableList ); |
|
//----------------------------------------------------------------------------- |
|
// Clearnup |
|
//----------------------------------------------------------------------------- |
|
CScrollableList::~CScrollableList() |
|
{ |
|
ClearAutoLayoutPanels(); |
|
} |
|
|
|
void CScrollableList::PerformLayout() |
|
{ |
|
int nYpos = -m_nLastScrollValue; |
|
|
|
for( int i=0; i<m_vecAutoLayoutPanels.Count(); ++i ) |
|
{ |
|
LayoutInfo_t layout = m_vecAutoLayoutPanels[ i ]; |
|
nYpos += layout.m_nGap; |
|
|
|
layout.m_pPanel->SetPos( layout.m_pPanel->GetXPos(), nYpos ); |
|
|
|
nYpos += layout.m_pPanel->GetTall(); |
|
} |
|
|
|
BaseClass::PerformLayout(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Add a panel to the bottom |
|
//----------------------------------------------------------------------------- |
|
void CScrollableList::AddPanel( Panel* pPanel, int nGap ) |
|
{ |
|
// We're the captain now |
|
pPanel->SetParent( this ); |
|
pPanel->SetAutoDelete( false ); |
|
|
|
auto idx = m_vecAutoLayoutPanels.AddToTail(); |
|
LayoutInfo_t& layout = m_vecAutoLayoutPanels[ idx ]; |
|
layout.m_pPanel = pPanel; |
|
layout.m_nGap = nGap; |
|
|
|
// Need to do a perform layout so we get sized correctly |
|
InvalidateLayout(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Delete any panels we own |
|
//----------------------------------------------------------------------------- |
|
void CScrollableList::ClearAutoLayoutPanels() |
|
{ |
|
FOR_EACH_VEC( m_vecAutoLayoutPanels, i ) |
|
{ |
|
m_vecAutoLayoutPanels[ i ].m_pPanel->MarkForDeletion(); |
|
} |
|
|
|
m_vecAutoLayoutPanels.Purge(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
//----------------------------------------------------------------------------- |
|
CExpandablePanel::CExpandablePanel( Panel* pParent, const char* pszName ) |
|
: vgui::EditablePanel( pParent, pszName ) |
|
, m_bExpanded( false ) |
|
, m_flAnimEndTime( 0.f ) |
|
, m_flResizeTime( 0.f ) |
|
{} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Set spcific collapsed state |
|
//----------------------------------------------------------------------------- |
|
void CExpandablePanel::SetCollapsed( bool bCollapsed ) |
|
{ |
|
if ( bCollapsed == m_bExpanded ) |
|
{ |
|
ToggleCollapse(); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Toggle collapsed state |
|
//----------------------------------------------------------------------------- |
|
void CExpandablePanel::ToggleCollapse() |
|
{ |
|
m_bExpanded = !m_bExpanded; |
|
// Allow for quick bounce-back if they click while we're already animating |
|
float flEndTime = RemapValClamped( GetPercentAnimated(), 0.f, 1.f, 0.f, m_flResizeTime ); |
|
m_flAnimEndTime = Plat_FloatTime() + flEndTime; |
|
|
|
OnToggleCollapse( m_bExpanded ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Toggle collapsed state |
|
//----------------------------------------------------------------------------- |
|
void CExpandablePanel::OnCommand( const char *command ) |
|
{ |
|
if ( FStrEq( "toggle_collapse", command ) ) |
|
{ |
|
ToggleCollapse(); |
|
|
|
return; |
|
} |
|
|
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Do collapsing interpolation |
|
//----------------------------------------------------------------------------- |
|
void CExpandablePanel::OnThink() |
|
{ |
|
BaseClass::OnThink(); |
|
|
|
float flTimeProgress = Gain( GetPercentAnimated(), 0.8f ); |
|
|
|
const int& nStartHeight = m_bExpanded ? m_nCollapsedHeight : m_nExpandedHeight; |
|
const int& nEndHeight = m_bExpanded ? m_nExpandedHeight : m_nCollapsedHeight; |
|
int nCurrentHeight = RemapValClamped( flTimeProgress, 0.f, 1.f, nStartHeight, nEndHeight ); |
|
|
|
if ( nCurrentHeight != GetTall() ) |
|
{ |
|
SetTall( nCurrentHeight ); |
|
Panel* pParent = GetParent(); |
|
if ( pParent ) |
|
{ |
|
pParent->InvalidateLayout(); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Where we're at in our interpolation |
|
//----------------------------------------------------------------------------- |
|
float CExpandablePanel::GetPercentAnimated() const |
|
{ |
|
return RemapValClamped( Plat_FloatTime() - ( m_flAnimEndTime - m_flResizeTime ), 0.f, m_flResizeTime, 0.f, 1.f ); |
|
} |
|
|
|
|