//========= Copyright Jorge "BSVino" Rodriguez, All rights reserved. ============//
//
// Purpose:
//
//====================================================================================//
#include "cbase.h"
#include "menu_background.h"
#include <cdll_client_int.h>
#include <ienginevgui.h>
#include <KeyValues.h>
#include "iclientmode.h"
#include <vgui/IScheme.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
#include "clienteffectprecachesystem.h"
#include "tier0/icommandline.h"
#include "baseviewport.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Basically this entire file was given to me by Tony Sergi from Project Valkyrie.
CLIENTEFFECT_REGISTER_BEGIN( PrecacheMainMenu )
CLIENTEFFECT_MATERIAL( "console/mainmenu" )
CLIENTEFFECT_REGISTER_END()
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CMainMenu::CMainMenu( vgui::Panel *parent, const char *pElementName ) : vgui::Panel( NULL, "MainMenu" )
{
vgui::VPANEL pParent = enginevgui->GetPanel( PANEL_GAMEUIDLL );
SetParent( pParent );
SetBuildModeEditable( false );
SetVisible( false );
SetPaintEnabled( false );
SetProportional( true );
SetKeyBoardInputEnabled( false );
SetBlackBackground( false );
SetPaintBorderEnabled( false );
m_VideoMaterial = NULL;
m_nPlaybackWidth = 0;
m_nPlaybackHeight = 0;
m_bToolsMode = false;
m_bLoaded = false;
m_MainMenuRef.Init( "console/mainmenu.vmt", TEXTURE_GROUP_OTHER );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMainMenu::~CMainMenu()
{
ReleaseVideo();
MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMainMenu::ApplySchemeSettings( IScheme *pScheme )
{
SetPos( 0, 0 );
SetSize( ScreenWidth(), ScreenHeight() );
SetZPos( 500 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CMainMenu::IsVideoPlaying()
{
return m_bPaintVideo;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMainMenu::StartVideo()
{
m_bToolsMode = ( IsPC() && ( CommandLine()->CheckParm( "-tools" ) != NULL ) ) ? true : false;
SetVisible( true );
SetPaintEnabled( true );
bool isWide = false;
if ( (ScreenWidth() / 4) != (ScreenHeight() / 3) )
isWide = true;
m_bLoaded = false;
if ( isWide )
{
//DevMsg( "Attempting to play widescreen video\n" );
if ( BeginPlayback( "media/mainmenu_wide.bik" ) )
{
m_bLoaded = true;
}
else
{
if ( BeginPlayback( "media/mainmenu.bik" ) )
m_bLoaded = true;
}
}
else
{
if ( BeginPlayback( "media/mainmenu.bik" ) )
m_bLoaded = true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMainMenu::StopVideo()
{
// NOTE(Tony): Release the video when stopping
// NOTE(Tony): Modified, don't hide the panel anymore, because we draw the main menu logo thing for in-game
//SetVisible( false );
//SetPaintEnabled( false );
ReleaseVideo();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMainMenu::GetPanelPos( int &xpos, int &ypos )
{
vgui::ipanel()->GetAbsPos( GetVPanel(), xpos, ypos );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMainMenu::Paint( void )
{
if ( m_bToolsMode )
return;
if ( engine->IsConnected() )
return;
if ( !m_bLoaded )
return;
if ( m_bPaintVideo )
{
// No video to play, so do nothing
if ( m_VideoMaterial == NULL )
return;
// Update our frame
if ( m_VideoMaterial->Update() == false )
return;
// Sit in the "center"
int xpos, ypos;
GetPanelPos( xpos, ypos );
// Black out the background (we could omit drawing under the video surface, but this is straight-forward)
if ( m_bBlackBackground )
{
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() );
}
// Draw the polys to draw this out
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->Bind( m_pMaterial, NULL );
CMeshBuilder meshBuilder;
IMesh *pMesh = pRenderContext->GetDynamicMesh( true );
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
float flLeftX = xpos;
float flRightX = xpos + ( m_nPlaybackWidth - 1 );
float flTopY = ypos;
float flBottomY = ypos + ( m_nPlaybackHeight - 1 );
// Map our UVs to cut out just the portion of the video we're interested in
float flLeftU = 0.0f;
float flTopV = 0.0f;
// We need to subtract off a pixel to make sure we don't bleed
float flRightU = m_flU - ( 1.0f / (float)m_nPlaybackWidth );
float flBottomV = m_flV - ( 1.0f / (float)m_nPlaybackHeight );
// Get the current viewport size
int vx, vy, vw, vh;
pRenderContext->GetViewport( vx, vy, vw, vh );
// Map from screen pixel coords to -1..1
flRightX = FLerp( -1, 1, 0, vw, flRightX );
flLeftX = FLerp( -1, 1, 0, vw, flLeftX );
flTopY = FLerp( 1, -1, 0, vh , flTopY );
flBottomY = FLerp( 1, -1, 0, vh, flBottomY );
float alpha = ( (float)GetFgColor()[3] / 255.0f );
for ( int corner = 0; corner < 4; corner++ )
{
bool bLeft = ( corner == 0 ) || ( corner == 3 );
meshBuilder.Position3f( ( bLeft ) ? flLeftX : flRightX, ( corner & 2 ) ? flBottomY : flTopY, 0.0f );
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
meshBuilder.TexCoord2f( 0, ( bLeft ) ? flLeftU : flRightU, ( corner & 2 ) ? flBottomV : flTopV );
meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
meshBuilder.Color4f( 1.0f, 1.0f, 1.0f, alpha );
meshBuilder.AdvanceVertex();
}
meshBuilder.End();
pMesh->Draw();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PopMatrix();
}
// NOTE(Tony): now draw the mainmenu.vmt overtop!
{
CMatRenderContextPtr pRenderContext( materials );
CMeshBuilder mb;
IMesh *mesh;
pRenderContext->Bind( m_MainMenuRef );
mesh = pRenderContext->GetDynamicMesh( true );
mb.Begin( mesh, MATERIAL_QUADS, 1 );
mb.Color4ub( 255, 255, 255, 255 );
mb.TexCoord2f( 0, 0, 0 );
mb.Position3f( 0.0f, 0.0f, 0 );
mb.AdvanceVertex();
mb.Color4ub( 255, 255, 255, 255);
mb.TexCoord2f( 0, 1, 0 );
mb.Position3f( ScreenWidth(), 0.0f, 0 );
mb.AdvanceVertex();
mb.Color4ub( 255, 255, 255, 255);
mb.TexCoord2f( 0, 1, 1 );
mb.Position3f( ScreenWidth(), ScreenHeight(), 0 );
mb.AdvanceVertex();
mb.Color4ub( 255, 255, 255, 255);
mb.TexCoord2f( 0, 0, 1 );
mb.Position3f( 0.0f, ScreenHeight(), 0 );
mb.AdvanceVertex();
mb.End();
mesh->Draw();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CMainMenu::BeginPlayback( const char *pFilename )
{
// Need working video services
if ( g_pVideo == NULL )
return false;
// Destroy any previously allocated video
if ( m_VideoMaterial != NULL )
{
g_pVideo->DestroyVideoMaterial( m_VideoMaterial );
m_VideoMaterial = NULL;
}
// Create new Video material
m_VideoMaterial = g_pVideo->CreateVideoMaterial( "VideoMaterial", pFilename, "GAME",
VideoPlaybackFlags::DEFAULT_MATERIAL_OPTIONS,
VideoSystem::DETERMINE_FROM_FILE_EXTENSION, m_bAllowAlternateMedia );
if ( m_VideoMaterial == NULL )
return false;
m_bPaintVideo = true;
m_VideoMaterial->SetLooping( true );
int nWidth, nHeight;
m_VideoMaterial->GetVideoImageSize( &nWidth, &nHeight );
m_VideoMaterial->GetVideoTexCoordRange( &m_flU, &m_flV );
m_pMaterial = m_VideoMaterial->GetMaterial();
m_nPlaybackWidth = ScreenWidth();
m_nPlaybackHeight = ScreenHeight();
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMainMenu::ReleaseVideo()
{
m_bPaintVideo = false;
// NOTE(Tony): Not touching the sound!!
//enginesound->NotifyEndMoviePlayback();
// Destroy any previously allocated video
// Shut down this video, destroy the video material
if ( g_pVideo != NULL && m_VideoMaterial != NULL )
{
g_pVideo->DestroyVideoMaterial( m_VideoMaterial );
m_VideoMaterial = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMainMenu::SetBlackBackground( bool bBlack )
{
m_bBlackBackground = bBlack;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMainMenu::DoModal()
{
vgui::surface()->RestrictPaintToSinglePanel( GetVPanel() );
}
//-----------------------------------------------------------------------------
// Purpose: If we get disconnected, load the menu
//-----------------------------------------------------------------------------
void CMainMenu::OnDisconnectFromGame()
{
StartVideo();
}
//-----------------------------------------------------------------------------
// Purpose: Find the disconnect command, and rename it...
//-----------------------------------------------------------------------------
CON_COMMAND( __disconnect, "Disconnect game from server." )
{
CBaseViewport *pViewPort = dynamic_cast<CBaseViewport *>( g_pClientMode->GetViewport() );
if ( pViewPort )
pViewPort->StartMainMenuVideo();
engine->ClientCmd_Unrestricted( "__real_disconnect" );
}
void SwapDisconnectCommand()
{
//DevMsg("SwapDisconnectCommand\n");
ConCommand *_realDisconnectCommand = dynamic_cast<ConCommand *>( g_pCVar->FindCommand( "disconnect" ) );
ConCommand *_DisconnectCommand = dynamic_cast<ConCommand *>( g_pCVar->FindCommand( "__disconnect" ) );
if ( !_realDisconnectCommand )
return;
if ( !_DisconnectCommand )
return;
_realDisconnectCommand->Shutdown();
_realDisconnectCommand->Create( "__real_disconnect", "" );
_realDisconnectCommand->Init();
_DisconnectCommand->Shutdown();
_DisconnectCommand->Create( "disconnect", "Disconnect game from server." );
_DisconnectCommand->Init();
}