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.
882 lines
24 KiB
882 lines
24 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
//=======================================================================================// |
|
|
|
#include "cbase.h" |
|
|
|
#ifdef SAXXYMAINMENU_ENABLED |
|
|
|
#include "tf_hud_saxxycontest.h" |
|
#include "econ_item_inventory.h" |
|
#include "econ/confirm_dialog.h" |
|
#include "econ/econ_controls.h" |
|
#include "vgui/IVGui.h" |
|
#include "vgui/ILocalize.h" |
|
#include "vgui/IInput.h" |
|
#include "vgui/ISurface.h" |
|
#include "vgui_controls/TextEntry.h" |
|
#include "vgui_controls/ComboBox.h" |
|
#include "ienginevgui.h" |
|
#include "replaybrowsermainpanel.h" |
|
#include "gc_clientsystem.h" |
|
|
|
#include "rtime.h" |
|
#include "tf_gcmessages.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
DECLARE_BUILD_FACTORY( CSaxxyAwardsPanel ); |
|
|
|
static void SaxxyAwards_ShowSubmitForm(); |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
int CSaxxyAwardsPanel::sm_nShowCounter = -1; |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
#define FOR_EACH_FLASH( i_ ) for ( int i_ = 0; i_ < MAX_FLASHES; ++i_ ) |
|
#define FOR_EACH_GLOW( i_ ) for ( int i_ = 0; i_ < MAX_GLOWS; ++i_ ) |
|
#define FOR_EACH_CLAP( i_ ) for ( int i_ = 0; i_ < MAX_CLAPS; ++i_ ) |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
#define NUM_FLASH_SOUNDS 11 |
|
#define NUM_FLASH_MATERIALS 3 |
|
#define FREAKOUT_THRESHOLD 0.7f |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
inline float SCurve( float t ) |
|
{ |
|
t = clamp( t, 0.0f, 1.0f ); |
|
return t * t * (3 - 2*t); |
|
} |
|
|
|
inline float LerpScale( float flIn, float flInMin, float flInMax, float flOutMin, float flOutMax ) |
|
{ |
|
float flDenom = flInMax - flInMin; |
|
if ( flDenom == 0.0f ) |
|
return 0.0f; |
|
|
|
float t = clamp( ( flIn - flInMin ) / flDenom, 0.0f, 1.0f ); |
|
return Lerp( t, flOutMin, flOutMax ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
CSaxxyAwardsPanel::CSaxxyAwardsPanel( Panel *pParent, const char *pName ) |
|
: EditablePanel( pParent, pName ), |
|
m_pCameraFlashKv( NULL ) |
|
{ |
|
ivgui()->AddTickSignal( GetVPanel(), 17 ); |
|
|
|
Init(); |
|
|
|
++sm_nShowCounter; |
|
} |
|
|
|
CSaxxyAwardsPanel::~CSaxxyAwardsPanel() |
|
{ |
|
ivgui()->RemoveTickSignal( GetVPanel() ); |
|
} |
|
|
|
void CSaxxyAwardsPanel::Init() |
|
{ |
|
m_flShowTime = GetCurrentTime(); |
|
|
|
m_vDialogsParent = (VPANEL)-1; |
|
m_nNumTargetFlashes = 0; |
|
m_flLastTickTime = 0.0f; |
|
m_flEarliestNextFlashTime = 0.0f; |
|
m_flGlowFade = 0.0f; |
|
m_flNextPanelTestTime = 0.0f; |
|
m_pBackgroundPanel = NULL; |
|
m_pSaxxyModelPanel = NULL; |
|
m_pStageBgPanel = NULL; |
|
m_pSubmitButton = NULL; |
|
m_pInfoLabel = NULL; |
|
m_pCurtainPanel = NULL; |
|
m_pContestOverLabel = NULL; |
|
m_pSpotlightPanel = NULL; |
|
|
|
m_flCurtainStartAnimTime = -1.0f; |
|
|
|
FOR_EACH_CLAP( i ) |
|
{ |
|
m_aClapPlayTimes[i] = 0.0f; |
|
} |
|
|
|
for ( int i = 0; i < 2; ++i ) |
|
{ |
|
m_aFilteredMousePos[i][0] = ScreenWidth() / 2; |
|
m_aFilteredMousePos[i][1] = ScreenHeight() / 2; |
|
} |
|
|
|
FOR_EACH_FLASH( i ) |
|
{ |
|
CFmtStr fmtPanelName( "FlashPanel_%i", i ); |
|
FlashInfo_t *pCurFlashInfo = &m_aFlashes[ i ]; |
|
pCurFlashInfo->m_pPanel = new ImagePanel( NULL, fmtPanelName.Access() ); |
|
pCurFlashInfo->m_bInUse = false; |
|
} |
|
|
|
m_angModelRot.Init(); |
|
m_vSaxxyDefaultPos.Init(); |
|
} |
|
|
|
void CSaxxyAwardsPanel::ApplySettings( KeyValues *pInResourceData ) |
|
{ |
|
BaseClass::ApplySettings( pInResourceData ); |
|
|
|
// Delete old KeyValues |
|
if ( m_pCameraFlashKv ) |
|
{ |
|
m_pCameraFlashKv->deleteThis(); |
|
m_pCameraFlashKv = NULL; |
|
} |
|
|
|
// Copy camera flash keyvalues for creating instances |
|
KeyValues *pCameraFlash = pInResourceData->FindKey( "CameraFlashSettings" ); |
|
Assert( pCameraFlash ); |
|
if ( pCameraFlash ) |
|
{ |
|
m_pCameraFlashKv = pCameraFlash->MakeCopy(); |
|
} |
|
} |
|
|
|
bool CSaxxyAwardsPanel::CreateFlash() |
|
{ |
|
if ( GetActiveFlashCount() == MAX_FLASHES ) |
|
return false; |
|
|
|
const int iUnusedSlot = GetUnusedFlashSlot(); Assert( iUnusedSlot >= 0 && iUnusedSlot < MAX_FLASHES ); |
|
|
|
if ( iUnusedSlot < 0 ) |
|
return false; // Should never happen, since GetActiveFlashCount() didn't return 0 |
|
|
|
FlashInfo_t *pFlashInfo = &m_aFlashes[ iUnusedSlot ]; |
|
ImagePanel *pPanel = pFlashInfo->m_pPanel; |
|
|
|
// Apply base settings |
|
if ( !m_pCameraFlashKv ) |
|
return false; |
|
|
|
pPanel->ApplySettings( m_pCameraFlashKv ); |
|
|
|
// Set the image to a random image |
|
const int iImage = 1 + rand() % NUM_FLASH_MATERIALS; |
|
CFmtStr fmtImageName( "../models/effects/camera_flash/camera_flash_%02i", iImage ); |
|
pPanel->SetImage( fmtImageName.Access() ); |
|
|
|
pFlashInfo->m_flStartTime = GetCurrentTime(); |
|
pFlashInfo->m_flLifeLength = FRand( m_flFlashLifeLengthMin, m_flFlashLifeLengthMax ); |
|
pFlashInfo->m_bInUse = true; |
|
|
|
// Put the flash at a random position in the "flash bounds" |
|
pFlashInfo->m_nCenterX = (int)FRand( m_nFlashBoundsX, m_nFlashBoundsX + m_nFlashBoundsW ); |
|
pFlashInfo->m_nCenterY = (int)FRand( m_nFlashBoundsY, m_nFlashBoundsY + m_nFlashBoundsH ); |
|
|
|
pFlashInfo->m_nMinSize = (int)Lerp( FRand( 0.0f, 1.0f ), m_nFlashStartSizeMin, m_nFlashStartSizeMax ); |
|
pFlashInfo->m_nMaxSize = pFlashInfo->m_nMinSize * FRand( .5f * m_flFlashMaxScale, m_flFlashMaxScale ); |
|
|
|
Assert( pFlashInfo->m_nMaxSize > pFlashInfo->m_nMinSize ); |
|
|
|
pFlashInfo->m_nCurW = pFlashInfo->m_nMinSize; |
|
pFlashInfo->m_nCurH = pFlashInfo->m_nMinSize; |
|
|
|
PlaceFlash( pFlashInfo ); |
|
|
|
// Setup visibility |
|
pPanel->SetAlpha( 0 ); |
|
pPanel->SetVisible( true ); |
|
|
|
// Play a random flash sound |
|
int iSound = rand() % NUM_FLASH_SOUNDS + 1; |
|
Assert( iSound >= 1 && iSound <= NUM_FLASH_SOUNDS ); |
|
CFmtStr fmtSoundFilename( "misc/tf_camera_%02i.wav", iSound ); |
|
surface()->PlaySound( fmtSoundFilename.Access() ); |
|
|
|
return true; |
|
} |
|
|
|
void CSaxxyAwardsPanel::PlaceFlash( FlashInfo_t *pFlashInfo ) |
|
{ |
|
pFlashInfo->m_pPanel->SetBounds( |
|
pFlashInfo->m_nCenterX - pFlashInfo->m_nCurW / 2, |
|
pFlashInfo->m_nCenterY - pFlashInfo->m_nCurH / 2, |
|
pFlashInfo->m_nCurW, |
|
pFlashInfo->m_nCurH |
|
); |
|
} |
|
|
|
void CSaxxyAwardsPanel::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
LoadControlSettings( "resource/UI/MainMenu_SaxxyAwards.res" ); |
|
|
|
SetupContestPanels(); |
|
|
|
m_vDialogsParent = GetDialogsParent(); |
|
|
|
m_pBackgroundPanel = dynamic_cast< EditablePanel * >( FindChildByName( "Background" ) ); |
|
m_pSubmitButton = dynamic_cast< CExButton *>( FindChildByName( "SubmitButton" ) ); |
|
m_pInfoLabel = FindChildByName( "InfoLabel" ); |
|
m_pContestOverLabel = FindChildByName( "ContestOverLabel" ); |
|
m_pSpotlightPanel = dynamic_cast< ImagePanel * >( FindChildByName( "SpotlightPanel" ) ); |
|
|
|
m_pStageBgPanel = dynamic_cast< ImagePanel * >( FindChildByName( "StageBackground" ) ); |
|
m_pCurtainPanel = dynamic_cast< EditablePanel * >( FindChildByName( "CurtainsPanel" ) ); |
|
if ( m_pCurtainPanel ) |
|
{ |
|
m_Curtains[0].m_pPanel = dynamic_cast< ImagePanel * >( m_pCurtainPanel->FindChildByName( "CurtainsLeft" ) ); |
|
m_Curtains[1].m_pPanel = dynamic_cast< ImagePanel * >( m_pCurtainPanel->FindChildByName( "CurtainsRight" ) ); |
|
|
|
// Hide curtains if this isn't the first view |
|
if ( sm_nShowCounter > 0 ) |
|
{ |
|
for ( int i = 0; i < 2; ++i ) |
|
{ |
|
if ( !m_Curtains[i].m_pPanel ) |
|
continue; |
|
m_Curtains[i].m_pPanel->SetVisible( false ); |
|
} |
|
} |
|
|
|
// Set all flash parents to background panel |
|
if ( m_pBackgroundPanel ) |
|
{ |
|
FOR_EACH_FLASH( i ) |
|
{ |
|
m_aFlashes[ i ].m_pPanel->SetParent( m_pStageBgPanel ); |
|
} |
|
} |
|
|
|
// Setup Saxxy model |
|
m_pSaxxyModelPanel = dynamic_cast< CBaseModelPanel * >( m_pCurtainPanel->FindChildByName( "SaxxyModelPanel" ) ); |
|
if ( m_pSaxxyModelPanel ) |
|
{ |
|
MDLHandle_t hModel = mdlcache->FindMDL( "models/effects/saxxy_flash/saxxy_flash.mdl" ); |
|
m_pSaxxyModelPanel->SetMDL( hModel ); |
|
m_pSaxxyModelPanel->SetSequence( ACT_RESET ); |
|
mdlcache->Release( hModel ); // counterbalance addref from within FindMDL |
|
|
|
m_pSaxxyModelPanel->InvalidateLayout( true, true ); // Updates player position |
|
m_vSaxxyDefaultPos = m_pSaxxyModelPanel->GetPlayerPos(); |
|
} |
|
} |
|
} |
|
|
|
void CSaxxyAwardsPanel::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
} |
|
|
|
void CSaxxyAwardsPanel::Refresh() |
|
{ |
|
Init(); |
|
InvalidateLayout( true, true ); |
|
} |
|
|
|
void CSaxxyAwardsPanel::OnCommand( const char *pCommand ) |
|
{ |
|
if ( FStrEq( pCommand, "viewdetails" ) ) |
|
{ |
|
if ( steamapicontext && steamapicontext->SteamFriends() ) |
|
{ |
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( "http://www.teamfortress.com/saxxyawards/" ); |
|
} |
|
} |
|
else if ( FStrEq( pCommand, "submit" ) ) |
|
{ |
|
SaxxyAwards_ShowSubmitForm(); |
|
} |
|
else |
|
{ |
|
BaseClass::OnCommand( pCommand ); |
|
} |
|
} |
|
|
|
void CSaxxyAwardsPanel::OnTick() |
|
{ |
|
if ( C_BasePlayer::GetLocalPlayer() ) |
|
return; |
|
|
|
if ( ReplayUI_GetBrowserPanel() && ReplayUI_GetBrowserPanel()->IsVisible() ) |
|
return; |
|
|
|
if ( !IsVisible() ) |
|
return; |
|
|
|
// Calculate elapsed |
|
const float flCurTime = GetCurrentTime(); |
|
const float flElapsed = clamp( flCurTime - m_flLastTickTime, 0, 0.1f ); |
|
m_flLastTickTime = flCurTime; |
|
|
|
// Msg( "initial freakout? %s\n", InInitialFreakoutPeriod() ? "yes" : "no" ); |
|
|
|
const bool bOtherPanelsOpen = AreOtherPanelsOpen( flCurTime ); |
|
|
|
UpdateMousePos( flElapsed ); |
|
CurtainsThink(); |
|
RotateModel( flElapsed ); |
|
FlashThink( bOtherPanelsOpen ); |
|
SpotlightThink(); |
|
ClapsThink( flCurTime, flElapsed, bOtherPanelsOpen ); |
|
|
|
SetupContestPanels(); |
|
} |
|
|
|
bool CSaxxyAwardsPanel::AreOtherPanelsOpen( float flCurTime ) |
|
{ |
|
static bool s_bOtherPanelsOpen = false; |
|
|
|
if ( flCurTime < m_flNextPanelTestTime ) |
|
return s_bOtherPanelsOpen; |
|
|
|
// Setup next think time |
|
m_flNextPanelTestTime = flCurTime + 2.0f; |
|
|
|
// Do tests to see if other panels are open |
|
bool bOtherPanelsOpen = false; |
|
{ |
|
const int nNumGameUICarePanels = 4; |
|
const char *pCarePanels[nNumGameUICarePanels] = { "GameConsole", "character_info", "store_panel", "BugUIPanel" }; |
|
bOtherPanelsOpen = bOtherPanelsOpen || AreNonMainMenuPanelsOpen( enginevgui->GetPanel( PANEL_GAMEUIDLL ), pCarePanels, nNumGameUICarePanels ); |
|
} |
|
|
|
// Msg( "-----\n" ); |
|
|
|
if ( m_vDialogsParent != (VPANEL)-1 ) |
|
{ |
|
const int nNumCarePanels = 2; |
|
const char *pCarePanels[nNumCarePanels] = { "CServerBrowserDialog", "OptionsDialog" }; |
|
|
|
bOtherPanelsOpen = bOtherPanelsOpen || AreNonMainMenuPanelsOpen( m_vDialogsParent, pCarePanels, nNumCarePanels ); |
|
} |
|
|
|
// Cache so we don't have to think every frame |
|
s_bOtherPanelsOpen = bOtherPanelsOpen; |
|
|
|
return bOtherPanelsOpen; |
|
} |
|
|
|
void CSaxxyAwardsPanel::PaintBackground() |
|
{ |
|
BaseClass::PaintBackground(); |
|
} |
|
|
|
void CSaxxyAwardsPanel::UpdateMousePos( float flElapsed ) |
|
{ |
|
// Set target mouse pos |
|
int x, y; |
|
input()->GetCursorPos( x, y ); |
|
m_aFilteredMousePos[1][0] = x; |
|
m_aFilteredMousePos[1][1] = y; |
|
|
|
// Move towards target |
|
const float t = flElapsed * 1.5f; |
|
m_aFilteredMousePos[0][0] = Lerp( t, m_aFilteredMousePos[0][0], m_aFilteredMousePos[1][0] ); |
|
m_aFilteredMousePos[0][1] = Lerp( t, m_aFilteredMousePos[0][1], m_aFilteredMousePos[1][1] ); |
|
|
|
// Msg( "mouse pos: current=(%f %f) target=(%f %f)\n", m_aFilteredMousePos[0][0], m_aFilteredMousePos[0][1], |
|
// m_aFilteredMousePos[1][0], m_aFilteredMousePos[1][1] ); |
|
} |
|
|
|
void CSaxxyAwardsPanel::CurtainsThink() |
|
{ |
|
if ( !m_Curtains[0].m_pPanel || !m_Curtains[1].m_pPanel ) |
|
return; |
|
|
|
// Has enough time passed? Only open the curtains m_flOpenCurtainsTime seconds after m_flShowTime. |
|
const float flElapsedSinceShowTime = GetCurrentTime() - m_flShowTime; |
|
if ( flElapsedSinceShowTime < m_flOpenCurtainsTime ) |
|
return; |
|
|
|
// Start animating now? |
|
if ( CurtainsClosed() ) |
|
{ |
|
m_flCurtainStartAnimTime = GetCurrentTime(); |
|
|
|
// Play crowd the first time the menu is shown |
|
if ( sm_nShowCounter == 0 ) |
|
{ |
|
surface()->PlaySound( "misc/boring_applause_1.wav" ); |
|
} |
|
|
|
// Init positions to those set in res file |
|
for ( int i = 0; i < 2; ++i ) |
|
{ |
|
m_Curtains[i].m_pPanel->GetPos( m_Curtains[i].m_aInitialPos[0], m_Curtains[i].m_aInitialPos[1] ); |
|
} |
|
} |
|
else // Already animating? |
|
{ |
|
// Set updated positions for both curtains |
|
const float flCurTime = GetCurrentTime(); |
|
for ( int i = 0; i < 2; ++i ) |
|
{ |
|
CurtainInfo_t *pCurCurtain = &m_Curtains[i]; |
|
Panel *pPanel = pCurCurtain->m_pPanel; |
|
|
|
const int nSign = i == 0 ? -1 : 1; |
|
const float t = SCurve( clamp( ( flCurTime - m_flCurtainStartAnimTime ) / m_flCurtainAnimDuration, 0.0f, 1.0f ) ); |
|
int aCurPos[2] = { |
|
Lerp( t, pCurCurtain->m_aInitialPos[0], pCurCurtain->m_aInitialPos[0] + nSign * pPanel->GetWide() ), |
|
pCurCurtain->m_aInitialPos[1] |
|
}; |
|
m_Curtains[i].m_pPanel->SetPos( aCurPos[0], aCurPos[1] ); |
|
} |
|
} |
|
} |
|
|
|
void CSaxxyAwardsPanel::RotateModel( float flElapsed ) |
|
{ |
|
if ( m_pSaxxyModelPanel ) |
|
{ |
|
const float flOsc = .28f * sinf( .5f * GetCurrentTime() ); |
|
const Vector vCurPos( |
|
Lerp( m_flGlowFade, m_vSaxxyDefaultPos.x, m_vSaxxyDefaultPos.x - 8.0f ), |
|
m_vSaxxyDefaultPos.y, |
|
Lerp( m_flGlowFade, m_vSaxxyDefaultPos.z, m_vSaxxyDefaultPos.z - 3.0f ) + flOsc |
|
); |
|
m_angModelRot.y += flElapsed * 45 * 0.5f * Lerp( m_flGlowFade, 0.5f, 1.0f ); |
|
m_pSaxxyModelPanel->SetModelAnglesAndPosition( m_angModelRot, vCurPos ); |
|
} |
|
} |
|
|
|
void CSaxxyAwardsPanel::FlashThink( bool bOtherPanelsOpen ) |
|
{ |
|
if ( !m_pSaxxyModelPanel ) |
|
return; |
|
|
|
// Set the target number of flashes based on how far the mouse is from the saxxy |
|
int aModelBounds[4]; |
|
m_pSaxxyModelPanel->GetSize( aModelBounds[2], aModelBounds[3] ); |
|
ipanel()->GetAbsPos( m_pSaxxyModelPanel->GetVPanel(), aModelBounds[0], aModelBounds[1] ); |
|
const float flDistX = aModelBounds[0] + aModelBounds[2]/2.0f - m_aFilteredMousePos[0][0]; |
|
const float flDistY = aModelBounds[1] + aModelBounds[3]/2.0f - m_aFilteredMousePos[0][1]; |
|
const float flDistanceToSaxxy = sqrtf( flDistX * flDistX + flDistY * flDistY ); |
|
// Msg( "xdist: %f ydist: %f distance: %f\n", flDistX, flDistY, flDistanceToSaxxy ); |
|
|
|
const float flMaxDistance = 750.0f; |
|
m_flGlowFade = clamp( 1.0f - clamp( flDistanceToSaxxy / flMaxDistance, 0.0f, 1.0f ), 0.0f, 1.0f ); |
|
// Msg( "glow fade: %f\n", m_flGlowFade ); |
|
|
|
const float flCurTime = GetCurrentTime(); |
|
|
|
// Set alpha for active flashes, kill any that are done animating, update positions of actives |
|
FOR_EACH_FLASH( i ) |
|
{ |
|
FlashInfo_t *pCurFlashInfo = &m_aFlashes[ i ]; |
|
if ( !pCurFlashInfo->m_bInUse ) |
|
continue; |
|
|
|
const float t = ( flCurTime - pCurFlashInfo->m_flStartTime ) / pCurFlashInfo->m_flLifeLength; |
|
if ( t >= 1.0f ) |
|
{ |
|
ClearFlash( pCurFlashInfo ); |
|
} |
|
else |
|
{ |
|
// Set opacity |
|
const float flPhase = M_PI * t; |
|
const float flFade = clamp( sinf( flPhase ), 0.0f, 1.0f ); |
|
pCurFlashInfo->m_pPanel->SetAlpha( 255 * flFade ); |
|
|
|
// Update size |
|
pCurFlashInfo->m_nCurW = (int)Lerp( flFade, pCurFlashInfo->m_nMinSize, pCurFlashInfo->m_nMaxSize ); |
|
pCurFlashInfo->m_nCurH = pCurFlashInfo->m_nCurW; |
|
|
|
// Update position/size |
|
PlaceFlash( pCurFlashInfo ); |
|
} |
|
} |
|
|
|
// Create new flashes / freak out |
|
const bool bEnoughTimeHasPassed = flCurTime >= m_flEarliestNextFlashTime; |
|
if ( !bOtherPanelsOpen && bEnoughTimeHasPassed && FlashingStartTimePassed() && GetUnusedFlashCount() ) |
|
{ |
|
CreateFlash(); |
|
|
|
const bool bFreakout = InInitialFreakoutPeriod() || InFreakoutMode(); |
|
const float flOffset = bFreakout ? FRand( .1f, .2f ) : FRand( 2.0f, 5.0f ); |
|
m_flEarliestNextFlashTime = flCurTime + flOffset; |
|
} |
|
} |
|
|
|
VPANEL CSaxxyAwardsPanel::GetDialogsParent() |
|
{ |
|
VPANEL vGameUI = enginevgui->GetPanel( PANEL_GAMEUIDLL ); |
|
const int nNumChildren = ipanel()->GetChildCount( vGameUI ); |
|
|
|
for ( int i = 0; i < nNumChildren; ++i ) |
|
{ |
|
VPANEL vChild = ipanel()->GetChild( vGameUI, i ); |
|
const char *pDlgName = ipanel()->GetName( vChild ); |
|
if ( FStrEq( pDlgName, "BaseGameUIPanel" ) ) |
|
{ |
|
return vChild; |
|
} |
|
} |
|
|
|
return (VPANEL)-1; |
|
} |
|
|
|
bool CSaxxyAwardsPanel::AreNonMainMenuPanelsOpen( VPANEL vRoot, const char **pCarePanels, int nNumCarePanels ) |
|
{ |
|
int nNumChildren = ipanel()->GetChildCount( vRoot ); |
|
for ( int i = 0; i < nNumChildren; ++i ) |
|
{ |
|
VPANEL vChild = ipanel()->GetChild( vRoot, i ); |
|
const char *pDlgName = ipanel()->GetName( vChild ); |
|
bool bCare = false; |
|
for ( int j = 0; j < nNumCarePanels; ++j ) |
|
{ |
|
if ( FStrEq( pCarePanels[j], pDlgName ) ) |
|
{ |
|
// Msg( "CARE: %s\n", pDlgName ); |
|
bCare = true; |
|
break; |
|
} |
|
} |
|
if ( !bCare ) |
|
{ |
|
// Msg( "DONT CARE: %s\n", pDlgName ); |
|
continue; |
|
} |
|
|
|
if ( ipanel()->IsVisible( vChild ) ) |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
void CSaxxyAwardsPanel::SpotlightThink() |
|
{ |
|
if ( !m_pSpotlightPanel ) |
|
return; |
|
|
|
const float flOscillateAmount = 0.10f; |
|
const float flSpeed = 0.7f; |
|
const float flFade = .1f + flOscillateAmount * ( .5f + .5f * cosf( flSpeed * GetCurrentTime() ) ); |
|
m_pSpotlightPanel->SetAlpha( 255 * flFade ); |
|
} |
|
|
|
void CSaxxyAwardsPanel::PlaySomeClaps() |
|
{ |
|
// Play each clap offset by a bit |
|
const float flCurTime = GetCurrentTime(); |
|
FOR_EACH_CLAP( i ) |
|
{ |
|
// If this sound is already playing, continue |
|
float &flCurClapPlayTime = m_aClapPlayTimes[i]; |
|
|
|
const bool bAlreadyPlaying = flCurClapPlayTime != 0.0f; |
|
if ( bAlreadyPlaying ) |
|
continue; |
|
|
|
// Some chance that not all claps will be played |
|
if ( rand() % 100 < 30 ) |
|
{ |
|
SetNextPossibleClapTime( &flCurClapPlayTime ); |
|
continue; |
|
} |
|
|
|
flCurClapPlayTime = flCurTime + LerpScale( FRand( 0.0f, 1.0f ), 0.0f, 1.0f, .3f, 1.5f ); |
|
} |
|
} |
|
|
|
void CSaxxyAwardsPanel::ClapsThink( float flCurTime, float flElapsed, bool bOtherPanelsOpen ) |
|
{ |
|
if ( !bOtherPanelsOpen && InFreakoutMode() && !InInitialFreakoutPeriod() ) |
|
{ |
|
PlaySomeClaps(); |
|
} |
|
|
|
FOR_EACH_CLAP( i ) |
|
{ |
|
float &flCurClapTime = m_aClapPlayTimes[i]; |
|
// Msg( "clap %i: %f\n", i, flCurClapTime ); |
|
|
|
if ( flCurClapTime < 0.0f ) |
|
{ |
|
// Once enough time has elapsed, this slot will be > 0 and available again. |
|
flCurClapTime = MIN( flCurClapTime + flElapsed, 0.0f ); |
|
continue; |
|
} |
|
|
|
// Start playing now? |
|
if ( flCurClapTime <= flCurTime && flCurClapTime != 0.0f ) |
|
{ |
|
// Play. |
|
CFmtStr fmtSound( "misc/clap_single_%i.wav", i + 1 ); |
|
surface()->PlaySound( fmtSound.Access() ); |
|
|
|
SetNextPossibleClapTime( &flCurClapTime ); |
|
} |
|
} |
|
} |
|
|
|
void CSaxxyAwardsPanel::SetNextPossibleClapTime( float *pClapTime ) |
|
{ |
|
// Set the next possible time to the duration of the sound + some randomn offset |
|
const float flExtraOffset = LerpScale( FRand( 0.0f, 1.0f ), 0.0f, 1.0f, 1.0f, 5.0f ); |
|
*pClapTime = -( m_flClapSoundDuration + flExtraOffset ); |
|
} |
|
|
|
void CSaxxyAwardsPanel::ClearFlash( FlashInfo_t *pFlashInfo ) |
|
{ |
|
pFlashInfo->m_bInUse = false; |
|
pFlashInfo->m_pPanel->SetAlpha( 0 ); |
|
pFlashInfo->m_pPanel->SetVisible( false ); |
|
} |
|
|
|
void CSaxxyAwardsPanel::ClearFlashes() |
|
{ |
|
FOR_EACH_FLASH( i ) |
|
{ |
|
ClearFlash( &m_aFlashes[i] ); |
|
} |
|
} |
|
|
|
int CSaxxyAwardsPanel::GetActiveFlashCount() const |
|
{ |
|
int nResult = 0; |
|
FOR_EACH_FLASH( i ) |
|
{ |
|
if ( m_aFlashes[ i ].m_bInUse ) |
|
++nResult; |
|
} |
|
return nResult; |
|
} |
|
|
|
int CSaxxyAwardsPanel::GetUnusedFlashCount() const |
|
{ |
|
return MAX_FLASHES - GetActiveFlashCount(); |
|
} |
|
|
|
int CSaxxyAwardsPanel::GetUnusedFlashSlot() const |
|
{ |
|
FOR_EACH_FLASH( i ) |
|
{ |
|
if ( !m_aFlashes[ i ].m_bInUse ) |
|
return i; |
|
} |
|
return -1; |
|
} |
|
|
|
float CSaxxyAwardsPanel::GetCurrentTime() const |
|
{ |
|
return gpGlobals->curtime; |
|
} |
|
|
|
bool CSaxxyAwardsPanel::InInitialFreakoutPeriod() const |
|
{ |
|
return ( GetCurrentTime() - m_flShowTime ) <= m_flInitialFreakoutDuration; |
|
} |
|
|
|
bool CSaxxyAwardsPanel::InFreakoutMode() const |
|
{ |
|
return m_flGlowFade > FREAKOUT_THRESHOLD; |
|
} |
|
|
|
bool CSaxxyAwardsPanel::CurtainsClosed() const |
|
{ |
|
return m_flCurtainStartAnimTime < 0.0f; |
|
} |
|
|
|
bool CSaxxyAwardsPanel::FlashingStartTimePassed() const |
|
{ |
|
return ( GetCurrentTime() - m_flShowTime ) >= m_flFlashStartTime; |
|
} |
|
|
|
void CSaxxyAwardsPanel::SetupContestPanels() |
|
{ |
|
CRTime now; |
|
now.SetToCurrentTime(); |
|
now.SetToGMT( true ); |
|
|
|
CRTime deadline = CRTime::RTime32FromString( "2011-05-21 00:00:00" ); |
|
deadline.SetToGMT( true ); |
|
|
|
if ( now > deadline ) |
|
{ |
|
if ( m_pInfoLabel && m_pInfoLabel->IsVisible() ) |
|
{ |
|
m_pInfoLabel->SetVisible( false ); |
|
} |
|
if ( m_pSubmitButton && m_pSubmitButton->IsVisible() ) |
|
{ |
|
m_pSubmitButton->SetVisible( false ); |
|
} |
|
if ( m_pContestOverLabel && !m_pContestOverLabel->IsVisible() ) |
|
{ |
|
m_pContestOverLabel->SetVisible( true ); |
|
} |
|
} |
|
} |
|
|
|
CSaxxyAwardsSubmitForm::CSaxxyAwardsSubmitForm( Panel *pParent ) |
|
: BaseClass( pParent, "SaxxySubmitForm" ), |
|
m_pURLInput( NULL ), |
|
m_pCategoryCombo( NULL ) |
|
{ |
|
} |
|
|
|
void CSaxxyAwardsSubmitForm::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
// Link in TF scheme |
|
extern IEngineVGui *enginevgui; |
|
vgui::HScheme pTFScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" ); |
|
SetScheme( pTFScheme ); |
|
SetProportional( true ); |
|
|
|
BaseClass::ApplySchemeSettings( vgui::scheme()->GetIScheme( pTFScheme ) ); |
|
|
|
LoadControlSettings( "resource/UI/SaxxyAwards_SubmitForm.res" ); |
|
|
|
m_pURLInput = dynamic_cast< TextEntry * >( FindChildByName( "URLInput" ) ); |
|
if ( m_pURLInput ) |
|
{ |
|
m_pURLInput->SetText( "#Replay_YouTubeURL" ); |
|
} |
|
|
|
m_pCategoryCombo = dynamic_cast< ComboBox * >( FindChildByName( "CategoryCombo" ) ); |
|
if ( m_pCategoryCombo ) |
|
{ |
|
// Add "Categories" text |
|
const int nDefaultItemID = m_pCategoryCombo->AddItem( "#Replay_Category", NULL ); |
|
m_pCategoryCombo->ActivateItem( nDefaultItemID ); |
|
|
|
// Add all categories |
|
const wchar_t *pCategoryText = L""; |
|
int i = 0; |
|
while ( true ) |
|
{ |
|
CFmtStr fmtCategoryToken( "#Replay_Contest_Category%i", i++ ); |
|
pCategoryText = g_pVGuiLocalize->Find( fmtCategoryToken.Access() ); |
|
if ( !pCategoryText || !pCategoryText[0] ) |
|
break; |
|
m_pCategoryCombo->AddItem( pCategoryText, NULL ); |
|
} |
|
|
|
m_pCategoryCombo->SetNumberOfEditLines( i ); |
|
} |
|
} |
|
|
|
void CSaxxyAwardsSubmitForm::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
} |
|
|
|
void CSaxxyAwardsSubmitForm::OnCommand( const char *pCommand ) |
|
{ |
|
if ( FStrEq( pCommand, "submit" ) ) |
|
{ |
|
// need a category |
|
if ( m_pCategoryCombo->GetActiveItem() == 0 ) |
|
{ |
|
ShowMessageBox( "#Replay_Contest_StatusTitle", "#Replay_Contest_ChooseCategory", "#GameUI_OK" ); |
|
return; |
|
} |
|
|
|
// need a non-empty string |
|
char szText[256]; |
|
m_pURLInput->GetText( szText, sizeof( szText ) ); |
|
if ( Q_strlen( szText ) == 0 ) |
|
{ |
|
ShowMessageBox( "#Replay_Contest_StatusTitle", "#Replay_Contest_EnterURL", "#GameUI_OK" ); |
|
return; |
|
} |
|
|
|
// waiting dialog |
|
ShowWaitingDialog( new CGenericWaitingDialog( this ), "#Replay_Contest_Waiting", true, true, 30.0f ); |
|
|
|
// send the url |
|
GCSDK::CProtoBufMsg< CMsgReplaySubmitContestEntry > msg( k_EMsgGCReplay_SubmitContestEntry ); |
|
msg.Body().set_youtube_url( szText ); |
|
msg.Body().set_category( m_pCategoryCombo->GetActiveItem() - 1 ); |
|
GCClientSystem()->GetGCClient()->BSendMessage( msg ); |
|
|
|
// close the submit dialog |
|
Close(); |
|
} |
|
else if ( FStrEq( pCommand, "cancel" ) ) |
|
{ |
|
Close(); |
|
} |
|
else if ( FStrEq( pCommand, "rules" ) ) |
|
{ |
|
if ( steamapicontext && steamapicontext->SteamFriends() ) |
|
{ |
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( "http://www.teamfortress.com/saxxyawards/#rules" ); |
|
} |
|
} |
|
else |
|
{ |
|
BaseClass::OnCommand( pCommand ); |
|
} |
|
} |
|
|
|
void CSaxxyAwardsSubmitForm::Close() |
|
{ |
|
TFModalStack()->PopModal( this ); |
|
MarkForDeletion(); |
|
} |
|
|
|
void CSaxxyAwardsSubmitForm::OnKeyCodeTyped( vgui::KeyCode nCode ) |
|
{ |
|
if ( nCode == KEY_ESCAPE ) |
|
{ |
|
Close(); |
|
} |
|
else |
|
{ |
|
BaseClass::OnKeyCodeTyped( nCode ); |
|
} |
|
} |
|
|
|
static void SaxxyAwards_ShowSubmitForm() |
|
{ |
|
CSaxxyAwardsSubmitForm *pSubmitDialog = vgui::SETUP_PANEL( new CSaxxyAwardsSubmitForm( NULL ) ); |
|
|
|
pSubmitDialog->SetVisible( true ); |
|
pSubmitDialog->MakePopup(); |
|
pSubmitDialog->MoveToFront(); |
|
pSubmitDialog->SetKeyBoardInputEnabled( true ); |
|
pSubmitDialog->SetMouseInputEnabled( true ); |
|
TFModalStack()->PushModal( pSubmitDialog ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Refresh the saxxy awards portion of the main menu |
|
//----------------------------------------------------------------------------- |
|
class CGC_Replay_SubmitContestEntryResponse_Status : public GCSDK::CGCClientJob |
|
{ |
|
public: |
|
CGC_Replay_SubmitContestEntryResponse_Status( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {} |
|
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket ) |
|
{ |
|
GCSDK::CProtoBufMsg< CMsgReplaySubmitContestEntryResponse > msg( pNetPacket ); |
|
|
|
CloseWaitingDialog(); |
|
|
|
if ( msg.Body().success() ) |
|
{ |
|
ShowMessageBox( "#Replay_Contest_StatusTitle", "#Replay_Contest_StatusSuccess", "#GameUI_OK" ); |
|
} |
|
else |
|
{ |
|
ShowMessageBox( "#Replay_Contest_StatusTitle", "#Replay_Contest_StatusFailure", "#GameUI_OK" ); |
|
} |
|
|
|
return true; |
|
} |
|
protected: |
|
}; |
|
GC_REG_JOB( GCSDK::CGCClient, CGC_Replay_SubmitContestEntryResponse_Status, "CGC_Replay_SubmitContestEntryResponse_Status", k_EMsgGCReplay_SubmitContestEntryResponse, GCSDK::k_EServerTypeGCClient ); |
|
#endif // #ifdef SAXXYMAINMENU_ENABLED
|