1742 lines
49 KiB
C++
1742 lines
49 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "BasePanel.h"
|
|
#include "NewGameDialog.h"
|
|
#include "EngineInterface.h"
|
|
#include "vgui_controls/Button.h"
|
|
#include "vgui_controls/CheckButton.h"
|
|
#include "KeyValues.h"
|
|
#include "vgui/ISurface.h"
|
|
#include "vgui/IInput.h"
|
|
#include "vgui/ILocalize.h"
|
|
#include <vgui/ISystem.h>
|
|
#include "vgui_controls/RadioButton.h"
|
|
#include "vgui_controls/ComboBox.h"
|
|
#include "vgui_controls/ImagePanel.h"
|
|
#include "vgui_controls/Frame.h"
|
|
#include "vgui_controls/ControllerMap.h"
|
|
#include "filesystem.h"
|
|
#include "ModInfo.h"
|
|
#include "tier1/convar.h"
|
|
#include "GameUI_Interface.h"
|
|
#include "tier0/icommandline.h"
|
|
#include "vgui_controls/AnimationController.h"
|
|
#include "CommentaryExplanationDialog.h"
|
|
#include "vgui_controls/BitmapImagePanel.h"
|
|
#include "BonusMapsDatabase.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
using namespace vgui;
|
|
|
|
static float g_ScrollSpeedSlow;
|
|
static float g_ScrollSpeedFast;
|
|
|
|
// sort function used in displaying chapter list
|
|
struct chapter_t
|
|
{
|
|
char filename[32];
|
|
};
|
|
static int __cdecl ChapterSortFunc(const void *elem1, const void *elem2)
|
|
{
|
|
chapter_t *c1 = (chapter_t *)elem1;
|
|
chapter_t *c2 = (chapter_t *)elem2;
|
|
|
|
// compare chapter number first
|
|
static int chapterlen = strlen("chapter");
|
|
if (atoi(c1->filename + chapterlen) > atoi(c2->filename + chapterlen))
|
|
return 1;
|
|
else if (atoi(c1->filename + chapterlen) < atoi(c2->filename + chapterlen))
|
|
return -1;
|
|
|
|
// compare length second (longer string show up later in the list, eg. chapter9 before chapter9a)
|
|
if (strlen(c1->filename) > strlen(c2->filename))
|
|
return 1;
|
|
else if (strlen(c1->filename) < strlen(c2->filename))
|
|
return -1;
|
|
|
|
// compare strings third
|
|
return strcmp(c1->filename, c2->filename);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: invisible panel used for selecting a chapter panel
|
|
//-----------------------------------------------------------------------------
|
|
class CSelectionOverlayPanel : public vgui::Panel
|
|
{
|
|
DECLARE_CLASS_SIMPLE( CSelectionOverlayPanel, Panel );
|
|
int m_iChapterIndex;
|
|
CNewGameDialog *m_pSelectionTarget;
|
|
public:
|
|
CSelectionOverlayPanel( Panel *parent, CNewGameDialog *selectionTarget, int chapterIndex ) : BaseClass( parent, NULL )
|
|
{
|
|
m_iChapterIndex = chapterIndex;
|
|
m_pSelectionTarget = selectionTarget;
|
|
SetPaintEnabled(false);
|
|
SetPaintBackgroundEnabled(false);
|
|
}
|
|
|
|
virtual void OnMousePressed( vgui::MouseCode code )
|
|
{
|
|
if (GetParent()->IsEnabled())
|
|
{
|
|
m_pSelectionTarget->SetSelectedChapterIndex( m_iChapterIndex );
|
|
}
|
|
}
|
|
|
|
virtual void OnMouseDoublePressed( vgui::MouseCode code )
|
|
{
|
|
// call the panel
|
|
OnMousePressed( code );
|
|
if (GetParent()->IsEnabled())
|
|
{
|
|
PostMessage( m_pSelectionTarget, new KeyValues("Command", "command", "play") );
|
|
}
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: selectable item with screenshot for an individual chapter in the dialog
|
|
//-----------------------------------------------------------------------------
|
|
class CGameChapterPanel : public vgui::EditablePanel
|
|
{
|
|
DECLARE_CLASS_SIMPLE( CGameChapterPanel, vgui::EditablePanel );
|
|
|
|
ImagePanel *m_pLevelPicBorder;
|
|
ImagePanel *m_pLevelPic;
|
|
ImagePanel *m_pCommentaryIcon;
|
|
Label *m_pChapterLabel;
|
|
Label *m_pChapterNameLabel;
|
|
|
|
Color m_TextColor;
|
|
Color m_DisabledColor;
|
|
Color m_SelectedColor;
|
|
Color m_FillColor;
|
|
|
|
char m_szConfigFile[_MAX_PATH];
|
|
char m_szChapter[32];
|
|
|
|
bool m_bTeaserChapter;
|
|
bool m_bHasBonus;
|
|
bool m_bCommentaryMode;
|
|
|
|
bool m_bIsSelected;
|
|
|
|
public:
|
|
CGameChapterPanel( CNewGameDialog *parent, const char *name, const char *chapterName, int chapterIndex, const char *chapterNumber, const char *chapterConfigFile, bool bCommentary ) : BaseClass( parent, name )
|
|
{
|
|
Q_strncpy( m_szConfigFile, chapterConfigFile, sizeof(m_szConfigFile) );
|
|
Q_strncpy( m_szChapter, chapterNumber, sizeof(m_szChapter) );
|
|
|
|
m_pLevelPicBorder = SETUP_PANEL( new ImagePanel( this, "LevelPicBorder" ) );
|
|
m_pLevelPic = SETUP_PANEL( new ImagePanel( this, "LevelPic" ) );
|
|
m_pCommentaryIcon = NULL;
|
|
m_bCommentaryMode = bCommentary;
|
|
m_bIsSelected = false;
|
|
|
|
wchar_t text[32];
|
|
wchar_t num[32];
|
|
wchar_t *chapter = g_pVGuiLocalize->Find("#GameUI_Chapter");
|
|
g_pVGuiLocalize->ConvertANSIToUnicode( chapterNumber, num, sizeof(num) );
|
|
_snwprintf( text, ARRAYSIZE(text), L"%ls %ls", chapter ? chapter : L"CHAPTER", num );
|
|
|
|
if ( ModInfo().IsSinglePlayerOnly() )
|
|
{
|
|
m_pChapterLabel = new Label( this, "ChapterLabel", text );
|
|
m_pChapterNameLabel = new Label( this, "ChapterNameLabel", chapterName );
|
|
}
|
|
else
|
|
{
|
|
m_pChapterLabel = new Label( this, "ChapterLabel", chapterName );
|
|
m_pChapterNameLabel = new Label( this, "ChapterNameLabel", "#GameUI_LoadCommentary" );
|
|
}
|
|
|
|
SetPaintBackgroundEnabled( false );
|
|
|
|
KeyValues *pKeys = NULL;
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
pKeys = BasePanel()->GetConsoleControlSettings()->FindKey( "NewGameChapterPanel.res" );
|
|
}
|
|
LoadControlSettings( "Resource/NewGameChapterPanel.res", NULL, pKeys );
|
|
|
|
// the image has the same name as the config file
|
|
char szMaterial[MAX_PATH];
|
|
Q_snprintf(szMaterial, sizeof(szMaterial), "chapters/%s", chapterConfigFile);
|
|
char* ext = strstr(szMaterial, ".");
|
|
if (ext)
|
|
{
|
|
*ext = 0;
|
|
}
|
|
m_pLevelPic->SetImage(szMaterial);
|
|
|
|
int px, py;
|
|
m_pLevelPicBorder->GetPos( px, py );
|
|
SetSize( m_pLevelPicBorder->GetWide(), py + m_pLevelPicBorder->GetTall() );
|
|
|
|
// create a selection panel the size of the page
|
|
CSelectionOverlayPanel *overlay = new CSelectionOverlayPanel( this, parent, chapterIndex );
|
|
overlay->SetBounds(0, 0, GetWide(), GetTall());
|
|
overlay->MoveToFront();
|
|
|
|
// HACK: Detect new episode teasers by the "Coming Soon" text
|
|
wchar_t w_szStrTemp[256];
|
|
m_pChapterNameLabel->GetText( w_szStrTemp, sizeof(w_szStrTemp) );
|
|
m_bTeaserChapter = !wcscmp(w_szStrTemp, L"Coming Soon");
|
|
m_bHasBonus = false;
|
|
}
|
|
|
|
virtual void ApplySchemeSettings( IScheme *pScheme )
|
|
{
|
|
m_TextColor = pScheme->GetColor( "NewGame.TextColor", Color(255, 255, 255, 255) );
|
|
m_FillColor = pScheme->GetColor( "NewGame.FillColor", Color(255, 255, 255, 255) );
|
|
m_DisabledColor = pScheme->GetColor( "NewGame.DisabledColor", Color(255, 255, 255, 255) );
|
|
m_SelectedColor = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) );
|
|
|
|
BaseClass::ApplySchemeSettings( pScheme );
|
|
|
|
// Hide chapter numbers for new episode teasers
|
|
if ( m_bTeaserChapter )
|
|
{
|
|
m_pChapterLabel->SetVisible( false );
|
|
}
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
m_pChapterNameLabel->SetVisible( false );
|
|
}
|
|
|
|
m_pCommentaryIcon = dynamic_cast<ImagePanel*>( FindChildByName( "CommentaryIcon" ) );
|
|
if ( m_pCommentaryIcon )
|
|
m_pCommentaryIcon->SetVisible( m_bCommentaryMode );
|
|
}
|
|
|
|
bool IsSelected( void ) const { return m_bIsSelected; }
|
|
|
|
void SetSelected( bool state )
|
|
{
|
|
m_bIsSelected = state;
|
|
|
|
// update the text/border colors
|
|
if ( !IsEnabled() )
|
|
{
|
|
m_pChapterLabel->SetFgColor( m_DisabledColor );
|
|
m_pChapterNameLabel->SetFgColor( Color(0, 0, 0, 0) );
|
|
m_pLevelPicBorder->SetFillColor( m_DisabledColor );
|
|
m_pLevelPic->SetAlpha( GameUI().IsConsoleUI() ? 64 : 128 );
|
|
return;
|
|
}
|
|
|
|
if ( state )
|
|
{
|
|
if ( !GameUI().IsConsoleUI() )
|
|
{
|
|
m_pChapterLabel->SetFgColor( m_SelectedColor );
|
|
m_pChapterNameLabel->SetFgColor( m_SelectedColor );
|
|
}
|
|
m_pLevelPicBorder->SetFillColor( m_SelectedColor );
|
|
}
|
|
else
|
|
{
|
|
m_pChapterLabel->SetFgColor( m_TextColor );
|
|
m_pChapterNameLabel->SetFgColor( m_TextColor );
|
|
m_pLevelPicBorder->SetFillColor( m_FillColor );
|
|
}
|
|
m_pLevelPic->SetAlpha( 255 );
|
|
}
|
|
|
|
const char *GetConfigFile()
|
|
{
|
|
return m_szConfigFile;
|
|
}
|
|
|
|
const char *GetChapter()
|
|
{
|
|
return m_szChapter;
|
|
}
|
|
|
|
bool IsTeaserChapter()
|
|
{
|
|
return m_bTeaserChapter;
|
|
}
|
|
|
|
bool HasBonus()
|
|
{
|
|
return m_bHasBonus;
|
|
}
|
|
|
|
void SetCommentaryMode( bool bCommentaryMode )
|
|
{
|
|
m_bCommentaryMode = bCommentaryMode;
|
|
if ( m_pCommentaryIcon )
|
|
m_pCommentaryIcon->SetVisible( m_bCommentaryMode );
|
|
}
|
|
};
|
|
|
|
const char *COM_GetModDirectory()
|
|
{
|
|
static char modDir[MAX_PATH];
|
|
if ( Q_strlen( modDir ) == 0 )
|
|
{
|
|
const char *gamedir = CommandLine()->ParmValue("-game", CommandLine()->ParmValue( "-defaultgamedir", "hl2" ) );
|
|
Q_strncpy( modDir, gamedir, sizeof(modDir) );
|
|
if ( strchr( modDir, '/' ) || strchr( modDir, '\\' ) )
|
|
{
|
|
Q_StripLastDir( modDir, sizeof(modDir) );
|
|
int dirlen = Q_strlen( modDir );
|
|
Q_strncpy( modDir, gamedir + dirlen, sizeof(modDir) - dirlen );
|
|
}
|
|
}
|
|
|
|
return modDir;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: new game chapter selection
|
|
//-----------------------------------------------------------------------------
|
|
CNewGameDialog::CNewGameDialog(vgui::Panel *parent, bool bCommentaryMode) : BaseClass(parent, "NewGameDialog")
|
|
{
|
|
SetDeleteSelfOnClose(true);
|
|
SetBounds(0, 0, 372, 160);
|
|
SetSizeable( false );
|
|
m_iSelectedChapter = -1;
|
|
m_ActiveTitleIdx = 0;
|
|
|
|
m_bCommentaryMode = bCommentaryMode;
|
|
m_bMapStarting = false;
|
|
m_bScrolling = false;
|
|
m_ScrollCt = 0;
|
|
m_ScrollSpeed = 0.f;
|
|
m_ButtonPressed = SCROLL_NONE;
|
|
m_ScrollDirection = SCROLL_NONE;
|
|
m_pCommentaryLabel = NULL;
|
|
|
|
m_iBonusSelection = 0;
|
|
m_bScrollToFirstBonusMap = false;
|
|
|
|
SetTitle("#GameUI_NewGame", true);
|
|
|
|
m_pNextButton = new Button( this, "Next", "#gameui_next" );
|
|
m_pPrevButton = new Button( this, "Prev", "#gameui_prev" );
|
|
m_pPlayButton = new CNewGamePlayButton( this, "Play", "#GameUI_Play" );
|
|
m_pPlayButton->SetCommand( "Play" );
|
|
|
|
vgui::Button *cancel = new vgui::Button( this, "Cancel", "#GameUI_Cancel" );
|
|
cancel->SetCommand( "Close" );
|
|
|
|
m_pCenterBg = SETUP_PANEL( new Panel( this, "CenterBG" ) );
|
|
m_pCenterBg->SetVisible( false );
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
m_pNextButton->SetVisible( false );
|
|
m_pPrevButton->SetVisible( false );
|
|
m_pPlayButton->SetVisible( false );
|
|
cancel->SetVisible( false );
|
|
|
|
m_pCenterBg->SetPaintBackgroundType( 2 );
|
|
m_pCenterBg->SetVisible( true );
|
|
|
|
m_pChapterTitleLabels[0] = SETUP_PANEL( new Label( this, "ChapterTitleLabel", "" ) );
|
|
m_pChapterTitleLabels[0]->SetVisible( true );
|
|
m_pChapterTitleLabels[0]->SetFgColor( Color( 255, 255, 255, 255 ) );
|
|
|
|
m_pChapterTitleLabels[1] = SETUP_PANEL( new Label( this, "ChapterTitleLabel2", "" ) );
|
|
m_pChapterTitleLabels[1]->SetVisible( true );
|
|
m_pChapterTitleLabels[1]->SetAlpha( 0 );
|
|
m_pChapterTitleLabels[1]->SetFgColor( Color( 255, 255, 255, 255 ) );
|
|
|
|
m_pBonusSelection = SETUP_PANEL( new Label( this, "BonusSelectionLabel", "#GameUI_BonusMapsStandard" ) );
|
|
m_pBonusSelectionBorder = SETUP_PANEL( new ImagePanel( this, "BonusSelectionBorder" ) );
|
|
|
|
m_pFooter = new CFooterPanel( parent, "NewGameFooter" );
|
|
m_pFooter->AddNewButtonLabel( "#GameUI_Play", "#GameUI_Icons_A_BUTTON" );
|
|
m_pFooter->AddNewButtonLabel( "#GameUI_Close", "#GameUI_Icons_B_BUTTON" );
|
|
}
|
|
else
|
|
{
|
|
m_pFooter = NULL;
|
|
}
|
|
|
|
// parse out the chapters off disk
|
|
static const int MAX_CHAPTERS = 32;
|
|
chapter_t chapters[MAX_CHAPTERS];
|
|
|
|
char szFullFileName[MAX_PATH];
|
|
int chapterIndex = 0;
|
|
|
|
if ( IsPC() || !IsX360() )
|
|
{
|
|
FileFindHandle_t findHandle = FILESYSTEM_INVALID_FIND_HANDLE;
|
|
const char *fileName = "cfg/chapter*.cfg";
|
|
fileName = g_pFullFileSystem->FindFirst( fileName, &findHandle );
|
|
while ( fileName && chapterIndex < MAX_CHAPTERS )
|
|
{
|
|
if ( fileName[0] )
|
|
{
|
|
// Only load chapter configs from the current mod's cfg dir
|
|
// or else chapters appear that we don't want!
|
|
Q_snprintf( szFullFileName, sizeof(szFullFileName), "cfg/%s", fileName );
|
|
FileHandle_t f = g_pFullFileSystem->Open( szFullFileName, "rb", "MOD" );
|
|
if ( f )
|
|
{
|
|
// don't load chapter files that are empty, used in the demo
|
|
if ( g_pFullFileSystem->Size(f) > 0 )
|
|
{
|
|
Q_strncpy(chapters[chapterIndex].filename, fileName, sizeof(chapters[chapterIndex].filename));
|
|
++chapterIndex;
|
|
}
|
|
g_pFullFileSystem->Close( f );
|
|
}
|
|
}
|
|
fileName = g_pFullFileSystem->FindNext(findHandle);
|
|
}
|
|
}
|
|
else if ( IsX360() )
|
|
{
|
|
int ChapterStringIndex = 0;
|
|
bool bExists = true;
|
|
while ( bExists && chapterIndex < MAX_CHAPTERS )
|
|
{
|
|
Q_snprintf( szFullFileName, sizeof( szFullFileName ), "cfg/chapter%d.cfg", ChapterStringIndex+1 );
|
|
|
|
FileHandle_t f = g_pFullFileSystem->Open( szFullFileName, "rb", "MOD" );
|
|
if ( f )
|
|
{
|
|
Q_strncpy(chapters[chapterIndex].filename, szFullFileName + 4, sizeof(chapters[chapterIndex].filename));
|
|
++chapterIndex;
|
|
++ChapterStringIndex;
|
|
g_pFullFileSystem->Close( f );
|
|
}
|
|
else
|
|
{
|
|
bExists = false;
|
|
}
|
|
//Hack to account for xbox360 missing chapter9a
|
|
if ( ChapterStringIndex == 10 )
|
|
{
|
|
Q_snprintf( szFullFileName, sizeof( szFullFileName ), "cfg/chapter9a.cfg" );
|
|
FileHandle_t fChap = g_pFullFileSystem->Open( szFullFileName, "rb", "MOD" );
|
|
if ( fChap )
|
|
{
|
|
Q_strncpy(chapters[chapterIndex].filename, szFullFileName + 4, sizeof(chapters[chapterIndex].filename));
|
|
++chapterIndex;
|
|
g_pFullFileSystem->Close( fChap );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bool bBonusesUnlocked = false;
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
if ( !m_bCommentaryMode )
|
|
{
|
|
// Scan to see if the bonus maps have been unlocked
|
|
bBonusesUnlocked = BonusMapsDatabase()->BonusesUnlocked();
|
|
}
|
|
}
|
|
|
|
// sort the chapters
|
|
qsort(chapters, chapterIndex, sizeof(chapter_t), &ChapterSortFunc);
|
|
|
|
// work out which chapters are unlocked
|
|
ConVarRef var( "sv_unlockedchapters" );
|
|
|
|
if ( bBonusesUnlocked )
|
|
{
|
|
// Bonuses are unlocked so we need to unlock all the chapters too
|
|
var.SetValue( 15 );
|
|
}
|
|
|
|
const char *unlockedChapter = var.IsValid() ? var.GetString() : "1";
|
|
int iUnlockedChapter = atoi(unlockedChapter);
|
|
|
|
// add chapters to combobox
|
|
for (int i = 0; i < chapterIndex; i++)
|
|
{
|
|
const char *fileName = chapters[i].filename;
|
|
char chapterID[32] = { 0 };
|
|
sscanf(fileName, "chapter%s", chapterID);
|
|
// strip the extension
|
|
char *ext = V_stristr(chapterID, ".cfg");
|
|
if (ext)
|
|
{
|
|
*ext = 0;
|
|
}
|
|
|
|
const char *pGameDir = COM_GetModDirectory();
|
|
|
|
char chapterName[64];
|
|
Q_snprintf(chapterName, sizeof(chapterName), "#%s_Chapter%s_Title", pGameDir, chapterID);
|
|
|
|
Q_snprintf( szFullFileName, sizeof( szFullFileName ), "%s", fileName );
|
|
CGameChapterPanel *chapterPanel = SETUP_PANEL( new CGameChapterPanel( this, NULL, chapterName, i, chapterID, szFullFileName, m_bCommentaryMode ) );
|
|
chapterPanel->SetVisible( false );
|
|
|
|
UpdatePanelLockedStatus( iUnlockedChapter, i + 1, chapterPanel );
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
if ( bBonusesUnlocked )
|
|
{
|
|
// check to see if it has associated challenges
|
|
for ( int iBonusMap = 0; iBonusMap < BonusMapsDatabase()->BonusCount(); ++iBonusMap )
|
|
{
|
|
BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( iBonusMap );
|
|
if ( Q_stricmp( pMap->szChapterName, szFullFileName ) == 0 && !pMap->bLocked )
|
|
{
|
|
chapterPanel->m_bHasBonus = true;
|
|
chapterPanel->SetControlVisible( "HasBonusLabel", true );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_ChapterPanels.AddToTail( chapterPanel );
|
|
}
|
|
|
|
KeyValues *pKeys = NULL;
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
pKeys = BasePanel()->GetConsoleControlSettings()->FindKey( "NewGameDialog.res" );
|
|
}
|
|
LoadControlSettings( "Resource/NewGameDialog.res", NULL, pKeys );
|
|
|
|
// Reset all properties
|
|
for ( int i = 0; i < NUM_SLOTS; ++i )
|
|
{
|
|
m_PanelIndex[i] = INVALID_INDEX;
|
|
}
|
|
|
|
if ( !m_ChapterPanels.Count() )
|
|
{
|
|
UpdateMenuComponents( SCROLL_NONE );
|
|
return;
|
|
}
|
|
|
|
int indent = 8;
|
|
if ( IsProportional() )
|
|
{
|
|
indent = scheme()->GetProportionalScaledValueEx( GetScheme(), indent );
|
|
}
|
|
|
|
int wide = 16;
|
|
if ( IsProportional() )
|
|
{
|
|
wide = scheme()->GetProportionalScaledValueEx( GetScheme(), wide );
|
|
}
|
|
|
|
// Layout panel positions relative to the dialog center.
|
|
int panelWidth = m_ChapterPanels[0]->GetWide() + wide;
|
|
int dialogWidth = GetWide();
|
|
|
|
m_PanelXPos[2] = ( dialogWidth - panelWidth ) / 2 + indent;
|
|
|
|
if (m_ChapterPanels.Count() > 1)
|
|
{
|
|
m_PanelXPos[1] = m_PanelXPos[2] - panelWidth;
|
|
m_PanelXPos[0] = m_PanelXPos[1];
|
|
m_PanelXPos[3] = m_PanelXPos[2] + panelWidth;
|
|
m_PanelXPos[4] = m_PanelXPos[3];
|
|
}
|
|
else
|
|
{
|
|
m_PanelXPos[0] = m_PanelXPos[1] = m_PanelXPos[3] =
|
|
m_PanelXPos[4] = m_PanelXPos[2];
|
|
}
|
|
|
|
|
|
m_PanelAlpha[0] = 0;
|
|
m_PanelAlpha[1] = 255;
|
|
m_PanelAlpha[2] = 255;
|
|
m_PanelAlpha[3] = 255;
|
|
m_PanelAlpha[4] = 0;
|
|
|
|
int panelHeight;
|
|
m_ChapterPanels[0]->GetSize( panelWidth, panelHeight );
|
|
m_pCenterBg->SetWide( panelWidth + wide);
|
|
m_pCenterBg->SetPos( m_PanelXPos[2] - indent, m_PanelYPos[2] - (m_pCenterBg->GetTall() - panelHeight) + indent );
|
|
m_pCenterBg->SetBgColor( Color( 190, 115, 0, 255 ) );
|
|
|
|
// start the first item selected
|
|
SetSelectedChapterIndex( 0 );
|
|
}
|
|
|
|
CNewGameDialog::~CNewGameDialog()
|
|
{
|
|
delete m_pFooter;
|
|
m_pFooter = NULL;
|
|
}
|
|
|
|
void CNewGameDialog::Activate( void )
|
|
{
|
|
m_bMapStarting = false;
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
// Stop blinking the menu item now that we've seen the unlocked stuff
|
|
CBasePanel *pBasePanel = BasePanel();
|
|
if ( pBasePanel )
|
|
pBasePanel->SetMenuItemBlinkingState( "OpenNewGameDialog", false );
|
|
|
|
BonusMapsDatabase()->SetBlink( false );
|
|
}
|
|
|
|
// Commentary stuff is set up on activate because in XBox the new game menu is never deleted
|
|
SetTitle( ( ( m_bCommentaryMode ) ? ( "#GameUI_LoadCommentary" ) : ( "#GameUI_NewGame") ), true);
|
|
|
|
if ( m_pCommentaryLabel )
|
|
m_pCommentaryLabel->SetVisible( m_bCommentaryMode );
|
|
|
|
// work out which chapters are unlocked
|
|
ConVarRef var( "sv_unlockedchapters" );
|
|
const char *unlockedChapter = var.IsValid() ? var.GetString() : "1";
|
|
int iUnlockedChapter = atoi(unlockedChapter);
|
|
|
|
for ( int i = 0; i < m_ChapterPanels.Count(); i++)
|
|
{
|
|
CGameChapterPanel *pChapterPanel = m_ChapterPanels[ i ];
|
|
|
|
if ( pChapterPanel )
|
|
{
|
|
pChapterPanel->SetCommentaryMode( m_bCommentaryMode );
|
|
|
|
UpdatePanelLockedStatus( iUnlockedChapter, i + 1, pChapterPanel );
|
|
}
|
|
}
|
|
|
|
BaseClass::Activate();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Apply special properties of the menu
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::ApplySettings( KeyValues *inResourceData )
|
|
{
|
|
BaseClass::ApplySettings( inResourceData );
|
|
|
|
int ypos = inResourceData->GetInt( "chapterypos", 40 );
|
|
if ( IsProportional() )
|
|
{
|
|
ypos = scheme()->GetProportionalScaledValueEx( GetScheme(), ypos );
|
|
}
|
|
|
|
for ( int i = 0; i < NUM_SLOTS; ++i )
|
|
{
|
|
m_PanelYPos[i] = ypos;
|
|
}
|
|
|
|
m_pCenterBg->SetTall( inResourceData->GetInt( "centerbgtall", 0 ) );
|
|
|
|
g_ScrollSpeedSlow = inResourceData->GetFloat( "scrollslow", 0.0f );
|
|
g_ScrollSpeedFast = inResourceData->GetFloat( "scrollfast", 0.0f );
|
|
SetFastScroll( false );
|
|
}
|
|
|
|
void CNewGameDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
|
|
{
|
|
BaseClass::ApplySchemeSettings( pScheme );
|
|
|
|
if ( m_pFooter )
|
|
{
|
|
KeyValues *pFooterControlSettings = BasePanel()->GetConsoleControlSettings()->FindKey( "NewGameFooter.res" );
|
|
m_pFooter->LoadControlSettings( "null", NULL, pFooterControlSettings );
|
|
}
|
|
|
|
UpdateMenuComponents( SCROLL_NONE );
|
|
|
|
m_pCommentaryLabel = dynamic_cast<vgui::Label*>( FindChildByName( "CommentaryUnlock" ) );
|
|
if ( m_pCommentaryLabel )
|
|
m_pCommentaryLabel->SetVisible( m_bCommentaryMode );
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
if ( !m_bCommentaryMode && BonusMapsDatabase()->BonusesUnlocked() && !m_ChapterPanels[ m_PanelIndex[SLOT_CENTER] ]->HasBonus() )
|
|
{
|
|
// Find the first bonus
|
|
ScrollSelectionPanels( SCROLL_LEFT );
|
|
m_bScrollToFirstBonusMap = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
static float GetArrowAlpha( void )
|
|
{
|
|
// X360TBD: Pulsing arrows
|
|
return 255.f;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: sets the correct properties for visible components
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::UpdateMenuComponents( EScrollDirection dir )
|
|
{
|
|
// This is called prior to any scrolling,
|
|
// so we need to look ahead to the post-scroll state
|
|
int centerIdx = SLOT_CENTER;
|
|
if ( dir == SCROLL_LEFT )
|
|
{
|
|
++centerIdx;
|
|
}
|
|
else if ( dir == SCROLL_RIGHT )
|
|
{
|
|
--centerIdx;
|
|
}
|
|
int leftIdx = centerIdx - 1;
|
|
int rightIdx = centerIdx + 1;
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
bool bHasBonus = false;
|
|
if ( m_PanelIndex[centerIdx] != INVALID_INDEX )
|
|
{
|
|
wchar_t buffer[ MAX_PATH ];
|
|
m_ChapterPanels[ m_PanelIndex[centerIdx] ]->m_pChapterNameLabel->GetText( buffer, sizeof(buffer) );
|
|
m_pChapterTitleLabels[(unsigned)m_ActiveTitleIdx]->SetText( buffer );
|
|
|
|
// If it has bonuses show the scroll up and down arrows
|
|
bHasBonus = m_ChapterPanels[ m_PanelIndex[centerIdx] ]->HasBonus();
|
|
}
|
|
|
|
vgui::Panel *leftArrow = this->FindChildByName( "LeftArrow" );
|
|
vgui::Panel *rightArrow = this->FindChildByName( "RightArrow" );
|
|
if ( leftArrow )
|
|
{
|
|
if ( m_PanelIndex[leftIdx] != INVALID_INDEX )
|
|
{
|
|
leftArrow->SetFgColor( Color( 255, 255, 255, GetArrowAlpha() ) );
|
|
}
|
|
else
|
|
{
|
|
leftArrow->SetFgColor( Color( 128, 128, 128, 64 ) );
|
|
}
|
|
}
|
|
if ( rightArrow )
|
|
{
|
|
if ( m_PanelIndex[rightIdx] != INVALID_INDEX )
|
|
{
|
|
rightArrow->SetFgColor( Color( 255, 255, 255, GetArrowAlpha() ) );
|
|
}
|
|
else
|
|
{
|
|
rightArrow->SetFgColor( Color( 128, 128, 128, 64 ) );
|
|
}
|
|
}
|
|
|
|
if ( bHasBonus )
|
|
{
|
|
// Find the bonus description for this panel
|
|
for ( int iBonus = 0; iBonus < BonusMapsDatabase()->BonusCount(); ++iBonus )
|
|
{
|
|
m_pBonusMapDescription = BonusMapsDatabase()->GetBonusData( iBonus );
|
|
if ( Q_stricmp( m_pBonusMapDescription->szChapterName, m_ChapterPanels[ m_PanelIndex[centerIdx] ]->GetConfigFile() ) == 0 )
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pBonusMapDescription = NULL;
|
|
}
|
|
|
|
vgui::Panel *upArrow = this->FindChildByName( "UpArrow" );
|
|
vgui::Panel *downArrow = this->FindChildByName( "DownArrow" );
|
|
|
|
if ( upArrow )
|
|
upArrow->SetVisible( bHasBonus );
|
|
if ( downArrow )
|
|
downArrow->SetVisible( bHasBonus );
|
|
|
|
m_pBonusSelection->SetVisible( bHasBonus );
|
|
m_pBonusSelectionBorder->SetVisible( bHasBonus );
|
|
|
|
UpdateBonusSelection();
|
|
}
|
|
|
|
// No buttons in the xbox ui
|
|
if ( !GameUI().IsConsoleUI() )
|
|
{
|
|
if ( m_PanelIndex[leftIdx] == INVALID_INDEX || m_PanelIndex[leftIdx] == 0 )
|
|
{
|
|
m_pPrevButton->SetVisible( false );
|
|
m_pPrevButton->SetEnabled( false );
|
|
}
|
|
else
|
|
{
|
|
m_pPrevButton->SetVisible( true );
|
|
m_pPrevButton->SetEnabled( true );
|
|
}
|
|
|
|
if ( m_ChapterPanels.Count() < 4 ) // if there are less than 4 chapters show the next button but disabled
|
|
{
|
|
m_pNextButton->SetVisible( true );
|
|
m_pNextButton->SetEnabled( false );
|
|
}
|
|
else if ( m_PanelIndex[rightIdx] == INVALID_INDEX || m_PanelIndex[rightIdx] == m_ChapterPanels.Count()-1 )
|
|
{
|
|
m_pNextButton->SetVisible( false );
|
|
m_pNextButton->SetEnabled( false );
|
|
}
|
|
else
|
|
{
|
|
m_pNextButton->SetVisible( true );
|
|
m_pNextButton->SetEnabled( true );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CNewGameDialog::UpdateBonusSelection( void )
|
|
{
|
|
int iNumChallenges = 0;
|
|
if ( m_pBonusMapDescription )
|
|
{
|
|
if ( m_pBonusMapDescription->m_pChallenges )
|
|
iNumChallenges = m_pBonusMapDescription->m_pChallenges->Count();
|
|
|
|
// Wrap challenge selection to fit number of possible selections
|
|
if ( m_iBonusSelection < 0 )
|
|
m_iBonusSelection = iNumChallenges + 1;
|
|
else if ( m_iBonusSelection >= iNumChallenges + 2 )
|
|
m_iBonusSelection = 0;
|
|
}
|
|
else
|
|
{
|
|
// No medals to show
|
|
SetControlVisible( "ChallengeEarnedMedal", false );
|
|
SetControlVisible( "ChallengeBestLabel", false );
|
|
SetControlVisible( "ChallengeNextMedal", false );
|
|
SetControlVisible( "ChallengeNextLabel", false );
|
|
return;
|
|
}
|
|
|
|
if ( m_iBonusSelection == 0 )
|
|
{
|
|
m_pBonusSelection->SetText( "#GameUI_BonusMapsStandard" );
|
|
SetControlVisible( "ChallengeEarnedMedal", false );
|
|
SetControlVisible( "ChallengeBestLabel", false );
|
|
SetControlVisible( "ChallengeNextMedal", false );
|
|
SetControlVisible( "ChallengeNextLabel", false );
|
|
}
|
|
else if ( m_iBonusSelection == 1 )
|
|
{
|
|
m_pBonusSelection->SetText( "#GameUI_BonusMapsAdvanced" );
|
|
SetControlVisible( "ChallengeEarnedMedal", false );
|
|
SetControlVisible( "ChallengeBestLabel", false );
|
|
SetControlVisible( "ChallengeNextMedal", false );
|
|
SetControlVisible( "ChallengeNextLabel", false );
|
|
|
|
char szMapAdvancedName[ 256 ] = "";
|
|
if ( m_pBonusMapDescription )
|
|
{
|
|
Q_snprintf( szMapAdvancedName, sizeof( szMapAdvancedName ), "%s_advanced", m_pBonusMapDescription->szMapFileName );
|
|
}
|
|
|
|
BonusMapDescription_t *pAdvancedDescription = NULL;
|
|
|
|
// Find the bonus description for this panel
|
|
for ( int iBonus = 0; iBonus < BonusMapsDatabase()->BonusCount(); ++iBonus )
|
|
{
|
|
pAdvancedDescription = BonusMapsDatabase()->GetBonusData( iBonus );
|
|
if ( Q_stricmp( szMapAdvancedName, pAdvancedDescription->szMapFileName ) == 0 )
|
|
break;
|
|
}
|
|
|
|
if ( pAdvancedDescription && pAdvancedDescription->bComplete )
|
|
{
|
|
CBitmapImagePanel *pBitmap = dynamic_cast<CBitmapImagePanel*>( FindChildByName( "ChallengeEarnedMedal" ) );
|
|
pBitmap->SetVisible( true );
|
|
pBitmap->setTexture( "hud/icon_complete" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int iChallenge = m_iBonusSelection - 2;
|
|
ChallengeDescription_t *pChallengeDescription = &((*m_pBonusMapDescription->m_pChallenges)[ iChallenge ]);
|
|
|
|
// Set the display text for the selected challenge
|
|
m_pBonusSelection->SetText( pChallengeDescription->szName );
|
|
|
|
int iBest, iEarnedMedal, iNext, iNextMedal;
|
|
GetChallengeMedals( pChallengeDescription, iBest, iEarnedMedal, iNext, iNextMedal );
|
|
|
|
char szBuff[ 512 ];
|
|
|
|
// Set earned medal
|
|
if ( iEarnedMedal > -1 && iBest != -1 )
|
|
{
|
|
if ( iChallenge < 10 )
|
|
Q_snprintf( szBuff, sizeof( szBuff ), "medals/medal_0%i_%s", iChallenge, g_pszMedalNames[ iEarnedMedal ] );
|
|
else
|
|
Q_snprintf( szBuff, sizeof( szBuff ), "medals/medal_%i_%s", iChallenge, g_pszMedalNames[ iEarnedMedal ] );
|
|
|
|
CBitmapImagePanel *pBitmap = dynamic_cast<CBitmapImagePanel*>( FindChildByName( "ChallengeEarnedMedal" ) );
|
|
pBitmap->SetVisible( true );
|
|
pBitmap->setTexture( szBuff );
|
|
}
|
|
else
|
|
{
|
|
CBitmapImagePanel *pBitmap = dynamic_cast<CBitmapImagePanel*>( FindChildByName( "ChallengeEarnedMedal" ) );
|
|
pBitmap->SetVisible( false );
|
|
}
|
|
|
|
// Set next medal
|
|
if ( iNextMedal > 0 )
|
|
{
|
|
if ( iChallenge < 10 )
|
|
Q_snprintf( szBuff, sizeof( szBuff ), "medals/medal_0%i_%s", iChallenge, g_pszMedalNames[ iNextMedal ] );
|
|
else
|
|
Q_snprintf( szBuff, sizeof( szBuff ), "medals/medal_%i_%s", iChallenge, g_pszMedalNames[ iNextMedal ] );
|
|
|
|
CBitmapImagePanel *pBitmap = dynamic_cast<CBitmapImagePanel*>( FindChildByName( "ChallengeNextMedal" ) );
|
|
pBitmap->SetVisible( true );
|
|
pBitmap->setTexture( szBuff );
|
|
}
|
|
else
|
|
{
|
|
SetControlVisible( "ChallengeNextMedal", false );
|
|
}
|
|
|
|
wchar_t szWideBuff[ 64 ];
|
|
wchar_t szWideBuff2[ 64 ];
|
|
|
|
// Best label
|
|
if ( iBest != -1 )
|
|
{
|
|
Q_snprintf( szBuff, sizeof( szBuff ), "%i", iBest );
|
|
g_pVGuiLocalize->ConvertANSIToUnicode( szBuff, szWideBuff2, sizeof( szWideBuff2 ) );
|
|
g_pVGuiLocalize->ConstructString( szWideBuff, sizeof( szWideBuff ), g_pVGuiLocalize->Find( "#GameUI_BonusMapsBest" ), 1, szWideBuff2 );
|
|
g_pVGuiLocalize->ConvertUnicodeToANSI( szWideBuff, szBuff, sizeof( szBuff ) );
|
|
|
|
SetControlString( "ChallengeBestLabel", szBuff );
|
|
SetControlVisible( "ChallengeBestLabel", true );
|
|
}
|
|
else
|
|
{
|
|
SetControlVisible( "ChallengeBestLabel", false );
|
|
}
|
|
|
|
// Next label
|
|
if ( iNext != -1 )
|
|
{
|
|
Q_snprintf( szBuff, sizeof( szBuff ), "%i", iNext );
|
|
g_pVGuiLocalize->ConvertANSIToUnicode( szBuff, szWideBuff2, sizeof( szWideBuff2 ) );
|
|
g_pVGuiLocalize->ConstructString( szWideBuff, sizeof( szWideBuff ), g_pVGuiLocalize->Find( "#GameUI_BonusMapsGoal" ), 1, szWideBuff2 );
|
|
g_pVGuiLocalize->ConvertUnicodeToANSI( szWideBuff, szBuff, sizeof( szBuff ) );
|
|
|
|
SetControlString( "ChallengeNextLabel", szBuff );
|
|
SetControlVisible( "ChallengeNextLabel", true );
|
|
}
|
|
else
|
|
{
|
|
SetControlVisible( "ChallengeNextLabel", false );
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: sets a chapter as selected
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::SetSelectedChapterIndex( int index )
|
|
{
|
|
m_iSelectedChapter = index;
|
|
|
|
for (int i = 0; i < m_ChapterPanels.Count(); i++)
|
|
{
|
|
if ( i == index )
|
|
{
|
|
m_ChapterPanels[i]->SetSelected( true );
|
|
}
|
|
else
|
|
{
|
|
m_ChapterPanels[i]->SetSelected( false );
|
|
}
|
|
}
|
|
|
|
if ( m_pPlayButton )
|
|
{
|
|
m_pPlayButton->SetEnabled( true );
|
|
}
|
|
|
|
// Setup panels to the left of the selected panel
|
|
int selectedSlot = GameUI().IsConsoleUI() ? SLOT_CENTER : index % 3 + 1;
|
|
int currIdx = index;
|
|
for ( int i = selectedSlot; i >= 0 && currIdx >= 0; --i )
|
|
{
|
|
m_PanelIndex[i] = currIdx;
|
|
--currIdx;
|
|
InitPanelIndexForDisplay( i );
|
|
}
|
|
|
|
// Setup panels to the right of the selected panel
|
|
currIdx = index + 1;
|
|
for ( int i = selectedSlot + 1; i < NUM_SLOTS && currIdx < m_ChapterPanels.Count(); ++i )
|
|
{
|
|
m_PanelIndex[i] = currIdx;
|
|
++currIdx;
|
|
InitPanelIndexForDisplay( i );
|
|
}
|
|
|
|
UpdateMenuComponents( SCROLL_NONE );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: sets a chapter as selected
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::SetSelectedChapter( const char *chapter )
|
|
{
|
|
Assert( chapter );
|
|
for (int i = 0; i < m_ChapterPanels.Count(); i++)
|
|
{
|
|
if ( chapter && !Q_stricmp(m_ChapterPanels[i]->GetChapter(), chapter) )
|
|
{
|
|
m_iSelectedChapter = i;
|
|
m_ChapterPanels[m_iSelectedChapter]->SetSelected( true );
|
|
}
|
|
else
|
|
{
|
|
m_ChapterPanels[i]->SetSelected( false );
|
|
}
|
|
}
|
|
|
|
if ( m_pPlayButton )
|
|
{
|
|
m_pPlayButton->SetEnabled( true );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// iUnlockedChapter - the value of sv_unlockedchapters, 1-based. A value of 0
|
|
// is treated as a 1, since at least one chapter must be unlocked.
|
|
//
|
|
// i - the 1-based index of the chapter we're considering.
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::UpdatePanelLockedStatus( int iUnlockedChapter, int i, CGameChapterPanel *pChapterPanel )
|
|
{
|
|
if ( iUnlockedChapter <= 0 )
|
|
{
|
|
iUnlockedChapter = 1;
|
|
}
|
|
|
|
// Commentary mode requires chapters to be finished before they can be chosen
|
|
bool bLocked = false;
|
|
|
|
if ( m_bCommentaryMode )
|
|
{
|
|
bLocked = ( iUnlockedChapter <= i );
|
|
}
|
|
else
|
|
{
|
|
if ( iUnlockedChapter < i )
|
|
{
|
|
// Never lock the first chapter
|
|
bLocked = ( i != 0 );
|
|
}
|
|
}
|
|
|
|
pChapterPanel->SetEnabled( !bLocked );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Called before a panel scroll starts.
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::PreScroll( EScrollDirection dir )
|
|
{
|
|
int hideIdx = INVALID_INDEX;
|
|
if ( dir == SCROLL_LEFT )
|
|
{
|
|
hideIdx = m_PanelIndex[SLOT_LEFT];
|
|
}
|
|
else if ( dir == SCROLL_RIGHT )
|
|
{
|
|
hideIdx = m_PanelIndex[SLOT_RIGHT];
|
|
}
|
|
if ( hideIdx != INVALID_INDEX )
|
|
{
|
|
// Push back the panel that's about to be hidden
|
|
// so the next panel scrolls over the top of it.
|
|
m_ChapterPanels[hideIdx]->SetZPos( 0 );
|
|
}
|
|
|
|
// Flip the active title label prior to the crossfade
|
|
m_ActiveTitleIdx ^= 0x01;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Called after a panel scroll finishes.
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::PostScroll( EScrollDirection dir )
|
|
{
|
|
int index = INVALID_INDEX;
|
|
if ( dir == SCROLL_LEFT )
|
|
{
|
|
index = m_PanelIndex[SLOT_RIGHT];
|
|
}
|
|
else if ( dir == SCROLL_RIGHT )
|
|
{
|
|
index = m_PanelIndex[SLOT_LEFT];
|
|
}
|
|
|
|
// Fade in the revealed panel
|
|
if ( index != INVALID_INDEX )
|
|
{
|
|
CGameChapterPanel *panel = m_ChapterPanels[index];
|
|
panel->SetZPos( 50 );
|
|
GetAnimationController()->RunAnimationCommand( panel, "alpha", 255, 0, m_ScrollSpeed, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
}
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
if ( BonusMapsDatabase()->BonusesUnlocked() && m_bScrollToFirstBonusMap )
|
|
{
|
|
if ( !m_ChapterPanels[ m_PanelIndex[SLOT_CENTER] ]->HasBonus() )
|
|
{
|
|
// Find the first bonus
|
|
ScrollSelectionPanels( SCROLL_LEFT );
|
|
}
|
|
else
|
|
{
|
|
// Found a bonus, stop scrolling
|
|
m_bScrollToFirstBonusMap = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Initiates a panel scroll and starts the animation.
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::ScrollSelectionPanels( EScrollDirection dir )
|
|
{
|
|
// Only initiate a scroll if panels aren't currently scrolling
|
|
if ( !m_bScrolling )
|
|
{
|
|
// Handle any pre-scroll setup
|
|
PreScroll( dir );
|
|
|
|
if ( dir == SCROLL_LEFT)
|
|
{
|
|
m_ScrollCt += SCROLL_LEFT;
|
|
}
|
|
else if ( dir == SCROLL_RIGHT && m_PanelIndex[SLOT_CENTER] != 0 )
|
|
{
|
|
m_ScrollCt += SCROLL_RIGHT;
|
|
}
|
|
|
|
m_bScrolling = true;
|
|
AnimateSelectionPanels();
|
|
|
|
// Update the arrow colors, help text, and buttons. Doing it here looks better than having
|
|
// the components change after the entire scroll animation has finished.
|
|
UpdateMenuComponents( m_ScrollDirection );
|
|
}
|
|
}
|
|
|
|
void CNewGameDialog::ScrollBonusSelection( EScrollDirection dir )
|
|
{
|
|
// Don't scroll if there's no bonuses for this panel
|
|
if ( !m_pBonusMapDescription )
|
|
return;
|
|
|
|
m_iBonusSelection += dir;
|
|
|
|
vgui::surface()->PlaySound( "UI/buttonclick.wav" );
|
|
|
|
UpdateBonusSelection();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Initiates the scripted scroll and fade effects of all five slotted panels
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::AnimateSelectionPanels( void )
|
|
{
|
|
int idxOffset = 0;
|
|
int startIdx = SLOT_LEFT;
|
|
int endIdx = SLOT_RIGHT;
|
|
|
|
// Don't scroll outside the bounds of the panel list
|
|
if ( m_ScrollCt >= SCROLL_LEFT && (m_PanelIndex[SLOT_CENTER] < m_ChapterPanels.Count() - 1 || !GameUI().IsConsoleUI()) )
|
|
{
|
|
idxOffset = -1;
|
|
endIdx = SLOT_OFFRIGHT;
|
|
m_ScrollDirection = SCROLL_LEFT;
|
|
}
|
|
else if ( m_ScrollCt <= SCROLL_RIGHT && (m_PanelIndex[SLOT_CENTER] > 0 || !GameUI().IsConsoleUI()) )
|
|
{
|
|
idxOffset = 1;
|
|
startIdx = SLOT_OFFLEFT;
|
|
m_ScrollDirection = SCROLL_RIGHT;
|
|
}
|
|
|
|
if ( 0 == idxOffset )
|
|
{
|
|
// Kill the scroll, it's outside the bounds
|
|
m_ScrollCt = 0;
|
|
m_bScrolling = false;
|
|
m_ScrollDirection = SCROLL_NONE;
|
|
vgui::surface()->PlaySound( "player/suit_denydevice.wav" );
|
|
return;
|
|
}
|
|
|
|
// Should never happen
|
|
if ( startIdx > endIdx )
|
|
return;
|
|
|
|
for ( int i = startIdx; i <= endIdx; ++i )
|
|
{
|
|
if ( m_PanelIndex[i] != INVALID_INDEX )
|
|
{
|
|
int nextIdx = i + idxOffset;
|
|
CGameChapterPanel *panel = m_ChapterPanels[ m_PanelIndex[i] ];
|
|
GetAnimationController()->RunAnimationCommand( panel, "xpos", m_PanelXPos[nextIdx], 0, m_ScrollSpeed, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
GetAnimationController()->RunAnimationCommand( panel, "ypos", m_PanelYPos[nextIdx], 0, m_ScrollSpeed, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
GetAnimationController()->RunAnimationCommand( panel, "alpha", m_PanelAlpha[nextIdx], 0, m_ScrollSpeed, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
}
|
|
}
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
vgui::surface()->PlaySound( "UI/buttonclick.wav" );
|
|
|
|
// Animate the center background panel
|
|
GetAnimationController()->RunAnimationCommand( m_pCenterBg, "alpha", 0, 0, m_ScrollSpeed * 0.25f, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
|
|
// Crossfade the chapter title labels
|
|
int inactiveTitleIdx = m_ActiveTitleIdx ^ 0x01;
|
|
GetAnimationController()->RunAnimationCommand( m_pChapterTitleLabels[(unsigned)m_ActiveTitleIdx], "alpha", 255, 0, m_ScrollSpeed, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
GetAnimationController()->RunAnimationCommand( m_pChapterTitleLabels[inactiveTitleIdx], "alpha", 0, 0, m_ScrollSpeed, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
|
|
// Scrolling up through chapters, offset is negative
|
|
m_iSelectedChapter -= idxOffset;
|
|
}
|
|
|
|
PostMessage( this, new KeyValues( "FinishScroll" ), m_ScrollSpeed );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: After a scroll, each panel slot holds the index of a panel that has
|
|
// scrolled to an adjacent slot. This function updates each slot so
|
|
// it holds the index of the panel that is actually in that slot's position.
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::ShiftPanelIndices( int offset )
|
|
{
|
|
// Shift all the elements over one slot, then calculate what the last slot's index should be.
|
|
int lastSlot = NUM_SLOTS - 1;
|
|
if ( offset > 0 )
|
|
{
|
|
// Hide the panel that's dropping out of the slots
|
|
if ( IsValidPanel( m_PanelIndex[0] ) )
|
|
{
|
|
m_ChapterPanels[ m_PanelIndex[0] ]->SetVisible( false );
|
|
}
|
|
|
|
// Scrolled panels to the right, so shift the indices one slot to the left
|
|
Q_memmove( &m_PanelIndex[0], &m_PanelIndex[1], lastSlot * sizeof( m_PanelIndex[0] ) );
|
|
if ( m_PanelIndex[lastSlot] != INVALID_INDEX )
|
|
{
|
|
int num = m_PanelIndex[ lastSlot ] + 1;
|
|
if ( IsValidPanel( num ) )
|
|
{
|
|
m_PanelIndex[lastSlot] = num;
|
|
InitPanelIndexForDisplay( lastSlot );
|
|
}
|
|
else
|
|
{
|
|
m_PanelIndex[lastSlot] = INVALID_INDEX;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Hide the panel that's dropping out of the slots
|
|
if ( IsValidPanel( m_PanelIndex[lastSlot] ) )
|
|
{
|
|
m_ChapterPanels[ m_PanelIndex[lastSlot] ]->SetVisible( false );
|
|
}
|
|
|
|
// Scrolled panels to the left, so shift the indices one slot to the right
|
|
Q_memmove( &m_PanelIndex[1], &m_PanelIndex[0], lastSlot * sizeof( m_PanelIndex[0] ) );
|
|
if ( m_PanelIndex[0] != INVALID_INDEX )
|
|
{
|
|
int num = m_PanelIndex[0] - 1;
|
|
if ( IsValidPanel( num ) )
|
|
{
|
|
m_PanelIndex[0] = num;
|
|
InitPanelIndexForDisplay( 0 );
|
|
}
|
|
else
|
|
{
|
|
m_PanelIndex[0] = INVALID_INDEX;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Validates an index into the selection panels vector
|
|
//-----------------------------------------------------------------------------
|
|
bool CNewGameDialog::IsValidPanel( const int idx )
|
|
{
|
|
if ( idx < 0 || idx >= m_ChapterPanels.Count() )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Sets up a panel's properties before it is displayed
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::InitPanelIndexForDisplay( const int idx )
|
|
{
|
|
CGameChapterPanel *panel = m_ChapterPanels[ m_PanelIndex[idx] ];
|
|
if ( panel )
|
|
{
|
|
panel->SetPos( m_PanelXPos[idx], m_PanelYPos[idx] );
|
|
panel->SetAlpha( m_PanelAlpha[idx] );
|
|
panel->SetVisible( true );
|
|
if ( m_PanelAlpha[idx] )
|
|
{
|
|
panel->SetZPos( 50 );
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Sets which scroll speed should be used
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::SetFastScroll( bool fast )
|
|
{
|
|
m_ScrollSpeed = fast ? g_ScrollSpeedFast : g_ScrollSpeedSlow;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Checks if a button is being held down, and speeds up the scroll
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::ContinueScrolling( void )
|
|
{
|
|
if ( !GameUI().IsConsoleUI() )
|
|
{
|
|
if ( m_PanelIndex[SLOT_CENTER-1] % 3 )
|
|
{
|
|
// m_ButtonPressed = m_ScrollDirection;
|
|
ScrollSelectionPanels( m_ScrollDirection );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ( m_ButtonPressed == m_ScrollDirection )
|
|
{
|
|
SetFastScroll( true );
|
|
ScrollSelectionPanels( m_ScrollDirection );
|
|
}
|
|
else if ( m_ButtonPressed != SCROLL_NONE )
|
|
{
|
|
// The other direction has been pressed - start a slow scroll
|
|
SetFastScroll( false );
|
|
ScrollSelectionPanels( (EScrollDirection)m_ButtonPressed );
|
|
}
|
|
else
|
|
{
|
|
SetFastScroll( false );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Called when a scroll distance of one slot has been completed
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::FinishScroll( void )
|
|
{
|
|
// Fade the center bg panel back in
|
|
GetAnimationController()->RunAnimationCommand( m_pCenterBg, "alpha", 255, 0, m_ScrollSpeed * 0.25f, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
|
|
ShiftPanelIndices( m_ScrollDirection );
|
|
m_bScrolling = false;
|
|
m_ScrollCt = 0;
|
|
|
|
// End of scroll step
|
|
PostScroll( m_ScrollDirection );
|
|
|
|
// Continue scrolling if necessary
|
|
ContinueScrolling();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: starts the game at the specified skill level
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::StartGame( void )
|
|
{
|
|
if ( m_ChapterPanels.IsValidIndex( m_iSelectedChapter ) )
|
|
{
|
|
char mapcommand[512];
|
|
mapcommand[0] = 0;
|
|
Q_snprintf( mapcommand, sizeof( mapcommand ), "disconnect\ndeathmatch 0\nprogress_enable\nexec %s\n", m_ChapterPanels[m_iSelectedChapter]->GetConfigFile() );
|
|
|
|
// Set commentary
|
|
ConVarRef commentary( "commentary" );
|
|
commentary.SetValue( m_bCommentaryMode );
|
|
|
|
ConVarRef sv_cheats( "sv_cheats" );
|
|
sv_cheats.SetValue( m_bCommentaryMode );
|
|
|
|
if ( IsPC() )
|
|
{
|
|
// If commentary is on, we go to the explanation dialog (but not for teaser trailers)
|
|
if ( m_bCommentaryMode && !m_ChapterPanels[m_iSelectedChapter]->IsTeaserChapter() )
|
|
{
|
|
// Check our current state and disconnect us from any multiplayer server we're connected to.
|
|
// This fixes an exploit where players would click "start" on the commentary dialog to enable
|
|
// sv_cheats on the client (via the code above) and then hit <esc> to get out of the explanation dialog.
|
|
if ( GameUI().IsInMultiplayer() )
|
|
{
|
|
engine->ExecuteClientCmd( "disconnect" );
|
|
}
|
|
|
|
DHANDLE<CCommentaryExplanationDialog> hCommentaryExplanationDialog;
|
|
if ( !hCommentaryExplanationDialog.Get() )
|
|
{
|
|
hCommentaryExplanationDialog = new CCommentaryExplanationDialog( BasePanel(), mapcommand );
|
|
}
|
|
hCommentaryExplanationDialog->Activate();
|
|
}
|
|
else
|
|
{
|
|
// start map
|
|
BasePanel()->FadeToBlackAndRunEngineCommand( mapcommand );
|
|
}
|
|
}
|
|
else if ( IsX360() )
|
|
{
|
|
if ( m_ChapterPanels[m_iSelectedChapter]->HasBonus() && m_iBonusSelection > 0 )
|
|
{
|
|
if ( m_iBonusSelection == 1 )
|
|
{
|
|
// Run the advanced chamber instead of the config file
|
|
char *pLastSpace = Q_strrchr( mapcommand, '\n' );
|
|
pLastSpace[ 0 ] = '\0';
|
|
pLastSpace = Q_strrchr( mapcommand, '\n' );
|
|
|
|
Q_snprintf( pLastSpace, sizeof( mapcommand ) - Q_strlen( mapcommand ), "\nmap %s_advanced\n", m_pBonusMapDescription->szMapFileName );
|
|
}
|
|
else
|
|
{
|
|
char sz[ 256 ];
|
|
|
|
int iChallenge = m_iBonusSelection - 1;
|
|
|
|
// Set up the challenge mode
|
|
Q_snprintf( sz, sizeof( sz ), "sv_bonus_challenge %i\n", iChallenge );
|
|
engine->ClientCmd_Unrestricted( sz );
|
|
|
|
ChallengeDescription_t *pChallengeDescription = &((*m_pBonusMapDescription->m_pChallenges)[ iChallenge - 1 ]);
|
|
|
|
// Set up medal goals
|
|
BonusMapsDatabase()->SetCurrentChallengeObjectives( pChallengeDescription->iBronze, pChallengeDescription->iSilver, pChallengeDescription->iGold );
|
|
BonusMapsDatabase()->SetCurrentChallengeNames( m_pBonusMapDescription->szFileName, m_pBonusMapDescription->szMapName, pChallengeDescription->szName );
|
|
}
|
|
}
|
|
|
|
m_bMapStarting = true;
|
|
BasePanel()->FadeToBlackAndRunEngineCommand( mapcommand );
|
|
}
|
|
|
|
OnClose();
|
|
}
|
|
}
|
|
|
|
void CNewGameDialog::OnClose( void )
|
|
{
|
|
m_KeyRepeat.Reset();
|
|
|
|
if ( GameUI().IsConsoleUI() && !m_bMapStarting )
|
|
{
|
|
BasePanel()->RunCloseAnimation( "CloseNewGameDialog_OpenMainMenu" );
|
|
BonusMapsDatabase()->WriteSaveData(); // Closing this dialog is a good time to save
|
|
}
|
|
BaseClass::OnClose();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: handles button commands
|
|
//-----------------------------------------------------------------------------
|
|
void CNewGameDialog::OnCommand( const char *command )
|
|
{
|
|
bool bReset = true;
|
|
|
|
if ( !stricmp( command, "Play" ) )
|
|
{
|
|
if ( m_bMapStarting )
|
|
return;
|
|
|
|
if ( GameUI().IsConsoleUI() )
|
|
{
|
|
if ( m_ChapterPanels[m_iSelectedChapter]->IsEnabled() )
|
|
{
|
|
if ( !GameUI().HasSavedThisMenuSession() && GameUI().IsInLevel() && engine->GetMaxClients() == 1 )
|
|
{
|
|
vgui::surface()->PlaySound( "UI/buttonclickrelease.wav" );
|
|
BasePanel()->ShowMessageDialog( MD_SAVE_BEFORE_NEW_GAME, this );
|
|
}
|
|
else
|
|
{
|
|
OnCommand( "StartNewGame" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This chapter isn't unlocked!
|
|
m_bMapStarting = false;
|
|
vgui::surface()->PlaySound( "player/suit_denydevice.wav" );
|
|
|
|
if ( m_bCommentaryMode )
|
|
{
|
|
BasePanel()->ShowMessageDialog( MD_COMMENTARY_CHAPTER_UNLOCK_EXPLANATION, this );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StartGame();
|
|
}
|
|
}
|
|
|
|
#ifdef _X360
|
|
else if ( !stricmp( command, "StartNewGame" ) )
|
|
{
|
|
ConVarRef commentary( "commentary" );
|
|
|
|
if ( m_bCommentaryMode && !commentary.GetBool() )
|
|
{
|
|
// Using the commentary menu, but not already in commentary mode, explain the rules
|
|
PostMessage( (vgui::Panel*)this, new KeyValues( "command", "command", "StartNewGameWithCommentaryExplanation" ), 0.2f );
|
|
}
|
|
else
|
|
{
|
|
if ( XBX_GetStorageDeviceId() == XBX_INVALID_STORAGE_ID || XBX_GetStorageDeviceId() == XBX_STORAGE_DECLINED ||
|
|
!ModInfo().IsSinglePlayerOnly() )
|
|
{
|
|
// Multiplayer or no storage device so don't bore them with autosave details
|
|
m_bMapStarting = true;
|
|
OnCommand( "StartNewGameNoCommentaryExplanation" );
|
|
}
|
|
else
|
|
{
|
|
// Don't allow other inputs
|
|
m_bMapStarting = true;
|
|
|
|
// Remind them how autosaves work
|
|
PostMessage( (vgui::Panel*)this, new KeyValues( "command", "command", "StartNewGameWithAutosaveExplanation" ), 0.2f );
|
|
}
|
|
}
|
|
}
|
|
else if ( !stricmp( command, "StartNewGameWithAutosaveExplanation" ) )
|
|
{
|
|
BasePanel()->ShowMessageDialog( MD_AUTOSAVE_EXPLANATION, this );
|
|
}
|
|
else if ( !stricmp( command, "StartNewGameWithCommentaryExplanation" ) )
|
|
{
|
|
if ( ModInfo().IsSinglePlayerOnly() )
|
|
{
|
|
// Don't allow other inputs
|
|
m_bMapStarting = true;
|
|
BasePanel()->ShowMessageDialog( MD_COMMENTARY_EXPLANATION, this );
|
|
}
|
|
else
|
|
{
|
|
// Don't allow other inputs
|
|
m_bMapStarting = true;
|
|
BasePanel()->ShowMessageDialog( MD_COMMENTARY_EXPLANATION_MULTI, this );
|
|
}
|
|
}
|
|
else if ( !stricmp( command, "StartNewGameNoCommentaryExplanation" ) )
|
|
{
|
|
vgui::surface()->PlaySound( "UI/buttonclickrelease.wav" );
|
|
BasePanel()->RunAnimationWithCallback( this, "CloseNewGameDialog", new KeyValues( "StartGame" ) );
|
|
}
|
|
#endif
|
|
|
|
else if ( !stricmp( command, "Next" ) )
|
|
{
|
|
if ( m_bMapStarting )
|
|
return;
|
|
|
|
ScrollSelectionPanels( SCROLL_LEFT );
|
|
bReset = false;
|
|
}
|
|
else if ( !stricmp( command, "Prev" ) )
|
|
{
|
|
if ( m_bMapStarting )
|
|
return;
|
|
|
|
ScrollSelectionPanels( SCROLL_RIGHT );
|
|
bReset = false;
|
|
}
|
|
else if ( !stricmp( command, "Mode_Next" ) )
|
|
{
|
|
if ( m_bMapStarting )
|
|
return;
|
|
|
|
ScrollBonusSelection( SCROLL_LEFT );
|
|
bReset = false;
|
|
}
|
|
else if ( !stricmp( command, "Mode_Prev" ) )
|
|
{
|
|
if ( m_bMapStarting )
|
|
return;
|
|
|
|
ScrollBonusSelection( SCROLL_RIGHT );
|
|
bReset = false;
|
|
}
|
|
else if ( !Q_stricmp( command, "ReleaseModalWindow" ) )
|
|
{
|
|
vgui::surface()->RestrictPaintToSinglePanel(NULL);
|
|
}
|
|
else
|
|
{
|
|
BaseClass::OnCommand( command );
|
|
}
|
|
|
|
if ( bReset )
|
|
{
|
|
m_KeyRepeat.Reset();
|
|
}
|
|
}
|
|
|
|
void CNewGameDialog::PaintBackground()
|
|
{
|
|
if ( !GameUI().IsConsoleUI() )
|
|
{
|
|
BaseClass::PaintBackground();
|
|
return;
|
|
}
|
|
|
|
int wide, tall;
|
|
GetSize( wide, tall );
|
|
|
|
Color col = GetBgColor();
|
|
DrawBox( 0, 0, wide, tall, col, 1.0f );
|
|
|
|
int y = 0;
|
|
if ( m_pChapterTitleLabels[0] )
|
|
{
|
|
// offset by title
|
|
int titleX, titleY, titleWide, titleTall;
|
|
m_pChapterTitleLabels[0]->GetBounds( titleX, titleY, titleWide, titleTall );
|
|
y += titleY + titleTall;
|
|
}
|
|
else
|
|
{
|
|
y = 8;
|
|
}
|
|
|
|
// draw an inset
|
|
Color darkColor;
|
|
darkColor.SetColor( 0.70f * (float)col.r(), 0.70f * (float)col.g(), 0.70f * (float)col.b(), col.a() );
|
|
vgui::surface()->DrawSetColor( darkColor );
|
|
vgui::surface()->DrawFilledRect( 8, y, wide - 8, tall - 8 );
|
|
}
|
|
|
|
void CNewGameDialog::OnKeyCodePressed( KeyCode code )
|
|
{
|
|
switch ( code )
|
|
{
|
|
case KEY_XBUTTON_LEFT:
|
|
case KEY_XSTICK1_LEFT:
|
|
case KEY_XSTICK2_LEFT:
|
|
case KEY_LEFT:
|
|
case STEAMCONTROLLER_DPAD_LEFT:
|
|
if ( !m_bScrolling )
|
|
{
|
|
for ( int i = 0; i < m_ChapterPanels.Count(); ++i )
|
|
{
|
|
if ( m_ChapterPanels[ i ]->IsSelected() )
|
|
{
|
|
int nNewChapter = i - 1;
|
|
if ( nNewChapter >= 0 )
|
|
{
|
|
if ( nNewChapter < m_PanelIndex[ SLOT_LEFT ] && m_PanelIndex[ SLOT_LEFT ] != -1 )
|
|
{
|
|
ScrollSelectionPanels( SCROLL_RIGHT );
|
|
}
|
|
else if ( m_ChapterPanels[ nNewChapter ]->IsEnabled() )
|
|
{
|
|
SetSelectedChapterIndex( nNewChapter );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
|
|
case KEY_XBUTTON_RIGHT:
|
|
case KEY_XSTICK1_RIGHT:
|
|
case KEY_XSTICK2_RIGHT:
|
|
case KEY_RIGHT:
|
|
case STEAMCONTROLLER_DPAD_RIGHT:
|
|
if ( !m_bScrolling )
|
|
{
|
|
for ( int i = 0; i < m_ChapterPanels.Count(); ++i )
|
|
{
|
|
if ( m_ChapterPanels[ i ]->IsSelected() )
|
|
{
|
|
int nNewChapter = i + 1;
|
|
if ( nNewChapter < m_ChapterPanels.Count() )
|
|
{
|
|
if ( nNewChapter > m_PanelIndex[ SLOT_RIGHT ] && m_PanelIndex[ SLOT_RIGHT ] != -1 )
|
|
{
|
|
ScrollSelectionPanels( SCROLL_LEFT );
|
|
}
|
|
else if ( m_ChapterPanels[ nNewChapter ]->IsEnabled() )
|
|
{
|
|
SetSelectedChapterIndex( nNewChapter );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
|
|
case KEY_XBUTTON_B:
|
|
case STEAMCONTROLLER_B:
|
|
OnCommand( "Close" );
|
|
return;
|
|
|
|
case KEY_XBUTTON_A:
|
|
case STEAMCONTROLLER_A:
|
|
OnCommand( "Play" );
|
|
return;
|
|
}
|
|
|
|
m_KeyRepeat.KeyDown( code );
|
|
|
|
BaseClass::OnKeyCodePressed( code );
|
|
}
|
|
|
|
void CNewGameDialog::OnKeyCodeReleased( vgui::KeyCode code )
|
|
{
|
|
m_KeyRepeat.KeyUp( code );
|
|
|
|
BaseClass::OnKeyCodeReleased( code );
|
|
}
|
|
|
|
void CNewGameDialog::OnThink()
|
|
{
|
|
vgui::KeyCode code = m_KeyRepeat.KeyRepeated();
|
|
if ( code )
|
|
{
|
|
OnKeyCodeTyped( code );
|
|
}
|
|
|
|
BaseClass::OnThink();
|
|
}
|