Team Fortress 2 Source Code as on 22/4/2020
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.

754 lines
25 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include <vgui/ILocalize.h>
  8. #include "vgui_controls/TextEntry.h"
  9. #include "vgui_controls/ComboBox.h"
  10. #include "vgui_controls/CheckButton.h"
  11. #include "testitem_dialog.h"
  12. #include "tf_controls.h"
  13. #include "c_playerresource.h"
  14. #include "gcsdk/gcmsg.h"
  15. #include "tf_gcmessages.h"
  16. #include "econ_item_inventory.h"
  17. #include "econ_gcmessages.h"
  18. #include "ienginevgui.h"
  19. #include "filesystem.h"
  20. #include "vgui_controls/FileOpenDialog.h"
  21. #include "econ_item_system.h"
  22. #include "testitem_root.h"
  23. #include "econ_item_tools.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include <tier0/memdbgon.h>
  26. extern const char *g_TeamVisualSections[TEAM_VISUAL_SECTIONS];
  27. static const char *g_pszTestItemHideBodygroup[] =
  28. {
  29. "hat", // TI_HIDEBG_HAT,
  30. "headphones", // TI_HIDEBG_HEADPHONES,
  31. "medal", // TI_HIDEBG_MEDALS,
  32. "grenades", // TI_HIDEBG_GRENADES,
  33. "bullets", // TI_HIDEBG_BULLETS
  34. "arrows", // TI_HIDEBG_ARROWS
  35. "rightarm", // TI_HIDEBG_RIGHTARM
  36. "shoes_socks", // TI_HIDEBG_SHOES_SOCKS
  37. };
  38. COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszTestItemHideBodygroup ) == TI_HIDEBG_COUNT );
  39. static const char *g_pszClassSubdirectories[] =
  40. {
  41. "all_class", // TF_CLASS_UNDEFINED = 0,
  42. "scout", // TF_CLASS_SCOUT, // TF_FIRST_NORMAL_CLASS
  43. "sniper", // TF_CLASS_SNIPER,
  44. "soldier", // TF_CLASS_SOLDIER,
  45. "demo", // TF_CLASS_DEMOMAN,
  46. "medic", // TF_CLASS_MEDIC,
  47. "heavy", // TF_CLASS_HEAVYWEAPONS,
  48. "pyro", // TF_CLASS_PYRO,
  49. "spy", // TF_CLASS_SPY,
  50. "engineer", // TF_CLASS_ENGINEER,
  51. };
  52. //-----------------------------------------------------------------------------
  53. // Purpose:
  54. //-----------------------------------------------------------------------------
  55. CTestItemDialog::CTestItemDialog( vgui::Panel *parent, testitem_itemtypes_t iItemType, int iClassUsage, KeyValues *pExistingKVs ) : vgui::EditablePanel( parent, "TestItemDialog" )
  56. {
  57. // Need to use the clientscheme (we're not parented to a clientscheme'd panel)
  58. vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
  59. SetScheme(scheme);
  60. SetProportional( true );
  61. ListenForGameEvent( "gameui_hidden" );
  62. m_hImportModelDialog = NULL;
  63. m_pModelLabel = NULL;
  64. m_pSelectModelLabel = NULL;
  65. m_pNoItemsToReplaceLabel = NULL;
  66. m_pSelectModelButton = NULL;
  67. m_pOkButton = NULL;
  68. m_pItemReplacedPanel = new vgui::EditablePanel( this, "ItemReplacedPanel" );
  69. m_pItemReplacedComboBox = new vgui::ComboBox( m_pItemReplacedPanel, "ItemReplacedComboBox", 20, false );
  70. m_pItemReplacedComboBox->AddActionSignalTarget( this );
  71. m_pExistingItemToTestPanel = new vgui::EditablePanel( this, "ExistingItemToTestPanel" );
  72. m_pExistingItemComboBox = new vgui::ComboBox( m_pExistingItemToTestPanel, "ExistingItemComboBox", 20, false );
  73. m_pExistingItemComboBox->AddActionSignalTarget( this );
  74. m_pBodygroupPanel = new vgui::EditablePanel( this, "BodygroupPanel" );
  75. for ( int i = 0; i < TI_HIDEBG_COUNT; i++ )
  76. {
  77. m_pBodygroupCheckButtons[i] = new vgui::CheckButton( m_pBodygroupPanel, VarArgs("HideBodygroupCheckBox%d",i), "" );
  78. m_pBodygroupCheckButtons[i]->AddActionSignalTarget( this );
  79. }
  80. m_pCustomizationsPanel = new vgui::EditablePanel( this, "CustomizationsPanel" );
  81. m_pPaintColorComboBox = new vgui::ComboBox( m_pCustomizationsPanel, "PaintColorComboBox", 20, false );
  82. m_pPaintColorComboBox->AddActionSignalTarget( this );
  83. m_pUnusualEffectComboBox = new vgui::ComboBox( m_pCustomizationsPanel, "UnusualEffectComboBox", 20, false );
  84. m_pUnusualEffectComboBox->AddActionSignalTarget( this );
  85. m_iItemType = iItemType;
  86. m_iClassUsage = iClassUsage;
  87. m_szRelativePath[0] = '\0';
  88. SetDialogVariable("testmodel", g_pVGuiLocalize->Find( "#IT_NoModel" ) );
  89. SetEntryStep( TI_STEP_MODELNAME );
  90. // Load our scheme right away so we have all our pieces ready
  91. MakeReadyForUse();
  92. SetupPaintColorComboBox();
  93. SetupUnusualEffectComboBox();
  94. // Pull the data out of the existing KVs
  95. if ( pExistingKVs )
  96. {
  97. InitializeFromExistingKVs( pExistingKVs );
  98. }
  99. else
  100. {
  101. for ( int i = 0; i < TI_HIDEBG_COUNT; i++ )
  102. {
  103. // Start with the "hat" bodygroup checked (for non-weapons)
  104. bool bIsHat = ( m_iItemType != TI_TYPE_WEAPON ) && ( i == 0 );
  105. m_pBodygroupCheckButtons[i]->SetSelected( bIsHat );
  106. }
  107. }
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Purpose:
  111. //-----------------------------------------------------------------------------
  112. void CTestItemDialog::InitializeFromExistingKVs( KeyValues *pExistingKVs )
  113. {
  114. // If we're testing an existing item, it supercedes everything else
  115. item_definition_index_t iExistingItemDef = pExistingKVs->GetInt( "existing_itemdef", INVALID_ITEM_DEF_INDEX );
  116. if ( iExistingItemDef != INVALID_ITEM_DEF_INDEX )
  117. {
  118. SetupItemComboBox( m_pExistingItemComboBox );
  119. // Loop through the entries until we find the specified item def
  120. for ( int i = 0; i < m_pExistingItemComboBox->GetItemCount(); i++ )
  121. {
  122. int iItemID = m_pExistingItemComboBox->GetItemIDFromRow(i);
  123. KeyValues *pRowKV = m_pExistingItemComboBox->GetItemUserData( iItemID );
  124. if ( pRowKV && pRowKV->GetInt( "item", INVALID_ITEM_DEF_INDEX ) == iExistingItemDef )
  125. {
  126. m_pExistingItemComboBox->SilentActivateItemByRow(i);
  127. SetEntryStep( TI_STEP_FINISHED );
  128. }
  129. }
  130. }
  131. else
  132. {
  133. const char *pszModel = pExistingKVs->GetString( "model_player", NULL );
  134. if ( pszModel && pszModel[0] )
  135. {
  136. Q_strncpy( m_szRelativePath, pszModel, MAX_PATH );
  137. SetDialogVariable("testmodel", m_szRelativePath );
  138. SetEntryStep( TI_STEP_MODELNAME );
  139. SetEntryStep( TI_STEP_WPN_ITEMREPLACED );
  140. if ( m_iItemType == TI_TYPE_WEAPON )
  141. {
  142. item_definition_index_t iItemDefToReplace = pExistingKVs->GetInt( "item_replace", INVALID_ITEM_DEF_INDEX );
  143. if ( iItemDefToReplace != INVALID_ITEM_DEF_INDEX )
  144. {
  145. SetupItemComboBox( m_pItemReplacedComboBox );
  146. // Loop through the entries until we find the specified item def
  147. for ( int i = 0; i < m_pItemReplacedComboBox->GetItemCount(); i++ )
  148. {
  149. int iItemID = m_pItemReplacedComboBox->GetItemIDFromRow(i);
  150. KeyValues *pRowKV = m_pItemReplacedComboBox->GetItemUserData( iItemID );
  151. if ( pRowKV && pRowKV->GetInt( "item", INVALID_ITEM_DEF_INDEX ) == iItemDefToReplace )
  152. {
  153. m_pItemReplacedComboBox->SilentActivateItemByRow(i);
  154. SetEntryStep( TI_STEP_FINISHED );
  155. }
  156. }
  157. }
  158. }
  159. else
  160. {
  161. KeyValues *pkvVisuals = pExistingKVs->FindKey( g_TeamVisualSections[0] );
  162. if ( pkvVisuals )
  163. {
  164. KeyValues *pKVEntry = pkvVisuals->GetFirstSubKey();
  165. while ( pKVEntry )
  166. {
  167. if ( !Q_stricmp( pKVEntry->GetName(), "player_bodygroups" ) )
  168. {
  169. FOR_EACH_SUBKEY( pKVEntry, pKVSubEntry )
  170. {
  171. int iBG = StringFieldToInt( pKVSubEntry->GetName(), g_pszTestItemHideBodygroup, ARRAYSIZE(g_pszTestItemHideBodygroup) );
  172. if ( iBG >= 0 && iBG < TI_HIDEBG_COUNT )
  173. {
  174. m_pBodygroupCheckButtons[iBG]->SetSelected( pKVSubEntry->GetInt() == 0 );
  175. }
  176. }
  177. }
  178. pKVEntry = pKVEntry->GetNextKey();
  179. }
  180. }
  181. // Start with the right paint can selected
  182. int iPaintCanIndex = pExistingKVs->GetInt("paintcan_index", 0);
  183. for ( int i = 0; i < m_pPaintColorComboBox->GetItemCount(); i++ )
  184. {
  185. int iItemID = m_pPaintColorComboBox->GetItemIDFromRow(i);
  186. KeyValues *pRowKV = m_pPaintColorComboBox->GetItemUserData( iItemID );
  187. if ( pRowKV && pRowKV->GetInt("paintcan_index",0) == iPaintCanIndex )
  188. {
  189. m_pPaintColorComboBox->SilentActivateItemByRow(i);
  190. }
  191. }
  192. // Start with the right unusual effect selected
  193. int iUnusualIndex = pExistingKVs->GetInt("unusual_index", 0);
  194. for ( int i = 0; i < m_pUnusualEffectComboBox->GetItemCount(); i++ )
  195. {
  196. int iItemID = m_pUnusualEffectComboBox->GetItemIDFromRow(i);
  197. KeyValues *pRowKV = m_pUnusualEffectComboBox->GetItemUserData( iItemID );
  198. if ( pRowKV && pRowKV->GetInt("unusual_index",0) == iUnusualIndex )
  199. {
  200. m_pUnusualEffectComboBox->SilentActivateItemByRow(i);
  201. }
  202. }
  203. }
  204. }
  205. }
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Purpose:
  209. //-----------------------------------------------------------------------------
  210. CTestItemDialog::~CTestItemDialog( void )
  211. {
  212. }
  213. //-----------------------------------------------------------------------------
  214. // Purpose:
  215. //-----------------------------------------------------------------------------
  216. void CTestItemDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
  217. {
  218. BaseClass::ApplySchemeSettings( pScheme );
  219. LoadControlSettings( "resource/ui/TestItemDialog.res" );
  220. m_pModelLabel = dynamic_cast<CExLabel*>( FindChildByName( "ModelLabel" ) );
  221. m_pSelectModelLabel = dynamic_cast<CExLabel*>( FindChildByName( "SelectModelLabel" ) );
  222. m_pSelectModelButton = dynamic_cast<CExButton*>( FindChildByName( "SelectModelButton" ) );
  223. m_pOkButton = dynamic_cast<CExButton*>( FindChildByName( "OkButton" ) );
  224. m_pNoItemsToReplaceLabel = dynamic_cast<CExLabel*>( m_pItemReplacedPanel->FindChildByName( "NoItemsToReplaceLabel" ) );
  225. SetEntryStep( m_iEntryStep );
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Purpose:
  229. //-----------------------------------------------------------------------------
  230. void CTestItemDialog::PerformLayout( void )
  231. {
  232. BaseClass::PerformLayout();
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Purpose:
  236. //-----------------------------------------------------------------------------
  237. void CTestItemDialog::FireGameEvent( IGameEvent *event )
  238. {
  239. const char *type = event->GetName();
  240. if ( Q_strcmp(type, "gameui_hidden") == 0 )
  241. {
  242. Close();
  243. }
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Purpose:
  247. //-----------------------------------------------------------------------------
  248. void CTestItemDialog::Close( void )
  249. {
  250. TFModalStack()->PopModal( this );
  251. SetVisible( false );
  252. MarkForDeletion();
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Purpose:
  256. //-----------------------------------------------------------------------------
  257. void CTestItemDialog::CloseAndUpdateItem( void )
  258. {
  259. // We're going to assemble a KV block that describes this test item
  260. KeyValues *kv = new KeyValues( "SetTestItemKVs" );
  261. kv->SetInt( "item_type", m_iItemType );
  262. kv->SetString( "model_player", m_szRelativePath );
  263. kv->SetBool( "test_existing_item", false );
  264. kv->SetInt( "attach_to_hands", (m_iItemType == TI_TYPE_WEAPON) );
  265. KeyValues *pKVModels = new KeyValues( "model_player_per_class" );
  266. kv->AddSubKey( pKVModels );
  267. const char *pFilename = V_UnqualifiedFileName( m_szRelativePath );
  268. if ( pFilename)
  269. {
  270. for ( int i = TF_FIRST_NORMAL_CLASS; i < ARRAYSIZE( g_pszClassSubdirectories ); i++ )
  271. {
  272. if ( m_iClassUsage == 1 || ( m_iClassUsage & (1 << i) ) )
  273. {
  274. CFmtStr1024 path( "models/player/items/%s/%s", g_pszClassSubdirectories[i], pFilename );
  275. if ( g_pFullFileSystem->FileExists( path.Access() ) )
  276. {
  277. pKVModels->SetString( ItemSystem()->GetItemSchema()->GetClassUsabilityStrings()[i], path.Access() );
  278. }
  279. }
  280. }
  281. }
  282. KeyValues *pkvVisuals = new KeyValues( g_TeamVisualSections[0] ),
  283. *pkvPlayerBodyGroups = new KeyValues( "player_bodygroups" );
  284. kv->AddSubKey( pkvVisuals );
  285. pkvVisuals->AddSubKey( pkvPlayerBodyGroups );
  286. for ( int i = 0; i < TI_HIDEBG_COUNT; i++ )
  287. {
  288. KeyValues *pKVBG = new KeyValues( g_pszTestItemHideBodygroup[i] );
  289. pKVBG->SetInt( NULL, m_pBodygroupCheckButtons[i]->IsSelected() ? 0 : 1 );
  290. pkvPlayerBodyGroups->AddSubKey( pKVBG );
  291. }
  292. // Extract the paint can index
  293. KeyValues *pPaintComboKV = m_pPaintColorComboBox->GetActiveItemUserData();
  294. int iPaintCanIndex = pPaintComboKV ? pPaintComboKV->GetInt( "paintcan_index", 0 ) : 0;
  295. kv->SetInt( "paintcan_index", iPaintCanIndex );
  296. // Extract the unusual effect index
  297. KeyValues *pUnusualComboKV = m_pUnusualEffectComboBox->GetActiveItemUserData();
  298. int iUnusualIndex = pUnusualComboKV ? pUnusualComboKV->GetInt( "unusual_index", 0 ) : 0;
  299. kv->SetInt( "unusual_index", iUnusualIndex );
  300. item_definition_index_t iItemDef = INVALID_ITEM_DEF_INDEX;
  301. // See if we're copying an existing item
  302. KeyValues *pExistingUserData = m_pExistingItemComboBox->GetActiveItemUserData();
  303. item_definition_index_t iExistingItemDef = pExistingUserData ? pExistingUserData->GetInt( "item", INVALID_ITEM_DEF_INDEX ) : INVALID_ITEM_DEF_INDEX;
  304. if ( iExistingItemDef != INVALID_ITEM_DEF_INDEX )
  305. {
  306. iItemDef = iExistingItemDef;
  307. kv->SetInt( "existing_itemdef", iItemDef );
  308. kv->SetBool( "test_existing_item", true );
  309. // copy model path from existing items
  310. GameItemDefinition_t *pItemDef = ItemSystem()->GetStaticDataForItemByDefIndex( iItemDef );
  311. if ( pItemDef )
  312. {
  313. for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass < TF_LAST_NORMAL_CLASS; iClass++ )
  314. {
  315. if ( m_iClassUsage == 1 || ( m_iClassUsage & (1 << iClass) ) )
  316. {
  317. const char *pszClassString = ItemSystem()->GetItemSchema()->GetClassUsabilityStrings()[iClass];
  318. const char *pszModel = pItemDef->GetPlayerDisplayModel( iClass );
  319. pKVModels->SetString( pszClassString, pszModel );
  320. }
  321. }
  322. }
  323. }
  324. else
  325. {
  326. KeyValues *pUserData = m_pItemReplacedComboBox->GetActiveItemUserData();
  327. iItemDef = pUserData ? pUserData->GetInt( "item", INVALID_ITEM_DEF_INDEX ) : INVALID_ITEM_DEF_INDEX;
  328. // Find the item def we're going to build off
  329. switch ( m_iItemType )
  330. {
  331. case TI_TYPE_WEAPON:
  332. // Need an item def to replace
  333. if ( iItemDef == INVALID_ITEM_DEF_INDEX )
  334. return;
  335. break;
  336. case TI_TYPE_HEADGEAR:
  337. iItemDef = ItemSystem()->GetItemSchema()->GetItemDefinitionByName("Football Helmet")->GetDefinitionIndex();
  338. break;
  339. case TI_TYPE_MISC1:
  340. iItemDef = ItemSystem()->GetItemSchema()->GetItemDefinitionByName("Employee Badge A")->GetDefinitionIndex();
  341. break;
  342. case TI_TYPE_MISC2:
  343. iItemDef = ItemSystem()->GetItemSchema()->GetItemDefinitionByName("High Five Taunt")->GetDefinitionIndex();
  344. break;
  345. }
  346. }
  347. // Tell the server what item we're replacing, and what def index we used
  348. kv->SetInt( "item_replace", iItemDef );
  349. // Send it to the testing root panel
  350. PostMessage( GetParent(), kv );
  351. Close();
  352. }
  353. //-----------------------------------------------------------------------------
  354. // Purpose:
  355. //-----------------------------------------------------------------------------
  356. void CTestItemDialog::OnCommand( const char *command )
  357. {
  358. if ( !Q_stricmp( command, "cancel" ) )
  359. {
  360. Close();
  361. return;
  362. }
  363. else if ( !Q_stricmp( command, "ok" ) )
  364. {
  365. CloseAndUpdateItem();
  366. return;
  367. }
  368. else if ( !Q_stricmp( command, "reloadscheme" ) )
  369. {
  370. InvalidateLayout( false, true );
  371. return;
  372. }
  373. else if ( !Q_stricmp( command, "select_model" ) )
  374. {
  375. OpenSelectModelDialog();
  376. return;
  377. }
  378. BaseClass::OnCommand( command );
  379. }
  380. //-----------------------------------------------------------------------------
  381. // Purpose:
  382. //-----------------------------------------------------------------------------
  383. void CTestItemDialog::OpenSelectModelDialog( void )
  384. {
  385. if (m_hImportModelDialog == NULL)
  386. {
  387. m_hImportModelDialog = new vgui::FileOpenDialog( NULL, "#ToolCustomizeTextureTitle", true );
  388. m_hImportModelDialog->AddFilter( "*.mdl", "#IT_MDL_Files", true );
  389. m_hImportModelDialog->AddActionSignalTarget( this );
  390. }
  391. char szModelsDir[MAX_PATH];
  392. switch( m_iItemType )
  393. {
  394. default:
  395. break;
  396. case TI_TYPE_WEAPON:
  397. m_hImportModelDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( "models/weapons/c_models", "MOD", szModelsDir, sizeof(szModelsDir) ) );
  398. break;
  399. case TI_TYPE_HEADGEAR:
  400. case TI_TYPE_MISC1:
  401. case TI_TYPE_MISC2:
  402. {
  403. const char *pszSubDir = NULL;
  404. // All classes?
  405. if ( m_iClassUsage == 1 )
  406. {
  407. pszSubDir = g_pszClassSubdirectories[0];
  408. }
  409. else
  410. {
  411. // If we only have one class, jump into that directory
  412. for ( int i = TF_FIRST_NORMAL_CLASS; i < LOADOUT_COUNT; i++ )
  413. {
  414. if ( m_iClassUsage & (1 << i) )
  415. {
  416. if ( !pszSubDir )
  417. {
  418. pszSubDir = g_pszClassSubdirectories[i];
  419. }
  420. else
  421. {
  422. // Found multiple classes. Move back up to the base dir.
  423. pszSubDir = NULL;
  424. break;
  425. }
  426. }
  427. }
  428. }
  429. if ( pszSubDir )
  430. {
  431. m_hImportModelDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( VarArgs("models/player/items/%s",pszSubDir), "MOD", szModelsDir, sizeof(szModelsDir) ) );
  432. }
  433. else
  434. {
  435. m_hImportModelDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( "models/player/items", "MOD", szModelsDir, sizeof(szModelsDir) ) );
  436. }
  437. }
  438. break;
  439. }
  440. m_hImportModelDialog->DoModal( false );
  441. m_hImportModelDialog->Activate();
  442. // Base file dialog won't refresh if it's opening to the same directory it was in. Force it to.
  443. PostMessage( m_hImportModelDialog->GetVPanel(), new KeyValues( "PopulateFileList" ) );
  444. }
  445. //-----------------------------------------------------------------------------
  446. // Purpose:
  447. //-----------------------------------------------------------------------------
  448. struct ComboBoxTestItem_t
  449. {
  450. const wchar_t *pwszItemName;
  451. item_definition_index_t itemDef;
  452. };
  453. static int SortComboBoxTestItem( const ComboBoxTestItem_t *a, const ComboBoxTestItem_t *b )
  454. {
  455. return V_wcscmp( a->pwszItemName, b->pwszItemName );
  456. }
  457. void CTestItemDialog::SetupItemComboBox( vgui::ComboBox *pComboBox )
  458. {
  459. pComboBox->RemoveAll();
  460. CUtlVector<item_definition_index_t> vecDefs;
  461. int iReplacements = ((CTestItemRoot*)GetParent())->FindReplaceableItemsForSelectedClass( &vecDefs, m_iItemType == TI_TYPE_WEAPON );
  462. if ( iReplacements )
  463. {
  464. KeyValues *pKeyValues = new KeyValues( "data" );
  465. pKeyValues->SetInt( "item", INVALID_ITEM_DEF_INDEX );
  466. pComboBox->AddItem( "#IT_ItemReplaced_Select", pKeyValues );
  467. CUtlVector< ComboBoxTestItem_t > testItems;
  468. FOR_EACH_VEC( vecDefs, i )
  469. {
  470. CEconItemDefinition *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( vecDefs[i] );
  471. if ( pDef )
  472. {
  473. const wchar_t *pwszLocalizedItemName = g_pVGuiLocalize->Find( pDef->GetItemBaseName() );
  474. if ( pwszLocalizedItemName )
  475. {
  476. int newIndex = testItems.AddToTail();
  477. testItems[newIndex].itemDef = vecDefs[i];
  478. testItems[newIndex].pwszItemName = pwszLocalizedItemName;
  479. }
  480. }
  481. }
  482. if ( testItems.Count() )
  483. {
  484. testItems.Sort( &SortComboBoxTestItem );
  485. FOR_EACH_VEC( testItems, i )
  486. {
  487. pKeyValues = new KeyValues( "data" );
  488. pKeyValues->SetInt( "item", testItems[i].itemDef );
  489. pComboBox->AddItem( testItems[i].pwszItemName, pKeyValues );
  490. }
  491. }
  492. }
  493. // No valid entries?
  494. if ( pComboBox == m_pItemReplacedComboBox )
  495. {
  496. if ( m_pNoItemsToReplaceLabel )
  497. {
  498. m_pNoItemsToReplaceLabel->SetVisible( !iReplacements );
  499. }
  500. m_pItemReplacedPanel->SetVisible( iReplacements );
  501. }
  502. pComboBox->SetItemEnabled( 0, false );
  503. pComboBox->SilentActivateItemByRow( 0 );
  504. pComboBox->GetMenu()->SetBgColor( Color(0,0,0,255) );
  505. }
  506. //-----------------------------------------------------------------------------
  507. // Purpose:
  508. //-----------------------------------------------------------------------------
  509. void CTestItemDialog::SetupPaintColorComboBox( void )
  510. {
  511. m_pPaintColorComboBox->RemoveAll();
  512. KeyValues *pKeyValues = new KeyValues( "data" );
  513. pKeyValues->SetInt( "paintcan_index", 0 );
  514. m_pPaintColorComboBox->AddItem( "#IT_PaintNone", pKeyValues );
  515. // Now loop through all our paints and add them to the list
  516. const CEconItemSchema::SortedItemDefinitionMap_t& mapItemDefs = ItemSystem()->GetItemSchema()->GetSortedItemDefinitionMap();
  517. FOR_EACH_MAP( mapItemDefs, i )
  518. {
  519. const CEconItemDefinition *pDef = mapItemDefs[i];
  520. const CEconTool_PaintCan *pEconToolPaintCan = pDef->GetTypedEconTool<CEconTool_PaintCan>();
  521. if ( !pEconToolPaintCan )
  522. continue;
  523. pKeyValues->SetInt( "paintcan_index", pDef->GetDefinitionIndex() );
  524. m_pPaintColorComboBox->AddItem( g_pVGuiLocalize->Find( pDef->GetItemBaseName() ), pKeyValues );
  525. // Make sure it has valid colors (to skip the store version of the paint can)
  526. KeyValues *pAttribs = pDef->GetDefinitionKey( "attributes" );
  527. if ( !pAttribs )
  528. continue;
  529. KeyValues *pRGBAttrib = pAttribs->FindKey( "set_item_tint_rgb" );
  530. if ( !pRGBAttrib )
  531. continue;
  532. int iModifiedRGB = pRGBAttrib->GetInt( "value", -1 );
  533. if ( iModifiedRGB != -1 )
  534. {
  535. m_pPaintColorComboBox->AddItem( g_pVGuiLocalize->Find( pDef->GetItemBaseName() ), pKeyValues );
  536. }
  537. }
  538. m_pPaintColorComboBox->SilentActivateItemByRow( 0 );
  539. m_pPaintColorComboBox->GetMenu()->SetBgColor( Color(0,0,0,255) );
  540. }
  541. //-----------------------------------------------------------------------------
  542. // Purpose:
  543. //-----------------------------------------------------------------------------
  544. void CTestItemDialog::SetupUnusualEffectComboBox( void )
  545. {
  546. m_pUnusualEffectComboBox->RemoveAll();
  547. KeyValues *pKeyValues = new KeyValues( "data" );
  548. pKeyValues->SetInt( "unusual_index", 0 );
  549. m_pUnusualEffectComboBox->AddItem( "#IT_UnusualNone", pKeyValues );
  550. // Now loop through all unusual effects and add them to the list.
  551. const CEconItemSchema::ParticleDefinitionMap_t& mapParticleDefs = ItemSystem()->GetItemSchema()->GetAttributeControlledParticleSystems();
  552. FOR_EACH_MAP( mapParticleDefs, i )
  553. {
  554. pKeyValues->SetInt( "unusual_index", mapParticleDefs[i].nSystemID );
  555. char particleNameEntry[128];
  556. Q_snprintf( particleNameEntry, ARRAYSIZE( particleNameEntry ), "#Attrib_Particle%i", mapParticleDefs[i].nSystemID );
  557. m_pUnusualEffectComboBox->AddItem( g_pVGuiLocalize->Find( particleNameEntry ), pKeyValues );
  558. }
  559. m_pUnusualEffectComboBox->SilentActivateItemByRow( 0 );
  560. m_pUnusualEffectComboBox->GetMenu()->SetBgColor( Color(0,0,0,255) );
  561. }
  562. //-----------------------------------------------------------------------------
  563. // Purpose:
  564. //-----------------------------------------------------------------------------
  565. void CTestItemDialog::SetEntryStep( testitem_entrysteps_t iStep )
  566. {
  567. // Skip over the item replacement if we're not a weapon
  568. if ( iStep == TI_STEP_WPN_ITEMREPLACED && m_iItemType != TI_TYPE_WEAPON )
  569. {
  570. iStep = (testitem_entrysteps_t)(iStep+1);
  571. }
  572. if ( iStep == TI_STEP_NONWPN_BODYGROUPS || iStep == TI_STEP_OTHER_OPTIONS )
  573. {
  574. // Move to "finished" straight away
  575. iStep = TI_STEP_FINISHED;
  576. }
  577. m_iEntryStep = iStep;
  578. if ( m_pSelectModelButton )
  579. {
  580. m_pSelectModelButton->SetVisible( iStep >= TI_STEP_MODELNAME );
  581. m_pSelectModelLabel->SetVisible( iStep >= TI_STEP_MODELNAME );
  582. m_pModelLabel->SetVisible( iStep >= TI_STEP_MODELNAME );
  583. }
  584. bool bTestingExistingItem = (iStep > TI_STEP_MODELNAME && m_szRelativePath[0] == '\0');
  585. m_pBodygroupPanel->SetVisible( iStep >= TI_STEP_NONWPN_BODYGROUPS && m_iItemType != TI_TYPE_WEAPON && !bTestingExistingItem );
  586. m_pExistingItemToTestPanel->SetVisible( iStep == TI_STEP_MODELNAME || bTestingExistingItem );
  587. m_pItemReplacedPanel->SetVisible( iStep >= TI_STEP_WPN_ITEMREPLACED && m_iItemType == TI_TYPE_WEAPON && !bTestingExistingItem );
  588. if ( m_pNoItemsToReplaceLabel )
  589. {
  590. m_pNoItemsToReplaceLabel->SetVisible( false );
  591. }
  592. m_pCustomizationsPanel->SetVisible( (iStep >= TI_STEP_CUSTOMIZATION && m_iItemType != TI_TYPE_WEAPON) );
  593. if ( m_pOkButton )
  594. {
  595. m_pOkButton->SetEnabled( m_iEntryStep >= TI_STEP_FINISHED );
  596. }
  597. switch ( m_iEntryStep )
  598. {
  599. case TI_STEP_MODELNAME:
  600. if ( !m_szRelativePath[0] )
  601. {
  602. SetDialogVariable("testmodel", g_pVGuiLocalize->Find( "#IT_NoModel" ) );
  603. }
  604. SetupItemComboBox( m_pExistingItemComboBox );
  605. break;
  606. case TI_STEP_WPN_ITEMREPLACED:
  607. SetupItemComboBox( m_pItemReplacedComboBox );
  608. break;
  609. case TI_STEP_NONWPN_BODYGROUPS:
  610. break;
  611. default:
  612. case TI_STEP_FINISHED:
  613. break;
  614. }
  615. SetDialogVariable( "testtitle", g_pVGuiLocalize->Find( VarArgs("#IT_Title_%d",m_iItemType) ) );
  616. }
  617. //-----------------------------------------------------------------------------
  618. // Purpose:
  619. //-----------------------------------------------------------------------------
  620. void CTestItemDialog::OnTextChanged( KeyValues *data )
  621. {
  622. Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
  623. if ( pPanel == m_pExistingItemComboBox )
  624. {
  625. if ( m_iItemType != TI_TYPE_WEAPON )
  626. {
  627. SetEntryStep( TI_STEP_OTHER_OPTIONS );
  628. }
  629. else
  630. {
  631. SetEntryStep( TI_STEP_FINISHED );
  632. }
  633. }
  634. else if ( pPanel == m_pItemReplacedComboBox )
  635. {
  636. SetEntryStep( TI_STEP_FINISHED );
  637. }
  638. }
  639. //-----------------------------------------------------------------------------
  640. // Purpose:
  641. //-----------------------------------------------------------------------------
  642. void CTestItemDialog::OnFileSelected(const char *fullpath)
  643. {
  644. m_szRelativePath[0] = '\0';
  645. if ( g_pFullFileSystem->FullPathToRelativePathEx( fullpath, "GAME", m_szRelativePath, sizeof(m_szRelativePath) ) )
  646. {
  647. Q_FixSlashes( m_szRelativePath, '/' );
  648. SetDialogVariable("testmodel", m_szRelativePath );
  649. SetEntryStep( TI_STEP_WPN_ITEMREPLACED );
  650. }
  651. else
  652. {
  653. SetDialogVariable("testmodel", g_pVGuiLocalize->Find( "#IT_NoModel" ) );
  654. }
  655. // Nuke the file open dialog
  656. m_hImportModelDialog->MarkForDeletion();
  657. m_hImportModelDialog = NULL;
  658. }