summaryrefslogtreecommitdiff
path: root/gameui/BonusMapsDialog.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /gameui/BonusMapsDialog.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'gameui/BonusMapsDialog.cpp')
-rw-r--r--gameui/BonusMapsDialog.cpp1006
1 files changed, 1006 insertions, 0 deletions
diff --git a/gameui/BonusMapsDialog.cpp b/gameui/BonusMapsDialog.cpp
new file mode 100644
index 0000000..f5243a7
--- /dev/null
+++ b/gameui/BonusMapsDialog.cpp
@@ -0,0 +1,1006 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "BonusMapsDialog.h"
+#include "EngineInterface.h"
+
+#include "vgui/ISystem.h"
+#include "vgui/ISurface.h"
+#include "vgui/IVGui.h"
+#include <vgui/ILocalize.h>
+#include "filesystem.h"
+
+#include "vgui_controls/Button.h"
+#include "vgui_controls/ComboBox.h"
+#include "vgui_controls/PanelListPanel.h"
+#include "vgui_controls/QueryBox.h"
+#include "vgui_controls/ImagePanel.h"
+#include "vgui_controls/BitmapImagePanel.h"
+#include "vgui_controls/FileOpenDialog.h"
+
+#include "TGAImagePanel.h"
+#include "MouseMessageForwardingPanel.h"
+
+#include "BasePanel.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+using namespace vgui;
+
+
+#define MAX_LISTED_BONUS_MAPS 128
+
+
+extern const char *COM_GetModDirectory( void );
+
+
+bool ConstructFullImagePath( const char *pCurrentPath, const char *pchImageName, char *pchImageFileName )
+{
+ char *ext = Q_strstr( pchImageName , ".tga" );
+ if ( ext )
+ {
+ // Use the specified image
+ if ( pchImageName[ 0 ] != '.' )
+ Q_snprintf( pchImageFileName, _MAX_PATH, "%s", pchImageName );
+ else
+ Q_snprintf( pchImageFileName, _MAX_PATH, "%s/%s", pCurrentPath, pchImageName );
+
+ return true;
+ }
+
+ Q_strcpy( pchImageFileName, pchImageName );
+
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Describes the layout of a same game pic
+//-----------------------------------------------------------------------------
+class CBonusMapPanel : public vgui::EditablePanel
+{
+ DECLARE_CLASS_SIMPLE( CBonusMapPanel, vgui::EditablePanel );
+public:
+ CBonusMapPanel( PanelListPanel *parent, const char *name, int bonusMapListItemID ) : BaseClass( parent, name )
+ {
+ m_iBonusMapListItemID = bonusMapListItemID;
+ m_pParent = parent;
+ m_pBonusMapTGAImage = new CTGAImagePanel( this, "BonusMapTGAImage" );
+ m_pBonusMapImage = SETUP_PANEL( new ImagePanel( this, "BonusMapImage" ) );
+ m_pBonusMapScreenshotBackground = SETUP_PANEL( new ImagePanel( this, "BonusMapScreenshotBackground" ) );
+ m_pMapNameLabel = new Label( this, "MapNameLabel", "" );
+ m_pLockIcon = new ImagePanel( this, "LockIcon" );
+ m_pCompleteIcon = new ImagePanel( this, "CompleteIcon" );
+
+ CMouseMessageForwardingPanel *panel = new CMouseMessageForwardingPanel(this, NULL);
+ panel->SetZPos(2);
+
+ SetSize( 200, 140 );
+
+ LoadControlSettings( "resource/BonusMapPanel.res" );
+
+ m_FillColor = m_pBonusMapScreenshotBackground->GetFillColor();
+ }
+
+ void SetBonusMapInfo( const char *pCurrentPath, BonusMapDescription_t &map )
+ {
+ // set the image to display
+ char szImageFileName[_MAX_PATH];
+
+ bool bIsTGA = false;
+
+ if ( map.bIsFolder )
+ {
+ if ( map.szImageName[ 0 ] == '\0' )
+ {
+ // use associate bonus folder icon
+ Q_snprintf( szImageFileName, sizeof(szImageFileName), "%s/foldericon.tga", map.szFileName );
+ bIsTGA = true;
+
+ // use default folder icon
+ if( !g_pFullFileSystem->FileExists( szImageFileName, "MOD" ) )
+ {
+ V_strcpy_safe( szImageFileName, "bonusmaps/icon_bonus_map_folder" );
+ bIsTGA = false;
+ }
+ }
+ else
+ {
+ // Use the specified image
+ bIsTGA = ConstructFullImagePath( pCurrentPath, map.szImageName, szImageFileName );
+ }
+ }
+ else
+ {
+ if ( map.szImageName[ 0 ] == '\0' )
+ {
+ // Didn't specify an image name, so pair it with the name of this file
+ char szImpliedTgaName[_MAX_PATH];
+ Q_snprintf( szImpliedTgaName, sizeof( szImpliedTgaName ), "%s.tga", map.szMapFileName );
+ bIsTGA = ConstructFullImagePath( pCurrentPath, szImpliedTgaName, szImageFileName );
+
+ // if it doesn't exist use default bonus map icon
+ if( !g_pFullFileSystem->FileExists( szImageFileName, "MOD" ) )
+ {
+ V_strcpy_safe( szImageFileName, "bonusmaps/icon_bonus_map_default" );
+ bIsTGA = false;
+ }
+ }
+ else
+ {
+ // Use the specified image
+ bIsTGA = ConstructFullImagePath( pCurrentPath, map.szImageName, szImageFileName );
+ }
+ }
+
+ if ( bIsTGA )
+ {
+ m_pBonusMapTGAImage->SetTGANonMod( szImageFileName );
+ m_pBonusMapTGAImage->SetSize( 180, 100 );
+ m_pBonusMapTGAImage->SetVisible( true );
+ m_pBonusMapImage->SetVisible( false );
+ }
+ else
+ {
+ m_pBonusMapImage->SetImage( szImageFileName );
+ m_pBonusMapImage->SetSize( 180, 100 );
+ m_pBonusMapImage->SetVisible( true );
+ m_pBonusMapTGAImage->SetVisible( false );
+ }
+
+ m_pLockIcon->SetVisible( map.bLocked );
+ m_pCompleteIcon->SetVisible( map.bComplete );
+
+ // set the title text
+ m_pMapNameLabel->SetText( map.szMapName );
+ }
+
+ MESSAGE_FUNC_INT( OnPanelSelected, "PanelSelected", state )
+ {
+ if ( state )
+ {
+ // set the text color to be orange, and the pic border to be orange
+ m_pBonusMapScreenshotBackground->SetFillColor( m_SelectedColor );
+ m_pMapNameLabel->SetFgColor( Color( 0, 0, 0, 255 ) );
+ }
+ else
+ {
+ m_pBonusMapScreenshotBackground->SetFillColor( m_FillColor );
+ m_pMapNameLabel->SetFgColor( m_TextColor );
+ }
+
+ PostMessage( m_pParent->GetVParent(), new KeyValues("PanelSelected") );
+ }
+
+ virtual void OnMousePressed( vgui::MouseCode code )
+ {
+ m_pParent->SetSelectedPanel( this );
+ }
+
+ virtual void ApplySchemeSettings( IScheme *pScheme )
+ {
+ m_TextColor = pScheme->GetColor( "NewGame.TextColor", Color(255, 255, 255, 255) );
+ m_SelectedColor = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) );
+
+ BaseClass::ApplySchemeSettings( pScheme );
+ }
+
+ virtual void OnMouseDoublePressed( vgui::MouseCode code )
+ {
+ // call the panel
+ OnMousePressed( code );
+ PostMessage( m_pParent->GetParent(), new KeyValues("Command", "command", "loadbonusmap") );
+ }
+
+ int GetBonusMapListItemID()
+ {
+ return m_iBonusMapListItemID;
+ }
+
+private:
+ vgui::PanelListPanel *m_pParent;
+ vgui::Label *m_pMapNameLabel;
+ ImagePanel *m_pBonusMapImage;
+ CTGAImagePanel *m_pBonusMapTGAImage;
+
+ ImagePanel *m_pLockIcon;
+ ImagePanel *m_pCompleteIcon;
+
+ // things to change color when the selection changes
+ ImagePanel *m_pBonusMapScreenshotBackground;
+ Color m_TextColor, m_FillColor, m_SelectedColor;
+
+ int m_iBonusMapListItemID;
+};
+
+CBonusMapsDialog *g_pBonusMapsDialog = NULL;
+
+
+//-----------------------------------------------------------------------------
+// Purpose:Constructor
+//-----------------------------------------------------------------------------
+CBonusMapsDialog::CBonusMapsDialog(vgui::Panel *parent) : BaseClass(parent, "BonusMapsDialog")
+{
+ g_pBonusMapsDialog = this;
+ m_hImportBonusMapsDialog = NULL;
+
+ BonusMapsDatabase()->RootPath();
+
+ CreateBonusMapsList();
+
+ BuildMapsList();
+
+ new vgui::Button( this, "loadbonusmap", "" );
+ SetControlEnabled( "loadbonusmap", false );
+
+ SetDeleteSelfOnClose(true);
+ //SetBounds(0, 0, 512, 384);
+ //SetMinimumSize( 256, 300 );
+ SetSizeable( false );
+
+ SetTitle("#GameUI_BonusMaps", true);
+
+ vgui::Button *cancel = new vgui::Button( this, "Cancel", "#GameUI_Cancel" );
+ cancel->SetCommand( "Close" );
+
+ m_pPercentageBarBackground = SETUP_PANEL( new ImagePanel( this, "PercentageBarBackground" ) );
+ m_pPercentageBar = SETUP_PANEL( new ImagePanel( this, "PercentageBar" ) );
+
+ LoadControlSettings("resource/BonusMapsDialog.res");
+
+ // Stop blinking the bonus maps menu item
+ CBasePanel *pBasePanel = BasePanel();
+ if ( pBasePanel )
+ pBasePanel->SetMenuItemBlinkingState( "OpenBonusMapsDialog", false );
+
+ BonusMapsDatabase()->SetBlink( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CBonusMapsDialog::~CBonusMapsDialog()
+{
+ BonusMapsDatabase()->WriteSaveData(); // Closing this dialog is a good time to save
+ g_pBonusMapsDialog = NULL;
+}
+
+
+bool CBonusMapsDialog::ImportZippedBonusMaps( const char *pchZippedFileName )
+{
+ // Get the zip file's name with dir info
+ char *pchShortFileName = Q_strrchr( pchZippedFileName, CORRECT_PATH_SEPARATOR );
+
+ if ( !pchShortFileName )
+ return false;
+
+ // It's going to go in the maps folder
+ char szOutFilename[ 512 ];
+
+ Q_snprintf( szOutFilename, sizeof( szOutFilename ), "maps%s", pchShortFileName );
+ Q_StripExtension( szOutFilename, szOutFilename, sizeof( szOutFilename ) );
+
+ // If there's already a folder by the same name we're going to tack a number onto the end
+ int iOutFilenameLength = Q_strlen( szOutFilename );
+ int iSameFolderCount = 1;
+
+ while ( g_pFullFileSystem->FileExists( szOutFilename, "MOD" ) )
+ {
+ ++iSameFolderCount;
+
+ if ( iSameFolderCount > 99 )
+ {
+ return false;
+ }
+
+ szOutFilename[ iOutFilenameLength ] = '\0';
+ Q_snprintf( szOutFilename, sizeof( szOutFilename ), "%s%02i", szOutFilename, iSameFolderCount );
+ }
+
+ // Pull the files out of the zip
+ if ( g_pFullFileSystem->UnzipFile( pchZippedFileName, "MOD", szOutFilename ) )
+ {
+ // New maps have been imported, so refresh the list
+ BuildMapsList();
+ }
+
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: builds bonus map list from directory
+//-----------------------------------------------------------------------------
+void CBonusMapsDialog::BuildMapsList( void )
+{
+ // clear the current list
+ m_pGameList->DeleteAllItems();
+
+ BonusMapsDatabase()->ClearBonusMapsList();
+ BonusMapsDatabase()->ScanBonusMaps();
+
+ // Enable back button if we're in a sub folder
+ bool bIsRoot = ( Q_strcmp( BonusMapsDatabase()->GetPath(), "." ) == 0 );
+ SetControlEnabled( "Back", !bIsRoot );
+ SetControlVisible( "Back", !bIsRoot );
+ SetControlEnabled( "ImportBonusMaps", bIsRoot );
+ SetControlVisible( "ImportBonusMaps", bIsRoot );
+
+ char szDisplayPath[_MAX_PATH];
+ Q_snprintf( szDisplayPath, _MAX_PATH, "%s/", BonusMapsDatabase()->GetPath() );
+
+ SetControlString( "FileName", szDisplayPath );
+ SetControlString( "CommentLabel", "" );
+
+ int iMapCount = BonusMapsDatabase()->BonusCount();
+
+ // add to the list
+ for ( int iMapIndex = 0; iMapIndex < iMapCount && iMapIndex < MAX_LISTED_BONUS_MAPS; ++iMapIndex )
+ {
+ CBonusMapPanel *bonusMapPanel = new CBonusMapPanel( m_pGameList, "BonusMapPanel", iMapIndex );
+ bonusMapPanel->SetBonusMapInfo( BonusMapsDatabase()->GetPath(), *(BonusMapsDatabase()->GetBonusData( iMapIndex )) );
+ m_pGameList->AddItem( NULL, bonusMapPanel );
+ }
+
+ // display a message if there are no save games
+ if ( iMapCount <= 0 )
+ {
+ vgui::Label *pNoSavesLabel = SETUP_PANEL(new Label(m_pGameList, "NoBonusMapsLabel", "#GameUI_NoBonusMapsToDisplay"));
+ pNoSavesLabel->SetTextColorState(vgui::Label::CS_DULL);
+ m_pGameList->AddItem( NULL, pNoSavesLabel );
+ m_pGameList->SetNumColumns( 1 );
+ }
+ else
+ {
+ m_pGameList->SetNumColumns( 3 );
+ }
+
+ RefreshCompletionPercentage();
+
+ // Disable load button
+ SetControlEnabled( "loadbonusmap", false );
+
+ // Make challenge selection invisible
+ m_pChallengeSelection->SetEnabled( false );
+ m_pChallengeSelection->SetVisible( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Creates the load game display list
+//-----------------------------------------------------------------------------
+void CBonusMapsDialog::CreateBonusMapsList()
+{
+ m_pGameList = new vgui::PanelListPanel( this, "listpanel_bonusmaps" );
+ m_pGameList->SetFirstColumnWidth( 0 );
+
+ new Label( this, "FileName", "./" );
+ new Label( this, "CommentLabel", "" );
+
+ m_pChallengeSelection = new vgui::ComboBox( this, "ChallengeSelection", 0, false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the save file name of the selected item
+//-----------------------------------------------------------------------------
+int CBonusMapsDialog::GetSelectedItemBonusMapIndex()
+{
+ CBonusMapPanel *panel = dynamic_cast<CBonusMapPanel *>(m_pGameList->GetSelectedPanel());
+ if ( panel && panel->GetBonusMapListItemID() < BonusMapsDatabase()->BonusCount() )
+ return panel->GetBonusMapListItemID();
+
+ return BonusMapsDatabase()->InvalidIndex();
+}
+
+void CBonusMapsDialog::SetSelectedBooleanStatus( const char *pchName, bool bValue )
+{
+ CBonusMapPanel *pSelectedBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetSelectedPanel();
+ if ( !pSelectedBonusMapPanel )
+ return;
+
+ BonusMapsDatabase()->SetBooleanStatus( pchName, pSelectedBonusMapPanel->GetBonusMapListItemID(), bValue );
+
+ // Change the status in the dialog
+ BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( pSelectedBonusMapPanel->GetBonusMapListItemID() );
+ pSelectedBonusMapPanel->SetBonusMapInfo( BonusMapsDatabase()->GetPath(), *pMap );
+
+ RefreshCompletionPercentage();
+ RefreshDialog( pMap );
+}
+
+void CBonusMapsDialog::RefreshData( void )
+{
+ for ( int iMap = 0; iMap < m_pGameList->GetItemCount(); ++iMap )
+ {
+ CBonusMapPanel *pBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetItemPanel( iMap );
+
+ if ( pBonusMapPanel )
+ pBonusMapPanel->SetBonusMapInfo( BonusMapsDatabase()->GetPath(), *(BonusMapsDatabase()->GetBonusData( pBonusMapPanel->GetBonusMapListItemID() ) ) );
+ }
+
+ CBonusMapPanel *pSelectedBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetSelectedPanel();
+ if ( !pSelectedBonusMapPanel )
+ return;
+
+ BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( pSelectedBonusMapPanel->GetBonusMapListItemID() );
+
+ RefreshCompletionPercentage();
+ RefreshDialog( pMap );
+}
+
+int CBonusMapsDialog::GetSelectedChallenge( void )
+{
+ if ( !m_pChallengeSelection->IsEnabled() )
+ return -1;
+
+ KeyValues *pUserDataKey = m_pChallengeSelection->GetActiveItemUserData();
+ return pUserDataKey->GetInt( "challenge" );
+}
+
+void CBonusMapsDialog::RefreshDialog( BonusMapDescription_t *pMap )
+{
+ if ( !pMap || pMap->bLocked || ( m_pChallengeSelection->IsEnabled() && GetSelectedChallenge() == -1 ) )
+ {
+ // It's locked or no challenge is selected, so disable the load button
+ SetControlEnabled( "loadbonusmap", false );
+ }
+ else
+ {
+ // Enable the load button
+ SetControlEnabled( "loadbonusmap", true );
+ }
+
+ RefreshMedalDisplay( pMap );
+
+ if ( pMap )
+ SetControlString( "CommentLabel", pMap->szComment );
+ else
+ SetControlString( "CommentLabel", "" );
+}
+
+void CBonusMapsDialog::RefreshMedalDisplay( BonusMapDescription_t *pMap )
+{
+ {
+ int iFirstChildIndex = FindChildIndexByName( "ChallengeMedalOverview00" );
+ for ( int iMedal = 0; iMedal < 5; ++iMedal )
+ {
+ Panel *pMedalImage = GetChild( iFirstChildIndex + iMedal );
+ pMedalImage->SetVisible( false );
+ }
+ }
+ if ( !pMap || !pMap->m_pChallenges )
+ {
+ SetControlVisible( "ChallengeCommentLabel", false );
+ SetControlVisible( "ChallengeEarnedMedal", false );
+ SetControlVisible( "ChallengeBestLabel", false );
+ SetControlVisible( "ChallengeNextMedal", false );
+ SetControlVisible( "ChallengeNextLabel", false );
+
+ return;
+ }
+
+ char szBuff[ 512 ];
+
+ int iChallenge = GetSelectedChallenge();
+
+ if ( iChallenge < 0 )
+ {
+ SetControlVisible( "ChallengeCommentLabel", false );
+ SetControlVisible( "ChallengeEarnedMedal", false );
+ SetControlVisible( "ChallengeBestLabel", false );
+ SetControlVisible( "ChallengeNextMedal", false );
+ SetControlVisible( "ChallengeNextLabel", false );
+
+ int iFirstChildIndex = FindChildIndexByName( "ChallengeMedalOverview00" );
+ for ( int iChallengeIndex = 0; iChallengeIndex < m_pChallengeSelection->GetItemCount(); ++iChallengeIndex )
+ {
+ KeyValues *pUserDataKey = m_pChallengeSelection->GetItemUserData( iChallengeIndex );
+ int iChallengeNum = pUserDataKey->GetInt( "challenge" );
+
+ if ( iChallengeNum >= 0 )
+ {
+ ChallengeDescription_t *pChallengeDescription = NULL;
+
+ for ( int i = 0 ; i < pMap->m_pChallenges->Count(); ++i )
+ {
+ int iType = ((*pMap->m_pChallenges)[ i ]).iType;
+
+ if ( iType == -1 )
+ {
+ iType = i;
+ }
+
+ if ( iType == iChallengeNum )
+ pChallengeDescription = &((*pMap->m_pChallenges)[ i ]);
+ }
+
+ if ( pChallengeDescription )
+ {
+ int iBest, iEarnedMedal, iNext, iNextMedal;
+ GetChallengeMedals( pChallengeDescription, iBest, iEarnedMedal, iNext, iNextMedal );
+
+ if ( iChallengeNum < 10 )
+ Q_snprintf( szBuff, 256, "medals/medal_0%i_%s", iChallengeNum, g_pszMedalNames[ iEarnedMedal ] );
+ else
+ Q_snprintf( szBuff, 256, "medals/medal_%i_%s", iChallengeNum, g_pszMedalNames[ iEarnedMedal ] );
+ }
+
+ CBitmapImagePanel *pBitmap = dynamic_cast<CBitmapImagePanel*>( GetChild( iFirstChildIndex + iChallengeNum ) );
+ pBitmap->SetVisible( true );
+ pBitmap->setTexture( szBuff );
+ }
+ }
+
+ return;
+ }
+
+ ChallengeDescription_t *pChallengeDescription = NULL;
+
+ for ( int i = 0 ; i < pMap->m_pChallenges->Count(); ++i )
+ {
+ int iType = ((*pMap->m_pChallenges)[ i ]).iType;
+
+ if ( iType == -1 )
+ {
+ iType = i;
+ }
+
+ if ( iType == iChallenge )
+ pChallengeDescription = &((*pMap->m_pChallenges)[ i ]);
+ }
+
+ if ( !pChallengeDescription )
+ return;
+
+ const char *pchChallengeComment = pChallengeDescription->szComment;
+
+ int iBest, iEarnedMedal, iNext, iNextMedal;
+ GetChallengeMedals( pChallengeDescription, iBest, iEarnedMedal, iNext, iNextMedal );
+
+ // Set comment label
+ SetControlString( "ChallengeCommentLabel", pchChallengeComment );
+ SetControlVisible( "ChallengeCommentLabel", true );
+
+ // Set earned medal
+ if ( iEarnedMedal > -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 );
+ }
+
+ // 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 );
+}
+
+void CBonusMapsDialog::RefreshCompletionPercentage( void )
+{
+ float fPercentage = BonusMapsDatabase()->GetCompletionPercentage();
+ if ( fPercentage > 0.0f )
+ {
+ char szBuff[ 256 ];
+ if ( fPercentage * 100.0f < 1.0f )
+ Q_snprintf( szBuff, 256, "%.2f%%", fPercentage * 100.0f ); // Show decimal places if less than 1%
+ else
+ Q_snprintf( szBuff, 256, "%.0f%%", fPercentage * 100.0f );
+
+ SetControlString( "PercentageText", szBuff );
+ SetControlVisible( "PercentageText", true );
+ SetControlVisible( "CompletionText", true );
+
+ // Blend the color from backround color 0% to selected color 100%
+ Color cProgressBar = Color( static_cast<float>( m_PercentageBarBackgroundColor.r() ) * ( 1.0f - fPercentage ) + static_cast<float>( m_PercentageBarColor.r() ) * fPercentage,
+ static_cast<float>( m_PercentageBarBackgroundColor.g() ) * ( 1.0f - fPercentage ) + static_cast<float>( m_PercentageBarColor.g() ) * fPercentage,
+ static_cast<float>( m_PercentageBarBackgroundColor.b() ) * ( 1.0f - fPercentage ) + static_cast<float>( m_PercentageBarColor.b() ) * fPercentage,
+ static_cast<float>( m_PercentageBarBackgroundColor.a() ) * ( 1.0f - fPercentage ) + static_cast<float>( m_PercentageBarColor.a() ) * fPercentage );
+
+ m_pPercentageBar->SetFillColor( cProgressBar );
+ m_pPercentageBar->SetWide( m_pPercentageBarBackground->GetWide() * fPercentage );
+
+ SetControlVisible( "PercentageBarBackground", true );
+ SetControlVisible( "PercentageBar", true );
+ }
+ else
+ {
+ // 0% complete so don't display
+ SetControlVisible( "PercentageText", false );
+ SetControlVisible( "CompletionText", false );
+ SetControlVisible( "PercentageBarBackground", false );
+ SetControlVisible( "PercentageBar", false );
+ }
+}
+
+
+void CBonusMapsDialog::ApplySchemeSettings( IScheme *pScheme )
+{
+ m_PercentageBarBackgroundColor = Color( 0, 0, 0, 64 );
+ m_PercentageBarColor = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) );
+
+ BaseClass::ApplySchemeSettings( pScheme );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBonusMapsDialog::OnCommand( const char *command )
+{
+ if ( !stricmp( command, "loadbonusmap" ) )
+ {
+ int mapIndex = GetSelectedItemBonusMapIndex();
+ if ( BonusMapsDatabase()->IsValidIndex( mapIndex ) )
+ {
+ BonusMapDescription_t *pBonusMap = BonusMapsDatabase()->GetBonusData( mapIndex );
+
+ // Don't do anything with locked items
+ if ( pBonusMap->bLocked || ( m_pChallengeSelection->IsEnabled() && GetSelectedChallenge() == -1 ) )
+ return;
+
+ const char *shortName = pBonusMap->szShortName;
+ if ( shortName && shortName[ 0 ] )
+ {
+ if ( pBonusMap->bIsFolder )
+ {
+ BonusMapsDatabase()->AppendPath( shortName );
+
+ // repopulate list with current directory
+ BuildMapsList();
+
+ m_pGameList->MoveScrollBarToTop();
+ }
+ else
+ {
+ // Load the game, return to top and switch to engine
+ char sz[ 256 ];
+
+ // Set the challenge mode if one is selected
+ int iChallenge = GetSelectedChallenge() + 1;
+
+ if ( iChallenge > 0 )
+ {
+ Q_snprintf( sz, sizeof( sz ), "sv_bonus_challenge %i\n", iChallenge );
+ engine->ClientCmd_Unrestricted( sz );
+
+ ChallengeDescription_t *pChallengeDescription = &((*pBonusMap->m_pChallenges)[ iChallenge - 1 ]);
+
+ // Set up medal goals
+ BonusMapsDatabase()->SetCurrentChallengeObjectives( pChallengeDescription->iBronze, pChallengeDescription->iSilver, pChallengeDescription->iGold );
+ BonusMapsDatabase()->SetCurrentChallengeNames( pBonusMap->szFileName, pBonusMap->szMapName, pChallengeDescription->szName );
+ }
+
+ if ( pBonusMap->szMapFileName[ 0 ] != '.' )
+ {
+ Q_snprintf( sz, sizeof( sz ), "map %s\n", pBonusMap->szMapFileName );
+ }
+ else
+ {
+ const char *pchSubDir = Q_strnchr( BonusMapsDatabase()->GetPath(), '/', Q_strlen( BonusMapsDatabase()->GetPath() ) );
+
+ if ( pchSubDir )
+ {
+ pchSubDir = Q_strnchr( pchSubDir + 1, '/', Q_strlen( pchSubDir ) );
+
+ if ( pchSubDir )
+ {
+ ++pchSubDir;
+ const char *pchMapFileName = pBonusMap->szMapFileName + 2;
+ Q_snprintf( sz, sizeof( sz ), "map %s/%s\n", pchSubDir, pchMapFileName );
+ }
+ }
+ }
+
+ engine->ClientCmd_Unrestricted( sz );
+
+ // Close this dialog
+ //OnClose();
+ }
+ }
+ }
+ }
+ else if ( !stricmp( command, "back" ) )
+ {
+ BonusMapsDatabase()->BackPath();
+
+ // repopulate list with current directory
+ BuildMapsList();
+
+ m_pChallengeSelection->RemoveAll();
+ m_pChallengeSelection->AddItem( "<Select A Challenge>", new KeyValues( "ChallengeSelection", "challenge", -1 ) );
+
+ RefreshDialog( NULL );
+
+ m_pGameList->MoveScrollBarToTop();
+ }
+ else if ( !stricmp( command, "ImportBonusMaps" ) )
+ {
+ if ( m_hImportBonusMapsDialog == NULL )
+ {
+ m_hImportBonusMapsDialog = new FileOpenDialog( NULL, "#GameUI_ImportBonusMaps", true );
+ m_hImportBonusMapsDialog->AddFilter( "*.bmz", "#GameUI_BMZ_Files", true );
+ m_hImportBonusMapsDialog->AddActionSignalTarget( this );
+ }
+ m_hImportBonusMapsDialog->DoModal(false);
+ m_hImportBonusMapsDialog->Activate();
+ }
+ else
+ {
+ BaseClass::OnCommand( command );
+ }
+}
+
+void CBonusMapsDialog::OnKeyCodeTyped( vgui::KeyCode code )
+{
+ if ( code == KEY_ESCAPE )
+ {
+ OnCommand( "Close" );
+ return;
+ }
+
+ BaseClass::OnKeyCodeTyped( code );
+}
+
+void CBonusMapsDialog::OnKeyCodePressed( vgui::KeyCode code )
+{
+ if ( code == KEY_XBUTTON_B )
+ {
+ OnCommand( "Close" );
+ return;
+ }
+ else if ( code == KEY_XSTICK1_RIGHT ||
+ code == KEY_XSTICK2_RIGHT ||
+ code == KEY_XBUTTON_RIGHT ||
+ code == KEY_RIGHT )
+ {
+ if ( m_pGameList->GetItemCount() )
+ {
+ Panel *pSelectedPanel = m_pGameList->GetSelectedPanel();
+ if ( !pSelectedPanel )
+ {
+ m_pGameList->SetSelectedPanel( m_pGameList->GetItemPanel( m_pGameList->FirstItem() ) );
+ m_pGameList->ScrollToItem( m_pGameList->FirstItem() );
+ return;
+ }
+ else
+ {
+ int nNextPanelID = m_pGameList->FirstItem();
+ while ( nNextPanelID != m_pGameList->InvalidItemID() )
+ {
+ if ( m_pGameList->GetItemPanel( nNextPanelID ) == pSelectedPanel )
+ {
+ nNextPanelID = m_pGameList->NextItem( nNextPanelID );
+ if ( nNextPanelID != m_pGameList->InvalidItemID() )
+ {
+ m_pGameList->SetSelectedPanel( m_pGameList->GetItemPanel( nNextPanelID ) );
+ m_pGameList->ScrollToItem( nNextPanelID );
+ return;
+ }
+
+ break;
+ }
+
+ nNextPanelID = m_pGameList->NextItem( nNextPanelID );
+ }
+ }
+ }
+ }
+ else if ( code == KEY_XSTICK1_LEFT ||
+ code == KEY_XSTICK2_LEFT ||
+ code == KEY_XBUTTON_LEFT ||
+ code == KEY_LEFT )
+ {
+ if ( m_pGameList->GetItemCount() )
+ {
+ Panel *pSelectedPanel = m_pGameList->GetSelectedPanel();
+ if ( !pSelectedPanel )
+ {
+ m_pGameList->SetSelectedPanel( m_pGameList->GetItemPanel( m_pGameList->FirstItem() ) );
+ m_pGameList->ScrollToItem( m_pGameList->FirstItem() );
+ return;
+ }
+ else
+ {
+ int nNextPanelID = m_pGameList->FirstItem();
+ if ( m_pGameList->GetItemPanel( nNextPanelID ) != pSelectedPanel )
+ {
+ while ( nNextPanelID != m_pGameList->InvalidItemID() )
+ {
+ int nOldPanelID = nNextPanelID;
+ nNextPanelID = m_pGameList->NextItem( nNextPanelID );
+
+ if ( nNextPanelID != m_pGameList->InvalidItemID() )
+ {
+ if ( m_pGameList->GetItemPanel( nNextPanelID ) == pSelectedPanel )
+ {
+ m_pGameList->SetSelectedPanel( m_pGameList->GetItemPanel( nOldPanelID ) );
+ m_pGameList->ScrollToItem( nOldPanelID );
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if ( code == KEY_XSTICK1_DOWN ||
+ code == KEY_XSTICK2_DOWN ||
+ code == KEY_XBUTTON_DOWN ||
+ code == KEY_DOWN )
+ {
+ int nOldActiveItem = m_pChallengeSelection->GetActiveItem();
+ int nActiveItem = min( nOldActiveItem + 1, m_pChallengeSelection->GetItemCount() - 1 );
+
+ if ( nOldActiveItem != nActiveItem )
+ {
+ m_pChallengeSelection->ActivateItem( nActiveItem );
+ return;
+ }
+ }
+ else if ( code == KEY_XSTICK1_UP ||
+ code == KEY_XSTICK2_UP ||
+ code == KEY_XBUTTON_UP ||
+ code == KEY_UP )
+ {
+ int nOldActiveItem = m_pChallengeSelection->GetActiveItem();
+ int nActiveItem = max( nOldActiveItem - 1, 0 );
+
+ if ( nOldActiveItem != nActiveItem )
+ {
+ m_pChallengeSelection->ActivateItem( nActiveItem );
+ return;
+ }
+ }
+ else if ( code == KEY_ENTER || code == KEY_XBUTTON_A || code == STEAMCONTROLLER_A )
+ {
+ Panel *pSelectedPanel = m_pGameList->GetSelectedPanel();
+ if ( pSelectedPanel )
+ {
+ OnCommand( "loadbonusmap" );
+ return;
+ }
+ }
+
+ BaseClass::OnKeyCodePressed( code );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: One item has been selected
+//-----------------------------------------------------------------------------
+void CBonusMapsDialog::OnPanelSelected()
+{
+ CBonusMapPanel *pSelectedBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetSelectedPanel();
+ if ( !pSelectedBonusMapPanel )
+ return;
+
+ BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( pSelectedBonusMapPanel->GetBonusMapListItemID() );
+ if ( !pMap )
+ return;
+
+ SetControlString( "CommentLabel", pMap->szComment );
+
+ // Handle challenge selection box
+ int iNumChallenges = 0;
+
+ if ( pMap->m_pChallenges )
+ {
+ // Get the name of the previously selected challenge so that we can select a matching challenge (if one exists)
+ int iSelectedChallenge = GetSelectedChallenge();
+
+ m_pChallengeSelection->RemoveAll();
+
+ m_pChallengeSelection->AddItem( "<Select A Challenge>", new KeyValues( "ChallengeSelection", "challenge", -1 ) );
+
+ int iFoundSimilar = 0;
+
+ for ( iNumChallenges; iNumChallenges < pMap->m_pChallenges->Count(); ++iNumChallenges )
+ {
+ ChallengeDescription_t *pChallenge = &(*pMap->m_pChallenges)[ iNumChallenges ];
+ int iType = iNumChallenges;
+
+ // If the challenge type was specified then use that instead of (legacy) the order the challenges were listed
+ if ( pChallenge->iType != -1 )
+ iType = pChallenge->iType;
+
+ m_pChallengeSelection->AddItem( pChallenge->szName, new KeyValues( "ChallengeSelection", "challenge", iType ) );
+
+ if ( iSelectedChallenge == iNumChallenges )
+ iFoundSimilar = iNumChallenges + 1;
+ }
+
+ m_pChallengeSelection->ActivateItemByRow( iFoundSimilar );
+ }
+
+ if ( iNumChallenges > 0 )
+ {
+ m_pChallengeSelection->SetEnabled( true );
+ m_pChallengeSelection->SetVisible( true );
+ m_pChallengeSelection->SetNumberOfEditLines( iNumChallenges + 1 );
+ }
+ else
+ {
+ m_pChallengeSelection->SetEnabled( false );
+ m_pChallengeSelection->SetVisible( false );
+ }
+
+ RefreshDialog( pMap );
+}
+
+void CBonusMapsDialog::OnControlModified()
+{
+ CBonusMapPanel *pSelectedBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetSelectedPanel();
+ if ( !pSelectedBonusMapPanel )
+ return;
+ BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( pSelectedBonusMapPanel->GetBonusMapListItemID() );
+ if ( !pMap )
+ return;
+ RefreshDialog( pMap );
+}
+
+// file selected. This can only happen when someone selects an image to be imported as a spray logo.
+void CBonusMapsDialog::OnFileSelected( const char *fullpath )
+{
+ if ( fullpath == NULL || fullpath[ 0 ] == '\0' )
+ return;
+
+ // this can take a while, put up a waiting cursor
+ surface()->SetCursor(dc_hourglass);
+
+ ImportZippedBonusMaps( fullpath );
+
+ // change the cursor back to normal
+ surface()->SetCursor(dc_user);
+}