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.

1742 lines
54 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "matsys_controls/mdlpicker.h"
  7. #include "tier1/KeyValues.h"
  8. #include "tier1/utldict.h"
  9. #include "filesystem.h"
  10. #include "studio.h"
  11. #include "matsys_controls/matsyscontrols.h"
  12. #include "matsys_controls/mdlpanel.h"
  13. #include "vgui_controls/Splitter.h"
  14. #include "vgui_controls/ComboBox.h"
  15. #include "vgui_controls/Button.h"
  16. #include "vgui_controls/PropertySheet.h"
  17. #include "vgui_controls/MessageBox.h"
  18. #include "vgui_controls/PropertyPage.h"
  19. #include "vgui_controls/CheckButton.h"
  20. #include "vgui_controls/DirectorySelectDialog.h"
  21. #include "vgui/IVGui.h"
  22. #include "vgui/IInput.h"
  23. #include "vgui/ISurface.h"
  24. #include "vgui/Cursor.h"
  25. #include "matsys_controls/assetpicker.h"
  26. #include "matsys_controls/colorpickerpanel.h"
  27. #include "dmxloader/dmxloader.h"
  28. #include "tier1/utlbuffer.h"
  29. #include "bitmap/tgawriter.h"
  30. #include "tier3/tier3.h"
  31. #include "istudiorender.h"
  32. #include "../vgui2/src/VPanel.h"
  33. #include "tier2/p4helpers.h"
  34. #include "ivtex.h"
  35. #include "bitmap/tgaloader.h"
  36. // memdbgon must be the last include file in a .cpp file!!!
  37. #include "tier0/memdbgon.h"
  38. using namespace vgui;
  39. static bool SaveTgaAndAddToP4( unsigned char *pImage, ImageFormat imageFormat, int Width, int Height, const char *szDestFilename )
  40. {
  41. // allocate a buffer to write the tga into
  42. int iMaxTGASize = 1024 + (Width * Height * 4);
  43. void *pTGA = malloc( iMaxTGASize );
  44. CUtlBuffer buffer( pTGA, iMaxTGASize );
  45. if( !TGAWriter::WriteToBuffer( pImage, buffer, Width, Height, imageFormat, IMAGE_FORMAT_BGRA8888 ) )
  46. {
  47. Error( "Couldn't write bitmap data snapshot.\n" );
  48. return false;
  49. }
  50. CP4AutoEditAddFile autop4( szDestFilename );
  51. // async write to disk (this will take ownership of the memory)
  52. char szDirName[ _MAX_PATH ];
  53. strcpy( szDirName, szDestFilename );
  54. V_StripFilename( szDirName );
  55. g_pFullFileSystem->CreateDirHierarchy( szDirName, "" );
  56. g_pFullFileSystem->AsyncWrite( szDestFilename, buffer.Base(), buffer.TellPut(), true );
  57. return true;
  58. }
  59. //-----------------------------------------------------------------------------
  60. //
  61. // MDL Picker
  62. //
  63. //-----------------------------------------------------------------------------
  64. //-----------------------------------------------------------------------------
  65. // Sort by MDL name
  66. //-----------------------------------------------------------------------------
  67. static int __cdecl MDLBrowserSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
  68. {
  69. const char *string1 = item1.kv->GetString("mdl");
  70. const char *string2 = item2.kv->GetString("mdl");
  71. return stricmp( string1, string2 );
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Purpose: Constructor
  75. //-----------------------------------------------------------------------------
  76. CMDLPicker::CMDLPicker( vgui::Panel *pParent, int nFlags ) :
  77. BaseClass( pParent, "MDL Files", "mdl", "models", "mdlName" )
  78. {
  79. for( int i = 0; i < MAX_SELECTED_MODELS; i++ )
  80. {
  81. m_hSelectedMDL[ i ] = MDLHANDLE_INVALID;
  82. }
  83. m_nFlags = nFlags; // remember what we show and what not
  84. m_pRenderPage = NULL;
  85. m_pSequencesPage = NULL;
  86. m_pActivitiesPage = NULL;
  87. m_pSkinsPage = NULL;
  88. m_pInfoPage = NULL;
  89. m_pScreenCapsPage = NULL;
  90. m_pSequencesList = NULL;
  91. m_pActivitiesList = NULL;
  92. m_hDirectorySelectDialog = NULL;
  93. // Horizontal splitter for mdls
  94. m_pFileBrowserSplitter = new Splitter( this, "FileBrowserSplitter", SPLITTER_MODE_VERTICAL, 1 );
  95. float flFractions[] = { 0.33f, 0.67f };
  96. m_pFileBrowserSplitter->RespaceSplitters( flFractions );
  97. vgui::Panel *pSplitterLeftSide = m_pFileBrowserSplitter->GetChild( 0 );
  98. vgui::Panel *pSplitterRightSide = m_pFileBrowserSplitter->GetChild( 1 );
  99. // Standard browser controls
  100. pSplitterLeftSide->RequestFocus();
  101. CreateStandardControls( pSplitterLeftSide, false );
  102. // property sheet - revisions, changes, etc.
  103. m_pPreviewSplitter = new Splitter( pSplitterRightSide, "PreviewSplitter", SPLITTER_MODE_HORIZONTAL, 1 );
  104. vgui::Panel *pSplitterTopSide = m_pPreviewSplitter->GetChild( 0 );
  105. vgui::Panel *pSplitterBottomSide = m_pPreviewSplitter->GetChild( 1 );
  106. // MDL preview
  107. m_pMDLPreview = new CMDLPanel( pSplitterTopSide, "MDLPreview" );
  108. SetSkipChildDuringPainting( m_pMDLPreview );
  109. m_pViewsSheet = new vgui::PropertySheet( pSplitterBottomSide, "ViewsSheet" );
  110. m_pViewsSheet->AddActionSignalTarget( this );
  111. // now add wanted features
  112. if ( nFlags & PAGE_RENDER )
  113. {
  114. m_pRenderPage = new vgui::PropertyPage( m_pViewsSheet, "RenderPage" );
  115. m_pRenderPage->AddActionSignalTarget( this );
  116. m_pRenderPage->LoadControlSettingsAndUserConfig( "resource/mdlpickerrender.res" );
  117. RefreshRenderSettings();
  118. // ground
  119. Button *pSelectProbe = (Button*)m_pRenderPage->FindChildByName( "ChooseLightProbe" );
  120. pSelectProbe->AddActionSignalTarget( this );
  121. }
  122. if ( nFlags & PAGE_SEQUENCES )
  123. {
  124. m_pSequencesPage = new vgui::PropertyPage( m_pViewsSheet, "SequencesPage" );
  125. m_pSequencesList = new vgui::ListPanel( m_pSequencesPage, "SequencesList" );
  126. m_pSequencesList->AddColumnHeader( 0, "sequence", "sequence", 52, 0 );
  127. m_pSequencesList->AddActionSignalTarget( this );
  128. m_pSequencesList->SetSelectIndividualCells( true );
  129. m_pSequencesList->SetEmptyListText("No .MDL file currently selected.");
  130. m_pSequencesList->SetDragEnabled( true );
  131. m_pSequencesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 6, 6, -6, -6 );
  132. }
  133. if ( nFlags & PAGE_ACTIVITIES )
  134. {
  135. m_pActivitiesPage = new vgui::PropertyPage( m_pViewsSheet, "ActivitiesPage" );
  136. m_pActivitiesList = new vgui::ListPanel( m_pActivitiesPage, "ActivitiesList" );
  137. m_pActivitiesList->AddColumnHeader( 0, "activity", "activity", 52, 0 );
  138. m_pActivitiesList->AddActionSignalTarget( this );
  139. m_pActivitiesList->SetSelectIndividualCells( true );
  140. m_pActivitiesList->SetEmptyListText( "No .MDL file currently selected." );
  141. m_pActivitiesList->SetDragEnabled( true );
  142. m_pActivitiesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 6, 6, -6, -6 );
  143. }
  144. if ( nFlags & PAGE_SKINS )
  145. {
  146. m_pSkinsPage = new vgui::PropertyPage( m_pViewsSheet, "SkinsPage" );
  147. m_pSkinsList = new vgui::ListPanel( m_pSkinsPage, "SkinsList" );
  148. m_pSkinsList->AddColumnHeader( 0, "skin", "skin", 52, 0 );
  149. m_pSkinsList->AddActionSignalTarget( this );
  150. m_pSkinsList->SetSelectIndividualCells( true );
  151. m_pSkinsList->SetEmptyListText( "No .MDL file currently selected." );
  152. m_pSkinsList->SetDragEnabled( true );
  153. m_pSkinsList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 6, 6, -6, -6 );
  154. }
  155. if ( nFlags & PAGE_INFO )
  156. {
  157. m_pInfoPage = new vgui::PropertyPage( m_pViewsSheet, "InfoPage" );
  158. m_pInfoPage->AddActionSignalTarget( this );
  159. m_pInfoPage->LoadControlSettingsAndUserConfig( "resource/mdlpickerinfo.res" );
  160. CheckButton * pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName( "PhysicsObject" );
  161. pTempCheck->SetDisabledFgColor1( pTempCheck->GetFgColor());
  162. pTempCheck->SetDisabledFgColor2( pTempCheck->GetFgColor());
  163. pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName( "StaticObject" );
  164. pTempCheck->SetDisabledFgColor1( pTempCheck->GetFgColor());
  165. pTempCheck->SetDisabledFgColor2( pTempCheck->GetFgColor());
  166. pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName( "DynamicObject" );
  167. pTempCheck->SetDisabledFgColor1( pTempCheck->GetFgColor());
  168. pTempCheck->SetDisabledFgColor2( pTempCheck->GetFgColor());
  169. m_pPropDataList = new vgui::ListPanel( m_pInfoPage, "PropData" );
  170. m_pPropDataList->AddColumnHeader( 0, "key", "key", 250, ListPanel::COLUMN_FIXEDSIZE );
  171. m_pPropDataList->AddColumnHeader( 1, "value", "value", 52, 0 );
  172. m_pPropDataList->AddActionSignalTarget( this );
  173. m_pPropDataList->SetSelectIndividualCells( false );
  174. m_pPropDataList->SetEmptyListText( "No prop_data available." );
  175. m_pPropDataList->SetDragEnabled( true );
  176. m_pPropDataList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 6, 72, -6, -6 );
  177. RefreshRenderSettings();
  178. }
  179. if ( nFlags & PAGE_SCREEN_CAPS )
  180. {
  181. m_pScreenCapsPage = new vgui::PropertyPage( m_pViewsSheet, "ScreenCapsPage" );
  182. // not sure why we have to do this for the color picker
  183. CColorPickerButton *m_pBackgroundColor;
  184. m_pBackgroundColor = new CColorPickerButton( m_pScreenCapsPage, "BackgroundColor", this );
  185. m_pScreenCapsPage->LoadControlSettingsAndUserConfig( "resource/mdlpickerscreencaps.res" );
  186. TextEntry *pTempValue;
  187. pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "WidthText" );
  188. pTempValue->SetText( "256" );
  189. pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "HeightText" );
  190. pTempValue->SetText( "256" );
  191. // not sure why this doesn't work
  192. // m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
  193. m_pBackgroundColor->SetColor( 255, 0, 0, 255 );
  194. Label *m_pOutputDirectory;
  195. m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
  196. m_pOutputDirectory->SetText( "c:\\" );
  197. Button *pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "Capture" );
  198. pSelectProbe->AddActionSignalTarget( this );
  199. pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "OutputDirectorySelect" );
  200. pSelectProbe->AddActionSignalTarget( this );
  201. pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "SaveCaps" );
  202. pSelectProbe->AddActionSignalTarget( this );
  203. pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "RestoreCaps" );
  204. pSelectProbe->AddActionSignalTarget( this );
  205. pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "GenerateBackpackIcons" );
  206. pSelectProbe->AddActionSignalTarget( this );
  207. }
  208. // Load layout settings; has to happen before pinning occurs in code
  209. LoadControlSettingsAndUserConfig( "resource/mdlpicker.res" );
  210. // Pages must be added after control settings are set up
  211. if ( m_pRenderPage )
  212. {
  213. m_pViewsSheet->AddPage( m_pRenderPage, "Render" );
  214. }
  215. if ( m_pSequencesPage )
  216. {
  217. m_pViewsSheet->AddPage( m_pSequencesPage, "Sequences" );
  218. }
  219. if ( m_pActivitiesPage )
  220. {
  221. m_pViewsSheet->AddPage( m_pActivitiesPage, "Activities" );
  222. }
  223. if ( m_pSkinsPage )
  224. {
  225. m_pViewsSheet->AddPage( m_pSkinsPage, "Skins" );
  226. }
  227. if ( m_pInfoPage )
  228. {
  229. m_pViewsSheet->AddPage( m_pInfoPage, "Info" );
  230. }
  231. if ( m_pScreenCapsPage )
  232. {
  233. m_pViewsSheet->AddPage( m_pScreenCapsPage, "Screen Caps" );
  234. }
  235. }
  236. void CMDLPicker::RefreshRenderSettings()
  237. {
  238. vgui::CheckButton *pToggle;
  239. if ( !m_pRenderPage )
  240. return;
  241. // ground
  242. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("NoGround");
  243. pToggle->AddActionSignalTarget( this );
  244. m_pMDLPreview->SetGroundGrid( !pToggle->IsSelected() );
  245. // collision
  246. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("Collision");
  247. pToggle->AddActionSignalTarget( this );
  248. m_pMDLPreview->SetCollsionModel( pToggle->IsSelected() );
  249. // wireframe
  250. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("Wireframe");
  251. pToggle->AddActionSignalTarget( this );
  252. m_pMDLPreview->SetWireFrame( pToggle->IsSelected() );
  253. // lockview
  254. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("LockView");
  255. pToggle->AddActionSignalTarget( this );
  256. m_pMDLPreview->SetLockView( pToggle->IsSelected() );
  257. // look at camera
  258. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("LookAtCamera");
  259. pToggle->AddActionSignalTarget( this );
  260. m_pMDLPreview->SetLookAtCamera( pToggle->IsSelected() );
  261. // thumbnail safe zone
  262. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("ThumbnailSafeZone");
  263. pToggle->AddActionSignalTarget( this );
  264. m_pMDLPreview->SetThumbnailSafeZone( pToggle->IsSelected() );
  265. }
  266. //-----------------------------------------------------------------------------
  267. // Purpose: Destructor
  268. //-----------------------------------------------------------------------------
  269. CMDLPicker::~CMDLPicker()
  270. {
  271. }
  272. //-----------------------------------------------------------------------------
  273. // Performs layout
  274. //-----------------------------------------------------------------------------
  275. void CMDLPicker::PerformLayout()
  276. {
  277. // NOTE: This call should cause auto-resize to occur
  278. // which should fix up the width of the panels
  279. BaseClass::PerformLayout();
  280. int w, h;
  281. GetSize( w, h );
  282. // Layout the mdl splitter
  283. m_pFileBrowserSplitter->SetBounds( 0, 0, w, h );
  284. }
  285. //-----------------------------------------------------------------------------
  286. // Buttons on various pages
  287. //-----------------------------------------------------------------------------
  288. void CMDLPicker::OnAssetSelected( KeyValues *pParams )
  289. {
  290. const char *pAsset = pParams->GetString( "asset" );
  291. char pProbeBuf[MAX_PATH];
  292. Q_snprintf( pProbeBuf, sizeof(pProbeBuf), "materials/lightprobes/%s", pAsset );
  293. BeginDMXContext();
  294. CDmxElement *pLightProbe = NULL;
  295. bool bOk = UnserializeDMX( pProbeBuf, "GAME", true, &pLightProbe );
  296. if ( !pLightProbe || !bOk )
  297. {
  298. char pBuf[1024];
  299. Q_snprintf( pBuf, sizeof(pBuf), "Error loading lightprobe file '%s'!\n", pProbeBuf );
  300. vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Error Loading File!\n", pBuf, GetParent() );
  301. pMessageBox->DoModal( );
  302. EndDMXContext( true );
  303. return;
  304. }
  305. m_pMDLPreview->SetLightProbe( pLightProbe );
  306. EndDMXContext( true );
  307. }
  308. //-----------------------------------------------------------------------------
  309. // Buttons on various pages
  310. //-----------------------------------------------------------------------------
  311. void CMDLPicker::OnCommand( const char *pCommand )
  312. {
  313. if ( !Q_stricmp( pCommand, "ChooseLightProbe" ) )
  314. {
  315. CAssetPickerFrame *pPicker = new CAssetPickerFrame( this, "Select Light Probe (.prb) File",
  316. "Light Probe", "prb", "materials/lightprobes", "lightprobe" );
  317. pPicker->DoModal();
  318. return;
  319. }
  320. else if ( !Q_stricmp( pCommand, "OutputDirectorySelect" ) )
  321. {
  322. if ( !m_hDirectorySelectDialog.Get() )
  323. {
  324. m_hDirectorySelectDialog = new DirectorySelectDialog( this, "Choose Screen Caps output folder" );
  325. }
  326. Label *m_pOutputDirectory;
  327. char temp[ MAX_PATH ];
  328. m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
  329. m_pOutputDirectory->GetText( temp, sizeof( temp ) );
  330. m_hDirectorySelectDialog->MakeReadyForUse();
  331. m_hDirectorySelectDialog->SetStartDirectory( temp );
  332. m_hDirectorySelectDialog->DoModal();
  333. return;
  334. }
  335. else if ( !Q_stricmp( pCommand, "Capture" ) )
  336. {
  337. CaptureScreenCaps();
  338. return;
  339. }
  340. else if ( !Q_stricmp( pCommand, "GenerateBackpackIcons" ) )
  341. {
  342. // shut off the ground grid
  343. vgui::CheckButton *pGroundToggle = (vgui::CheckButton *)m_pRenderPage->FindChildByName( "NoGround" );
  344. bool bOriginalGridState = pGroundToggle->IsSelected();
  345. vgui::CheckButton *pSafeZoneToggle = (vgui::CheckButton *)m_pRenderPage->FindChildByName( "ThumbnailSafeZone" );
  346. bool bOriginalSafeZoneState = pSafeZoneToggle->IsSelected();
  347. m_pMDLPreview->SetGroundGrid( false );
  348. m_pMDLPreview->SetThumbnailSafeZone( false );
  349. // make the icons
  350. GenerateBackpackIcons();
  351. // return the ground grid to its original state
  352. m_pMDLPreview->SetGroundGrid( !bOriginalGridState );
  353. m_pMDLPreview->SetThumbnailSafeZone( bOriginalSafeZoneState );
  354. return;
  355. }
  356. else if ( !Q_stricmp( pCommand, "SaveCaps" ) )
  357. {
  358. SaveCaps( NULL );
  359. return;
  360. }
  361. else if ( !Q_stricmp( pCommand, "RestoreCaps" ) )
  362. {
  363. if ( input()->IsKeyDown( KEY_RCONTROL ) || input()->IsKeyDown( KEY_LCONTROL ) )
  364. {
  365. int nCount = m_AssetList.Count();
  366. for ( int i = 0; i < nCount; ++i )
  367. {
  368. if ( m_pAssetBrowser->IsItemVisible( m_AssetList[ i ].m_nItemId ) &&
  369. m_pAssetBrowser->IsItemSelected( m_AssetList[ i ].m_nItemId ) )
  370. {
  371. KeyValues *pItemKeyValues = m_pAssetBrowser->GetItem( m_AssetList[ i ].m_nItemId );
  372. const char *pSelectedAsset = pItemKeyValues->GetString( "asset" );
  373. char szBathPath[ _MAX_PATH ];
  374. Label *m_pOutputDirectory;
  375. m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
  376. m_pOutputDirectory->GetText( szBathPath, sizeof( szBathPath ) );
  377. char szPathedFileName[ _MAX_PATH ];
  378. sprintf( szPathedFileName, "%s%s", szBathPath, pSelectedAsset );
  379. Label *m_pResults = ( Label * )m_pScreenCapsPage->FindChildByName( "CaptureResults" );
  380. if ( RestoreCaps( szPathedFileName ) )
  381. {
  382. m_pResults->SetText( "Prefs Restored" );
  383. }
  384. else
  385. {
  386. m_pResults->SetText( "Prefs NOT FOUND" );
  387. }
  388. break;
  389. }
  390. }
  391. }
  392. else
  393. {
  394. RestoreCaps( NULL );
  395. }
  396. return;
  397. }
  398. BaseClass::OnCommand( pCommand );
  399. }
  400. //-----------------------------------------------------------------------------
  401. // Handles the directory selection for screen caps
  402. //-----------------------------------------------------------------------------
  403. void CMDLPicker::OnDirectorySelected( char const *dir )
  404. {
  405. if ( m_hDirectorySelectDialog != 0 )
  406. {
  407. m_hDirectorySelectDialog->MarkForDeletion();
  408. }
  409. Label *m_pOutputDirectory;
  410. m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
  411. m_pOutputDirectory->SetText( dir );
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Screen captures the specific model and writes out a .tga. Assumes the MDLPreview
  415. // panel has been properly adjusted to 0,0 in screen space and that width / height
  416. // have been set.
  417. //-----------------------------------------------------------------------------
  418. const char *CMDLPicker::CaptureModel( int nModIndex, const char *AssetName, const char *OutputPath, int Width, int Height, Color BackgroundColor, bool bSelectedOnly )
  419. {
  420. char pBuf[ MAX_PATH ];
  421. Q_snprintf( pBuf, sizeof( pBuf ), "%s\\%s\\%s", GetModPath( nModIndex ), m_pAssetSubDir, AssetName );
  422. Q_FixSlashes( pBuf );
  423. if ( !bSelectedOnly )
  424. {
  425. SelectMDL( pBuf, false, -1 );
  426. }
  427. CMatRenderContextPtr pRenderContext( materials );
  428. g_pMaterialSystem->BeginFrame( 0 );
  429. g_pStudioRender->BeginFrame();
  430. // pRenderContext->ClearColor4ub( 0, 0, 0, 0 );
  431. // pRenderContext->ClearBuffers( true, true );
  432. Color NewPanelColor;
  433. NewPanelColor.SetColor( 0, 0, 0, 0 );
  434. m_pMDLPreview->SetBackgroundColor( NewPanelColor );
  435. g_pVGuiSurface->PaintTraverseEx( m_pMDLPreview->GetVPanel(), false );
  436. g_pStudioRender->EndFrame();
  437. g_pMaterialSystem->EndFrame( );
  438. // get the data from the backbuffer and save to disk
  439. // bitmap bits
  440. unsigned char *pImageBlack = ( unsigned char * )malloc( Width * 4 * Height );
  441. // Get Bits from the material system
  442. pRenderContext->ReadPixels( 0, 0, Width, Height, pImageBlack, IMAGE_FORMAT_BGRA8888 );
  443. g_pMaterialSystem->BeginFrame( 0 );
  444. g_pStudioRender->BeginFrame();
  445. // pRenderContext->ClearColor4ub( 255, 255, 255, 0 );
  446. // pRenderContext->ClearBuffers( true, true );
  447. NewPanelColor.SetColor( 255, 255, 255, 0 );
  448. m_pMDLPreview->SetBackgroundColor( NewPanelColor );
  449. g_pVGuiSurface->PaintTraverseEx( m_pMDLPreview->GetVPanel(), false );
  450. g_pStudioRender->EndFrame();
  451. g_pMaterialSystem->EndFrame( );
  452. // get the data from the backbuffer and save to disk
  453. // bitmap bits
  454. unsigned char *pImageWhite = ( unsigned char * )malloc( Width * 4 * Height );
  455. // Get Bits from the material system
  456. pRenderContext->ReadPixels( 0, 0, Width, Height, pImageWhite, IMAGE_FORMAT_BGRA8888 );
  457. unsigned char *pBlackPos = pImageBlack;
  458. unsigned char *pWhitePos = pImageWhite;
  459. for( int y = 0; y < Height; y++ )
  460. {
  461. for( int x = 0; x < Width; x++, pBlackPos += 4, pWhitePos += 4 )
  462. {
  463. if ( ( *( pBlackPos + 0 ) ) != ( *( pWhitePos + 0 ) ) || // blue
  464. ( *( pBlackPos + 1 ) ) != ( *( pWhitePos + 1 ) ) || // green
  465. ( *( pBlackPos + 2 ) ) != ( *( pWhitePos + 2 ) ) ) // red
  466. {
  467. unsigned char nBlueDiff = ( *( pBlackPos + 0 ) );
  468. unsigned char nGreenDiff = ( *( pBlackPos + 1 ) );
  469. unsigned char nRedDiff = ( *( pBlackPos + 2 ) );
  470. unsigned char nMax = nBlueDiff;
  471. if ( nGreenDiff > nMax )
  472. {
  473. nMax = nGreenDiff;
  474. }
  475. if ( nRedDiff > nMax )
  476. {
  477. nMax = nRedDiff;
  478. }
  479. *( pBlackPos + 3 ) = nMax;
  480. }
  481. else
  482. {
  483. *( pBlackPos + 3 ) = 0xff;
  484. }
  485. }
  486. }
  487. static char szPathedFileName[ _MAX_PATH ];
  488. sprintf( szPathedFileName, "%s%s", OutputPath, AssetName );
  489. V_SetExtension( szPathedFileName, ".tga", sizeof( szPathedFileName ) );
  490. bool bResult = SaveTgaAndAddToP4( pImageBlack, IMAGE_FORMAT_BGRA8888, Width, Height, szPathedFileName );
  491. free( pImageBlack );
  492. free( pImageWhite );
  493. if ( !bResult) return NULL;
  494. if ( bSelectedOnly )
  495. {
  496. SaveCaps( szPathedFileName );
  497. }
  498. return szPathedFileName;
  499. }
  500. //-----------------------------------------------------------------------------
  501. // Will go through the asset browser and capture each visible item.
  502. //-----------------------------------------------------------------------------
  503. void CMDLPicker::CaptureScreenCaps( void )
  504. {
  505. char temp[ 256 ];
  506. TextEntry *pTempValue;
  507. int width;
  508. int height;
  509. char szBathPath[ _MAX_PATH ];
  510. Label *m_pOutputDirectory;
  511. m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
  512. m_pOutputDirectory->GetText( szBathPath, sizeof( szBathPath ) );
  513. pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "WidthText" );
  514. pTempValue->GetText( temp, sizeof( temp ) );
  515. width = atoi( temp );
  516. pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "HeightText" );
  517. pTempValue->GetText( temp, sizeof( temp ) );
  518. height = atoi( temp );
  519. int PanelX, PanelY, PanelWidth, PanelHeight;
  520. Color PanelColor;
  521. Panel *pParent = m_pMDLPreview->GetParent();
  522. m_pMDLPreview->GetPos( PanelX, PanelY );
  523. m_pMDLPreview->GetSize( PanelWidth, PanelHeight );
  524. PanelColor = m_pMDLPreview->GetBackgroundColor();
  525. m_pMDLPreview->SetParent( ( vgui::Panel * )NULL );
  526. m_pMDLPreview->SetPos( 0, 0 );
  527. m_pMDLPreview->SetSize( width, height );
  528. CColorPickerButton *m_pBackgroundColor;
  529. m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
  530. Color NewPanelColor = m_pBackgroundColor->GetColor();
  531. NewPanelColor[3] = 0;
  532. m_pMDLPreview->SetBackgroundColor( NewPanelColor );
  533. ((VPanel *)m_pMDLPreview->GetVPanel())->Solve();
  534. bool bSelectedOnly = false;
  535. if ( input()->IsKeyDown( KEY_RCONTROL ) || input()->IsKeyDown( KEY_LCONTROL ) )
  536. {
  537. bSelectedOnly = true;
  538. }
  539. int nCount = m_AssetList.Count();
  540. int nNumItems = 0;
  541. for ( int i = 0; i < nCount; ++i )
  542. {
  543. if ( m_pAssetBrowser->IsItemVisible( m_AssetList[ i ].m_nItemId ) &&
  544. ( !bSelectedOnly || m_pAssetBrowser->IsItemSelected( m_AssetList[ i ].m_nItemId ) ) )
  545. {
  546. KeyValues *pItemKeyValues = m_pAssetBrowser->GetItem( m_AssetList[ i ].m_nItemId );
  547. const char *pSelectedAsset = pItemKeyValues->GetString( "asset" );
  548. int nModIndex = pItemKeyValues->GetInt( "modIndex" );
  549. CaptureModel( nModIndex, pSelectedAsset, szBathPath, width, height, NewPanelColor, bSelectedOnly );
  550. nNumItems++;
  551. }
  552. }
  553. m_pMDLPreview->SetParent( pParent );
  554. m_pMDLPreview->SetPos( PanelX, PanelY );
  555. m_pMDLPreview->SetSize( PanelWidth, PanelHeight );
  556. m_pMDLPreview->SetBackgroundColor( PanelColor );
  557. ((VPanel *)m_pMDLPreview->GetVPanel())->Solve();
  558. Label *m_pResults;
  559. sprintf( temp, "Captured %d items", nNumItems );
  560. m_pResults = ( Label * )m_pScreenCapsPage->FindChildByName( "CaptureResults" );
  561. m_pResults->SetText( temp );
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Stub for XBox360 compiles
  565. //-----------------------------------------------------------------------------
  566. #if defined( _X360 )
  567. const char *getenv( const char *varname )
  568. {
  569. return NULL;
  570. }
  571. #endif
  572. //-----------------------------------------------------------------------------
  573. // Writes two very simple .vmt file, one for the passed in asset,
  574. // and the other for <asset>_large.
  575. //-----------------------------------------------------------------------------
  576. void CMDLPicker::WriteBackbackVMTFiles( const char *pAssetName )
  577. {
  578. const char *pVProject = getenv( "VPROJECT" );
  579. if ( !pVProject )
  580. return;
  581. char pStrippedAssetName[ MAX_PATH ];
  582. V_StripExtension( pAssetName, pStrippedAssetName, sizeof( pStrippedAssetName ) );
  583. V_strcat_safe( pStrippedAssetName, GetOutputFileSuffix().Get() );
  584. char pVMTFilename[ MAX_PATH ];
  585. Q_snprintf( pVMTFilename, sizeof( pVMTFilename ), "%s\\materials\\backpack\\%s.vmt", pVProject, pStrippedAssetName );
  586. Q_FixSlashes( pVMTFilename );
  587. char pBaseTextureName[ MAX_PATH ];
  588. Q_snprintf( pBaseTextureName, sizeof( pBaseTextureName ), "backpack\\%s", pStrippedAssetName );
  589. Q_FixSlashes( pBaseTextureName );
  590. {
  591. CP4AutoEditAddFile autop4( pVMTFilename );
  592. FileHandle_t fileHandle = g_pFullFileSystem->Open( pVMTFilename, "w" );
  593. if ( fileHandle )
  594. {
  595. g_pFullFileSystem->FPrintf( fileHandle, "\"UnlitGeneric\"\n" );
  596. g_pFullFileSystem->FPrintf( fileHandle, "{\n" );
  597. g_pFullFileSystem->FPrintf( fileHandle, " \"$baseTexture\" \"%s\"\n", pBaseTextureName );
  598. g_pFullFileSystem->FPrintf( fileHandle, " $translucent 1\n" );
  599. g_pFullFileSystem->FPrintf( fileHandle, " $vertexcolor 1\n" );
  600. g_pFullFileSystem->FPrintf( fileHandle, "}\n" );
  601. g_pFullFileSystem->Close( fileHandle );
  602. }
  603. }
  604. // now write the _large version
  605. Q_snprintf( pVMTFilename, sizeof( pVMTFilename ), "%s\\materials\\backpack\\%s_large", pVProject, pStrippedAssetName );
  606. V_SetExtension( pVMTFilename, ".vmt", sizeof( pVMTFilename ) );
  607. Q_FixSlashes( pVMTFilename );
  608. Q_snprintf( pBaseTextureName, sizeof( pBaseTextureName ), "backpack\\%s_large", pStrippedAssetName );
  609. Q_FixSlashes( pBaseTextureName );
  610. {
  611. CP4AutoEditAddFile autop4( pVMTFilename );
  612. FileHandle_t fileHandle = g_pFullFileSystem->Open( pVMTFilename, "w" );
  613. if ( fileHandle )
  614. {
  615. g_pFullFileSystem->FPrintf( fileHandle, "\"UnlitGeneric\"\n" );
  616. g_pFullFileSystem->FPrintf( fileHandle, "{\n" );
  617. g_pFullFileSystem->FPrintf( fileHandle, " \"$baseTexture\" \"%s\"\n", pBaseTextureName );
  618. g_pFullFileSystem->FPrintf( fileHandle, " $translucent 1\n" );
  619. g_pFullFileSystem->FPrintf( fileHandle, "}\n" );
  620. g_pFullFileSystem->Close( fileHandle );
  621. }
  622. }
  623. }
  624. //-----------------------------------------------------------------------------
  625. void *VTexFilesystemFactory( const char *pName, int *pReturnCode )
  626. {
  627. return g_pFullFileSystem;
  628. }
  629. void* MdlPickerFSFactory( const char *pName, int *pReturnCode )
  630. {
  631. if ( IsX360() )
  632. return NULL;
  633. if ( Q_stricmp( pName, FILESYSTEM_INTERFACE_VERSION ) == 0 )
  634. return g_pFullFileSystem;
  635. return NULL;
  636. }
  637. //-----------------------------------------------------------------------------
  638. // Creates the two required icons for the TF2 store/backpack system
  639. //-----------------------------------------------------------------------------
  640. void CMDLPicker::GenerateBackpackIcons( void )
  641. {
  642. if ( !g_pVTex )
  643. return;
  644. int width;
  645. int height;
  646. // find the index of the item we are currently viewing
  647. int selectedItemIndex;
  648. for ( selectedItemIndex = 0; selectedItemIndex < m_AssetList.Count(); ++selectedItemIndex )
  649. {
  650. if ( m_pAssetBrowser->IsItemVisible( m_AssetList[ selectedItemIndex ].m_nItemId ) &&
  651. m_pAssetBrowser->IsItemSelected( m_AssetList[ selectedItemIndex ].m_nItemId ) )
  652. {
  653. break;
  654. }
  655. }
  656. if ( selectedItemIndex >= m_AssetList.Count() )
  657. return;
  658. //
  659. // Fetch and check environment variables
  660. //
  661. const char *pVContent = getenv( "VCONTENT" );
  662. if ( !pVContent )
  663. {
  664. Error( "VCONTENT environment variable not set" );
  665. return;
  666. }
  667. const char *pVMod = getenv( "VMOD" );
  668. if ( !pVMod )
  669. {
  670. Error( "VMOD environment variable not set" );
  671. return;
  672. }
  673. const char *pVProject = getenv( "VPROJECT" );
  674. if ( !pVProject )
  675. {
  676. Error( "VPROJECT environment variable not set" );
  677. return;
  678. }
  679. // extract the filename of the model
  680. KeyValues *pItemKeyValues = m_pAssetBrowser->GetItem( m_AssetList[ selectedItemIndex ].m_nItemId );
  681. const char *pSelectedAsset = pItemKeyValues->GetString( "asset" );
  682. // set the P4 changelist label to refer to this set of icons
  683. char pChangelistLabel[ MAX_PATH ];
  684. V_strcpy_safe( pChangelistLabel, pSelectedAsset );
  685. V_FileBase( pChangelistLabel, pChangelistLabel, sizeof( pChangelistLabel ) );
  686. V_strcat_safe( pChangelistLabel, " Auto Checkout", sizeof( pChangelistLabel ) );
  687. g_p4factory->SetOpenFileChangeList( pChangelistLabel );
  688. // generate .VMT files for normal and _large icons
  689. WriteBackbackVMTFiles( pSelectedAsset );
  690. // store original state of model preview panel
  691. int PanelX, PanelY, PanelWidth, PanelHeight;
  692. Color PanelColor;
  693. Panel *pParent = m_pMDLPreview->GetParent();
  694. m_pMDLPreview->GetPos( PanelX, PanelY );
  695. m_pMDLPreview->GetSize( PanelWidth, PanelHeight );
  696. PanelColor = m_pMDLPreview->GetBackgroundColor();
  697. // slam preview panel to desired TGA size for large icon, and write it out
  698. width = 512;
  699. height = 512;
  700. m_pMDLPreview->SetParent( ( vgui::Panel * )NULL );
  701. m_pMDLPreview->SetPos( 0, 0 );
  702. m_pMDLPreview->SetSize( width, height );
  703. CColorPickerButton *m_pBackgroundColor;
  704. m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
  705. Color NewPanelColor = m_pBackgroundColor->GetColor();
  706. NewPanelColor[3] = 0;
  707. m_pMDLPreview->SetBackgroundColor( NewPanelColor );
  708. ((VPanel *)m_pMDLPreview->GetVPanel())->Solve();
  709. char pLargeAssetName[ MAX_PATH ];
  710. V_strcpy_safe( pLargeAssetName, pSelectedAsset );
  711. V_StripExtension( pLargeAssetName, pLargeAssetName, ARRAYSIZE( pLargeAssetName ) );
  712. CUtlString strExtention = GetOutputFileSuffix();
  713. strExtention += "_large.mdl";
  714. V_strcat_safe( pLargeAssetName, strExtention.String() );
  715. char pOutputPath[ MAX_PATH ];
  716. Q_snprintf( pOutputPath, sizeof( pOutputPath ), "%s\\%s\\materialsrc\\backpack\\", pVContent, pVMod );
  717. Q_FixSlashes( pOutputPath );
  718. int nModIndex = pItemKeyValues->GetInt( "modIndex" );
  719. const char *pLargeTGAName = CaptureModel( nModIndex, pLargeAssetName, pOutputPath, width, height, NewPanelColor, true );
  720. if ( !pLargeTGAName )
  721. return;
  722. // write corresponding .txt file with vtex options
  723. char pVTexOptionsFileName[ MAX_PATH ];
  724. V_strcpy_safe( pVTexOptionsFileName, pLargeTGAName );
  725. V_SetExtension( pVTexOptionsFileName, ".txt", sizeof( pVTexOptionsFileName ) );
  726. {
  727. CP4AutoEditAddFile autop4( pVTexOptionsFileName );
  728. FileHandle_t hVTexOptionsFile = g_pFullFileSystem->Open( pVTexOptionsFileName, "w" );
  729. if ( hVTexOptionsFile )
  730. {
  731. g_pFullFileSystem->FPrintf( hVTexOptionsFile, "nomip 1\n" );
  732. g_pFullFileSystem->FPrintf( hVTexOptionsFile, "nolod 1\n" );
  733. g_pFullFileSystem->Close( hVTexOptionsFile );
  734. }
  735. }
  736. // !KLUDGE! Everybody I've talked to says that vtex is *supposed* to
  737. // use VPROJECT. But it doesn't. I don't think I can safely change vtex
  738. // without breaking tons of stuff. So just force the output directory.
  739. // Determine the proper output directory based on VPROJECT
  740. char pOutputPathGame[ MAX_PATH ];
  741. Q_strncpy( pOutputPathGame, pVProject, sizeof( pOutputPathGame ) );
  742. Q_StripTrailingSlash( pOutputPathGame );
  743. Q_strncat( pOutputPathGame, "/materials/", sizeof( pOutputPathGame ) );
  744. const char *pBackpack = Q_stristr( pLargeTGAName, "backpack" );
  745. if ( pBackpack )
  746. {
  747. Q_strncat( pOutputPathGame, pBackpack, sizeof( pOutputPathGame ) );
  748. Q_StripFilename( pOutputPathGame );
  749. }
  750. Q_FixSlashes( pOutputPathGame );
  751. // run vtex on the TGA and .txt file to create .VTF and add it to our Perforce changelist
  752. char *vTexArgv[64];
  753. int vTexArgc = 0;
  754. vTexArgv[ vTexArgc++ ] = "";
  755. vTexArgv[ vTexArgc++ ] = "-quiet";
  756. vTexArgv[ vTexArgc++ ] = "-UseStandardError";
  757. vTexArgv[ vTexArgc++ ] = "-WarningsAsErrors";
  758. vTexArgv[ vTexArgc++ ] = "-p4skip";
  759. vTexArgv[ vTexArgc++ ] = "-outdir";
  760. vTexArgv[ vTexArgc++ ] = pOutputPathGame;
  761. vTexArgv[ vTexArgc++ ] = (char *)pLargeTGAName;
  762. g_pVTex->VTex( MdlPickerFSFactory, pOutputPathGame, vTexArgc, vTexArgv );
  763. // Generale small TGA name, by removing the "large" part
  764. char pSmallTGAName[ MAX_PATH ];
  765. strcpy( pSmallTGAName, pLargeTGAName );
  766. char *_large = Q_stristr( pSmallTGAName, "_large");
  767. Assert(_large);
  768. strcpy(_large, _large+6);
  769. // Load up the large icon
  770. int nCheckWidth, nCheckHeight;
  771. ImageFormat largeFmt;
  772. float gamma;
  773. CUtlBuffer largeTGAFileData;
  774. CUtlMemory<unsigned char> largeTGAImageData;
  775. if ( !g_pFullFileSystem->ReadFile( pLargeTGAName, NULL, largeTGAFileData )
  776. || !TGALoader::GetInfo( largeTGAFileData, &nCheckWidth, &nCheckHeight, &largeFmt, &gamma )
  777. || nCheckWidth != width || nCheckHeight != height )
  778. {
  779. Error( "Failed to reload image header %s", pLargeTGAName );
  780. Assert( false );
  781. return;
  782. }
  783. largeTGAFileData.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  784. if ( !TGALoader::LoadRGBA8888( largeTGAFileData, largeTGAImageData, nCheckWidth, nCheckHeight )
  785. || nCheckWidth != width || nCheckHeight != height )
  786. {
  787. Error( "Failed to reload image data %s", pLargeTGAName );
  788. Assert( false );
  789. return;
  790. }
  791. //
  792. // Perform a downsample. This is better than just re-rendering at the smaller size,
  793. // which essentially just point-samples the image.
  794. //
  795. CUtlMemory<unsigned char> smallTGAImageData;
  796. const int kSmallSize = 128;
  797. smallTGAImageData.EnsureCapacity(kSmallSize*kSmallSize*4);
  798. ImageLoader::ResampleInfo_t resampleInfo;
  799. resampleInfo.m_nSrcWidth = width;
  800. resampleInfo.m_nSrcHeight = height;
  801. resampleInfo.m_flSrcGamma = gamma;
  802. resampleInfo.m_pSrc = (unsigned char *)largeTGAImageData.Base();
  803. resampleInfo.m_nDestWidth = kSmallSize;
  804. resampleInfo.m_nDestHeight = kSmallSize;
  805. resampleInfo.m_flDestGamma = gamma;
  806. resampleInfo.m_pDest = (unsigned char *)smallTGAImageData.Base();
  807. resampleInfo.m_nFlags = ImageLoader::RESAMPLE_CLAMPS | ImageLoader::RESAMPLE_CLAMPT;
  808. //resampleInfo.m_nFlags |= ImageLoader::RESAMPLE_NICE_FILTER; // Turn this off. It has some sort of edge enhancement or something. Causes edges to ring.
  809. if ( !ImageLoader::ResampleRGBA8888( resampleInfo ) )
  810. {
  811. Error( "Failed to resample %s", pLargeTGAName );
  812. Assert( false );
  813. return;
  814. }
  815. // Save it
  816. if ( !SaveTgaAndAddToP4( resampleInfo.m_pDest, IMAGE_FORMAT_RGBA8888, resampleInfo.m_nDestWidth, resampleInfo.m_nDestHeight, pSmallTGAName ) )
  817. {
  818. return;
  819. }
  820. // Save the .cfg file.
  821. SaveCaps( pSmallTGAName );
  822. // write corresponding .txt file with vtex options
  823. V_strcpy_safe( pVTexOptionsFileName, pSmallTGAName );
  824. V_SetExtension( pVTexOptionsFileName, ".txt", sizeof( pVTexOptionsFileName ) );
  825. {
  826. CP4AutoEditAddFile autop4( pVTexOptionsFileName );
  827. FileHandle_t hVTexOptionsFile = g_pFullFileSystem->Open( pVTexOptionsFileName, "w" );
  828. if ( hVTexOptionsFile )
  829. {
  830. g_pFullFileSystem->FPrintf( hVTexOptionsFile, "nomip 1\n" );
  831. g_pFullFileSystem->FPrintf( hVTexOptionsFile, "nolod 1\n" );
  832. g_pFullFileSystem->Close( hVTexOptionsFile );
  833. }
  834. }
  835. // run vtex on the TGA and .txt file to create .VTF and add it to our Perforce changelist
  836. vTexArgc = 0;
  837. vTexArgv[ vTexArgc++ ] = "";
  838. vTexArgv[ vTexArgc++ ] = "-quiet";
  839. vTexArgv[ vTexArgc++ ] = "-UseStandardError";
  840. vTexArgv[ vTexArgc++ ] = "-WarningsAsErrors";
  841. vTexArgv[ vTexArgc++ ] = "-p4skip";
  842. vTexArgv[ vTexArgc++ ] = "-outdir";
  843. vTexArgv[ vTexArgc++ ] = pOutputPathGame;
  844. vTexArgv[ vTexArgc++ ] = (char *)pSmallTGAName;
  845. g_pVTex->VTex( MdlPickerFSFactory, pOutputPathGame, vTexArgc, vTexArgv );
  846. // restore the preview panel to its original state
  847. m_pMDLPreview->SetParent( pParent );
  848. m_pMDLPreview->SetPos( PanelX, PanelY );
  849. m_pMDLPreview->SetSize( PanelWidth, PanelHeight );
  850. m_pMDLPreview->SetBackgroundColor( PanelColor );
  851. ((VPanel *)m_pMDLPreview->GetVPanel())->Solve();
  852. }
  853. CUtlString CMDLPicker::GetOutputFileSuffix()
  854. {
  855. char temp[256];
  856. TextEntry *pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "SuffixText" );
  857. if ( pTempValue )
  858. {
  859. pTempValue->GetText( temp, sizeof( temp ) );
  860. }
  861. return temp;
  862. }
  863. //-----------------------------------------------------------------------------
  864. // Saves the screen cap information and camera position
  865. //-----------------------------------------------------------------------------
  866. void CMDLPicker::SaveCaps( const char *szFileName )
  867. {
  868. char temp[ _MAX_PATH ];
  869. KeyValues *CaptureData = new KeyValues( "ScreenCaps" );
  870. Vector vecPos;
  871. QAngle angDir;
  872. m_pMDLPreview->GetCameraPositionAndAngles( vecPos, angDir );
  873. sprintf( temp, "%g %g %g", vecPos.x, vecPos.y, vecPos.z );
  874. CaptureData->SetString( "CameraPosition", temp );
  875. sprintf( temp, "%g %g %g", angDir.x, angDir.y, angDir.z );
  876. CaptureData->SetString( "CameraAngles", temp );
  877. Vector vecOffset;
  878. m_pMDLPreview->GetCameraOffset( vecOffset );
  879. sprintf( temp, "%g %g %g", vecOffset.x, vecOffset.y, vecOffset.z );
  880. CaptureData->SetString( "CameraOffset", temp );
  881. CColorPickerButton *m_pBackgroundColor;
  882. m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
  883. Color color = m_pBackgroundColor->GetColor();
  884. sprintf( temp, "%d %d %d %d", color.r(), color.g(), color.b(), color.a() );
  885. CaptureData->SetString( "BackgroundColor", temp );
  886. TextEntry *pTempValue;
  887. pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "WidthText" );
  888. pTempValue->GetText( temp, sizeof( temp ) );
  889. CaptureData->SetString( "Width", temp );
  890. pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "HeightText" );
  891. pTempValue->GetText( temp, sizeof( temp ) );
  892. CaptureData->SetString( "Height", temp );
  893. vgui::CheckButton *pToggle;
  894. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "NoGround" );
  895. CaptureData->SetInt( "NoGround", pToggle->IsSelected() ? 1 : 0 );
  896. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "Collision" );
  897. CaptureData->SetInt( "Collision", pToggle->IsSelected() ? 1 : 0 );
  898. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "Wireframe" );
  899. CaptureData->SetInt( "Wifeframe", pToggle->IsSelected() ? 1 : 0 );
  900. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "LockView" );
  901. CaptureData->SetInt( "LockView", pToggle->IsSelected() ? 1 : 0 );
  902. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "LookAtCamera" );
  903. CaptureData->SetInt( "LookAtCamera", pToggle->IsSelected() ? 1 : 0 );
  904. for( int i = 1; i < MAX_SELECTED_MODELS; i++ )
  905. {
  906. if ( m_hSelectedMDL[ i ] != MDLHANDLE_INVALID )
  907. {
  908. const char *MergedModelName = vgui::MDLCache()->GetModelName( m_hSelectedMDL[ i ] );
  909. sprintf( temp, "Merged_%d", i );
  910. CaptureData->SetString( temp, MergedModelName );
  911. }
  912. }
  913. if ( szFileName != NULL )
  914. {
  915. strcpy( temp, szFileName );
  916. V_SetExtension( temp, ".cfg", sizeof( temp ) );
  917. }
  918. else
  919. {
  920. Label *m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
  921. m_pOutputDirectory->GetText( temp, sizeof( temp ) );
  922. strcat( temp, "ScreenCaps.cfg" );
  923. }
  924. CaptureData->SaveToFile( g_pFullFileSystem, temp );
  925. CP4AutoAddFile autop4( temp );
  926. }
  927. //-----------------------------------------------------------------------------
  928. // Restores the screen cap information and camera position
  929. //-----------------------------------------------------------------------------
  930. bool CMDLPicker::RestoreCaps( const char *szFileName )
  931. {
  932. char temp[ _MAX_PATH ];
  933. if ( szFileName != NULL )
  934. {
  935. strcpy( temp, szFileName );
  936. V_SetExtension( temp, ".cfg", sizeof( temp ) );
  937. }
  938. else
  939. {
  940. Label *m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
  941. m_pOutputDirectory->GetText( temp, sizeof( temp ) );
  942. strcat( temp, "ScreenCaps.cfg" );
  943. }
  944. KeyValues *CaptureData = new KeyValues( "ScreenCaps" );
  945. if ( !CaptureData->LoadFromFile( g_pFullFileSystem, temp ) )
  946. {
  947. return false;
  948. }
  949. Vector vecPos;
  950. QAngle angDir;
  951. Vector vecOffset;
  952. sscanf( CaptureData->GetString( "CameraPosition" ), "%g %g %g", &vecPos.x, &vecPos.y, &vecPos.z );
  953. sscanf( CaptureData->GetString( "CameraAngles" ), "%g %g %g", &angDir.x, &angDir.y, &angDir.z );
  954. sscanf( CaptureData->GetString( "CameraOffset" ), "%g %g %g", &vecOffset.x, &vecOffset.y, &vecOffset.z );
  955. m_pMDLPreview->SetCameraOffset( vecOffset );
  956. m_pMDLPreview->SetCameraPositionAndAngles( vecPos, angDir );
  957. CColorPickerButton *m_pBackgroundColor;
  958. int r, g, b, a;
  959. m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
  960. sscanf( CaptureData->GetString( "BackgroundColor" ), "%d %d %d %d", &r, &g, &b, &a );
  961. m_pBackgroundColor->SetColor( r, g, b, a );
  962. TextEntry *pTempValue;
  963. pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "WidthText" );
  964. pTempValue->SetText( CaptureData->GetString( "Width" ) );
  965. pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "HeightText" );
  966. pTempValue->SetText( CaptureData->GetString( "Height" ) );
  967. vgui::CheckButton *pToggle;
  968. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "NoGround" );
  969. pToggle->SetSelected( ( CaptureData->GetInt( "NoGround" ) == 1 ) );
  970. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "Collision" );
  971. pToggle->SetSelected( ( CaptureData->GetInt( "Collision" ) == 1 ) );
  972. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "Wireframe" );
  973. pToggle->SetSelected( ( CaptureData->GetInt( "Wireframe" ) == 1 ) );
  974. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "LockView" );
  975. pToggle->SetSelected( ( CaptureData->GetInt( "LockView" ) == 1 ) );
  976. pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "LookAtCamera" );
  977. pToggle->SetSelected( ( CaptureData->GetInt( "LookAtCamera" ) == 1 ) );
  978. for( int i = 1; i < MAX_SELECTED_MODELS; i++ )
  979. {
  980. sprintf( temp, "Merged_%d", i );
  981. const char *MergedModelName = CaptureData->GetString( temp, NULL );
  982. if ( MergedModelName )
  983. {
  984. SelectMDL( MergedModelName, false, i );
  985. }
  986. }
  987. return true;
  988. }
  989. //-----------------------------------------------------------------------------
  990. // Purpose: rebuilds the list of activities
  991. //-----------------------------------------------------------------------------
  992. void CMDLPicker::RefreshActivitiesAndSequencesList()
  993. {
  994. m_pActivitiesList->RemoveAll();
  995. m_pSequencesList->RemoveAll();
  996. m_pMDLPreview->SetSequence( 0 );
  997. if ( m_hSelectedMDL[ 0 ] == MDLHANDLE_INVALID )
  998. {
  999. m_pActivitiesList->SetEmptyListText("No .MDL file currently selected");
  1000. m_pSequencesList->SetEmptyListText("No .MDL file currently selected");
  1001. return;
  1002. }
  1003. m_pActivitiesList->SetEmptyListText(".MDL file contains no activities");
  1004. m_pSequencesList->SetEmptyListText(".MDL file contains no sequences");
  1005. studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
  1006. CUtlDict<int, unsigned short> activityNames( true, 0, hdr->GetNumSeq() );
  1007. for (int j = 0; j < hdr->GetNumSeq(); j++)
  1008. {
  1009. if ( /*g_viewerSettings.showHidden ||*/ !(hdr->pSeqdesc(j).flags & STUDIO_HIDDEN))
  1010. {
  1011. const char *pActivityName = hdr->pSeqdesc(j).pszActivityName();
  1012. if ( pActivityName && pActivityName[0] )
  1013. {
  1014. // Multiple sequences can have the same activity name; only add unique activity names
  1015. if ( activityNames.Find( pActivityName ) == activityNames.InvalidIndex() )
  1016. {
  1017. KeyValues *pkv = new KeyValues("node", "activity", pActivityName );
  1018. int nItemID = m_pActivitiesList->AddItem( pkv, 0, false, false );
  1019. KeyValues *pDrag = new KeyValues( "drag", "text", pActivityName );
  1020. pDrag->SetString( "texttype", "activityName" );
  1021. pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL[ 0 ] ) );
  1022. m_pActivitiesList->SetItemDragData( nItemID, pDrag );
  1023. activityNames.Insert( pActivityName, j );
  1024. }
  1025. }
  1026. const char *pSequenceName = hdr->pSeqdesc(j).pszLabel();
  1027. if ( pSequenceName && pSequenceName[0] )
  1028. {
  1029. KeyValues *pkv = new KeyValues("node", "sequence", pSequenceName);
  1030. int nItemID = m_pSequencesList->AddItem( pkv, 0, false, false );
  1031. KeyValues *pDrag = new KeyValues( "drag", "text", pSequenceName );
  1032. pDrag->SetString( "texttype", "sequenceName" );
  1033. pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL[ 0 ] ) );
  1034. m_pSequencesList->SetItemDragData( nItemID, pDrag );
  1035. }
  1036. }
  1037. }
  1038. }
  1039. //-----------------------------------------------------------------------------
  1040. // A MDL was selected
  1041. //-----------------------------------------------------------------------------
  1042. void CMDLPicker::OnSelectedAssetPicked( const char *pMDLName )
  1043. {
  1044. char pRelativePath[MAX_PATH];
  1045. int nSelectSecondary = -1;
  1046. if ( input()->IsKeyDown( KEY_RCONTROL ) || input()->IsKeyDown( KEY_LCONTROL ) )
  1047. {
  1048. nSelectSecondary = 0;
  1049. }
  1050. else if ( input()->IsMouseDown(MOUSE_RIGHT) )
  1051. {
  1052. nSelectSecondary = 1;
  1053. }
  1054. if ( pMDLName )
  1055. {
  1056. Q_snprintf( pRelativePath, sizeof(pRelativePath), "models\\%s", pMDLName );
  1057. SelectMDL( pRelativePath, true, nSelectSecondary );
  1058. }
  1059. else
  1060. {
  1061. SelectMDL( NULL, true, nSelectSecondary );
  1062. }
  1063. }
  1064. //-----------------------------------------------------------------------------
  1065. // Allows external apps to select a MDL
  1066. //-----------------------------------------------------------------------------
  1067. void CMDLPicker::SelectMDL( const char *pRelativePath, bool bDoLookAt, int nSelectSecondary )
  1068. {
  1069. MDLHandle_t hSelectedMDL = pRelativePath ? vgui::MDLCache()->FindMDL( pRelativePath ) : MDLHANDLE_INVALID;
  1070. int index = ( nSelectSecondary > 0 ? nSelectSecondary : 0 );
  1071. // We didn't change models after all...
  1072. if ( hSelectedMDL == m_hSelectedMDL[ index ] )
  1073. {
  1074. // vgui::MDLCache()->FindMDL adds a reference by default we don't use, release it again
  1075. if ( hSelectedMDL != MDLHANDLE_INVALID )
  1076. {
  1077. vgui::MDLCache()->Release( hSelectedMDL );
  1078. }
  1079. return;
  1080. }
  1081. m_hSelectedMDL[ index ] = hSelectedMDL;
  1082. if ( vgui::MDLCache()->IsErrorModel( m_hSelectedMDL[ index ] ) )
  1083. {
  1084. m_hSelectedMDL[ index ] = MDLHANDLE_INVALID;
  1085. }
  1086. if ( nSelectSecondary != -1 )
  1087. {
  1088. m_pMDLPreview->ClearMergeMDLs();
  1089. for( int i = 1; i < MAX_SELECTED_MODELS; i++ )
  1090. {
  1091. if ( i != index )
  1092. {
  1093. m_hSelectedMDL[ i ] = MDLHANDLE_INVALID;
  1094. }
  1095. }
  1096. }
  1097. if ( index > 0 )
  1098. {
  1099. m_pMDLPreview->SetMergeMDL( m_hSelectedMDL[ index ] );
  1100. }
  1101. else
  1102. {
  1103. m_pMDLPreview->SetMDL( m_hSelectedMDL[ index ] );
  1104. if ( bDoLookAt )
  1105. {
  1106. m_pMDLPreview->LookAtMDL();
  1107. }
  1108. if ( m_nFlags & ( PAGE_SKINS ) )
  1109. {
  1110. UpdateSkinsList();
  1111. }
  1112. if ( m_nFlags & ( PAGE_INFO ) )
  1113. {
  1114. UpdateInfoTab();
  1115. }
  1116. if ( m_nFlags & (PAGE_ACTIVITIES|PAGE_SEQUENCES) )
  1117. {
  1118. RefreshActivitiesAndSequencesList();
  1119. }
  1120. }
  1121. // vgui::MDLCache()->FindMDL adds a reference by default we don't use, release it again
  1122. if ( hSelectedMDL != MDLHANDLE_INVALID )
  1123. {
  1124. vgui::MDLCache()->Release( hSelectedMDL );
  1125. }
  1126. PostActionSignal( new KeyValues( "MDLPreviewChanged", "mdl", pRelativePath ? pRelativePath : "" ) );
  1127. }
  1128. //-----------------------------------------------------------------------------
  1129. // Purpose: updates revision view on a file being selected
  1130. //-----------------------------------------------------------------------------
  1131. void CMDLPicker::OnCheckButtonChecked(KeyValues *kv)
  1132. {
  1133. // RefreshMDLList();
  1134. BaseClass::OnCheckButtonChecked( kv );
  1135. RefreshRenderSettings();
  1136. }
  1137. void CMDLPicker::GetSelectedMDLName( char *pBuffer, int nMaxLen )
  1138. {
  1139. Assert( nMaxLen > 0 );
  1140. if ( GetSelectedAssetCount() > 0 )
  1141. {
  1142. Q_snprintf( pBuffer, nMaxLen, "models\\%s", GetSelectedAsset( ) );
  1143. }
  1144. else
  1145. {
  1146. pBuffer[0] = 0;
  1147. }
  1148. }
  1149. //-----------------------------------------------------------------------------
  1150. // Gets the selected activity/sequence
  1151. //-----------------------------------------------------------------------------
  1152. int CMDLPicker::GetSelectedPage( )
  1153. {
  1154. if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
  1155. return PAGE_SEQUENCES;
  1156. if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
  1157. return PAGE_ACTIVITIES;
  1158. return PAGE_NONE;
  1159. }
  1160. const char *CMDLPicker::GetSelectedSequenceName()
  1161. {
  1162. if ( !m_pSequencesPage )
  1163. return NULL;
  1164. int nIndex = m_pSequencesList->GetSelectedItem( 0 );
  1165. if ( nIndex >= 0 )
  1166. {
  1167. KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
  1168. return pkv->GetString( "sequence", NULL );
  1169. }
  1170. return NULL;
  1171. }
  1172. const char *CMDLPicker::GetSelectedActivityName()
  1173. {
  1174. if ( !m_pActivitiesPage )
  1175. return NULL;
  1176. int nIndex = m_pActivitiesList->GetSelectedItem( 0 );
  1177. if ( nIndex >= 0 )
  1178. {
  1179. KeyValues *pkv = m_pActivitiesList->GetItem( nIndex );
  1180. return pkv->GetString( "activity", NULL );
  1181. }
  1182. return NULL;
  1183. }
  1184. int CMDLPicker::GetSelectedSkin()
  1185. {
  1186. if ( !m_pSkinsPage )
  1187. return 0;
  1188. int nIndex = m_pSkinsList->GetSelectedItem( 0 );
  1189. if ( nIndex >= 0 )
  1190. {
  1191. return nIndex;
  1192. }
  1193. return 0;
  1194. }
  1195. //-----------------------------------------------------------------------------
  1196. // Plays the selected activity
  1197. //-----------------------------------------------------------------------------
  1198. void CMDLPicker::SelectActivity( const char *pActivityName )
  1199. {
  1200. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
  1201. for ( int i = 0; i < pstudiohdr->GetNumSeq(); i++ )
  1202. {
  1203. mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
  1204. if ( stricmp( seqdesc.pszActivityName(), pActivityName ) == 0 )
  1205. {
  1206. // FIXME: Add weighted sequence selection logic?
  1207. m_pMDLPreview->SetSequence( i );
  1208. break;
  1209. }
  1210. }
  1211. PostActionSignal( new KeyValues( "SequenceSelectionChanged", "activity", pActivityName ) );
  1212. }
  1213. //-----------------------------------------------------------------------------
  1214. // Plays the selected sequence
  1215. //-----------------------------------------------------------------------------
  1216. void CMDLPicker::SelectSequence( const char *pSequenceName )
  1217. {
  1218. studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
  1219. for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
  1220. {
  1221. mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
  1222. if ( !Q_stricmp( seqdesc.pszLabel(), pSequenceName ) )
  1223. {
  1224. m_pMDLPreview->SetSequence( i );
  1225. break;
  1226. }
  1227. }
  1228. PostActionSignal( new KeyValues( "SequenceSelectionChanged", "sequence", pSequenceName ) );
  1229. }
  1230. void CMDLPicker::SelectSkin( int nSkin )
  1231. {
  1232. m_pMDLPreview->SetSkin( nSkin );
  1233. PostActionSignal( new KeyValues( "SkinSelectionChanged", "skin", nSkin));
  1234. }
  1235. //-----------------------------------------------------------------------------
  1236. // Purpose: Updates preview when an item is selected
  1237. //-----------------------------------------------------------------------------
  1238. void CMDLPicker::OnItemSelected( KeyValues *kv )
  1239. {
  1240. Panel *pPanel = (Panel *)kv->GetPtr("panel", NULL);
  1241. if ( m_pSequencesList && (pPanel == m_pSequencesList ) )
  1242. {
  1243. const char *pSequenceName = GetSelectedSequenceName();
  1244. if ( pSequenceName )
  1245. {
  1246. SelectSequence( pSequenceName );
  1247. }
  1248. return;
  1249. }
  1250. if ( m_pActivitiesList && ( pPanel == m_pActivitiesList ) )
  1251. {
  1252. const char *pActivityName = GetSelectedActivityName();
  1253. if ( pActivityName )
  1254. {
  1255. SelectActivity( pActivityName );
  1256. }
  1257. return;
  1258. }
  1259. if ( m_pSkinsList && ( pPanel == m_pSkinsList ) )
  1260. {
  1261. int nSelectedSkin = GetSelectedSkin();
  1262. SelectSkin( nSelectedSkin );
  1263. return;
  1264. }
  1265. BaseClass::OnItemSelected( kv );
  1266. }
  1267. //-----------------------------------------------------------------------------
  1268. // Purpose: Called when a page is shown
  1269. //-----------------------------------------------------------------------------
  1270. void CMDLPicker::OnPageChanged( )
  1271. {
  1272. if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
  1273. {
  1274. m_pSequencesList->RequestFocus();
  1275. const char *pSequenceName = GetSelectedSequenceName();
  1276. if ( pSequenceName )
  1277. {
  1278. SelectSequence( pSequenceName );
  1279. }
  1280. return;
  1281. }
  1282. if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
  1283. {
  1284. m_pActivitiesList->RequestFocus();
  1285. const char *pActivityName = GetSelectedActivityName();
  1286. if ( pActivityName )
  1287. {
  1288. SelectActivity( pActivityName );
  1289. }
  1290. return;
  1291. }
  1292. }
  1293. //-----------------------------------------------------------------------------
  1294. //
  1295. // Purpose: Modal picker frame
  1296. //
  1297. //-----------------------------------------------------------------------------
  1298. CMDLPickerFrame::CMDLPickerFrame( vgui::Panel *pParent, const char *pTitle, int nFlags ) :
  1299. BaseClass( pParent )
  1300. {
  1301. SetAssetPicker( new CMDLPicker( this, nFlags ) );
  1302. LoadControlSettingsAndUserConfig( "resource/mdlpickerframe.res" );
  1303. SetTitle( pTitle, false );
  1304. }
  1305. CMDLPickerFrame::~CMDLPickerFrame()
  1306. {
  1307. }
  1308. //-----------------------------------------------------------------------------
  1309. // Allows external apps to select a MDL
  1310. //-----------------------------------------------------------------------------
  1311. void CMDLPickerFrame::SelectMDL( const char *pRelativePath )
  1312. {
  1313. static_cast<CMDLPicker*>( GetAssetPicker() )->SelectMDL( pRelativePath );
  1314. }
  1315. int CMDLPicker::UpdateSkinsList()
  1316. {
  1317. int nNumSkins = 0;
  1318. if ( m_pSkinsList )
  1319. {
  1320. m_pSkinsList->RemoveAll();
  1321. studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
  1322. if ( hdr )
  1323. {
  1324. nNumSkins = hdr->numskinfamilies;
  1325. for ( int i = 0; i < nNumSkins; i++ )
  1326. {
  1327. char skinText[25] = "";
  1328. sprintf( skinText, "skin%i", i );
  1329. KeyValues *pkv = new KeyValues("node", "skin", skinText );
  1330. m_pSkinsList->AddItem( pkv, 0, false, false );
  1331. }
  1332. }
  1333. }
  1334. return nNumSkins;
  1335. }
  1336. void CMDLPicker::UpdateInfoTab()
  1337. {
  1338. studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
  1339. if ( !hdr )
  1340. return;
  1341. int nMass = hdr->mass;
  1342. Panel *pTempPanel = m_pInfoPage->FindChildByName("MassValue");
  1343. char massBuff[10];
  1344. Q_snprintf( massBuff, 10, "%d", nMass );
  1345. ((vgui::Label *)pTempPanel)->SetText( massBuff );
  1346. bool bIsStatic = hdr->flags & STUDIOHDR_FLAGS_STATIC_PROP;
  1347. bool bIsPhysics = false;
  1348. const char* buf = hdr->KeyValueText();
  1349. Label * pTempLabel = (Label *)m_pInfoPage->FindChildByName("StaticText");
  1350. pTempLabel->SetVisible( false );
  1351. if( buf )
  1352. {
  1353. buf = Q_strstr( buf, "prop_data" );
  1354. if ( buf )
  1355. {
  1356. int iPropDataCount = UpdatePropDataList( buf, bIsStatic );
  1357. if( iPropDataCount )
  1358. {
  1359. bIsPhysics = true;
  1360. }
  1361. }
  1362. else
  1363. {
  1364. m_pPropDataList->RemoveAll();
  1365. }
  1366. }
  1367. else
  1368. {
  1369. m_pPropDataList->RemoveAll();
  1370. }
  1371. CheckButton * pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName("StaticObject");
  1372. pTempCheck->SetCheckButtonCheckable( true );
  1373. pTempCheck->SetSelected( bIsStatic );
  1374. pTempCheck->SetCheckButtonCheckable( false );
  1375. pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName("PhysicsObject");
  1376. pTempCheck->SetCheckButtonCheckable( true );
  1377. pTempCheck->SetSelected( bIsPhysics );
  1378. pTempCheck->SetCheckButtonCheckable( false );
  1379. pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName("DynamicObject");
  1380. pTempCheck->SetCheckButtonCheckable( true );
  1381. pTempCheck->SetSelected( !bIsPhysics );
  1382. pTempCheck->SetCheckButtonCheckable( false );
  1383. }
  1384. int CMDLPicker::UpdatePropDataList( const char* pszPropData, bool &bIsStatic )
  1385. {
  1386. int iCount = 0;
  1387. if ( m_pPropDataList )
  1388. {
  1389. m_pPropDataList->RemoveAll();
  1390. const char * endPropData = strchr( pszPropData, '}' );
  1391. char keyText[255] = "";
  1392. char valueText[255] = "";
  1393. const char *beginChunk = strchr( pszPropData, '\"' );
  1394. if ( !beginChunk )
  1395. {
  1396. return 0;
  1397. }
  1398. beginChunk++;
  1399. const char *endChunk = strchr( beginChunk, '\"' );
  1400. while( endChunk )
  1401. {
  1402. Q_memcpy( keyText, beginChunk, endChunk - beginChunk );
  1403. beginChunk = endChunk + 1;
  1404. beginChunk = strchr( beginChunk, '\"' ) + 1;
  1405. endChunk = strchr( beginChunk, '\"' );
  1406. Q_memcpy( valueText, beginChunk, endChunk - beginChunk );
  1407. if( !Q_strcmp( keyText, "allowstatic" ) && !Q_strcmp( valueText , "1" ) )
  1408. {
  1409. if ( !bIsStatic )
  1410. {
  1411. Label * pTempLabel = (Label *)m_pInfoPage->FindChildByName("StaticText");
  1412. pTempLabel->SetVisible( true );
  1413. }
  1414. bIsStatic &= true;
  1415. }
  1416. KeyValues *pkv = new KeyValues("node", "key", keyText, "value", valueText );
  1417. m_pPropDataList->AddItem( pkv, 0, false, false );
  1418. Q_memset( keyText, 0, 255 );
  1419. Q_memset( valueText, 0, 255 );
  1420. iCount++;
  1421. beginChunk = endChunk + 1;
  1422. beginChunk = strchr( beginChunk, '\"' );
  1423. if ( !beginChunk || beginChunk > endPropData )
  1424. {
  1425. return iCount;
  1426. }
  1427. beginChunk++;
  1428. endChunk = strchr( beginChunk, '\"' );
  1429. }
  1430. }
  1431. return iCount;
  1432. }