Team Fortress 2 Source Code as on 22/4/2020
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.

431 lines
14 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "backgroundpanel.h"
  9. #include <vgui/IVGui.h>
  10. #include <vgui/IScheme.h>
  11. #include <vgui/ISurface.h>
  12. #include <vgui_controls/Label.h>
  13. #include <vgui/ILocalize.h>
  14. #include "vgui_controls/BuildGroup.h"
  15. #include "vgui_controls/BitmapImagePanel.h"
  16. using namespace vgui;
  17. #define DEBUG_WINDOW_RESIZING 0
  18. #define DEBUG_WINDOW_REPOSITIONING 0
  19. class CaptionLabel : public Label
  20. {
  21. public:
  22. CaptionLabel(Panel *parent, const char *panelName, const char *text) : Label(parent, panelName, text)
  23. {
  24. }
  25. virtual void ApplySchemeSettings( vgui::IScheme *pScheme )
  26. {
  27. Label::ApplySchemeSettings( pScheme );
  28. SetFont( pScheme->GetFont( "MenuTitle", IsProportional() ) );
  29. }
  30. };
  31. //-----------------------------------------------------------------------------
  32. // Purpose: transform a normalized value into one that is scaled based the minimum
  33. // of the horizontal and vertical ratios
  34. //-----------------------------------------------------------------------------
  35. static int GetAlternateProportionalValueFromNormal(int normalizedValue)
  36. {
  37. int wide, tall;
  38. GetHudSize( wide, tall );
  39. int proH, proW;
  40. surface()->GetProportionalBase( proW, proH );
  41. double scaleH = (double)tall / (double)proH;
  42. double scaleW = (double)wide / (double)proW;
  43. double scale = (scaleW < scaleH) ? scaleW : scaleH;
  44. return (int)( normalizedValue * scale );
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Purpose: transform a standard scaled value into one that is scaled based the minimum
  48. // of the horizontal and vertical ratios
  49. //-----------------------------------------------------------------------------
  50. int GetAlternateProportionalValueFromScaled( HScheme hScheme, int scaledValue)
  51. {
  52. return GetAlternateProportionalValueFromNormal( scheme()->GetProportionalNormalizedValueEx( hScheme, scaledValue ) );
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Purpose: moves and resizes a single control
  56. //-----------------------------------------------------------------------------
  57. static void RepositionControl( Panel *pPanel )
  58. {
  59. int x, y, w, h;
  60. pPanel->GetBounds(x, y, w, h);
  61. #if DEBUG_WINDOW_RESIZING
  62. int x1, y1, w1, h1;
  63. pPanel->GetBounds(x1, y1, w1, h1);
  64. int x2, y2, w2, h2;
  65. x2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), x1 );
  66. y2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), y1 );
  67. w2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), w1 );
  68. h2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), h1 );
  69. #endif
  70. x = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),x);
  71. y = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),y);
  72. w = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),w);
  73. h = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),h);
  74. pPanel->SetBounds(x, y, w, h);
  75. #if DEBUG_WINDOW_RESIZING
  76. DevMsg( "Resizing '%s' from (%d,%d) %dx%d to (%d,%d) %dx%d -- initially was (%d,%d) %dx%d\n",
  77. pPanel->GetName(), x1, y1, w1, h1, x, y, w, h, x2, y2, w2, h2 );
  78. #endif
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Purpose: Sets colors etc for background image panels
  82. //-----------------------------------------------------------------------------
  83. void ApplyBackgroundSchemeSettings( EditablePanel *pWindow, vgui::IScheme *pScheme )
  84. {
  85. Color bgColor = Color( 255, 255, 255, pScheme->GetColor( "BgColor", Color( 0, 0, 0, 0 ) )[3] );
  86. Color fgColor = pScheme->GetColor( "FgColor", Color( 0, 0, 0, 0 ) );
  87. if ( !pWindow )
  88. return;
  89. CBitmapImagePanel *pBitmapPanel;
  90. // corners --------------------------------------------
  91. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopLeftPanel" ));
  92. if ( pBitmapPanel )
  93. {
  94. pBitmapPanel->setImageColor( bgColor );
  95. }
  96. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopRightPanel" ));
  97. if ( pBitmapPanel )
  98. {
  99. pBitmapPanel->setImageColor( bgColor );
  100. }
  101. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomLeftPanel" ));
  102. if ( pBitmapPanel )
  103. {
  104. pBitmapPanel->setImageColor( bgColor );
  105. }
  106. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomRightPanel" ));
  107. if ( pBitmapPanel )
  108. {
  109. pBitmapPanel->setImageColor( bgColor );
  110. }
  111. // background -----------------------------------------
  112. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopSolid" ));
  113. if ( pBitmapPanel )
  114. {
  115. pBitmapPanel->setImageColor( bgColor );
  116. }
  117. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "UpperMiddleSolid" ));
  118. if ( pBitmapPanel )
  119. {
  120. pBitmapPanel->setImageColor( bgColor );
  121. }
  122. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "LowerMiddleSolid" ));
  123. if ( pBitmapPanel )
  124. {
  125. pBitmapPanel->setImageColor( bgColor );
  126. }
  127. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomSolid" ));
  128. if ( pBitmapPanel )
  129. {
  130. pBitmapPanel->setImageColor( bgColor );
  131. }
  132. // Logo -----------------------------------------------
  133. pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "ExclamationPanel" ));
  134. if ( pBitmapPanel )
  135. {
  136. pBitmapPanel->setImageColor( fgColor );
  137. }
  138. }
  139. //-----------------------------------------------------------------------------
  140. // Purpose: Re-aligns background image panels so they are touching.
  141. //-----------------------------------------------------------------------------
  142. static void FixupBackgroundPanels( EditablePanel *pWindow, int offsetX, int offsetY )
  143. {
  144. if ( !pWindow )
  145. return;
  146. int screenWide, screenTall;
  147. pWindow->GetSize( screenWide, screenTall );
  148. int inset = GetAlternateProportionalValueFromNormal( 20 );
  149. int cornerSize = GetAlternateProportionalValueFromNormal( 10 );
  150. int titleHeight = GetAlternateProportionalValueFromNormal( 42 );
  151. int mainHeight = GetAlternateProportionalValueFromNormal( 376 );
  152. int logoSize = titleHeight;
  153. int captionInset = GetAlternateProportionalValueFromNormal( 76 );
  154. Panel *pPanel;
  155. // corners --------------------------------------------
  156. pPanel = pWindow->FindChildByName( "TopLeftPanel" );
  157. if ( pPanel )
  158. {
  159. pPanel->SetZPos( -20 );
  160. pPanel->SetBounds( offsetX + inset, offsetY + inset, cornerSize, cornerSize );
  161. }
  162. pPanel = pWindow->FindChildByName( "TopRightPanel" );
  163. if ( pPanel )
  164. {
  165. pPanel->SetZPos( -20 );
  166. pPanel->SetBounds( screenWide - offsetX - inset - cornerSize, offsetY + inset, cornerSize, cornerSize );
  167. }
  168. pPanel = pWindow->FindChildByName( "BottomLeftPanel" );
  169. if ( pPanel )
  170. {
  171. pPanel->SetZPos( -20 );
  172. pPanel->SetBounds( offsetX + inset, screenTall - offsetY - inset - cornerSize, cornerSize, cornerSize );
  173. }
  174. pPanel = pWindow->FindChildByName( "BottomRightPanel" );
  175. if ( pPanel )
  176. {
  177. pPanel->SetZPos( -20 );
  178. pPanel->SetBounds( screenWide - offsetX - inset - cornerSize, screenTall - offsetY - inset - cornerSize, cornerSize, cornerSize );
  179. }
  180. // background -----------------------------------------
  181. pPanel = pWindow->FindChildByName( "TopSolid" );
  182. if ( pPanel )
  183. {
  184. pPanel->SetZPos( -20 );
  185. pPanel->SetBounds( offsetX + inset + cornerSize, offsetY + inset, screenWide - 2*offsetX - 2*inset - 2*cornerSize, cornerSize );
  186. }
  187. pPanel = pWindow->FindChildByName( "UpperMiddleSolid" );
  188. if ( pPanel )
  189. {
  190. pPanel->SetZPos( -20 );
  191. pPanel->SetBounds( offsetX + inset, offsetY + inset + cornerSize, screenWide - 2*offsetX - 2*inset, titleHeight );
  192. }
  193. pPanel = pWindow->FindChildByName( "LowerMiddleSolid" );
  194. if ( pPanel )
  195. {
  196. pPanel->SetZPos( -20 );
  197. pPanel->SetBounds( offsetX + inset + cornerSize, screenTall - offsetY - inset - cornerSize, screenWide - 2*offsetX - 2*inset - 2*cornerSize, cornerSize );
  198. }
  199. pPanel = pWindow->FindChildByName( "BottomSolid" );
  200. if ( pPanel )
  201. {
  202. pPanel->SetZPos( -20 );
  203. pPanel->SetBounds( offsetX + inset, screenTall - offsetY - inset - cornerSize - mainHeight, screenWide - 2*offsetX - 2*inset, mainHeight );
  204. }
  205. // transparent border ---------------------------------
  206. pPanel = pWindow->FindChildByName( "TopClear" );
  207. if ( pPanel )
  208. {
  209. pPanel->SetZPos( -20 );
  210. pPanel->SetBounds( 0, 0, screenWide, offsetY + inset );
  211. }
  212. pPanel = pWindow->FindChildByName( "BottomClear" );
  213. if ( pPanel )
  214. {
  215. pPanel->SetZPos( -20 );
  216. pPanel->SetBounds( 0, screenTall - offsetY - inset, screenWide, offsetY + inset );
  217. }
  218. pPanel = pWindow->FindChildByName( "LeftClear" );
  219. if ( pPanel )
  220. {
  221. pPanel->SetZPos( -20 );
  222. pPanel->SetBounds( 0, offsetY + inset, offsetX + inset, screenTall - 2*offsetY - 2*inset );
  223. }
  224. pPanel = pWindow->FindChildByName( "RightClear" );
  225. if ( pPanel )
  226. {
  227. pPanel->SetZPos( -20 );
  228. pPanel->SetBounds( screenWide - offsetX - inset, offsetY + inset, offsetX + inset, screenTall - 2*offsetY - 2*inset );
  229. }
  230. // Logo -----------------------------------------------
  231. int logoInset = (cornerSize + titleHeight - logoSize)/2;
  232. pPanel = pWindow->FindChildByName( "ExclamationPanel" );
  233. if ( pPanel )
  234. {
  235. pPanel->SetZPos( -19 ); // higher than the background
  236. pPanel->SetBounds( offsetX + inset + logoInset, offsetY + inset + logoInset, logoSize, logoSize );
  237. }
  238. // Title caption --------------------------------------
  239. pPanel = dynamic_cast< Label * >(pWindow->FindChildByName( "CaptionLabel" ));
  240. if ( pPanel )
  241. {
  242. pPanel->SetZPos( -19 ); // higher than the background
  243. pPanel->SetBounds( offsetX + captionInset/*inset + 2*logoInset + logoSize*/, offsetY + inset + logoInset, screenWide, logoSize );
  244. }
  245. }
  246. //-----------------------------------------------------------------------------
  247. // Purpose: Creates background image panels
  248. //-----------------------------------------------------------------------------
  249. void CreateBackground( EditablePanel *pWindow )
  250. {
  251. // corners --------------------------------------------
  252. new CBitmapImagePanel( pWindow, "TopLeftPanel", "gfx/vgui/round_corner_nw" );
  253. new CBitmapImagePanel( pWindow, "TopRightPanel", "gfx/vgui/round_corner_ne" );
  254. new CBitmapImagePanel( pWindow, "BottomLeftPanel", "gfx/vgui/round_corner_sw" );
  255. new CBitmapImagePanel( pWindow, "BottomRightPanel", "gfx/vgui/round_corner_se" );
  256. // background -----------------------------------------
  257. new CBitmapImagePanel( pWindow, "TopSolid", "gfx/vgui/solid_background" );
  258. new CBitmapImagePanel( pWindow, "UpperMiddleSolid", "gfx/vgui/solid_background" );
  259. new CBitmapImagePanel( pWindow, "LowerMiddleSolid", "gfx/vgui/solid_background" );
  260. new CBitmapImagePanel( pWindow, "BottomSolid", "gfx/vgui/solid_background" );
  261. // transparent border ---------------------------------
  262. new CBitmapImagePanel( pWindow, "TopClear", "gfx/vgui/trans_background" );
  263. new CBitmapImagePanel( pWindow, "BottomClear", "gfx/vgui/trans_background" );
  264. new CBitmapImagePanel( pWindow, "LeftClear", "gfx/vgui/trans_background" );
  265. new CBitmapImagePanel( pWindow, "RightClear", "gfx/vgui/trans_background" );
  266. // Logo -----------------------------------------------
  267. new CBitmapImagePanel( pWindow, "ExclamationPanel", "gfx/vgui/hl2mp_logo" );
  268. // Title caption --------------------------------------
  269. Panel *pPanel = dynamic_cast< Label * >(pWindow->FindChildByName( "CaptionLabel" ));
  270. if ( !pPanel )
  271. new CaptionLabel( pWindow, "CaptionLabel", "" );
  272. }
  273. void ResizeWindowControls( EditablePanel *pWindow, int tall, int wide, int offsetX, int offsetY )
  274. {
  275. if (!pWindow || !pWindow->GetBuildGroup() || !pWindow->GetBuildGroup()->GetPanelList())
  276. return;
  277. CUtlVector<PHandle> *panelList = pWindow->GetBuildGroup()->GetPanelList();
  278. CUtlVector<Panel *> resizedPanels;
  279. CUtlVector<Panel *> movedPanels;
  280. // Resize to account for 1.25 aspect ratio (1280x1024) screens
  281. {
  282. for ( int i = 0; i < panelList->Size(); ++i )
  283. {
  284. PHandle handle = (*panelList)[i];
  285. Panel *panel = handle.Get();
  286. bool found = false;
  287. for ( int j = 0; j < resizedPanels.Size(); ++j )
  288. {
  289. if (panel == resizedPanels[j])
  290. found = true;
  291. }
  292. if (!panel || found)
  293. {
  294. continue;
  295. }
  296. resizedPanels.AddToTail( panel ); // don't move a panel more than once
  297. if ( panel != pWindow )
  298. {
  299. RepositionControl( panel );
  300. }
  301. }
  302. }
  303. // and now re-center them. Woohoo!
  304. for ( int i = 0; i < panelList->Size(); ++i )
  305. {
  306. PHandle handle = (*panelList)[i];
  307. Panel *panel = handle.Get();
  308. bool found = false;
  309. for ( int j = 0; j < movedPanels.Size(); ++j )
  310. {
  311. if (panel == movedPanels[j])
  312. found = true;
  313. }
  314. if (!panel || found)
  315. {
  316. continue;
  317. }
  318. movedPanels.AddToTail( panel ); // don't move a panel more than once
  319. if ( panel != pWindow )
  320. {
  321. int x, y;
  322. panel->GetPos( x, y );
  323. panel->SetPos( x + offsetX, y + offsetY );
  324. #if DEBUG_WINDOW_REPOSITIONING
  325. DevMsg( "Repositioning '%s' from (%d,%d) to (%d,%d) -- a distance of (%d,%d)\n",
  326. panel->GetName(), x, y, x + offsetX, y + offsetY, offsetX, offsetY );
  327. #endif
  328. }
  329. }
  330. }
  331. //-----------------------------------------------------------------------------
  332. // Purpose: Resizes windows to fit completely on-screen (for 1280x1024), and
  333. // centers them on the screen. Sub-controls are also resized and moved.
  334. //-----------------------------------------------------------------------------
  335. void LayoutBackgroundPanel( EditablePanel *pWindow )
  336. {
  337. if ( !pWindow )
  338. return;
  339. int screenW, screenH;
  340. GetHudSize( screenW, screenH );
  341. int wide, tall;
  342. pWindow->GetSize( wide, tall );
  343. int offsetX = 0;
  344. int offsetY = 0;
  345. // Slide everything over to the center
  346. pWindow->SetBounds( 0, 0, screenW, screenH );
  347. if ( wide != screenW || tall != screenH )
  348. {
  349. wide = GetAlternateProportionalValueFromScaled(pWindow->GetScheme(), wide);
  350. tall = GetAlternateProportionalValueFromScaled(pWindow->GetScheme(), tall);
  351. offsetX = (screenW - wide)/2;
  352. offsetY = (screenH - tall)/2;
  353. ResizeWindowControls( pWindow, tall, wide, offsetX, offsetY );
  354. }
  355. // now that the panels are moved/resized, look for some bg panels, and re-align them
  356. FixupBackgroundPanels( pWindow, offsetX, offsetY );
  357. }
  358. //-----------------------------------------------------------------------------