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.
457 lines
13 KiB
457 lines
13 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#include "toolutils/miniviewport.h" |
|
#include "tier1/utlstring.h" |
|
#include "vgui/ISurface.h" |
|
#include "materialsystem/imaterialsystemhardwareconfig.h" |
|
#include "materialsystem/imaterialsystem.h" |
|
#include "materialsystem/MaterialSystemUtil.h" |
|
#include "materialsystem/imesh.h" |
|
#include "materialsystem/imaterial.h" |
|
#include "materialsystem/itexture.h" |
|
#include "tier1/KeyValues.h" |
|
#include "toolframework/ienginetool.h" |
|
#include "toolutils/enginetools_int.h" |
|
#include "VGuiMatSurface/IMatSystemSurface.h" |
|
#include "view_shared.h" |
|
#include "texture_group_names.h" |
|
#include "vgui_controls/PropertySheet.h" |
|
#include "tier2/tier2.h" |
|
#include <windows.h> // for MultiByteToWideChar |
|
#include "cdll_int.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
class CMiniViewportEngineRenderArea; |
|
|
|
using namespace vgui; |
|
|
|
extern IMatSystemSurface *g_pMatSystemSurface; |
|
|
|
#define DEFAULT_PREVIEW_WIDTH 1280 |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: This is a "frame" which is used to position the engine |
|
//----------------------------------------------------------------------------- |
|
class CMiniViewportPropertyPage : public vgui::EditablePanel |
|
{ |
|
DECLARE_CLASS_SIMPLE( CMiniViewportPropertyPage, vgui::EditablePanel ); |
|
|
|
public: |
|
CMiniViewportPropertyPage( Panel *parent, const char *panelName ); |
|
|
|
virtual Color GetBgColor(); |
|
|
|
void GetEngineBounds( int& x, int& y, int& w, int& h ); |
|
|
|
void RenderFrameBegin(); |
|
|
|
CMiniViewportEngineRenderArea *GetViewportArea() { return m_pViewportArea; } |
|
|
|
private: |
|
virtual void PerformLayout(); |
|
|
|
Color m_bgColor; |
|
|
|
CMiniViewportEngineRenderArea *m_pViewportArea; |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
// the actual renderable area |
|
// |
|
//----------------------------------------------------------------------------- |
|
class CMiniViewportEngineRenderArea : public vgui::EditablePanel |
|
{ |
|
DECLARE_CLASS_SIMPLE( CMiniViewportEngineRenderArea, vgui::EditablePanel ); |
|
|
|
public: |
|
CMiniViewportEngineRenderArea( Panel *parent, const char *panelName ); |
|
~CMiniViewportEngineRenderArea(); |
|
|
|
virtual void PaintBackground(); |
|
virtual void GetEngineBounds( int& x, int& y, int& w, int& h ); |
|
virtual void ApplySchemeSettings( IScheme *pScheme ); |
|
|
|
void RenderFrameBegin(); |
|
void SetOverlayText( const char *pText ); |
|
|
|
// Called when the layoff texture needs to be released |
|
void ReleaseLayoffTexture(); |
|
|
|
protected: |
|
void InitSceneMaterials(); |
|
void ShutdownSceneMaterials(); |
|
|
|
// Paints the black borders around the engine window |
|
void PaintEngineBorders( int x, int y, int w, int h ); |
|
|
|
// Paints the engine window itself |
|
void PaintEngineWindow( int x, int y, int w, int h ); |
|
|
|
// Paints the overlay text |
|
void PaintOverlayText( ); |
|
|
|
int m_nEngineOutputTexture; |
|
vgui::HFont m_OverlayTextFont; |
|
CUtlString m_OverlayText; |
|
|
|
CTextureReference m_ScreenBuffer; |
|
CMaterialReference m_ScreenMaterial; |
|
}; |
|
|
|
|
|
CMiniViewportEngineRenderArea::CMiniViewportEngineRenderArea( Panel *parent, const char *panelName ) |
|
: BaseClass( parent, panelName ) |
|
{ |
|
SetPaintEnabled( false ); |
|
SetPaintBorderEnabled( false ); |
|
SetPaintBackgroundEnabled( true ); |
|
|
|
m_nEngineOutputTexture = vgui::surface()->CreateNewTextureID(); |
|
} |
|
|
|
CMiniViewportEngineRenderArea::~CMiniViewportEngineRenderArea() |
|
{ |
|
ShutdownSceneMaterials(); |
|
} |
|
|
|
void CMiniViewportEngineRenderArea::RenderFrameBegin() |
|
{ |
|
if ( !enginetools->IsInGame() ) |
|
return; |
|
|
|
InitSceneMaterials(); |
|
|
|
CViewSetup playerViewSetup; |
|
int x, y, w, h; |
|
GetEngineBounds( x, y, w, h ); |
|
enginetools->GetPlayerView( playerViewSetup, 0, 0, w, h ); |
|
|
|
// NOTE: This is a workaround to a nasty problem. Vgui uses stencil |
|
// to determing if the panels should occlude each other. The engine |
|
// has now started to use stencil for various random effects. |
|
// To prevent these different stencil uses from clashing, we will |
|
// render the engine prior to vgui painting + cache the result off in |
|
// |
|
// Make the engine draw the scene |
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); |
|
pRenderContext->PushRenderTargetAndViewport( m_ScreenBuffer, 0, 0, w, h ); |
|
|
|
// Tell the engine to tell the client to render the view (sans viewmodel) |
|
enginetools->SetMainView( playerViewSetup.origin, playerViewSetup.angles ); |
|
enginetools->RenderView( playerViewSetup, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, RENDERVIEW_DRAWHUD | RENDERVIEW_DRAWVIEWMODEL ); |
|
|
|
// Pop the target |
|
pRenderContext->PopRenderTargetAndViewport(); |
|
} |
|
|
|
void CMiniViewportEngineRenderArea::InitSceneMaterials() |
|
{ |
|
if ( m_ScreenBuffer ) |
|
return; |
|
|
|
if ( g_pMaterialSystem->IsTextureLoaded( "_rt_LayoffResult" ) ) |
|
{ |
|
ITexture *pTexture = g_pMaterialSystem->FindTexture( "_rt_LayoffResult", TEXTURE_GROUP_RENDER_TARGET ); |
|
m_ScreenBuffer.Init( pTexture ); |
|
} |
|
else |
|
{ |
|
// For now, layoff dimensions match aspect of back buffer |
|
int nBackBufferWidth, nBackBufferHeight; |
|
g_pMaterialSystem->GetBackBufferDimensions( nBackBufferWidth, nBackBufferHeight ); |
|
float flAspect = nBackBufferWidth / (float)nBackBufferHeight; |
|
int nPreviewWidth = min( DEFAULT_PREVIEW_WIDTH, nBackBufferWidth ); |
|
int nPreviewHeight = ( int )( nPreviewWidth / flAspect + 0.5f ); |
|
|
|
g_pMaterialSystem->BeginRenderTargetAllocation(); // Begin allocating RTs which IFM can scribble into |
|
|
|
// LDR final result of either HDR or LDR rendering |
|
m_ScreenBuffer.Init( g_pMaterialSystem->CreateNamedRenderTargetTextureEx2( |
|
"_rt_LayoffResult", nPreviewWidth, nPreviewHeight, RT_SIZE_OFFSCREEN, |
|
g_pMaterialSystem->GetBackBufferFormat(), MATERIAL_RT_DEPTH_SHARED, TEXTUREFLAGS_BORDER ) ); |
|
|
|
g_pMaterialSystem->EndRenderTargetAllocation(); // End allocating RTs which IFM can scribble into |
|
} |
|
|
|
KeyValues *pVMTKeyValues = NULL; |
|
pVMTKeyValues= new KeyValues( "UnlitGeneric" ); |
|
pVMTKeyValues->SetString( "$basetexture", m_ScreenBuffer->GetName() ); |
|
pVMTKeyValues->SetInt( "$nofog", 1 ); |
|
m_ScreenMaterial.Init( "MiniViewportEngineRenderAreaSceneMaterial", pVMTKeyValues ); |
|
m_ScreenMaterial->Refresh(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Called when the layoff texture needs to be released |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewportEngineRenderArea::ReleaseLayoffTexture() |
|
{ |
|
m_ScreenBuffer.Shutdown(); |
|
m_ScreenMaterial.Shutdown(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Apply scheme settings |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewportEngineRenderArea::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
m_OverlayTextFont = pScheme->GetFont( "DefaultLargeOutline" ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewportEngineRenderArea::ShutdownSceneMaterials() |
|
{ |
|
m_ScreenBuffer.Shutdown(); |
|
m_ScreenMaterial.Shutdown(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Sets text to draw over the window |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewportEngineRenderArea::SetOverlayText( const char *pText ) |
|
{ |
|
m_OverlayText = pText; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Paints the black borders around the engine window |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewportEngineRenderArea::PaintEngineBorders( int x, int y, int w, int h ) |
|
{ |
|
// Draws black borders around the engine window |
|
surface()->DrawSetColor( Color( 0, 0, 0, 255 ) ); |
|
if ( x != 0 ) |
|
{ |
|
surface()->DrawFilledRect( 0, 0, x, h ); |
|
surface()->DrawFilledRect( x + w, 0, w + 2 * x, h ); |
|
} |
|
else if ( y != 0 ) |
|
{ |
|
surface()->DrawFilledRect( 0, 0, w, y ); |
|
surface()->DrawFilledRect( 0, y + h, w, h + 2 * y ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Paints the overlay text |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewportEngineRenderArea::PaintOverlayText( ) |
|
{ |
|
if ( !m_OverlayText.Length() ) |
|
return; |
|
|
|
int cw, ch; |
|
GetSize( cw, ch ); |
|
|
|
int nTextWidth, nTextHeight; |
|
int nBufLen = m_OverlayText.Length()+1; |
|
wchar_t *pTemp = (wchar_t*)_alloca( nBufLen * sizeof(wchar_t) ); |
|
::MultiByteToWideChar( CP_UTF8, 0, m_OverlayText.Get(), -1, pTemp, nBufLen ); |
|
|
|
g_pMatSystemSurface->GetTextSize( m_OverlayTextFont, pTemp, nTextWidth, nTextHeight ); |
|
int lx = (cw - nTextWidth) / 2; |
|
if ( lx < 10 ) |
|
{ |
|
lx = 10; |
|
} |
|
int ly = ch - 10 - nTextHeight; |
|
g_pMatSystemSurface->DrawColoredTextRect( m_OverlayTextFont, |
|
lx, ly, cw - lx, ch - ly, |
|
255, 255, 255, 255, "%s", m_OverlayText.Get() ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Paints the engine window itself |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewportEngineRenderArea::PaintEngineWindow( int x, int y, int w, int h ) |
|
{ |
|
if ( !enginetools->IsInGame() ) |
|
{ |
|
surface()->DrawSetColor( Color( 127, 127, 200, 63 ) ); |
|
surface()->DrawFilledRect( x, y, x + w, y + h ); |
|
} |
|
else |
|
{ |
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); |
|
|
|
g_pMatSystemSurface->DrawSetTextureMaterial( m_nEngineOutputTexture, m_ScreenMaterial ); |
|
surface()->DrawSetColor( Color( 0, 0, 0, 255 ) ); |
|
|
|
int nTexWidth = m_ScreenBuffer->GetActualWidth(); |
|
int nTexHeight = m_ScreenBuffer->GetActualHeight(); |
|
float flOOWidth = 1.0f / nTexWidth; |
|
float flOOHeight = 1.0f / nTexHeight; |
|
|
|
float s0, s1, t0, t1; |
|
|
|
s0 = ( 0.5f ) * flOOWidth; |
|
t0 = ( 0.5f ) * flOOHeight; |
|
s1 = ( (float)w - 0.5f ) * flOOWidth; |
|
t1 = ( (float)h - 0.5f ) * flOOHeight; |
|
|
|
vgui::surface()->DrawTexturedSubRect( x, y, x+w, y+h, s0, t0, s1, t1 ); |
|
|
|
PaintOverlayText(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Paints the background |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewportEngineRenderArea::PaintBackground() |
|
{ |
|
int x, y, w, h; |
|
GetEngineBounds( x, y, w, h ); |
|
PaintEngineBorders( x, y, w, h ); |
|
PaintEngineWindow( x, y, w, h ); |
|
} |
|
|
|
void CMiniViewportEngineRenderArea::GetEngineBounds( int& x, int& y, int& w, int& h ) |
|
{ |
|
x = 0; |
|
y = 0; |
|
GetSize( w, h ); |
|
|
|
// Check aspect ratio |
|
int sx, sy; |
|
surface()->GetScreenSize( sx, sy ); |
|
|
|
if ( sy > 0 && |
|
h > 0 ) |
|
{ |
|
float screenaspect = (float)sx / (float)sy; |
|
float aspect = (float)w / (float)h; |
|
|
|
float ratio = screenaspect / aspect; |
|
|
|
// Screen is wider, need bars at top and bottom |
|
if ( ratio > 1.0f ) |
|
{ |
|
int usetall = (float)w / screenaspect; |
|
y = ( h - usetall ) / 2; |
|
h = usetall; |
|
} |
|
// Screen is narrower, need bars at left/right |
|
else |
|
{ |
|
int usewide = (float)h * screenaspect; |
|
x = ( w - usewide ) / 2; |
|
w = usewide; |
|
} |
|
} |
|
} |
|
|
|
CMiniViewportPropertyPage::CMiniViewportPropertyPage(Panel *parent, const char *panelName ) : |
|
BaseClass( parent, panelName ) |
|
{ |
|
m_bgColor = Color( 0, 0, 0, 0 ); |
|
|
|
m_pViewportArea = new CMiniViewportEngineRenderArea( this, "Engine" ); |
|
} |
|
|
|
void CMiniViewportPropertyPage::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
int w, h; |
|
GetSize( w, h ); |
|
m_pViewportArea->SetBounds( 0, 0, w, h ); |
|
} |
|
|
|
Color CMiniViewportPropertyPage::GetBgColor() |
|
{ |
|
return m_bgColor; |
|
} |
|
|
|
|
|
void CMiniViewportPropertyPage::GetEngineBounds( int& x, int& y, int& w, int& h ) |
|
{ |
|
m_pViewportArea->GetEngineBounds( x, y, w, h ); |
|
m_pViewportArea->LocalToScreen( x, y ); |
|
} |
|
|
|
void CMiniViewportPropertyPage::RenderFrameBegin() |
|
{ |
|
m_pViewportArea->RenderFrameBegin(); |
|
} |
|
|
|
CMiniViewport::CMiniViewport( vgui::Panel *parent, bool contextLabel, vgui::IToolWindowFactory *factory /*= 0*/, |
|
vgui::Panel *page /*= NULL*/, char const *title /*= NULL*/, bool contextMenu /*= false*/ ) : |
|
BaseClass( parent, contextLabel, factory, page, title, contextMenu, false ) |
|
{ |
|
SetCloseButtonVisible( false ); |
|
|
|
GetPropertySheet()->SetDraggableTabs( false ); |
|
|
|
// Add the viewport panel |
|
m_hPage = new CMiniViewportPropertyPage( this, "ViewportPage" ); |
|
|
|
AddPage( m_hPage.Get(), "#ToolMiniViewport", false ); |
|
} |
|
|
|
void CMiniViewport::GetViewport( bool& enabled, int& x, int& y, int& w, int& h ) |
|
{ |
|
enabled = false; |
|
x = y = w = h = 0; |
|
|
|
int screenw, screenh; |
|
surface()->GetScreenSize( screenw, screenh ); |
|
|
|
m_hPage->GetEngineBounds( x, y, w, h ); |
|
|
|
y = screenh - ( y + h ); |
|
} |
|
|
|
void CMiniViewport::GetEngineBounds( int& x, int& y, int& w, int& h ) |
|
{ |
|
m_hPage->GetEngineBounds( x, y, w, h ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Called when the layoff texture needs to be released |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewport::ReleaseLayoffTexture() |
|
{ |
|
if ( m_hPage.Get() ) |
|
{ |
|
m_hPage->GetViewportArea()->ReleaseLayoffTexture(); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Sets text to draw over the window |
|
//----------------------------------------------------------------------------- |
|
void CMiniViewport::SetOverlayText( const char *pText ) |
|
{ |
|
if ( m_hPage.Get() ) |
|
{ |
|
m_hPage->GetViewportArea()->SetOverlayText( pText ); |
|
} |
|
} |
|
|
|
void CMiniViewport::RenderFrameBegin() |
|
{ |
|
if ( m_hPage.Get() ) |
|
{ |
|
m_hPage->RenderFrameBegin(); |
|
} |
|
}
|
|
|