Counter Strike : Global Offensive Source Code
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.

467 lines
14 KiB

  1. //===== Copyright � 1996-2011, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include <stdio.h>
  8. #include "vgui/ILocalize.h"
  9. #include "vgui_controls/footerpanel.h"
  10. #include "vgui_controls/Frame.h"
  11. #include "vgui/ISurface.h"
  12. #include "vgui_controls/Label.h"
  13. #include "vgui_controls/ControllerMap.h"
  14. #if defined( _X360 )
  15. #include "xbox/xbox_launch.h"
  16. #else
  17. #include "xbox/xboxstubs.h"
  18. #endif
  19. #undef MessageBox // Windows helpfully #define's this to MessageBoxA, we're using vgui::MessageBox
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. using namespace vgui;
  23. CFooterPanel::CFooterPanel( Panel *parent, const char *panelName ) : BaseClass( parent, panelName )
  24. {
  25. SetVisible( true );
  26. SetAlpha( 0 );
  27. m_pHelpName = NULL;
  28. m_pSizingLabel = new vgui::Label( this, "SizingLabel", "" );
  29. m_pSizingLabel->SetVisible( false );
  30. m_nButtonGap = 32;
  31. m_nButtonGapDefault = 32;
  32. m_ButtonPinRight = 100;
  33. m_FooterTall = 80;
  34. int wide, tall;
  35. surface()->GetScreenSize(wide, tall);
  36. if ( tall <= 480 )
  37. {
  38. m_FooterTall = 60;
  39. }
  40. m_ButtonOffsetFromTop = 0;
  41. m_ButtonSeparator = 4;
  42. m_TextAdjust = 0;
  43. m_bPaintBackground = false;
  44. m_bCenterHorizontal = false;
  45. m_szButtonFont[0] = '\0';
  46. m_szTextFont[0] = '\0';
  47. m_szFGColor[0] = '\0';
  48. m_szBGColor[0] = '\0';
  49. }
  50. CFooterPanel::~CFooterPanel()
  51. {
  52. SetHelpNameAndReset( NULL );
  53. delete m_pSizingLabel;
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose: apply scheme settings
  57. //-----------------------------------------------------------------------------
  58. void CFooterPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  59. {
  60. BaseClass::ApplySchemeSettings( pScheme );
  61. // $FIXME(hpe) quick hack for PC fonts
  62. if ( IsPC() )
  63. {
  64. m_hButtonFont = pScheme->GetFont( ( m_szButtonFont[0] != '\0' ) ? m_szButtonFont : "Default" );
  65. m_hTextFont = pScheme->GetFont( ( m_szTextFont[0] != '\0' ) ? m_szTextFont : "Default" );
  66. }
  67. else
  68. {
  69. m_hButtonFont = pScheme->GetFont( ( m_szButtonFont[0] != '\0' ) ? m_szButtonFont : "GameUIButtons" );
  70. m_hTextFont = pScheme->GetFont( ( m_szTextFont[0] != '\0' ) ? m_szTextFont : "X360_Title_1" );
  71. }
  72. SetFgColor( pScheme->GetColor( m_szFGColor, Color( 255, 255, 255, 255 ) ) );
  73. SetBgColor( pScheme->GetColor( m_szBGColor, Color( 0, 0, 0, 255 ) ) );
  74. int x, y, w, h;
  75. GetParent()->GetBounds( x, y, w, h );
  76. SetBounds( x, h - m_FooterTall, w, m_FooterTall );
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose: apply settings
  80. //-----------------------------------------------------------------------------
  81. void CFooterPanel::ApplySettings( KeyValues *inResourceData )
  82. {
  83. BaseClass::ApplySettings( inResourceData );
  84. // gap between hints
  85. m_nButtonGap = inResourceData->GetInt( "buttongap", 32 );
  86. m_nButtonGapDefault = m_nButtonGap;
  87. m_ButtonPinRight = inResourceData->GetInt( "button_pin_right", 100 );
  88. m_FooterTall = inResourceData->GetInt( "tall", 80 );
  89. m_ButtonOffsetFromTop = inResourceData->GetInt( "buttonoffsety", 0 );
  90. m_ButtonSeparator = inResourceData->GetInt( "button_separator", 4 );
  91. m_TextAdjust = inResourceData->GetInt( "textadjust", 0 );
  92. m_bCenterHorizontal = ( inResourceData->GetInt( "center", 0 ) == 1 );
  93. m_bPaintBackground = ( inResourceData->GetInt( "paintbackground", 0 ) == 1 );
  94. // fonts for text and button
  95. Q_strncpy( m_szTextFont, inResourceData->GetString( "fonttext", "MenuLarge" ), sizeof( m_szTextFont ) );
  96. Q_strncpy( m_szButtonFont, inResourceData->GetString( "fontbutton", "GameUIButtons" ), sizeof( m_szButtonFont ) );
  97. // fg and bg colors
  98. Q_strncpy( m_szFGColor, inResourceData->GetString( "fgcolor", "White" ), sizeof( m_szFGColor ) );
  99. Q_strncpy( m_szBGColor, inResourceData->GetString( "bgcolor", "Black" ), sizeof( m_szBGColor ) );
  100. for ( KeyValues *pButton = inResourceData->GetFirstSubKey(); pButton != NULL; pButton = pButton->GetNextKey() )
  101. {
  102. const char *pName = pButton->GetName();
  103. if ( !Q_stricmp( pName, "button" ) )
  104. {
  105. // Add a button to the footer
  106. const char *pText = pButton->GetString( "text", "NULL" );
  107. const char *pIcon = pButton->GetString( "icon", "NULL" );
  108. AddNewButtonLabel( pText, pIcon );
  109. }
  110. }
  111. InvalidateLayout( false, true ); // force ApplySchemeSettings to run
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Purpose: adds button icons and help text to the footer panel when activating a menu
  115. //-----------------------------------------------------------------------------
  116. void CFooterPanel::AddButtonsFromMap( vgui::Frame *pMenu )
  117. {
  118. SetHelpNameAndReset( pMenu->GetName() );
  119. CControllerMap *pMap = dynamic_cast<CControllerMap*>( pMenu->FindChildByName( "ControllerMap" ) );
  120. if ( pMap )
  121. {
  122. int buttonCt = pMap->NumButtons();
  123. for ( int i = 0; i < buttonCt; ++i )
  124. {
  125. const char *pText = pMap->GetBindingText( i );
  126. if ( pText )
  127. {
  128. AddNewButtonLabel( pText, pMap->GetBindingIcon( i ) );
  129. }
  130. }
  131. }
  132. }
  133. void CFooterPanel::SetStandardDialogButtons()
  134. {
  135. SetHelpNameAndReset( "Dialog" );
  136. //=============================================================================
  137. // HPE_BEGIN:
  138. // [tj] Changed "Action" to "Select"
  139. //=============================================================================
  140. AddNewButtonLabel( "#GameUI_Select", "#GameUI_Icons_A_BUTTON" );
  141. //=============================================================================
  142. // HPE_END
  143. //=============================================================================
  144. AddNewButtonLabel( "#GameUI_Back", "#GameUI_Icons_B_BUTTON" );
  145. }
  146. //-----------------------------------------------------------------------------
  147. // Purpose: Caller must tag the button layout. May support reserved names
  148. // to provide stock help layouts trivially.
  149. //-----------------------------------------------------------------------------
  150. void CFooterPanel::SetHelpNameAndReset( const char *pName )
  151. {
  152. if ( m_pHelpName )
  153. {
  154. free( m_pHelpName );
  155. m_pHelpName = NULL;
  156. }
  157. if ( pName )
  158. {
  159. m_pHelpName = strdup( pName );
  160. }
  161. ClearButtons();
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Purpose: Caller must tag the button layout
  165. //-----------------------------------------------------------------------------
  166. const char *CFooterPanel::GetHelpName()
  167. {
  168. return m_pHelpName;
  169. }
  170. void CFooterPanel::ClearButtons( void )
  171. {
  172. m_ButtonLabels.PurgeAndDeleteElements();
  173. }
  174. //=============================================================================
  175. // HPE_BEGIN:
  176. // [smessick]
  177. //=============================================================================
  178. //-----------------------------------------------------------------------------
  179. // Purpose: Sets the pin right location with adjustments based on the current
  180. // screen width and height. The given pixel offset is assumed to be based on
  181. // a 640x480 screen.
  182. //-----------------------------------------------------------------------------
  183. void CFooterPanel::SetButtonPinRightProportional( int nButtonPinRight )
  184. {
  185. int screenWide, screenTall;
  186. surface()->GetScreenSize(screenWide, screenTall);
  187. float tallDiff = screenTall / 480.0f;
  188. m_ButtonPinRight = ( ( screenWide - ( 640 * tallDiff ) ) * 0.5f ) + ( nButtonPinRight * tallDiff );
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose: Set the y offset from the top of the screen.
  192. // The given pixel offset is assumed to be based on a 640x480 screen.
  193. //-----------------------------------------------------------------------------
  194. void CFooterPanel::SetButtonOffsetFromTopProportional( int yOffset )
  195. {
  196. int screenWide, screenTall;
  197. surface()->GetScreenSize(screenWide, screenTall);
  198. m_ButtonOffsetFromTop = yOffset * screenTall / 480.0f;
  199. }
  200. //=============================================================================
  201. // HPE_END
  202. //=============================================================================
  203. //-----------------------------------------------------------------------------
  204. // Purpose: creates a new button label with icon and text
  205. //-----------------------------------------------------------------------------
  206. void CFooterPanel::AddNewButtonLabel( const char *text, const char *icon )
  207. {
  208. ButtonLabel_t *button = new ButtonLabel_t;
  209. Q_strncpy( button->name, text, MAX_PATH );
  210. button->bVisible = true;
  211. // Button icons are a single character
  212. wchar_t *pIcon = g_pVGuiLocalize->Find( icon );
  213. if ( pIcon )
  214. {
  215. button->icon[0] = pIcon[0];
  216. button->icon[1] = '\0';
  217. }
  218. else
  219. {
  220. button->icon[0] = '\0';
  221. }
  222. // Set the help text
  223. wchar_t *pText = g_pVGuiLocalize->Find( text );
  224. if ( pText )
  225. {
  226. wcsncpy( button->text, pText, wcslen( pText ) + 1 );
  227. }
  228. else
  229. {
  230. button->text[0] = '\0';
  231. }
  232. m_ButtonLabels.AddToTail( button );
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Purpose: Shows/Hides a button label
  236. //-----------------------------------------------------------------------------
  237. void CFooterPanel::ShowButtonLabel( const char *name, bool show )
  238. {
  239. for ( int i = 0; i < m_ButtonLabels.Count(); ++i )
  240. {
  241. if ( !Q_stricmp( m_ButtonLabels[ i ]->name, name ) )
  242. {
  243. m_ButtonLabels[ i ]->bVisible = show;
  244. break;
  245. }
  246. }
  247. }
  248. //-----------------------------------------------------------------------------
  249. // Purpose: Changes a button's text
  250. //-----------------------------------------------------------------------------
  251. void CFooterPanel::SetButtonText( const char *buttonName, const char *text )
  252. {
  253. for ( int i = 0; i < m_ButtonLabels.Count(); ++i )
  254. {
  255. if ( !Q_stricmp( m_ButtonLabels[ i ]->name, buttonName ) )
  256. {
  257. wchar_t *wtext = g_pVGuiLocalize->Find( text );
  258. if ( text )
  259. {
  260. wcsncpy( m_ButtonLabels[ i ]->text, wtext, wcslen( wtext ) + 1 );
  261. }
  262. else
  263. {
  264. m_ButtonLabels[ i ]->text[ 0 ] = '\0';
  265. }
  266. break;
  267. }
  268. }
  269. }
  270. //-----------------------------------------------------------------------------
  271. // Purpose: Footer panel background rendering
  272. //-----------------------------------------------------------------------------
  273. void CFooterPanel::PaintBackground( void )
  274. {
  275. if ( !m_bPaintBackground )
  276. return;
  277. BaseClass::PaintBackground();
  278. }
  279. //-----------------------------------------------------------------------------
  280. // Purpose: Footer panel rendering
  281. //-----------------------------------------------------------------------------
  282. void CFooterPanel::Paint( void )
  283. {
  284. //=============================================================================
  285. // HPE_BEGIN:
  286. // [smessick] Don't draw if alpha'd out.
  287. //=============================================================================
  288. if ( GetAlpha() == 0 )
  289. {
  290. return;
  291. }
  292. //=============================================================================
  293. // HPE_END
  294. //=============================================================================
  295. // inset from right edge
  296. int wide = GetWide();
  297. int right = wide - m_ButtonPinRight;
  298. // center the text within the button
  299. int buttonHeight = vgui::surface()->GetFontTall( m_hButtonFont );
  300. int fontHeight = vgui::surface()->GetFontTall( m_hTextFont );
  301. int textY = ( buttonHeight - fontHeight )/2 + m_TextAdjust;
  302. if ( textY < 0 )
  303. {
  304. textY = 0;
  305. }
  306. int y = m_ButtonOffsetFromTop;
  307. if ( !m_bCenterHorizontal )
  308. {
  309. // draw the buttons, right to left
  310. int x = right;
  311. for ( int i = 0; i < m_ButtonLabels.Count(); ++i )
  312. {
  313. ButtonLabel_t *pButton = m_ButtonLabels[i];
  314. if ( !pButton->bVisible )
  315. continue;
  316. // Get the string length
  317. m_pSizingLabel->SetFont( m_hTextFont );
  318. m_pSizingLabel->SetText( pButton->text );
  319. m_pSizingLabel->SizeToContents();
  320. int iTextWidth = m_pSizingLabel->GetWide();
  321. if ( iTextWidth == 0 )
  322. x += m_nButtonGap; // There's no text, so remove the gap between buttons
  323. else
  324. x -= iTextWidth;
  325. // Draw the string
  326. vgui::surface()->DrawSetTextFont( m_hTextFont );
  327. vgui::surface()->DrawSetTextColor( GetFgColor() );
  328. vgui::surface()->DrawSetTextPos( x, y + textY );
  329. vgui::surface()->DrawPrintText( pButton->text, wcslen( pButton->text ) );
  330. // Draw the button
  331. // back up button width and a little extra to leave a gap between button and text
  332. x -= ( vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] ) + m_ButtonSeparator );
  333. vgui::surface()->DrawSetTextFont( m_hButtonFont );
  334. vgui::surface()->DrawSetTextColor( 255, 255, 255, 255 );
  335. vgui::surface()->DrawSetTextPos( x, y );
  336. vgui::surface()->DrawPrintText( pButton->icon, 1 );
  337. // back up to next string
  338. x -= m_nButtonGap;
  339. }
  340. }
  341. else
  342. {
  343. // center the buttons (as a group)
  344. int x = wide / 2;
  345. int totalWidth = 0;
  346. int i = 0;
  347. int nButtonCount = 0;
  348. // need to loop through and figure out how wide our buttons and text are (with gaps between) so we can offset from the center
  349. for ( i = 0; i < m_ButtonLabels.Count(); ++i )
  350. {
  351. ButtonLabel_t *pButton = m_ButtonLabels[i];
  352. if ( !pButton->bVisible )
  353. continue;
  354. // Get the string length
  355. m_pSizingLabel->SetFont( m_hTextFont );
  356. m_pSizingLabel->SetText( pButton->text );
  357. m_pSizingLabel->SizeToContents();
  358. totalWidth += vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] );
  359. totalWidth += m_ButtonSeparator;
  360. totalWidth += m_pSizingLabel->GetWide();
  361. nButtonCount++; // keep track of how many active buttons we'll be drawing
  362. }
  363. totalWidth += ( nButtonCount - 1 ) * m_nButtonGap; // add in the gaps between the buttons
  364. x -= ( totalWidth / 2 );
  365. for ( i = 0; i < m_ButtonLabels.Count(); ++i )
  366. {
  367. ButtonLabel_t *pButton = m_ButtonLabels[i];
  368. if ( !pButton->bVisible )
  369. continue;
  370. // Get the string length
  371. m_pSizingLabel->SetFont( m_hTextFont );
  372. m_pSizingLabel->SetText( pButton->text );
  373. m_pSizingLabel->SizeToContents();
  374. int iTextWidth = m_pSizingLabel->GetWide();
  375. // Draw the icon
  376. vgui::surface()->DrawSetTextFont( m_hButtonFont );
  377. vgui::surface()->DrawSetTextColor( 255, 255, 255, 255 );
  378. vgui::surface()->DrawSetTextPos( x, y );
  379. vgui::surface()->DrawPrintText( pButton->icon, 1 );
  380. x += vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] ) + m_ButtonSeparator;
  381. // Draw the string
  382. vgui::surface()->DrawSetTextFont( m_hTextFont );
  383. vgui::surface()->DrawSetTextColor( GetFgColor() );
  384. vgui::surface()->DrawSetTextPos( x, y + textY );
  385. vgui::surface()->DrawPrintText( pButton->text, wcslen( pButton->text ) );
  386. x += iTextWidth + m_nButtonGap;
  387. }
  388. }
  389. }
  390. DECLARE_BUILD_FACTORY( CFooterPanel );