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.

430 lines
12 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "toolutils/miniviewport.h"
  7. #include "tier1/utlstring.h"
  8. #include "vgui/ISurface.h"
  9. #include "materialsystem/imaterialsystemhardwareconfig.h"
  10. #include "materialsystem/IMaterialSystem.h"
  11. #include "materialsystem/MaterialSystemUtil.h"
  12. #include "materialsystem/IMesh.h"
  13. #include "materialsystem/IMaterial.h"
  14. #include "materialsystem/itexture.h"
  15. #include "tier1/KeyValues.h"
  16. #include "toolframework/ienginetool.h"
  17. #include "toolutils/enginetools_int.h"
  18. #include "vguimatsurface/imatsystemsurface.h"
  19. #include "view_shared.h"
  20. #include "texture_group_names.h"
  21. #include "vgui_controls/PropertySheet.h"
  22. #include "tier3/tier3.h"
  23. #include <windows.h> // for MultiByteToWideChar
  24. #include "cdll_int.h"
  25. // memdbgon must be the last include file in a .cpp file!!!
  26. #include "tier0/memdbgon.h"
  27. class CMiniViewportEngineRenderArea;
  28. using namespace vgui;
  29. #define DEFAULT_PREVIEW_WIDTH 1280
  30. //-----------------------------------------------------------------------------
  31. // Purpose: This is a "frame" which is used to position the engine
  32. //-----------------------------------------------------------------------------
  33. class CMiniViewportPropertyPage : public vgui::EditablePanel
  34. {
  35. DECLARE_CLASS_SIMPLE( CMiniViewportPropertyPage, vgui::EditablePanel );
  36. public:
  37. CMiniViewportPropertyPage( Panel *parent, const char *panelName );
  38. virtual Color GetBgColor();
  39. void GetEngineBounds( int& x, int& y, int& w, int& h );
  40. void RenderFrameBegin();
  41. CMiniViewportEngineRenderArea *GetViewportArea() { return m_pViewportArea; }
  42. private:
  43. virtual void PerformLayout();
  44. Color m_bgColor;
  45. CMiniViewportEngineRenderArea *m_pViewportArea;
  46. };
  47. //-----------------------------------------------------------------------------
  48. //
  49. // the actual renderable area
  50. //
  51. //-----------------------------------------------------------------------------
  52. class CMiniViewportEngineRenderArea : public vgui::EditablePanel
  53. {
  54. DECLARE_CLASS_SIMPLE( CMiniViewportEngineRenderArea, vgui::EditablePanel );
  55. public:
  56. CMiniViewportEngineRenderArea( Panel *parent, const char *panelName );
  57. ~CMiniViewportEngineRenderArea();
  58. virtual void PaintBackground();
  59. virtual void GetEngineBounds( int& x, int& y, int& w, int& h );
  60. virtual void ApplySchemeSettings( IScheme *pScheme );
  61. void RenderFrameBegin();
  62. void SetOverlayText( const char *pText );
  63. protected:
  64. void InitSceneMaterials();
  65. void ShutdownSceneMaterials();
  66. // Paints the black borders around the engine window
  67. void PaintEngineBorders( int x, int y, int w, int h );
  68. // Paints the engine window itself
  69. void PaintEngineWindow( int x, int y, int w, int h );
  70. // Paints the overlay text
  71. void PaintOverlayText( );
  72. int m_nEngineOutputTexture;
  73. vgui::HFont m_OverlayTextFont;
  74. CUtlString m_OverlayText;
  75. CTextureReference m_ScreenBuffer;
  76. CMaterialReference m_ScreenMaterial;
  77. };
  78. CMiniViewportEngineRenderArea::CMiniViewportEngineRenderArea( Panel *parent, const char *panelName )
  79. : BaseClass( parent, panelName )
  80. {
  81. SetPaintEnabled( false );
  82. SetPaintBorderEnabled( false );
  83. SetPaintBackgroundEnabled( true );
  84. m_nEngineOutputTexture = vgui::surface()->CreateNewTextureID();
  85. }
  86. CMiniViewportEngineRenderArea::~CMiniViewportEngineRenderArea()
  87. {
  88. ShutdownSceneMaterials();
  89. }
  90. void CMiniViewportEngineRenderArea::RenderFrameBegin()
  91. {
  92. if ( !enginetools->IsInGame() )
  93. return;
  94. InitSceneMaterials();
  95. CViewSetup playerViewSetup;
  96. int x, y, w, h;
  97. GetEngineBounds( x, y, w, h );
  98. enginetools->GetPlayerView( playerViewSetup, 0, 0, w, h );
  99. // NOTE: This is a workaround to a nasty problem. Vgui uses stencil
  100. // to determing if the panels should occlude each other. The engine
  101. // has now started to use stencil for various random effects.
  102. // To prevent these different stencil uses from clashing, we will
  103. // render the engine prior to vgui painting + cache the result off in
  104. //
  105. // Make the engine draw the scene
  106. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  107. pRenderContext->PushRenderTargetAndViewport( m_ScreenBuffer, 0, 0, w, h );
  108. // Tell the engine to tell the client to render the view (sans viewmodel)
  109. enginetools->SetMainView( playerViewSetup.origin, playerViewSetup.angles );
  110. enginetools->RenderView( playerViewSetup, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, RENDERVIEW_DRAWHUD | RENDERVIEW_DRAWVIEWMODEL );
  111. // Pop the target
  112. pRenderContext->PopRenderTargetAndViewport();
  113. }
  114. void CMiniViewportEngineRenderArea::InitSceneMaterials()
  115. {
  116. if ( m_ScreenBuffer )
  117. return;
  118. if ( g_pMaterialSystem->IsTextureLoaded( "_rt_LayoffResult" ) )
  119. {
  120. ITexture *pTexture = g_pMaterialSystem->FindTexture( "_rt_LayoffResult", TEXTURE_GROUP_RENDER_TARGET );
  121. m_ScreenBuffer.Init( pTexture );
  122. }
  123. else
  124. {
  125. // For now, layoff dimensions match aspect of back buffer
  126. int nBackBufferWidth, nBackBufferHeight;
  127. g_pMaterialSystem->GetBackBufferDimensions( nBackBufferWidth, nBackBufferHeight );
  128. float flAspect = nBackBufferWidth / (float)nBackBufferHeight;
  129. int nPreviewWidth = min( DEFAULT_PREVIEW_WIDTH, nBackBufferWidth );
  130. int nPreviewHeight = ( int )( nPreviewWidth / flAspect + 0.5f );
  131. g_pMaterialSystem->BeginRenderTargetAllocation(); // Begin allocating RTs which IFM can scribble into
  132. // LDR final result of either HDR or LDR rendering
  133. m_ScreenBuffer.Init( g_pMaterialSystem->CreateNamedRenderTargetTextureEx2(
  134. "_rt_LayoffResult", nPreviewWidth, nPreviewHeight, RT_SIZE_OFFSCREEN,
  135. g_pMaterialSystem->GetBackBufferFormat(), MATERIAL_RT_DEPTH_SHARED, TEXTUREFLAGS_BORDER ) );
  136. g_pMaterialSystem->EndRenderTargetAllocation(); // End allocating RTs which IFM can scribble into
  137. }
  138. KeyValues *pVMTKeyValues = NULL;
  139. pVMTKeyValues= new KeyValues( "UnlitGeneric" );
  140. pVMTKeyValues->SetString( "$basetexture", m_ScreenBuffer->GetName() );
  141. pVMTKeyValues->SetInt( "$nofog", 1 );
  142. m_ScreenMaterial.Init( "MiniViewportEngineRenderAreaSceneMaterial", pVMTKeyValues );
  143. m_ScreenMaterial->Refresh();
  144. }
  145. //-----------------------------------------------------------------------------
  146. // Apply scheme settings
  147. //-----------------------------------------------------------------------------
  148. void CMiniViewportEngineRenderArea::ApplySchemeSettings( IScheme *pScheme )
  149. {
  150. BaseClass::ApplySchemeSettings( pScheme );
  151. m_OverlayTextFont = pScheme->GetFont( "DefaultLargeOutline" );
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Purpose:
  155. //-----------------------------------------------------------------------------
  156. void CMiniViewportEngineRenderArea::ShutdownSceneMaterials()
  157. {
  158. m_ScreenBuffer.Shutdown();
  159. m_ScreenMaterial.Shutdown();
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Sets text to draw over the window
  163. //-----------------------------------------------------------------------------
  164. void CMiniViewportEngineRenderArea::SetOverlayText( const char *pText )
  165. {
  166. m_OverlayText = pText;
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Paints the black borders around the engine window
  170. //-----------------------------------------------------------------------------
  171. void CMiniViewportEngineRenderArea::PaintEngineBorders( int x, int y, int w, int h )
  172. {
  173. // Draws black borders around the engine window
  174. surface()->DrawSetColor( Color( 0, 0, 0, 255 ) );
  175. if ( x != 0 )
  176. {
  177. surface()->DrawFilledRect( 0, 0, x, h );
  178. surface()->DrawFilledRect( x + w, 0, w + 2 * x, h );
  179. }
  180. else if ( y != 0 )
  181. {
  182. surface()->DrawFilledRect( 0, 0, w, y );
  183. surface()->DrawFilledRect( 0, y + h, w, h + 2 * y );
  184. }
  185. }
  186. //-----------------------------------------------------------------------------
  187. // Paints the overlay text
  188. //-----------------------------------------------------------------------------
  189. void CMiniViewportEngineRenderArea::PaintOverlayText( )
  190. {
  191. if ( !m_OverlayText.Length() )
  192. return;
  193. int cw, ch;
  194. GetSize( cw, ch );
  195. int nTextWidth, nTextHeight;
  196. int nBufLen = m_OverlayText.Length()+1;
  197. wchar_t *pTemp = (wchar_t*)_alloca( nBufLen * sizeof(wchar_t) );
  198. ::MultiByteToWideChar( CP_UTF8, 0, m_OverlayText.Get(), -1, pTemp, nBufLen );
  199. g_pMatSystemSurface->GetTextSize( m_OverlayTextFont, pTemp, nTextWidth, nTextHeight );
  200. int lx = (cw - nTextWidth) / 2;
  201. if ( lx < 10 )
  202. {
  203. lx = 10;
  204. }
  205. int ly = ch - 10 - nTextHeight;
  206. g_pMatSystemSurface->DrawColoredTextRect( m_OverlayTextFont,
  207. lx, ly, cw - lx, ch - ly,
  208. 255, 255, 255, 255, "%s", m_OverlayText.Get() );
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Paints the engine window itself
  212. //-----------------------------------------------------------------------------
  213. void CMiniViewportEngineRenderArea::PaintEngineWindow( int x, int y, int w, int h )
  214. {
  215. if ( !enginetools->IsInGame() )
  216. {
  217. surface()->DrawSetColor( Color( 127, 127, 200, 63 ) );
  218. surface()->DrawFilledRect( x, y, x + w, y + h );
  219. }
  220. else
  221. {
  222. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  223. g_pMatSystemSurface->DrawSetTextureMaterial( m_nEngineOutputTexture, m_ScreenMaterial );
  224. surface()->DrawSetColor( Color( 0, 0, 0, 255 ) );
  225. int nTexWidth = m_ScreenBuffer->GetActualWidth();
  226. int nTexHeight = m_ScreenBuffer->GetActualHeight();
  227. float flOOWidth = 1.0f / nTexWidth;
  228. float flOOHeight = 1.0f / nTexHeight;
  229. float s0, s1, t0, t1;
  230. s0 = ( 0.5f ) * flOOWidth;
  231. t0 = ( 0.5f ) * flOOHeight;
  232. s1 = ( (float)w - 0.5f ) * flOOWidth;
  233. t1 = ( (float)h - 0.5f ) * flOOHeight;
  234. vgui::surface()->DrawTexturedSubRect( x, y, x+w, y+h, s0, t0, s1, t1 );
  235. PaintOverlayText();
  236. }
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Paints the background
  240. //-----------------------------------------------------------------------------
  241. void CMiniViewportEngineRenderArea::PaintBackground()
  242. {
  243. int x, y, w, h;
  244. GetEngineBounds( x, y, w, h );
  245. PaintEngineBorders( x, y, w, h );
  246. PaintEngineWindow( x, y, w, h );
  247. }
  248. void CMiniViewportEngineRenderArea::GetEngineBounds( int& x, int& y, int& w, int& h )
  249. {
  250. x = 0;
  251. y = 0;
  252. GetSize( w, h );
  253. // Check aspect ratio
  254. int sx, sy;
  255. surface()->GetScreenSize( sx, sy );
  256. if ( sy > 0 &&
  257. h > 0 )
  258. {
  259. float screenaspect = (float)sx / (float)sy;
  260. float aspect = (float)w / (float)h;
  261. float ratio = screenaspect / aspect;
  262. // Screen is wider, need bars at top and bottom
  263. if ( ratio > 1.0f )
  264. {
  265. int usetall = (float)w / screenaspect;
  266. y = ( h - usetall ) / 2;
  267. h = usetall;
  268. }
  269. // Screen is narrower, need bars at left/right
  270. else
  271. {
  272. int usewide = (float)h * screenaspect;
  273. x = ( w - usewide ) / 2;
  274. w = usewide;
  275. }
  276. }
  277. }
  278. CMiniViewportPropertyPage::CMiniViewportPropertyPage(Panel *parent, const char *panelName ) :
  279. BaseClass( parent, panelName )
  280. {
  281. m_bgColor = Color( 0, 0, 0, 0 );
  282. m_pViewportArea = new CMiniViewportEngineRenderArea( this, "Engine" );
  283. }
  284. void CMiniViewportPropertyPage::PerformLayout()
  285. {
  286. BaseClass::PerformLayout();
  287. int w, h;
  288. GetSize( w, h );
  289. m_pViewportArea->SetBounds( 0, 0, w, h );
  290. }
  291. Color CMiniViewportPropertyPage::GetBgColor()
  292. {
  293. return m_bgColor;
  294. }
  295. void CMiniViewportPropertyPage::GetEngineBounds( int& x, int& y, int& w, int& h )
  296. {
  297. m_pViewportArea->GetEngineBounds( x, y, w, h );
  298. m_pViewportArea->LocalToScreen( x, y );
  299. }
  300. void CMiniViewportPropertyPage::RenderFrameBegin()
  301. {
  302. m_pViewportArea->RenderFrameBegin();
  303. }
  304. CMiniViewport::CMiniViewport( vgui::Panel *parent, bool contextLabel, vgui::IToolWindowFactory *factory /*= 0*/,
  305. vgui::Panel *page /*= NULL*/, char const *title /*= NULL*/, bool contextMenu /*= false*/ ) :
  306. BaseClass( parent, contextLabel, factory, page, title, contextMenu, false )
  307. {
  308. SetCloseButtonVisible( false );
  309. GetPropertySheet()->SetDraggableTabs( false );
  310. // Add the viewport panel
  311. m_hPage = new CMiniViewportPropertyPage( this, "ViewportPage" );
  312. AddPage( m_hPage.Get(), "#ToolMiniViewport", false );
  313. }
  314. void CMiniViewport::GetViewport( bool& enabled, int& x, int& y, int& w, int& h )
  315. {
  316. enabled = false;
  317. x = y = w = h = 0;
  318. int screenw, screenh;
  319. surface()->GetScreenSize( screenw, screenh );
  320. m_hPage->GetEngineBounds( x, y, w, h );
  321. y = screenh - ( y + h );
  322. }
  323. void CMiniViewport::GetEngineBounds( int& x, int& y, int& w, int& h )
  324. {
  325. m_hPage->GetEngineBounds( x, y, w, h );
  326. }
  327. //-----------------------------------------------------------------------------
  328. // Sets text to draw over the window
  329. //-----------------------------------------------------------------------------
  330. void CMiniViewport::SetOverlayText( const char *pText )
  331. {
  332. if ( m_hPage.Get() )
  333. {
  334. m_hPage->GetViewportArea()->SetOverlayText( pText );
  335. }
  336. }
  337. void CMiniViewport::RenderFrameBegin()
  338. {
  339. if ( m_hPage.Get() )
  340. {
  341. m_hPage->RenderFrameBegin();
  342. }
  343. }