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.
1647 lines
48 KiB
1647 lines
48 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================
|
||
|
#include "cbase.h"
|
||
|
|
||
|
#include "imageutils.h"
|
||
|
#include "econ_controls.h"
|
||
|
#include "econ/confirm_dialog.h"
|
||
|
#include "game/client/iviewport.h"
|
||
|
#include "ienginevgui.h"
|
||
|
#include "tf_hud_mainmenuoverride.h"
|
||
|
#include "vgui/ILocalize.h"
|
||
|
#include "vgui/ISurface.h"
|
||
|
#include "vgui/ISystem.h"
|
||
|
#include "vgui_bitmappanel.h"
|
||
|
#include <vgui_controls/FileOpenDialog.h>
|
||
|
|
||
|
#ifdef WORKSHOP_IMPORT_ENABLED
|
||
|
#include "itemtest/itemtest.h"
|
||
|
#include "workshop/item_import.h"
|
||
|
#endif
|
||
|
|
||
|
#include "steampublishedfiles/publish_file_dialog.h"
|
||
|
|
||
|
#include "tier1/checksum_crc.h"
|
||
|
|
||
|
// for hud element
|
||
|
#include "iclientmode.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include <tier0/memdbgon.h>
|
||
|
|
||
|
#define TF2_PREVIEW_IMAGE_HEIGHT 512
|
||
|
#define TF2_PREVIEW_IMAGE_WIDTH 512
|
||
|
|
||
|
#define COMMUNITY_DEV_HOST "http://localhost/"
|
||
|
|
||
|
extern ConVar publish_file_last_dir;
|
||
|
|
||
|
// milliseconds
|
||
|
ConVar tf_steam_workshop_query_timeout( "tf_steam_workshop_query_timeout", "10", FCVAR_CLIENTDLL, "Time in seconds to allow communication with the Steam Workshop server." );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Utility function
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static void MakeModalAndBringToFront( vgui::EditablePanel *dialog )
|
||
|
{
|
||
|
dialog->SetVisible( true );
|
||
|
if ( dialog->GetParent() == NULL )
|
||
|
{
|
||
|
dialog->MakePopup();
|
||
|
}
|
||
|
dialog->SetZPos( 10000 );
|
||
|
dialog->MoveToFront();
|
||
|
dialog->SetKeyBoardInputEnabled( true );
|
||
|
dialog->SetMouseInputEnabled( true );
|
||
|
TFModalStack()->PushModal( dialog );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: helper class that contains the list of published files for a user
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CPublishedFiles
|
||
|
{
|
||
|
public:
|
||
|
enum
|
||
|
{
|
||
|
kState_Initialized,
|
||
|
kState_PopulatingFileList,
|
||
|
kState_ErrorOccurred,
|
||
|
kState_DeletingFile,
|
||
|
kState_ErrorCannotDeleteFile,
|
||
|
kState_Timeout,
|
||
|
kState_Done,
|
||
|
};
|
||
|
|
||
|
CPublishedFiles();
|
||
|
~CPublishedFiles();
|
||
|
|
||
|
bool QueryHasTimedOut( void );
|
||
|
void PopulateFileList( void );
|
||
|
bool EnumerateUserPublishedFiles( uint32 unPage );
|
||
|
void RefreshPublishedFileDetails( uint64 nPublishedFileID );
|
||
|
void DeletePublishedFile( uint64 nPublishedFileID );
|
||
|
void ViewPublishedFile( uint64 nPublishedFileID );
|
||
|
const SteamUGCDetails_t *GetPublishedFileDetails( uint64 nPublishedFileID ) const;
|
||
|
|
||
|
// Enumerate subscribed files
|
||
|
CCallResult<CPublishedFiles, SteamUGCQueryCompleted_t> m_callbackEnumeratePublishedFiles;
|
||
|
void Steam_OnEnumeratePublishedFiles( SteamUGCQueryCompleted_t *pResult, bool bError );
|
||
|
|
||
|
// Callback for deleting files
|
||
|
CCallResult<CPublishedFiles, RemoteStorageDeletePublishedFileResult_t> m_callbackDeletePublishedFile;
|
||
|
void Steam_OnDeletePublishedFile( RemoteStorageDeletePublishedFileResult_t *pResult, bool bError );
|
||
|
|
||
|
unsigned int m_nTotalFilesToQuery;
|
||
|
CUtlQueue< PublishedFileId_t > m_FilesToQuery;
|
||
|
CUtlMap< PublishedFileId_t, SteamUGCDetails_t > m_FileDetails;
|
||
|
|
||
|
long m_nFileQueryTime;
|
||
|
bool m_bQueryErrorOccurred;
|
||
|
uint32 m_state;
|
||
|
uint32 m_unEnumerateStartPage;
|
||
|
PublishedFileId_t m_nCurrentQueryPublishedFileID;
|
||
|
};
|
||
|
|
||
|
CPublishedFiles::CPublishedFiles()
|
||
|
: m_nTotalFilesToQuery( 0 )
|
||
|
, m_nFileQueryTime( 0 )
|
||
|
, m_bQueryErrorOccurred( false )
|
||
|
, m_state( kState_Initialized )
|
||
|
, m_unEnumerateStartPage( 0 )
|
||
|
, m_nCurrentQueryPublishedFileID( 0 )
|
||
|
{
|
||
|
m_FileDetails.SetLessFunc( DefLessFunc( PublishedFileId_t ) );
|
||
|
}
|
||
|
|
||
|
CPublishedFiles::~CPublishedFiles()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Determine if our file query has timed out
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CPublishedFiles::QueryHasTimedOut( void )
|
||
|
{
|
||
|
return ( ( system()->GetTimeMillis() - m_nFileQueryTime ) > tf_steam_workshop_query_timeout.GetInt() * 1000 );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPublishedFiles::PopulateFileList( void )
|
||
|
{
|
||
|
// Start the process of showing all of our published files
|
||
|
if ( EnumerateUserPublishedFiles( 1 ) )
|
||
|
{
|
||
|
m_unEnumerateStartPage = 1;
|
||
|
|
||
|
// Get our starting tick
|
||
|
m_nFileQueryTime = system()->GetTimeMillis();
|
||
|
|
||
|
m_state = kState_PopulatingFileList;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Wrapper for creating and sending a CreateQueryUserUGCRequest for this user's published files
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CPublishedFiles::EnumerateUserPublishedFiles( uint32 unPage )
|
||
|
{
|
||
|
ISteamUGC *pUGC = steamapicontext->SteamUGC();
|
||
|
ISteamUser *pUser = steamapicontext->SteamUser();
|
||
|
if ( pUGC && pUser )
|
||
|
{
|
||
|
AccountID_t nAccountID = pUser->GetSteamID().GetAccountID();
|
||
|
|
||
|
UGCQueryHandle_t ugcHandle = pUGC->CreateQueryUserUGCRequest( nAccountID,
|
||
|
k_EUserUGCList_Published,
|
||
|
k_EUGCMatchingUGCType_Items,
|
||
|
k_EUserUGCListSortOrder_CreationOrderDesc,
|
||
|
engine->GetAppID(), engine->GetAppID(), unPage );
|
||
|
|
||
|
// make sure we get the entire description and not a truncated version
|
||
|
pUGC->SetReturnLongDescription( ugcHandle, true );
|
||
|
|
||
|
SteamAPICall_t hSteamAPICall = pUGC->SendQueryUGCRequest( ugcHandle );
|
||
|
m_callbackEnumeratePublishedFiles.Set( hSteamAPICall, this, &CPublishedFiles::Steam_OnEnumeratePublishedFiles );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPublishedFiles::DeletePublishedFile( uint64 nPublishedFileID )
|
||
|
{
|
||
|
m_state = kState_DeletingFile;
|
||
|
SteamAPICall_t hSteamAPICall = steamapicontext->SteamRemoteStorage()->DeletePublishedFile( nPublishedFileID );
|
||
|
m_callbackDeletePublishedFile.Set( hSteamAPICall, this, &CPublishedFiles::Steam_OnDeletePublishedFile );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
const SteamUGCDetails_t *CPublishedFiles::GetPublishedFileDetails( uint64 nPublishedFileID ) const
|
||
|
{
|
||
|
int idx = m_FileDetails.Find( nPublishedFileID );
|
||
|
if ( idx != m_FileDetails.InvalidIndex() )
|
||
|
{
|
||
|
return &m_FileDetails[idx];
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPublishedFiles::ViewPublishedFile( uint64 nPublishedFileID )
|
||
|
{
|
||
|
EUniverse universe = GetUniverse();
|
||
|
switch ( universe )
|
||
|
{
|
||
|
case k_EUniversePublic:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://steamcommunity.com/sharedfiles/filedetails/?id=%llu", nPublishedFileID ) );
|
||
|
break;
|
||
|
case k_EUniverseBeta:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://beta.steamcommunity.com/sharedfiles/filedetails/?id=%llu", nPublishedFileID ) );
|
||
|
break;
|
||
|
case k_EUniverseDev:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( COMMUNITY_DEV_HOST "sharedfiles/filedetails/?id=%llu", nPublishedFileID ) );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPublishedFiles::RefreshPublishedFileDetails( uint64 nPublishedFileID )
|
||
|
{
|
||
|
if ( m_state != kState_Done )
|
||
|
{
|
||
|
// Would confuse the refresh in progress
|
||
|
AssertMsg( m_state == kState_Done, "Shouldn't be refreshing file details while other operations are already happening" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ISteamUGC *pUGC = steamapicontext->SteamUGC();
|
||
|
Assert( pUGC );
|
||
|
if ( pUGC )
|
||
|
{
|
||
|
UGCQueryHandle_t ugcHandle = pUGC->CreateQueryUGCDetailsRequest( &nPublishedFileID, 1 );
|
||
|
SteamAPICall_t hSteamAPICall = pUGC->SendQueryUGCRequest( ugcHandle );
|
||
|
m_callbackEnumeratePublishedFiles.Set( hSteamAPICall, this, &CPublishedFiles::Steam_OnEnumeratePublishedFiles );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPublishedFiles::Steam_OnDeletePublishedFile( RemoteStorageDeletePublishedFileResult_t *pResult, bool bError )
|
||
|
{
|
||
|
if ( pResult && !bError )
|
||
|
{
|
||
|
if ( pResult->m_eResult != k_EResultOK )
|
||
|
{
|
||
|
m_state = kState_ErrorOccurred;
|
||
|
if ( pResult->m_eResult == k_EResultAccessDenied )
|
||
|
{
|
||
|
m_state = kState_ErrorCannotDeleteFile;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_state = kState_Done;
|
||
|
m_FileDetails.Remove( pResult->m_nPublishedFileId );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_state = kState_ErrorOccurred;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPublishedFiles::Steam_OnEnumeratePublishedFiles( SteamUGCQueryCompleted_t *pResult, bool bError )
|
||
|
{
|
||
|
// Make sure we succeeded
|
||
|
if ( bError || pResult->m_eResult != k_EResultOK )
|
||
|
{
|
||
|
m_state = kState_ErrorOccurred;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( m_state == kState_PopulatingFileList && m_unEnumerateStartPage == 1 )
|
||
|
{
|
||
|
// Start from scratch
|
||
|
m_FilesToQuery.Purge();
|
||
|
m_FileDetails.Purge();
|
||
|
}
|
||
|
|
||
|
const int nNumFiles = pResult->m_unNumResultsReturned;
|
||
|
for ( int i = 0; i < nNumFiles; i++ )
|
||
|
{
|
||
|
SteamUGCDetails_t sDetails = { 0 };
|
||
|
steamapicontext->SteamUGC()->GetQueryUGCResult( pResult->m_handle, i, &sDetails );
|
||
|
m_FileDetails.InsertOrReplace( sDetails.m_nPublishedFileId, sDetails );
|
||
|
}
|
||
|
|
||
|
if ( m_state == kState_Done )
|
||
|
{
|
||
|
// This was a one-off request from e.g. RefreshPublishedFileDetails
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !nNumFiles || m_FileDetails.Count() >= pResult->m_unTotalMatchingResults )
|
||
|
{
|
||
|
m_state = kState_Done;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
EnumerateUserPublishedFiles( ++m_unEnumerateStartPage );
|
||
|
}
|
||
|
|
||
|
// Tags
|
||
|
static const char *kClassTags[TF_LAST_NORMAL_CLASS] = {
|
||
|
"", // TF_CLASS_UNDEFINED
|
||
|
"Scout", // TF_CLASS_SCOUT
|
||
|
"Sniper", // TF_CLASS_SNIPER,
|
||
|
"Soldier", // TF_CLASS_SOLDIER,
|
||
|
"Demoman", // TF_CLASS_DEMOMAN,
|
||
|
"Medic", // TF_CLASS_MEDIC,
|
||
|
"Heavy", //TF_CLASS_HEAVYWEAPONS,
|
||
|
"Pyro", // TF_CLASS_PYRO,
|
||
|
"Spy", // TF_CLASS_SPY,
|
||
|
"Engineer", // TF_CLASS_ENGINEER,
|
||
|
};
|
||
|
|
||
|
struct TagPair_t
|
||
|
{
|
||
|
const char *pCheckboxElementName;
|
||
|
const char *pTag;
|
||
|
};
|
||
|
static TagPair_t kOtherTags[] = {
|
||
|
{ "TagCheckbox_Headgear", "Headgear" },
|
||
|
{ "TagCheckbox_Weapon", "Weapon" },
|
||
|
{ "TagCheckbox_Misc", "Misc" },
|
||
|
{ "TagCheckbox_SoundDevice", "Sound Device" },
|
||
|
{ "TagCheckbox_Halloween", "Halloween" },
|
||
|
{ "TagCheckbox_Taunt", "Taunt" },
|
||
|
{ "TagCheckbox_UnusualEffect", "Unusual Effect" },
|
||
|
{ "TagCheckbox_Jungle", "Jungle" },
|
||
|
};
|
||
|
static uint32 kNumOtherTags = ARRAYSIZE( kOtherTags );
|
||
|
|
||
|
// Map Tags
|
||
|
static TagPair_t kMapTags[] = {
|
||
|
{ "MapsCheckBox_CTF", "Capture the Flag" },
|
||
|
{ "MapsCheckBox_CP", "Control Point" },
|
||
|
{ "MapsCheckBox_Escort", "Payload" },
|
||
|
{ "MapsCheckBox_EscortRace", "Payload Race" },
|
||
|
{ "MapsCheckBox_Arena", "Arena" },
|
||
|
{ "MapsCheckBox_Koth", "King of the Hill" },
|
||
|
{ "MapsCheckBox_AttackDefense", "Attack / Defense" },
|
||
|
{ "MapsCheckBox_SD", "Special Delivery" },
|
||
|
{ "MapsCheckBox_RobotDestruction", "Robot Destruction" },
|
||
|
{ "MapsCheckBox_MVM", "Mann vs. Machine" },
|
||
|
{ "MapsCheckBox_Powerup", "Mannpower" },
|
||
|
{ "MapsCheckBox_Medieval", "Medieval" },
|
||
|
{ "MapsCheckBox_PassTime", "PASS Time" },
|
||
|
{ "MapsCheckBox_Specialty", "Specialty" },
|
||
|
{ "MapsCheckBox_Halloween", "Halloween" },
|
||
|
{ "MapsCheckbox_Smissmas", "Smissmas" },
|
||
|
{ "MapsCheckbox_Night", "Night" },
|
||
|
{ "MapsCheckbox_Jungle", "Jungle" },
|
||
|
};
|
||
|
static uint32 kNumMapTags = ARRAYSIZE( kMapTags );
|
||
|
|
||
|
static const char *kImportedTag = "Certified Compatible";
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Publish file dialog
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CTFFilePublishDialog : public CFilePublishDialog
|
||
|
{
|
||
|
DECLARE_CLASS_SIMPLE( CTFFilePublishDialog, CFilePublishDialog );
|
||
|
public:
|
||
|
CTFFilePublishDialog( Panel *parent, const char *name, PublishedFileDetails_t *pDetails ) : CFilePublishDialog( parent, name, pDetails ), m_bImported(false) {}
|
||
|
|
||
|
virtual ErrorCode_t ValidateFile( const char *lpszFilename )
|
||
|
{
|
||
|
if( !g_pFullFileSystem->FileExists( lpszFilename ) )
|
||
|
return kFailedFileNotFound;
|
||
|
|
||
|
// TODO This is the nominal max of SteamUGC, but should be found dynamically
|
||
|
const uint32 kMaxFileSize = 400 * 1024 * 1024;
|
||
|
unsigned int unFileSize = g_pFullFileSystem->Size( lpszFilename );
|
||
|
if ( unFileSize == 0 || unFileSize > kMaxFileSize )
|
||
|
{
|
||
|
return kFailedFileTooLarge;
|
||
|
}
|
||
|
return kNoError;
|
||
|
}
|
||
|
virtual AppId_t GetTargetAppID( void ) { return engine->GetAppID(); }
|
||
|
virtual unsigned int DesiredPreviewHeight( void ) { return TF2_PREVIEW_IMAGE_HEIGHT; }
|
||
|
virtual unsigned int DesiredPreviewWidth( void ) { return TF2_PREVIEW_IMAGE_WIDTH; }
|
||
|
virtual bool BForceSquarePreviewImage( void ) { return true; }
|
||
|
virtual EWorkshopFileType WorkshipFileTypeForFile( const char *pszFileName ) {
|
||
|
const char *pExt = V_GetFileExtension( pszFileName );
|
||
|
if ( pExt && V_strcmp( pExt, "bsp" ) == 0 )
|
||
|
{
|
||
|
return k_EWorkshopFileTypeCommunity;
|
||
|
}
|
||
|
|
||
|
AssertMsg( pExt && V_strcmp( pExt, "zip" ) == 0, "Unrecognized file type, defaulting to microtransaction\n" );
|
||
|
return k_EWorkshopFileTypeMicrotransaction;
|
||
|
}
|
||
|
virtual const char *GetPreviewFileTypes( void ) { return "*.tga,*.jpg,*.png"; }
|
||
|
virtual const char *GetPreviewFileTypeDescriptions( void ) { return "#TF_SteamWorkshop_Images"; }
|
||
|
virtual const char *GetFileTypes( eFilterType_t eType = IMPORT_FILTER_NONE ) OVERRIDE
|
||
|
{
|
||
|
if ( eType == IMPORT_FILTER_MAP )
|
||
|
{
|
||
|
return "*.bsp";
|
||
|
}
|
||
|
return "*.zip";
|
||
|
}
|
||
|
virtual const char *GetFileTypeDescriptions( eFilterType_t eType = IMPORT_FILTER_NONE ) OVERRIDE
|
||
|
{
|
||
|
if ( eType == IMPORT_FILTER_MAP )
|
||
|
{
|
||
|
return "#TF_SteamWorkshop_AcceptableFilesMaps";
|
||
|
}
|
||
|
return "#TF_SteamWorkshop_AcceptableFiles";
|
||
|
}
|
||
|
virtual const char *GetResFile() const { return "Resource/UI/PublishFileDialog.res"; }
|
||
|
|
||
|
virtual void SetFile( const char *lpszFilename, bool bImported )
|
||
|
{
|
||
|
BaseClass::SetFile( lpszFilename, bImported );
|
||
|
SetTagsVisible( true, WorkshipFileTypeForFile( lpszFilename ) );
|
||
|
|
||
|
m_sFilePath = lpszFilename;
|
||
|
|
||
|
CUtlBuffer buffer;
|
||
|
g_pFullFileSystem->ReadFile( lpszFilename, NULL, buffer );
|
||
|
m_fileCRC = CRC32_ProcessSingleBuffer( buffer.Base(), buffer.Size() );
|
||
|
|
||
|
m_bImported = bImported;
|
||
|
}
|
||
|
|
||
|
void SetTagsVisible( bool visible, EWorkshopFileType eFileType = k_EWorkshopFileTypeCommunity )
|
||
|
{
|
||
|
uint32 i;
|
||
|
vgui::CheckButton *pButton;
|
||
|
|
||
|
vgui::Label *pLabel = FindControl<vgui::Label>( "TagsTitle", true );
|
||
|
if ( pLabel )
|
||
|
{
|
||
|
pLabel->SetVisible( visible );
|
||
|
}
|
||
|
|
||
|
if ( !visible )
|
||
|
{
|
||
|
// no tags visible, so hide everything
|
||
|
// class tags
|
||
|
for ( i = TF_FIRST_NORMAL_CLASS; i < TF_LAST_NORMAL_CLASS; i++ )
|
||
|
{
|
||
|
pButton = FindControl<vgui::CheckButton>( VarArgs( "ClassCheckBox%d", i ), true );
|
||
|
if ( pButton )
|
||
|
{
|
||
|
pButton->SetVisible( visible );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// other tags
|
||
|
for ( i = 0; i < kNumOtherTags; ++i )
|
||
|
{
|
||
|
pButton = FindControl<vgui::CheckButton>( kOtherTags[i].pCheckboxElementName, true );
|
||
|
if ( pButton )
|
||
|
{
|
||
|
pButton->SetVisible( visible );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// map tags
|
||
|
for ( i = 0; i < kNumMapTags; ++i )
|
||
|
{
|
||
|
pButton = FindControl<vgui::CheckButton>( kMapTags[i].pCheckboxElementName, true );
|
||
|
if ( pButton )
|
||
|
{
|
||
|
pButton->SetVisible( visible );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bool bIsMap = ( eFileType == k_EWorkshopFileTypeCommunity );
|
||
|
|
||
|
// class tags
|
||
|
for ( i = TF_FIRST_NORMAL_CLASS; i < TF_LAST_NORMAL_CLASS; i++ )
|
||
|
{
|
||
|
pButton = FindControl<vgui::CheckButton>( VarArgs( "ClassCheckBox%d", i ), true );
|
||
|
if ( pButton )
|
||
|
{
|
||
|
pButton->SetVisible( !bIsMap );
|
||
|
|
||
|
if ( bIsMap && pButton->IsSelected() )
|
||
|
{
|
||
|
pButton->SetSelected( false ); // reset this button if we're using the maps tags
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// other tags
|
||
|
for ( i = 0; i < kNumOtherTags; ++i )
|
||
|
{
|
||
|
pButton = FindControl<vgui::CheckButton>( kOtherTags[i].pCheckboxElementName, true );
|
||
|
if ( pButton )
|
||
|
{
|
||
|
pButton->SetVisible( !bIsMap );
|
||
|
|
||
|
if ( bIsMap && pButton->IsSelected() )
|
||
|
{
|
||
|
pButton->SetSelected( false ); // reset this button if we're using the maps tags
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// map tags
|
||
|
for ( i = 0; i < kNumMapTags; ++i )
|
||
|
{
|
||
|
pButton = FindControl<vgui::CheckButton>( kMapTags[i].pCheckboxElementName, true );
|
||
|
if ( pButton )
|
||
|
{
|
||
|
pButton->SetVisible( bIsMap );
|
||
|
|
||
|
if ( !bIsMap && pButton->IsSelected() )
|
||
|
{
|
||
|
pButton->SetSelected( false ); // reset this button if we're not using the maps tags
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void PopulateTags( SteamParamStringArray_t &strArray )
|
||
|
{
|
||
|
m_vecTags.RemoveAll();
|
||
|
|
||
|
// class tags
|
||
|
vgui::EditablePanel* pClassUsagePanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "ClassUsagePanel" ) );
|
||
|
if ( pClassUsagePanel )
|
||
|
{
|
||
|
for ( int i = TF_FIRST_NORMAL_CLASS; i < TF_LAST_NORMAL_CLASS; i++ )
|
||
|
{
|
||
|
if ( IsChildButtonSelected( pClassUsagePanel, VarArgs("ClassCheckBox%d",i), false ) )
|
||
|
{
|
||
|
m_vecTags.AddToTail( kClassTags[i] );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// other tags
|
||
|
for ( uint32 i = 0; i < kNumOtherTags; ++i )
|
||
|
{
|
||
|
if ( IsChildButtonSelected( this, kOtherTags[i].pCheckboxElementName, true ) )
|
||
|
{
|
||
|
m_vecTags.AddToTail( kOtherTags[i].pTag );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// map tags
|
||
|
for ( uint32 i = 0; i < kNumMapTags; ++i )
|
||
|
{
|
||
|
if ( IsChildButtonSelected( this, kMapTags[i].pCheckboxElementName, true ) )
|
||
|
{
|
||
|
m_vecTags.AddToTail( kMapTags[i].pTag );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_bImported )
|
||
|
{
|
||
|
m_vecTags.AddToTail( kImportedTag );
|
||
|
}
|
||
|
|
||
|
strArray.m_ppStrings = m_vecTags.Base();
|
||
|
strArray.m_nNumStrings = m_vecTags.Count();
|
||
|
}
|
||
|
|
||
|
virtual void PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
// Center it, keeping requested size
|
||
|
int x, y, ww, wt, wide, tall;
|
||
|
vgui::surface()->GetWorkspaceBounds( x, y, ww, wt );
|
||
|
GetSize(wide, tall);
|
||
|
SetPos(x + ((ww - wide) / 2), y + ((wt - tall) / 2));
|
||
|
}
|
||
|
|
||
|
virtual bool PrepSteamCloudFilePath( const char *lpszFileName, CUtlString &steamCloudFileName )
|
||
|
{
|
||
|
char szShortName[ MAX_PATH ];
|
||
|
Q_FileBase( lpszFileName, szShortName, sizeof( szShortName ) );
|
||
|
const char *szExt = Q_GetFileExtension( lpszFileName );
|
||
|
Q_SetExtension( szShortName, CFmtStr( ".%s", szExt ).Access(), sizeof(szShortName ) );
|
||
|
steamCloudFileName.Format( "steamworkshop/tf2/%s", szShortName );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
virtual void ErrorMessage( ErrorCode_t errorCode, KeyValues *pkvTokens )
|
||
|
{
|
||
|
switch ( errorCode )
|
||
|
{
|
||
|
case kFailedToPublishFile:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFailedToPublishFile", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kFailedToPrepareFile:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFailedToPrepareFile", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kFailedToUpdateFile:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFailedToUpdateFile", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kSteamCloudNotAvailable:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kSteamCloudNotAvailable", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kSteamExceededCloudQuota:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kSteamExceededCloudQuota", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kFailedToWriteToSteamCloud:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFailedToWriteToSteamCloud", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kFileNotFound:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFileNotFound", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kNeedTitleAndDescription:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kNeedTitleAndDescription", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kFailedFileValidation:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFailedFileValidation", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kFailedFileTooLarge:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFailedFileTooLarge", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kFailedFileNotFound:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFailedFileNotFound", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kFailedUserModifiedFile:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kFailedUserModifiedFile", "#GameUI_OK" );
|
||
|
break;
|
||
|
case kInvalidMapName:
|
||
|
ShowMessageBox( "#TF_PublishFile_Error", "#TF_PublishFile_kInvalidMapName", "#GameUI_OK" );
|
||
|
break;
|
||
|
default:
|
||
|
Assert( false ); // Unhandled enum value
|
||
|
break;
|
||
|
}
|
||
|
if ( pkvTokens )
|
||
|
{
|
||
|
pkvTokens->deleteThis();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
if ( !m_bAddingNewFile )
|
||
|
{
|
||
|
bool bIsMap = ( m_FileDetails.publishedFileDetails.m_eFileType == k_EWorkshopFileTypeCommunity );
|
||
|
|
||
|
CExImageButton *pImageButton = FindControl<CExImageButton>( "ButtonSourceCosmetics", true );
|
||
|
if ( pImageButton )
|
||
|
{
|
||
|
pImageButton->SetVisible( !bIsMap );
|
||
|
}
|
||
|
|
||
|
vgui::Button *pButton = FindControl<Button>( "ButtonSourceOther", true );
|
||
|
if ( pButton )
|
||
|
{
|
||
|
pButton->SetVisible( !bIsMap );
|
||
|
}
|
||
|
|
||
|
pImageButton = FindControl<CExImageButton>( "ButtonSourceMaps", true );
|
||
|
if ( pImageButton )
|
||
|
{
|
||
|
pImageButton->SetVisible( bIsMap );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
virtual void PopulateEditFields( void )
|
||
|
{
|
||
|
BaseClass::PopulateEditFields();
|
||
|
|
||
|
// class tags
|
||
|
vgui::EditablePanel* pClassUsagePanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "ClassUsagePanel" ) );
|
||
|
if ( pClassUsagePanel )
|
||
|
{
|
||
|
for ( int i = TF_FIRST_NORMAL_CLASS; i < TF_LAST_NORMAL_CLASS; i++ )
|
||
|
{
|
||
|
bool bHasTag = Q_strstr( m_FileDetails.publishedFileDetails.m_rgchTags, kClassTags[i] ) != 0;
|
||
|
SetChildButtonSelected( pClassUsagePanel, VarArgs("ClassCheckBox%d",i), bHasTag );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// other tags
|
||
|
for ( uint32 i = 0; i < kNumOtherTags; ++i )
|
||
|
{
|
||
|
bool bHasTag = Q_strstr( m_FileDetails.publishedFileDetails.m_rgchTags, kOtherTags[i].pTag ) != 0;
|
||
|
SetChildButtonSelected( this, kOtherTags[i].pCheckboxElementName, bHasTag, true );
|
||
|
}
|
||
|
|
||
|
// map tags
|
||
|
for ( uint32 i = 0; i < kNumMapTags; ++i )
|
||
|
{
|
||
|
bool bHasTag = Q_strstr( m_FileDetails.publishedFileDetails.m_rgchTags, kMapTags[i].pTag ) != 0;
|
||
|
SetChildButtonSelected( this, kMapTags[i].pCheckboxElementName, bHasTag, true );
|
||
|
}
|
||
|
|
||
|
if ( Q_strstr( m_FileDetails.publishedFileDetails.m_rgchTags, kImportedTag ) )
|
||
|
{
|
||
|
m_bImported = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_bImported = false;
|
||
|
}
|
||
|
|
||
|
// Default the tags hidden until there is a file set
|
||
|
if ( !m_FileDetails.lpszFilename )
|
||
|
{
|
||
|
SetTagsVisible( false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetTagsVisible( true, m_FileDetails.publishedFileDetails.m_eFileType );
|
||
|
}
|
||
|
|
||
|
#ifndef WORKSHOP_IMPORT_ENABLED
|
||
|
vgui::Button *pImportButton = FindControl<vgui::Button>( "ButtonSourceCosmetics" );
|
||
|
if ( pImportButton )
|
||
|
pImportButton->SetVisible( false );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
const char* GetStatusString( StatusCode_t statusCode )
|
||
|
{
|
||
|
switch ( statusCode )
|
||
|
{
|
||
|
case kPublishing:
|
||
|
return "#TF_PublishFile_Publishing";
|
||
|
break;
|
||
|
case kUpdating:
|
||
|
return "#TF_PublishFile_Updating";
|
||
|
break;
|
||
|
}
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
void ShowStatusWindow( StatusCode_t statusCode )
|
||
|
{
|
||
|
ShowWaitingDialog( new CGenericWaitingDialog( this ), GetStatusString( statusCode ), true, false, 0.0f );
|
||
|
}
|
||
|
|
||
|
void HideStatusWindow( void )
|
||
|
{
|
||
|
CloseWaitingDialog();
|
||
|
}
|
||
|
|
||
|
virtual void OnCommand( const char *command )
|
||
|
{
|
||
|
if ( V_stricmp( command, "MainFileCosmetics" ) == 0 )
|
||
|
{
|
||
|
#ifdef WORKSHOP_IMPORT_ENABLED
|
||
|
if ( CItemUpload::InitManifest() )
|
||
|
{
|
||
|
CTFFileImportDialog *pImportDialog = new CTFFileImportDialog( this );
|
||
|
pImportDialog->SetDeleteSelfOnClose( true );
|
||
|
pImportDialog->SetSizeable( false );
|
||
|
MakeModalAndBringToFront( pImportDialog );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ShowMessageBox( "#TF_SteamWorkshop_Error", "#TF_ImportFile_InvalidManifest" );
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
else if ( V_stricmp( command, "Publish" ) == 0 || V_stricmp( command, "Update" ) == 0 )
|
||
|
{
|
||
|
if ( m_bImported )
|
||
|
{
|
||
|
CUtlBuffer buffer;
|
||
|
g_pFullFileSystem->ReadFile( m_sFilePath, NULL, buffer );
|
||
|
CRC32_t crc = CRC32_ProcessSingleBuffer( buffer.Base(), buffer.Size() );
|
||
|
if ( crc != m_fileCRC )
|
||
|
{
|
||
|
ErrorMessage( kFailedUserModifiedFile, NULL );
|
||
|
m_bImported = false;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BaseClass::OnCommand( command );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BaseClass::OnCommand( command );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
CUtlVector< const char* > m_vecTags;
|
||
|
|
||
|
CRC32_t m_fileCRC;
|
||
|
CUtlString m_sFilePath;
|
||
|
bool m_bImported;
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CUGCFileRequestCache
|
||
|
{
|
||
|
public:
|
||
|
CUGCFileRequestCache()
|
||
|
{
|
||
|
m_mapPreviewFileRequests.SetLessFunc( DefLessFunc( UGCHandle_t ) );
|
||
|
}
|
||
|
|
||
|
~CUGCFileRequestCache()
|
||
|
{
|
||
|
m_mapPreviewFileRequests.PurgeAndDeleteElements();
|
||
|
}
|
||
|
|
||
|
CUGCFileRequest *GetFileRequest( UGCHandle_t fileHandle )
|
||
|
{
|
||
|
int idx = m_mapPreviewFileRequests.Find( fileHandle );
|
||
|
if ( idx == m_mapPreviewFileRequests.InvalidIndex() )
|
||
|
{
|
||
|
idx = m_mapPreviewFileRequests.Insert( fileHandle, new CUGCFileRequest() );
|
||
|
}
|
||
|
return m_mapPreviewFileRequests[idx];
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
CUtlMap< UGCHandle_t, CUGCFileRequest* > m_mapPreviewFileRequests;
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CSteamWorkshopItemPanel : public vgui::EditablePanel
|
||
|
{
|
||
|
DECLARE_CLASS_SIMPLE( CSteamWorkshopItemPanel, vgui::EditablePanel );
|
||
|
public:
|
||
|
CSteamWorkshopItemPanel( vgui::Panel *parent, const char *panelName, CUGCFileRequestCache &previewFileCache )
|
||
|
: vgui::EditablePanel( parent, panelName )
|
||
|
, m_bSelected( false )
|
||
|
, m_bPreviewDownloadPending( false )
|
||
|
, m_pUGCPreviewFileRequest( NULL )
|
||
|
, m_previewFileCache( previewFileCache )
|
||
|
|
||
|
{
|
||
|
memset( &m_FileDetails, 0, sizeof( m_FileDetails ) );
|
||
|
m_pCroppedTextureImagePanel = new CBitmapPanel( this, "PreviewImage" );
|
||
|
m_pHighlightPanel = new vgui::EditablePanel( this, "HighlightPanel" );
|
||
|
vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
|
||
|
}
|
||
|
|
||
|
void SetPublishedFileDetails( const SteamUGCDetails_t *pDetails )
|
||
|
{
|
||
|
if ( pDetails )
|
||
|
{
|
||
|
m_FileDetails = *pDetails;
|
||
|
|
||
|
SetDialogVariable( "title", m_FileDetails.m_rgchTitle );
|
||
|
DownloadPreviewImage();
|
||
|
|
||
|
SetVisible( true );
|
||
|
InvalidateLayout( true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_bPreviewDownloadPending = false;
|
||
|
SetVisible( false );
|
||
|
m_pUGCPreviewFileRequest = NULL;
|
||
|
}
|
||
|
|
||
|
m_bSelected = false;
|
||
|
UpdateBorder();
|
||
|
}
|
||
|
|
||
|
virtual void ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
LoadControlSettings( "Resource/UI/SteamWorkshopItem.res" );
|
||
|
}
|
||
|
|
||
|
virtual void PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
}
|
||
|
|
||
|
virtual void OnTick()
|
||
|
{
|
||
|
BaseClass::OnTick();
|
||
|
|
||
|
if ( m_bPreviewDownloadPending && m_pUGCPreviewFileRequest )
|
||
|
{
|
||
|
UGCFileRequestStatus_t ugcStatus = m_pUGCPreviewFileRequest->Update();
|
||
|
switch ( ugcStatus )
|
||
|
{
|
||
|
case UGCFILEREQUEST_ERROR:
|
||
|
m_bPreviewDownloadPending = false;
|
||
|
break;
|
||
|
|
||
|
case UGCFILEREQUEST_FINISHED:
|
||
|
SetPreviewImage();
|
||
|
m_bPreviewDownloadPending = false;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
// Working, continue to wait...
|
||
|
return;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void OnCursorEntered()
|
||
|
{
|
||
|
m_pHighlightPanel->SetVisible( true );
|
||
|
}
|
||
|
|
||
|
virtual void OnCursorExited()
|
||
|
{
|
||
|
UpdateBorder();
|
||
|
}
|
||
|
|
||
|
virtual void OnMousePressed(vgui::MouseCode code)
|
||
|
{
|
||
|
if ( code != MOUSE_LEFT )
|
||
|
return;
|
||
|
|
||
|
PostActionSignal( new KeyValues( "ItemPanelMousePressed" ) );
|
||
|
}
|
||
|
|
||
|
void UpdateBorder()
|
||
|
{
|
||
|
m_pHighlightPanel->SetVisible( m_bSelected );
|
||
|
}
|
||
|
|
||
|
void SetSelected( bool bSelected ) { m_bSelected = bSelected; }
|
||
|
bool GetSelected() const { return m_bSelected; }
|
||
|
|
||
|
uint64 GetPublishedFileID() const { return m_FileDetails.m_nPublishedFileId; }
|
||
|
|
||
|
protected:
|
||
|
void DownloadPreviewImage()
|
||
|
{
|
||
|
m_pCroppedTextureImagePanel->SetImage( NULL );
|
||
|
m_pUGCPreviewFileRequest = m_previewFileCache.GetFileRequest( m_FileDetails.m_hPreviewFile );
|
||
|
|
||
|
switch ( m_pUGCPreviewFileRequest->GetStatus() )
|
||
|
{
|
||
|
case UGCFILEREQUEST_READY:
|
||
|
{
|
||
|
// Start off our download
|
||
|
char szTargetFilename[MAX_PATH];
|
||
|
V_snprintf( szTargetFilename, sizeof(szTargetFilename), "%llu_thumb.jpg", m_FileDetails.m_nPublishedFileId );
|
||
|
m_pUGCPreviewFileRequest->StartDownload( m_FileDetails.m_hPreviewFile, "downloads", szTargetFilename );
|
||
|
m_bPreviewDownloadPending = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case UGCFILEREQUEST_DOWNLOADING:
|
||
|
case UGCFILEREQUEST_DOWNLOAD_WRITING:
|
||
|
{
|
||
|
// download already going for another preview panel
|
||
|
m_bPreviewDownloadPending = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case UGCFILEREQUEST_FINISHED:
|
||
|
{
|
||
|
SetPreviewImage();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
m_pCroppedTextureImagePanel->SetVisible( false );
|
||
|
}
|
||
|
break;
|
||
|
} // switch
|
||
|
}
|
||
|
|
||
|
void SetPreviewImage()
|
||
|
{
|
||
|
// Update our image preview
|
||
|
char szLocalFilename[MAX_PATH];
|
||
|
m_pUGCPreviewFileRequest->GetLocalFileName( szLocalFilename, sizeof(szLocalFilename) );
|
||
|
char szLocalPath[ _MAX_PATH ];
|
||
|
g_pFullFileSystem->GetLocalPath( szLocalFilename, szLocalPath, sizeof(szLocalPath) );
|
||
|
SetPreviewImage( szLocalPath );
|
||
|
}
|
||
|
|
||
|
void SetPreviewImage( const char *lpszFilename )
|
||
|
{
|
||
|
if ( lpszFilename == NULL )
|
||
|
return;
|
||
|
|
||
|
ConversionErrorType nErrorCode = ImgUtl_LoadBitmap( lpszFilename, m_imgSource );
|
||
|
if ( nErrorCode == CE_SUCCESS )
|
||
|
{
|
||
|
m_pCroppedTextureImagePanel->SetBitmap( m_imgSource );
|
||
|
m_pCroppedTextureImagePanel->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// data
|
||
|
bool m_bSelected;
|
||
|
bool m_bPreviewDownloadPending;
|
||
|
Bitmap_t m_imgSource; // original resolution and aspect
|
||
|
CBitmapPanel *m_pCroppedTextureImagePanel;
|
||
|
vgui::EditablePanel *m_pHighlightPanel;
|
||
|
CUGCFileRequest *m_pUGCPreviewFileRequest;
|
||
|
SteamUGCDetails_t m_FileDetails;
|
||
|
CUGCFileRequestCache &m_previewFileCache;
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
#define MAX_ITEMS_VIEWABLE 4
|
||
|
|
||
|
class CSteamWorkshopDialog : public vgui::EditablePanel
|
||
|
{
|
||
|
DECLARE_CLASS_SIMPLE( CSteamWorkshopDialog, vgui::EditablePanel );
|
||
|
public:
|
||
|
CSteamWorkshopDialog( vgui::Panel *parent )
|
||
|
: vgui::EditablePanel( parent, "SteamWorkshopDialog" )
|
||
|
, m_lastPublishedFilesState( CPublishedFiles::kState_Initialized )
|
||
|
{
|
||
|
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" );
|
||
|
SetScheme(scheme);
|
||
|
SetProportional( true );
|
||
|
|
||
|
m_pContainer = new vgui::EditablePanel( this, "Container" );
|
||
|
m_pItemsContainer = new vgui::EditablePanel( m_pContainer, "ItemsContainer" );
|
||
|
|
||
|
vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
|
||
|
|
||
|
for ( uint32 i = 0; i < MAX_ITEMS_VIEWABLE; ++i )
|
||
|
{
|
||
|
m_items[i] = new CSteamWorkshopItemPanel( m_pItemsContainer, VarArgs("SteamWorkshopItem%d", i ), m_previewFileCache );
|
||
|
m_items[i]->AddActionSignalTarget( this );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual ~CSteamWorkshopDialog()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
virtual void OnTick( void )
|
||
|
{
|
||
|
BaseClass::OnTick();
|
||
|
|
||
|
if ( m_lastPublishedFilesState != m_publishedFiles.m_state )
|
||
|
{
|
||
|
CloseWaitingDialog();
|
||
|
switch ( m_publishedFiles.m_state )
|
||
|
{
|
||
|
case CPublishedFiles::kState_PopulatingFileList:
|
||
|
ShowWaitingDialog( new CGenericWaitingDialog( this ), "#TF_SteamWorkshop_PopulatingList", true, false, 30.0f );
|
||
|
break;
|
||
|
case CPublishedFiles::kState_ErrorOccurred:
|
||
|
ShowMessageBox( "#TF_SteamWorkshop_Error", "#TF_SteamWorkshop_ErrorText", "#GameUI_OK" );
|
||
|
break;
|
||
|
case CPublishedFiles::kState_DeletingFile:
|
||
|
ShowWaitingDialog( new CGenericWaitingDialog( this ), "#TF_SteamWorkshop_DeletingFile", true, false, 30.0f );
|
||
|
break;
|
||
|
case CPublishedFiles::kState_ErrorCannotDeleteFile:
|
||
|
ShowMessageBox( "#TF_SteamWorkshop_Error", "#TF_SteamWorkshop_CannotDeleteFile", "#GameUI_OK" );
|
||
|
break;
|
||
|
case CPublishedFiles::kState_Timeout:
|
||
|
ShowMessageBox( "#TF_SteamWorkshop_Error", "#TF_SteamWorkshop_Timeout", "#GameUI_OK" );
|
||
|
break;
|
||
|
case CPublishedFiles::kState_Done:
|
||
|
RefreshItemsUI();
|
||
|
break;
|
||
|
}
|
||
|
m_lastPublishedFilesState = m_publishedFiles.m_state;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
LoadControlSettings( "Resource/ui/SteamWorkshopDialog.res" );
|
||
|
|
||
|
SetupButton( "LearnMoreButton" );
|
||
|
SetupButton( "LearnMore2Button" );
|
||
|
SetupButton( "BrowseButton" );
|
||
|
SetupButton( "PublishButton" );
|
||
|
SetupButton( "ViewPublishedButton" );
|
||
|
SetupButton( "LoadTestMapButton" );
|
||
|
SetupButton( "ViewLegalAgreementButton" );
|
||
|
|
||
|
SetupButton( "PrevPageButton" );
|
||
|
SetupButton( "NextPageButton" );
|
||
|
SetupButton( "ViewButton" );
|
||
|
SetupButton( "EditButton" );
|
||
|
SetupButton( "DeleteButton" );
|
||
|
|
||
|
SetupButton( "CancelButton" );
|
||
|
|
||
|
SetChildPanelEnabled( this, "LoadTestMapButton", !engine->IsInGame() || !FStrEq( engine->GetLevelName(), "maps/itemtest.bsp" ), true );
|
||
|
}
|
||
|
|
||
|
virtual void PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
// Center it, keeping requested size
|
||
|
int x, y, ww, wt, wide, tall;
|
||
|
vgui::surface()->GetWorkspaceBounds( x, y, ww, wt );
|
||
|
GetSize(wide, tall);
|
||
|
SetPos(x + ((ww - wide) / 2), y + ((wt - tall) / 2));
|
||
|
}
|
||
|
|
||
|
virtual void Show()
|
||
|
{
|
||
|
TFModalStack()->PushModal( this );
|
||
|
|
||
|
// Make sure we're signed on
|
||
|
if ( !CheckSteamSignOn() )
|
||
|
{
|
||
|
Close();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SetVisible( true );
|
||
|
MakePopup();
|
||
|
MoveToFront();
|
||
|
SetKeyBoardInputEnabled( true );
|
||
|
SetMouseInputEnabled( true );
|
||
|
|
||
|
// start download
|
||
|
m_publishedFiles.PopulateFileList();
|
||
|
}
|
||
|
|
||
|
virtual void OnCommand( const char *pCommand )
|
||
|
{
|
||
|
if ( FStrEq( pCommand, "cancel" ) )
|
||
|
{
|
||
|
Close();
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "publish" ) )
|
||
|
{
|
||
|
ShowPublishFileDialog();
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "learn_more" ) )
|
||
|
{
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( "http://www.teamfortress.com/contribute/" );
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "view_files" ) )
|
||
|
{
|
||
|
EUniverse universe = GetUniverse();
|
||
|
uint64 ulSteamID = steamapicontext->SteamUser()->GetSteamID().ConvertToUint64();
|
||
|
switch ( universe )
|
||
|
{
|
||
|
case k_EUniversePublic:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://steamcommunity.com/profiles/%llu/mysharedfiles/", ulSteamID ) );
|
||
|
break;
|
||
|
case k_EUniverseBeta:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://beta.steamcommunity.com/profiles/%llu/mysharedfiles/", ulSteamID ) );
|
||
|
break;
|
||
|
case k_EUniverseDev:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( COMMUNITY_DEV_HOST "profiles/%llu/mysharedfiles/", ulSteamID ) );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "view_legal_agreement" ) )
|
||
|
{
|
||
|
EUniverse universe = GetUniverse();
|
||
|
switch ( universe )
|
||
|
{
|
||
|
case k_EUniversePublic:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://steamcommunity.com/workshop/workshoplegalagreement/?appid=%d", engine->GetAppID() ) );
|
||
|
break;
|
||
|
case k_EUniverseBeta:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://beta.steamcommunity.com/workshop/workshoplegalagreement/?appid=%d", engine->GetAppID() ) );
|
||
|
break;
|
||
|
case k_EUniverseDev:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( COMMUNITY_DEV_HOST "workshop/workshoplegalagreement/?appid=%d", engine->GetAppID() ) );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "browse" ) )
|
||
|
{
|
||
|
EUniverse universe = GetUniverse();
|
||
|
switch ( universe )
|
||
|
{
|
||
|
case k_EUniversePublic:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://steamcommunity.com/workshop/browse?appid=%d", engine->GetAppID() ) );
|
||
|
break;
|
||
|
case k_EUniverseBeta:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://beta.steamcommunity.com/workshop/browse?appid=%d", engine->GetAppID() ) );
|
||
|
break;
|
||
|
case k_EUniverseDev:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( COMMUNITY_DEV_HOST "workshop/browse?appid=%d", engine->GetAppID() ) );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "itemtest" ) )
|
||
|
{
|
||
|
Close();
|
||
|
engine->ClientCmd_Unrestricted( "disconnect\nwait\nwait\n\nprogress_enable\nmap itemtest\n" );
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "prevpage" ) )
|
||
|
{
|
||
|
if ( m_unCurrentPage > 0 )
|
||
|
{
|
||
|
--m_unCurrentPage;
|
||
|
}
|
||
|
PopulatePublishedFilesUI();
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "nextpage" ) )
|
||
|
{
|
||
|
uint32 unNumPages = ceil( (float)m_publishedFiles.m_FileDetails.Count() / (float)MAX_ITEMS_VIEWABLE );
|
||
|
if ( m_unCurrentPage < unNumPages )
|
||
|
{
|
||
|
++m_unCurrentPage;
|
||
|
PopulatePublishedFilesUI();
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "view" ) )
|
||
|
{
|
||
|
for ( uint32 i = 0; i < MAX_ITEMS_VIEWABLE; ++i )
|
||
|
{
|
||
|
if ( m_items[i]->GetSelected() )
|
||
|
{
|
||
|
ViewPublishedFile( m_items[i]->GetPublishedFileID() );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "edit" ) )
|
||
|
{
|
||
|
for ( uint32 i = 0; i < MAX_ITEMS_VIEWABLE; ++i )
|
||
|
{
|
||
|
if ( m_items[i]->GetSelected() )
|
||
|
{
|
||
|
EditPublishedFile( m_items[i]->GetPublishedFileID() );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( pCommand, "delete_item" ) )
|
||
|
{
|
||
|
for ( uint32 i = 0; i < MAX_ITEMS_VIEWABLE; ++i )
|
||
|
{
|
||
|
if ( m_items[i]->GetSelected() )
|
||
|
{
|
||
|
DeletePublishedFile( m_items[i]->GetPublishedFileID() );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BaseClass::OnCommand( pCommand );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void OnKeyCodeTyped( vgui::KeyCode code )
|
||
|
{
|
||
|
if( code == KEY_ESCAPE )
|
||
|
{
|
||
|
OnCommand( "cancel" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BaseClass::OnKeyCodeTyped( code );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void OnKeyCodePressed( vgui::KeyCode code )
|
||
|
{
|
||
|
if( GetBaseButtonCode( code ) == KEY_XBUTTON_B )
|
||
|
{
|
||
|
OnCommand( "cancel" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BaseClass::OnKeyCodePressed( code );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MESSAGE_FUNC_PTR( OnItemPanelMousePressed, "ItemPanelMousePressed", panel )
|
||
|
{
|
||
|
CSteamWorkshopItemPanel *pItemPanel = static_cast< CSteamWorkshopItemPanel * >( panel );
|
||
|
for ( uint32 i = 0; i < MAX_ITEMS_VIEWABLE; ++i )
|
||
|
{
|
||
|
m_items[i]->SetSelected( m_items[i] == pItemPanel );
|
||
|
m_items[i]->UpdateBorder();
|
||
|
}
|
||
|
|
||
|
// enable per item controls
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "ViewButton", true );
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "EditButton", true );
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "DeleteButton", true );
|
||
|
}
|
||
|
|
||
|
MESSAGE_FUNC_UINT64( OnChangedFile, "ChangedFile", nPublishedFileID )
|
||
|
{
|
||
|
m_publishedFiles.RefreshPublishedFileDetails( nPublishedFileID );
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
bool CheckSteamSignOn()
|
||
|
{
|
||
|
// Make sure we are connected to steam, or they are going to be disappointed
|
||
|
if ( steamapicontext == NULL
|
||
|
|| steamapicontext->SteamUtils() == NULL
|
||
|
|| steamapicontext->SteamMatchmakingServers() == NULL
|
||
|
|| steamapicontext->SteamUser() == NULL
|
||
|
|| !steamapicontext->SteamUser()->BLoggedOn()
|
||
|
) {
|
||
|
Warning( "Steam not properly initialized or connected.\n" );
|
||
|
ShowMessageBox( "#TF_MM_GenericFailure_Title", "#TF_MM_GenericFailure", "#GameUI_OK" );
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void RefreshItemsUI()
|
||
|
{
|
||
|
SetChildPanelVisible( m_pContainer, "NoItemsContainer", m_publishedFiles.m_FileDetails.Count() == 0 );
|
||
|
SetChildPanelVisible( m_pContainer, "ItemsContainer", m_publishedFiles.m_FileDetails.Count() != 0 );
|
||
|
SetChildPanelVisible( m_pContainer, "LearnMore2Button", m_publishedFiles.m_FileDetails.Count() != 0 );
|
||
|
SetChildPanelVisible( m_pContainer, "BrowseButton", m_publishedFiles.m_FileDetails.Count() == 0 );
|
||
|
|
||
|
m_unCurrentPage = 0;
|
||
|
PopulatePublishedFilesUI();
|
||
|
}
|
||
|
|
||
|
void PopulatePublishedFilesUI()
|
||
|
{
|
||
|
if ( m_publishedFiles.m_FileDetails.Count() != 0 )
|
||
|
{
|
||
|
uint32 unIndex = m_unCurrentPage * MAX_ITEMS_VIEWABLE;
|
||
|
int nFileIdx = m_publishedFiles.m_FileDetails.FirstInorder();
|
||
|
for ( uint32 i = 0; i < unIndex && nFileIdx != m_publishedFiles.m_FileDetails.InvalidIndex(); ++i )
|
||
|
{
|
||
|
nFileIdx = m_publishedFiles.m_FileDetails.NextInorder( nFileIdx );
|
||
|
}
|
||
|
bool bSelected = false;
|
||
|
for ( uint32 i = 0; i < MAX_ITEMS_VIEWABLE; ++i )
|
||
|
{
|
||
|
CSteamWorkshopItemPanel *pItemPanel = m_items[i];
|
||
|
if ( nFileIdx != m_publishedFiles.m_FileDetails.InvalidIndex() )
|
||
|
{
|
||
|
SteamUGCDetails_t &details = m_publishedFiles.m_FileDetails[ nFileIdx ];
|
||
|
pItemPanel->SetPublishedFileDetails( &details );
|
||
|
if ( !bSelected )
|
||
|
{
|
||
|
pItemPanel->SetSelected( true );
|
||
|
pItemPanel->UpdateBorder();
|
||
|
bSelected = true;
|
||
|
}
|
||
|
nFileIdx = m_publishedFiles.m_FileDetails.NextInorder( nFileIdx );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pItemPanel->SetPublishedFileDetails( NULL );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// paging
|
||
|
uint32 unNumPages = ceil( (float)m_publishedFiles.m_FileDetails.Count() / (float)MAX_ITEMS_VIEWABLE );
|
||
|
bool bMultiplePages = ( unNumPages > 1 );
|
||
|
if ( bMultiplePages )
|
||
|
{
|
||
|
m_pItemsContainer->SetDialogVariable( "page", CFmtStr( "%d/%d", m_unCurrentPage + 1, unNumPages ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pItemsContainer->SetDialogVariable( "page", "" );
|
||
|
}
|
||
|
SetChildPanelVisible( m_pItemsContainer, "NextPageButton", bMultiplePages );
|
||
|
SetChildPanelVisible( m_pItemsContainer, "PrevPageButton", bMultiplePages );
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "NextPageButton", m_unCurrentPage < unNumPages - 1 );
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "PrevPageButton", m_unCurrentPage > 0 );
|
||
|
|
||
|
// other controls
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "ViewButton", bSelected );
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "EditButton", bSelected );
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "DeleteButton", bSelected );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "ViewButton", false );
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "EditButton", false );
|
||
|
SetChildPanelEnabled( m_pItemsContainer, "DeleteButton", false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ShowPublishFileDialog()
|
||
|
{
|
||
|
CTFFilePublishDialog *pPublishDialog = new CTFFilePublishDialog( this, "PublishFileDialog", NULL );
|
||
|
pPublishDialog->AddActionSignalTarget( this );
|
||
|
pPublishDialog->SetDeleteSelfOnClose( true );
|
||
|
pPublishDialog->SetSizeable( false );
|
||
|
MakeModalAndBringToFront( pPublishDialog );
|
||
|
}
|
||
|
|
||
|
void ViewPublishedFile( uint64 nPublishedFileID )
|
||
|
{
|
||
|
EUniverse universe = GetUniverse();
|
||
|
switch ( universe )
|
||
|
{
|
||
|
case k_EUniversePublic:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://steamcommunity.com/sharedfiles/filedetails/?id=%llu", nPublishedFileID ) );
|
||
|
break;
|
||
|
case k_EUniverseBeta:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( "http://beta.steamcommunity.com/sharedfiles/filedetails/?id=%llu", nPublishedFileID ) );
|
||
|
break;
|
||
|
case k_EUniverseDev:
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( CFmtStrMax( COMMUNITY_DEV_HOST "sharedfiles/filedetails/?id=%llu", nPublishedFileID ) );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void EditPublishedFile( uint64 nPublishedFileID )
|
||
|
{
|
||
|
const SteamUGCDetails_t *pDetails = m_publishedFiles.GetPublishedFileDetails( nPublishedFileID );
|
||
|
if ( pDetails )
|
||
|
{
|
||
|
|
||
|
PublishedFileDetails_t fileDetails;
|
||
|
fileDetails.publishedFileDetails = *pDetails;
|
||
|
fileDetails.lpszFilename = pDetails->m_pchFileName;
|
||
|
|
||
|
CTFFilePublishDialog *pPublishDialog = new CTFFilePublishDialog( this, "PublishFileDialog", &fileDetails );
|
||
|
pPublishDialog->AddActionSignalTarget( this );
|
||
|
pPublishDialog->SetDeleteSelfOnClose( true );
|
||
|
pPublishDialog->SetSizeable( false );
|
||
|
MakeModalAndBringToFront( pPublishDialog );
|
||
|
|
||
|
if ( fileDetails.publishedFileDetails.m_eFileType == k_EWorkshopFileTypeMicrotransaction &&
|
||
|
!Q_strstr( fileDetails.publishedFileDetails.m_rgchTags, kImportedTag ) )
|
||
|
{
|
||
|
ShowMessageBox( "#TF_ImportFile_Warning", "#TF_ImportFile_NotCompatible" );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void ConfirmDeletePublishedFile( bool bConfirmed, void *pContext )
|
||
|
{
|
||
|
if ( bConfirmed )
|
||
|
{
|
||
|
CSteamWorkshopDialog *pDialog = static_cast< CSteamWorkshopDialog* >( pContext );
|
||
|
uint64 nPublishedFileID = 0;
|
||
|
for ( uint32 i = 0; i < MAX_ITEMS_VIEWABLE; ++i )
|
||
|
{
|
||
|
if ( pDialog->m_items[i]->GetSelected() )
|
||
|
{
|
||
|
nPublishedFileID = pDialog->m_items[i]->GetPublishedFileID();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( nPublishedFileID != 0 )
|
||
|
{
|
||
|
const SteamUGCDetails_t *pDetails = pDialog->m_publishedFiles.GetPublishedFileDetails( nPublishedFileID );
|
||
|
if ( pDetails )
|
||
|
{
|
||
|
pDialog->m_publishedFiles.DeletePublishedFile( nPublishedFileID );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void DeletePublishedFile( uint64 nPublishedFileID )
|
||
|
{
|
||
|
ShowConfirmDialog( "#TF_SteamWorkshop_DeleteConfirmTitle", "#TF_SteamWorkshop_DeleteConfirmText", "#GameUI_OK", "#GameuI_CancelBold", &ConfirmDeletePublishedFile, this, this );
|
||
|
}
|
||
|
|
||
|
void SetupButton( const char *pPanelName )
|
||
|
{
|
||
|
vgui::Panel *pPanel = m_pContainer->FindChildByName( pPanelName, true );
|
||
|
if ( pPanel )
|
||
|
{
|
||
|
pPanel->AddActionSignalTarget( this );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// called when the Cancel button is pressed
|
||
|
void Close()
|
||
|
{
|
||
|
SetVisible( false );
|
||
|
TFModalStack()->PopModal( this );
|
||
|
MarkForDeletion();
|
||
|
}
|
||
|
|
||
|
vgui::EditablePanel *m_pContainer;
|
||
|
vgui::EditablePanel *m_pItemsContainer;
|
||
|
CPublishedFiles m_publishedFiles;
|
||
|
uint32 m_lastPublishedFilesState;
|
||
|
uint32 m_unCurrentPage;
|
||
|
CSteamWorkshopItemPanel *m_items[MAX_ITEMS_VIEWABLE];
|
||
|
CUGCFileRequestCache m_previewFileCache;
|
||
|
};
|
||
|
static vgui::DHANDLE<CSteamWorkshopDialog> g_pSteamWorkshopDialog;
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Callback to open the game menus
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static void CL_OpenSteamWorkshopDialog( const CCommand &args )
|
||
|
{
|
||
|
if ( g_pSteamWorkshopDialog.Get() == NULL )
|
||
|
{
|
||
|
IViewPortPanel *pMMOverride = ( gViewPortInterface->FindPanelByName( PANEL_MAINMENUOVERRIDE ) );
|
||
|
g_pSteamWorkshopDialog = vgui::SETUP_PANEL( new CSteamWorkshopDialog( (CHudMainMenuOverride*)pMMOverride ) );
|
||
|
}
|
||
|
engine->ExecuteClientCmd( "gameui_activate" );
|
||
|
g_pSteamWorkshopDialog->Show();
|
||
|
}
|
||
|
|
||
|
// the console commands
|
||
|
static ConCommand steamworkshopdialog( "OpenSteamWorkshopDialog", &CL_OpenSteamWorkshopDialog, "" );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
class CItemTestHUDPanel : public CHudElement, public vgui::EditablePanel
|
||
|
{
|
||
|
DECLARE_CLASS_SIMPLE( CItemTestHUDPanel, vgui::EditablePanel );
|
||
|
public:
|
||
|
CItemTestHUDPanel( const char *pElementName )
|
||
|
: CHudElement( pElementName )
|
||
|
, BaseClass( NULL, "ItemTestHUDPanel" )
|
||
|
{
|
||
|
vgui::Panel *pParent = g_pClientMode->GetViewport();
|
||
|
SetParent( pParent );
|
||
|
|
||
|
SetHiddenBits( HIDEHUD_MISCSTATUS );
|
||
|
}
|
||
|
|
||
|
virtual ~CItemTestHUDPanel()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
virtual bool ShouldDraw( void )
|
||
|
{
|
||
|
if ( !CHudElement::ShouldDraw() )
|
||
|
return false;
|
||
|
|
||
|
if ( !engine->IsInGame() )
|
||
|
return false;
|
||
|
|
||
|
if ( TFGameRules() && TFGameRules()->IsInItemTestingMode() )
|
||
|
return true;
|
||
|
|
||
|
return FStrEq( engine->GetLevelName(), "maps/itemtest.bsp" );
|
||
|
}
|
||
|
|
||
|
virtual void PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
if ( m_pBGPanel_Blue && m_pBGPanel_Red && C_TFPlayer::GetLocalTFPlayer() )
|
||
|
{
|
||
|
bool bRed = ( C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() == TF_TEAM_RED );
|
||
|
m_pBGPanel_Blue->SetVisible( !bRed );
|
||
|
m_pBGPanel_Red->SetVisible( bRed );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void ApplySchemeSettings( vgui::IScheme *scheme )
|
||
|
{
|
||
|
if ( g_pFullFileSystem->FileExists( "resource/UI/ItemTestHUDPanel.res" ) )
|
||
|
{
|
||
|
LoadControlSettings( "resource/UI/ItemTestHUDPanel.res" );
|
||
|
}
|
||
|
|
||
|
BaseClass::ApplySchemeSettings( scheme );
|
||
|
|
||
|
m_pBGPanel_Blue = FindChildByName("Background_Blue");
|
||
|
m_pBGPanel_Red = FindChildByName("Background_Red");
|
||
|
|
||
|
if ( m_pBGPanel_Blue )
|
||
|
{
|
||
|
m_pBGPanel_Blue->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
|
||
|
{
|
||
|
if ( !IsVisible() )
|
||
|
return 1; // key not handled
|
||
|
|
||
|
if ( !down )
|
||
|
return 1; // key not handled
|
||
|
|
||
|
switch ( keynum )
|
||
|
{
|
||
|
case KEY_F7:
|
||
|
{
|
||
|
engine->ClientCmd_Unrestricted( "itemtest" );
|
||
|
return 0;
|
||
|
}
|
||
|
break;
|
||
|
case KEY_F8:
|
||
|
{
|
||
|
engine->ClientCmd_Unrestricted( "itemtest_botcontrols" );
|
||
|
return 0;
|
||
|
}
|
||
|
break;
|
||
|
case KEY_F9:
|
||
|
{
|
||
|
InvalidateLayout( true, true );
|
||
|
return 0;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return 1; // key not handled
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
vgui::Panel *m_pBGPanel_Blue;
|
||
|
vgui::Panel *m_pBGPanel_Red;
|
||
|
};
|
||
|
|
||
|
DECLARE_HUDELEMENT( CItemTestHUDPanel );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
// @return true if the item test HUD handled the input, false otherwise
|
||
|
bool ItemTestHandlesKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
|
||
|
{
|
||
|
CItemTestHUDPanel *pItemTestHUDPanel = ( CItemTestHUDPanel * )GET_HUDELEMENT( CItemTestHUDPanel );
|
||
|
if ( pItemTestHUDPanel )
|
||
|
{
|
||
|
return pItemTestHUDPanel->HudElementKeyInput( down, keynum, pszCurrentBinding ) == 0;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|