//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. =========== // // The copyright to the contents herein is the property of Valve, L.L.C. // The contents may be used and/or copied only with the written permission of // Valve, L.L.C., or in accordance with the terms and conditions stipulated in // the agreement/contract under which the contents have been supplied. // // Purpose: Contains implementation of various VGUI-derived objects // // $Workfile: $ // $Date: $ // //----------------------------------------------------------------------------- // $Log: $ // // $NoKeywords: $ //============================================================================= #include "VGUI_Font.h" #include "hud.h" #include "cl_util.h" #include "camera.h" #include "kbutton.h" #include "cvardef.h" #include "usercmd.h" #include "const.h" #include "camera.h" #include "in_defs.h" #include "parsemsg.h" #include "vgui_int.h" #include "vgui_TeamFortressViewport.h" #include "vgui_loadtga.h" // Arrow filenames const char *sArrowFilenames[] = { "arrowup", "arrowdn", "arrowlt", "arrowrt", }; // Get the name of TGA file, without a gamedir char *GetTGANameForRes( const char *pszName, bool allCapitalsVGUI = false ) { int i; char sz[256]; static char gd[256]; if( ScreenWidth < 640 ) i = 320; else i = 640; sprintf( sz, pszName, i ); if(!allCapitalsVGUI) sprintf( gd, "gfx/vgui/%s.tga", sz ); else sprintf( gd, "gfx/VGUI/%s.tga", sz ); return gd; } //----------------------------------------------------------------------------- // Purpose: Loads a .tga file and returns a pointer to the VGUI tga object //----------------------------------------------------------------------------- BitmapTGA *LoadTGAForRes( const char* pImageName ) { BitmapTGA *pTGA; char sz[256]; sprintf( sz, "%%d_%s", pImageName ); pTGA = vgui_LoadTGA( GetTGANameForRes( sz ) ); if(!pTGA) pTGA = vgui_LoadTGA( GetTGANameForRes( sz, true ) ); //Try all-captials return pTGA; } //=========================================================== // All TFC Hud buttons are derived from this one. CommandButton::CommandButton( const char *text, int x, int y, int wide, int tall, bool bNoHighlight ) : Button( "", x, y, wide, tall ) { m_iPlayerClass = 0; m_bNoHighlight = bNoHighlight; m_bFlat = false; Init(); setText( text ); } CommandButton::CommandButton( int iPlayerClass, const char *text, int x, int y, int wide, int tall, bool bFlat ) : Button( "", x, y, wide, tall ) { m_iPlayerClass = iPlayerClass; m_bNoHighlight = false; m_bFlat = bFlat; Init(); setText( text ); } CommandButton::CommandButton( const char *text, int x, int y, int wide, int tall, bool bNoHighlight, bool bFlat ) : Button( "", x, y, wide, tall ) { m_iPlayerClass = 0; m_bFlat = bFlat; m_bNoHighlight = bNoHighlight; Init(); setText( text ); } void CommandButton::Init( void ) { m_pSubMenu = NULL; m_pSubLabel = NULL; m_pParentMenu = NULL; // Set text color to orange setFgColor( Scheme::sc_primary1 ); // left align setContentAlignment( vgui::Label::a_west ); // Add the Highlight signal if( !m_bNoHighlight ) addInputSignal( new CHandler_CommandButtonHighlight( this ) ); // not bound to any button yet m_cBoundKey = 0; } //----------------------------------------------------------------------------- // Purpose: Prepends the button text with the current bound key // if no bound key, then a clear space ' ' instead //----------------------------------------------------------------------------- void CommandButton::RecalculateText( void ) { char szBuf[128]; if( m_cBoundKey != 0 ) { if( m_cBoundKey == (char)255 ) { strcpy( szBuf, m_sMainText ); } else { sprintf( szBuf, " %c %s", m_cBoundKey, m_sMainText ); } szBuf[MAX_BUTTON_SIZE-1] = 0; } else { // just draw a space if no key bound sprintf( szBuf, " %s", m_sMainText ); szBuf[MAX_BUTTON_SIZE - 1] = 0; } Button::setText( szBuf ); } void CommandButton::setText( const char *text ) { strncpy( m_sMainText, text, MAX_BUTTON_SIZE ); m_sMainText[MAX_BUTTON_SIZE - 1] = 0; RecalculateText(); } void CommandButton::setBoundKey( char boundKey ) { m_cBoundKey = boundKey; RecalculateText(); } char CommandButton::getBoundKey( void ) { return m_cBoundKey; } void CommandButton::AddSubMenu( CCommandMenu *pNewMenu ) { m_pSubMenu = pNewMenu; // Prevent this button from being pushed setMouseClickEnabled( MOUSE_LEFT, false ); } void CommandButton::UpdateSubMenus( int iAdjustment ) { if( m_pSubMenu ) m_pSubMenu->RecalculatePositions( iAdjustment ); } void CommandButton::paint() { // Make the sub label paint the same as the button if( m_pSubLabel ) { if( isSelected() ) m_pSubLabel->PushDown(); else m_pSubLabel->PushUp(); } // draw armed button text in white if( isArmed() ) { setFgColor( Scheme::sc_secondary2 ); } else { setFgColor( Scheme::sc_primary1 ); } Button::paint(); } void CommandButton::paintBackground() { if( m_bFlat ) { if( isArmed() ) { // Orange Border drawSetColor( Scheme::sc_secondary1 ); drawOutlinedRect( 0, 0, _size[0], _size[1] ); } } else { if( isArmed() ) { // Orange highlight background drawSetColor( Scheme::sc_primary2 ); drawFilledRect( 0, 0, _size[0], _size[1] ); } // Orange Border drawSetColor( Scheme::sc_secondary1 ); drawOutlinedRect( 0, 0, _size[0], _size[1] ); } } //----------------------------------------------------------------------------- // Purpose: Highlights the current button, and all it's parent menus //----------------------------------------------------------------------------- void CommandButton::cursorEntered( void ) { // unarm all the other buttons in this menu CCommandMenu *containingMenu = getParentMenu(); if( containingMenu ) { containingMenu->ClearButtonsOfArmedState(); // make all our higher buttons armed CCommandMenu *pCParent = containingMenu->GetParentMenu(); if( pCParent ) { CommandButton *pParentButton = pCParent->FindButtonWithSubmenu( containingMenu ); pParentButton->cursorEntered(); } } // arm ourselves setArmed( true ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CommandButton::cursorExited( void ) { // only clear ourselves if we have do not have a containing menu // only stay armed if we have a sub menu // the buttons only unarm themselves when another button is armed instead if( !getParentMenu() || !GetSubMenu() ) { setArmed( false ); } } //----------------------------------------------------------------------------- // Purpose: Returns the command menu that the button is part of, if any // Output : CCommandMenu * //----------------------------------------------------------------------------- CCommandMenu *CommandButton::getParentMenu( void ) { return m_pParentMenu; } //----------------------------------------------------------------------------- // Purpose: Sets the menu that contains this button // Input : *pParentMenu - //----------------------------------------------------------------------------- void CommandButton::setParentMenu( CCommandMenu *pParentMenu ) { m_pParentMenu = pParentMenu; } //=========================================================== int ClassButton::IsNotValid() { // If this is the main ChangeClass button, remove it if the player's only able to be civilians if( m_iPlayerClass == -1 ) { if( gViewPort->GetValidClasses( g_iTeamNumber ) == -1 ) return true; return false; } // Is it an illegal class? #ifdef _TFC if( ( gViewPort->GetValidClasses( 0 ) & sTFValidClassInts[m_iPlayerClass] ) || ( gViewPort->GetValidClasses( g_iTeamNumber ) & sTFValidClassInts[m_iPlayerClass] ) ) return true; #endif // Only check current class if they've got autokill on bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0; if( bAutoKill ) { // Is it the player's current class? if ( #ifdef _TFC (gViewPort->IsRandomPC() && m_iPlayerClass == PC_RANDOM) || #endif (!gViewPort->IsRandomPC() && (m_iPlayerClass == g_iPlayerClass)) ) return true; } return false; } //=========================================================== // Button with Class image beneath it CImageLabel::CImageLabel( const char *pImageName,int x,int y ) : Label( "", x, y ) { setContentFitted( true ); m_pTGA = LoadTGAForRes( pImageName ); setImage( m_pTGA ); } CImageLabel::CImageLabel( const char *pImageName, int x, int y, int wide, int tall ) : Label( "", x, y, wide, tall ) { setContentFitted( true ); m_pTGA = LoadTGAForRes( pImageName ); setImage( m_pTGA ); } //=========================================================== // Image size int CImageLabel::getImageWide( void ) { if( m_pTGA ) { int iXSize, iYSize; m_pTGA->getSize( iXSize, iYSize ); return iXSize; } else { return 1; } } int CImageLabel::getImageTall( void ) { if( m_pTGA ) { int iXSize, iYSize; m_pTGA->getSize( iXSize, iYSize ); return iYSize; } else { return 1; } } void CImageLabel::LoadImage( const char *pImageName ) { if( m_pTGA ) delete m_pTGA; // Load the Image m_pTGA = LoadTGAForRes( pImageName ); if( m_pTGA == NULL ) { // we didn't find a matching image file for this resolution // try to load file resolution independent char sz[256]; sprintf( sz, "%s/%s", gEngfuncs.pfnGetGameDirectory(), pImageName ); FileInputStream fis( sz, false ); m_pTGA = new BitmapTGA( &fis, true ); fis.close(); } if( m_pTGA == NULL ) return; // unable to load image int w,t; m_pTGA->getSize( w, t ); setSize( XRES ( w ),YRES ( t) ); setImage( m_pTGA ); } //=========================================================== // Various overloaded paint functions for Custom VGUI objects void CCommandMenu::paintBackground() { // Transparent black background if( m_iSpectCmdMenu ) drawSetColor( 0, 0, 0, 64 ); else drawSetColor( Scheme::sc_primary3 ); drawFilledRect( 0, 0, _size[0], _size[1] ); } //================================================================================= // CUSTOM SCROLLPANEL //================================================================================= CTFScrollButton::CTFScrollButton( int iArrow, const char *text, int x, int y, int wide, int tall ) : CommandButton( text, x, y, wide, tall ) { // Set text color to orange setFgColor( Scheme::sc_primary1 ); // Load in the arrow m_pTGA = LoadTGAForRes( sArrowFilenames[iArrow] ); setImage( m_pTGA ); // Highlight signal InputSignal *pISignal = new CHandler_CommandButtonHighlight( this ); addInputSignal( pISignal ); } void CTFScrollButton::paint( void ) { if( !m_pTGA ) return; // draw armed button text in white if( isArmed() ) { m_pTGA->setColor( Color( 255, 255, 255, 0 ) ); } else { m_pTGA->setColor( Color( 255, 255, 255, 128 ) ); } m_pTGA->doPaint( this ); } void CTFScrollButton::paintBackground( void ) { /* if( isArmed() ) { // Orange highlight background drawSetColor( Scheme::sc_primary2 ); drawFilledRect( 0, 0, _size[0], _size[1] ); } // Orange Border drawSetColor( Scheme::sc_secondary1 ); drawOutlinedRect( 0, 0, _size[0] - 1, _size[1] ); */ } void CTFSlider::paintBackground( void ) { int wide, tall, nobx, noby; getPaintSize( wide, tall ); getNobPos( nobx, noby ); // Border drawSetColor( Scheme::sc_secondary1 ); drawOutlinedRect( 0, 0, wide, tall ); if( isVertical() ) { // Nob Fill drawSetColor( Scheme::sc_primary2 ); drawFilledRect( 0, nobx, wide, noby ); // Nob Outline drawSetColor( Scheme::sc_primary1 ); drawOutlinedRect( 0, nobx, wide, noby ); } else { // Nob Fill drawSetColor( Scheme::sc_primary2 ); drawFilledRect( nobx, 0, noby, tall ); // Nob Outline drawSetColor( Scheme::sc_primary1 ); drawOutlinedRect( nobx, 0, noby, tall ); } } CTFScrollPanel::CTFScrollPanel( int x, int y, int wide, int tall ) : ScrollPanel( x, y, wide, tall ) { ScrollBar *pScrollBar = getVerticalScrollBar(); pScrollBar->setButton( new CTFScrollButton( ARROW_UP, "", 0, 0, 16, 16 ), 0 ); pScrollBar->setButton( new CTFScrollButton( ARROW_DOWN, "", 0, 0, 16, 16 ), 1 ); pScrollBar->setSlider( new CTFSlider( 0, wide - 1, wide, ( tall - ( wide * 2 ) ) + 2, true ) ); pScrollBar->setPaintBorderEnabled( false ); pScrollBar->setPaintBackgroundEnabled( false ); pScrollBar->setPaintEnabled( false ); pScrollBar = getHorizontalScrollBar(); pScrollBar->setButton( new CTFScrollButton( ARROW_LEFT, "", 0, 0, 16, 16 ), 0 ); pScrollBar->setButton( new CTFScrollButton( ARROW_RIGHT, "", 0, 0, 16, 16 ), 1 ); pScrollBar->setSlider( new CTFSlider( tall, 0, wide - ( tall * 2 ), tall, false ) ); pScrollBar->setPaintBorderEnabled( false ); pScrollBar->setPaintBackgroundEnabled( false ); pScrollBar->setPaintEnabled( false ); } //================================================================================= // CUSTOM HANDLERS //================================================================================= void CHandler_MenuButtonOver::cursorEntered(Panel *panel) { if( gViewPort && m_pMenuPanel ) { m_pMenuPanel->SetActiveInfo( m_iButton ); } } void CMenuHandler_StringCommandClassSelect::actionPerformed( Panel *panel ) { CMenuHandler_StringCommand::actionPerformed( panel ); // THIS IS NOW BEING DONE ON THE TFC SERVER TO AVOID KILLING SOMEONE THEN // HAVE THE SERVER SAY "SORRY...YOU CAN'T BE THAT CLASS". #if !defined _TFC bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0; if( bAutoKill && g_iPlayerClass != 0 ) gEngfuncs.pfnClientCmd( "kill" ); #endif }