Counter Strike : Global Offensive Source Code
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.

1722 lines
54 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "dme_controls/AssetBuilder.h"
  7. #include "dme_controls/DmePanel.h"
  8. #include "dme_controls/dmecontrols_utils.h"
  9. #include "tier1/keyvalues.h"
  10. #include "vgui_controls/ListPanel.h"
  11. #include "vgui_controls/MenuButton.h"
  12. #include "vgui_controls/TextEntry.h"
  13. #include "vgui_controls/MessageBox.h"
  14. #include "vgui_controls/ComboBox.h"
  15. #include "vgui_controls/FileOpenDialog.h"
  16. #include "vgui_controls/Splitter.h"
  17. #include "vgui_controls/FileOpenStateMachine.h"
  18. #include "vgui_controls/PropertySheet.h"
  19. #include "vgui_controls/PropertyPage.h"
  20. #include "vgui/ischeme.h"
  21. #include "vgui/ivgui.h"
  22. #include "vgui/isurface.h"
  23. #include "tier1/tier1.h"
  24. #include "movieobjects/dmemakefile.h"
  25. #include "matsys_controls/picker.h"
  26. #include "tier2/fileutils.h"
  27. #include "vgui/keycode.h"
  28. #include "filesystem.h"
  29. #include "movieobjects/idmemakefileutils.h"
  30. #include "tier3/tier3.h"
  31. // memdbgon must be the last include file in a .cpp file!!!
  32. #include "tier0/memdbgon.h"
  33. using namespace vgui;
  34. #define ASSET_FILE_FORMAT "model"
  35. //-----------------------------------------------------------------------------
  36. // Compile status bar
  37. //-----------------------------------------------------------------------------
  38. class CCompileStatusBar : public vgui::EditablePanel
  39. {
  40. DECLARE_CLASS_SIMPLE( CCompileStatusBar, EditablePanel );
  41. public:
  42. enum CompileStatus_t
  43. {
  44. NOT_COMPILING,
  45. CURRENTLY_COMPILING,
  46. COMPILATION_FAILED,
  47. COMPILATION_SUCCESSFUL
  48. };
  49. CCompileStatusBar( vgui::Panel *pParent, const char *pPanelName );
  50. virtual ~CCompileStatusBar();
  51. virtual void PaintBackground();
  52. void SetStatus( CompileStatus_t status, const char *pMessage );
  53. private:
  54. vgui::Label *m_pStatus;
  55. CompileStatus_t m_Status;
  56. int m_CompilingId;
  57. };
  58. //-----------------------------------------------------------------------------
  59. // Constructor, destructor
  60. //-----------------------------------------------------------------------------
  61. CCompileStatusBar::CCompileStatusBar( vgui::Panel *pParent, const char *pPanelName ) :
  62. BaseClass( pParent, pPanelName )
  63. {
  64. m_pStatus = new vgui::Label( this, "StatusLabel", "" );
  65. m_pStatus->SetAutoResize( PIN_TOPLEFT, AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
  66. m_pStatus->SetContentAlignment( vgui::Label::a_center );
  67. m_pStatus->SetTextColorState( vgui::Label::CS_BRIGHT );
  68. SetStatus( NOT_COMPILING, "" );
  69. SetPaintBackgroundEnabled( true );
  70. m_CompilingId = vgui::surface()->DrawGetTextureId( "vgui/progressbar" );
  71. if ( m_CompilingId == -1 ) // we didn't find it, so create a new one
  72. {
  73. m_CompilingId = vgui::surface()->CreateNewTextureID();
  74. }
  75. vgui::surface()->DrawSetTextureFile( m_CompilingId, "vgui/progressbar", true, false );
  76. }
  77. CCompileStatusBar::~CCompileStatusBar()
  78. {
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Sets compile status
  82. //-----------------------------------------------------------------------------
  83. void CCompileStatusBar::SetStatus( CompileStatus_t status, const char *pMessage )
  84. {
  85. m_Status = status;
  86. m_pStatus->SetText( pMessage );
  87. }
  88. void CCompileStatusBar::PaintBackground()
  89. {
  90. int w, h;
  91. GetSize( w, h );
  92. switch( m_Status )
  93. {
  94. case NOT_COMPILING:
  95. break;
  96. case COMPILATION_FAILED:
  97. vgui::surface()->DrawSetColor( 255, 0, 0, 255 );
  98. vgui::surface()->DrawFilledRect( 0, 0, w, h );
  99. break;
  100. case COMPILATION_SUCCESSFUL:
  101. vgui::surface()->DrawSetColor( 0, 255, 0, 255 );
  102. vgui::surface()->DrawFilledRect( 0, 0, w, h );
  103. break;
  104. case CURRENTLY_COMPILING:
  105. {
  106. float du = Plat_FloatTime() / 5.0f;
  107. du -= (int)du;
  108. du = 1.0f - du;
  109. Vertex_t verts[4];
  110. verts[0].Init( Vector2D( 0.0f, 0.0f ), Vector2D( du, 0.0f ) );
  111. verts[1].Init( Vector2D( w, 0.0f ), Vector2D( 1.0f + du, 0.0f ) );
  112. verts[2].Init( Vector2D( w, h ), Vector2D( 1.0f + du, 1.0f ) );
  113. verts[3].Init( Vector2D( 0.0f, h ), Vector2D( du, 1.0f ) );
  114. vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
  115. vgui::surface()->DrawSetTexture( m_CompilingId );
  116. vgui::surface()->DrawTexturedPolygon( 4, verts );
  117. }
  118. break;
  119. }
  120. }
  121. //-----------------------------------------------------------------------------
  122. //
  123. // Asset Builder
  124. //
  125. //-----------------------------------------------------------------------------
  126. IMPLEMENT_DMEPANEL_FACTORY( CAssetBuilder, DmeMakefile, "DmeMakeFileDefault", "MakeFile Editor", true );
  127. //-----------------------------------------------------------------------------
  128. // Static data
  129. //-----------------------------------------------------------------------------
  130. static PickerList_t s_AssetTypes;
  131. static bool s_bAssetTypeListBuilt = false;
  132. //-----------------------------------------------------------------------------
  133. // Builds the list of asset types
  134. //-----------------------------------------------------------------------------
  135. void BuildAssetTypeList( )
  136. {
  137. if ( s_bAssetTypeListBuilt )
  138. return;
  139. s_bAssetTypeListBuilt = true;
  140. CDisableUndoScopeGuard guard;
  141. int hFactory = g_pDataModel->GetFirstFactory();
  142. while ( g_pDataModel->IsValidFactory( hFactory ) )
  143. {
  144. // Add all DmeElements that inherit from DmeMakefile
  145. const char *pFactoryName = g_pDataModel->GetFactoryName( hFactory );
  146. CDmElement *pElement = GetElement< CDmElement >( g_pDataModel->CreateElement( pFactoryName, "temp", DMFILEID_INVALID ) );
  147. CDmeMakefile *pMakeFile = CastElement<CDmeMakefile>( pElement );
  148. if ( pMakeFile && pMakeFile->GetMakefileType() )
  149. {
  150. int i = s_AssetTypes.AddToTail();
  151. s_AssetTypes[i].m_pChoiceString = pMakeFile->GetMakefileType()->m_pHumanReadableName;
  152. s_AssetTypes[i].m_pChoiceValue = pFactoryName;
  153. }
  154. DestroyElement( pElement );
  155. hFactory = g_pDataModel->GetNextFactory( hFactory );
  156. }
  157. }
  158. //-----------------------------------------------------------------------------
  159. // Builds the list of asset types
  160. //-----------------------------------------------------------------------------
  161. static PickerList_t &BuildAssetSubTypeList( const char **ppSubTypes, PickerList_t &pickerList )
  162. {
  163. if ( !ppSubTypes )
  164. return s_AssetTypes;
  165. pickerList.RemoveAll();
  166. CDisableUndoScopeGuard guard;
  167. int nCount = s_AssetTypes.Count();
  168. for ( int i = 0; i < nCount; ++i )
  169. {
  170. // Add all DmeElements that inherit from DmeMakefile
  171. CDmElement *pElement = GetElement< CDmElement >( g_pDataModel->CreateElement( s_AssetTypes[i].m_pChoiceValue, "temp", DMFILEID_INVALID ) );
  172. CDmeMakefile *pMakeFile = CastElement< CDmeMakefile >( pElement );
  173. for ( int j = 0; ppSubTypes[j]; ++j )
  174. {
  175. if ( !pElement->IsA( ppSubTypes[j] ) )
  176. continue;
  177. int k = pickerList.AddToTail();
  178. pickerList[k].m_pChoiceString = pMakeFile->GetMakefileType()->m_pHumanReadableName;
  179. pickerList[k].m_pChoiceValue = s_AssetTypes[i].m_pChoiceValue;
  180. break;
  181. }
  182. DestroyElement( pElement );
  183. }
  184. return pickerList;
  185. }
  186. //-----------------------------------------------------------------------------
  187. // Shows the overwrite existing file dialog
  188. //-----------------------------------------------------------------------------
  189. static void OverwriteFileDialog( vgui::Panel *pActionTarget, const char *pFileName, KeyValues *pOkCommand )
  190. {
  191. if ( !g_pFullFileSystem->FileExists( pFileName ) )
  192. {
  193. pActionTarget->PostMessage( pActionTarget->GetVPanel(), pOkCommand );
  194. return;
  195. }
  196. char pBuf[1024];
  197. Q_snprintf( pBuf, sizeof(pBuf), "File already exists. Overwrite it?\n\n\"%s\"\n", pFileName );
  198. vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Overwrite Existing File?", pBuf, pActionTarget );
  199. pMessageBox->AddActionSignalTarget( pActionTarget );
  200. pMessageBox->SetOKButtonVisible( true );
  201. pMessageBox->SetOKButtonText( "Yes" );
  202. pMessageBox->SetCancelButtonVisible( true );
  203. pMessageBox->SetCancelButtonText( "No" );
  204. pMessageBox->SetCloseButtonVisible( false );
  205. pMessageBox->SetCommand( pOkCommand );
  206. pMessageBox->DoModal();
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Utility to load a makefile
  210. //-----------------------------------------------------------------------------
  211. static CDmeMakefile *ReadMakefile( const char *pFileName, CDmElement **ppRoot = NULL )
  212. {
  213. if ( ppRoot )
  214. {
  215. *ppRoot = NULL;
  216. }
  217. CDmElement *pRoot;
  218. DmFileId_t fileid = g_pDataModel->RestoreFromFile( pFileName, NULL, NULL, &pRoot, CR_DELETE_OLD );
  219. if ( fileid == DMFILEID_INVALID || !pRoot )
  220. {
  221. Warning( "Unable to read makefile \"%s\"!\n", pFileName );
  222. return NULL;
  223. }
  224. CDmeMakefile *pMakeFile = CastElement< CDmeMakefile >( pRoot );
  225. if ( !pMakeFile )
  226. {
  227. CDmElement *pElement = CastElement< CDmElement >( pRoot );
  228. pMakeFile = pElement->GetValueElement< CDmeMakefile >( "makefile" );
  229. if ( !pMakeFile )
  230. {
  231. DmFileId_t fileId = pRoot->GetFileId();
  232. DestroyElement( pRoot );
  233. if ( fileId != DMFILEID_INVALID && g_pDataModel->GetFileName( fileId )[0] )
  234. {
  235. g_pDataModel->RemoveFileId( fileId );
  236. }
  237. return NULL;
  238. }
  239. }
  240. if ( ppRoot )
  241. {
  242. *ppRoot = CastElement< CDmElement >( pRoot );
  243. }
  244. return pMakeFile;
  245. }
  246. //-----------------------------------------------------------------------------
  247. // Sort by MDL name
  248. //-----------------------------------------------------------------------------
  249. static int __cdecl TypeSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
  250. {
  251. const char *string1 = item1.kv->GetString("type");
  252. const char *string2 = item2.kv->GetString("type");
  253. int nRetVal = Q_stricmp( string1, string2 );
  254. if ( nRetVal != 0 )
  255. return nRetVal;
  256. string1 = item1.kv->GetString("file");
  257. string2 = item2.kv->GetString("file");
  258. nRetVal = Q_stricmp( string1, string2 );
  259. if ( nRetVal != 0 )
  260. return nRetVal;
  261. int nIndex1 = item1.kv->GetInt( "index" );
  262. int nIndex2 = item2.kv->GetInt( "index" );
  263. return nIndex1 - nIndex2;
  264. }
  265. static int __cdecl FileSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
  266. {
  267. const char *string1 = item1.kv->GetString("file");
  268. const char *string2 = item2.kv->GetString("file");
  269. int nRetVal = Q_stricmp( string1, string2 );
  270. if ( nRetVal != 0 )
  271. return nRetVal;
  272. string1 = item1.kv->GetString("type");
  273. string2 = item2.kv->GetString("type");
  274. nRetVal = Q_stricmp( string1, string2 );
  275. if ( nRetVal != 0 )
  276. return nRetVal;
  277. int nIndex1 = item1.kv->GetInt( "index" );
  278. int nIndex2 = item2.kv->GetInt( "index" );
  279. return nIndex1 - nIndex2;
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Purpose: Constructor, destructor
  283. //-----------------------------------------------------------------------------
  284. CAssetBuilder::CAssetBuilder( vgui::Panel *pParent, const char *pPanelName ) :
  285. BaseClass( pParent, pPanelName )
  286. {
  287. m_hContextMenu = NULL;
  288. m_hRootMakefile = NULL;
  289. m_bIsCompiling = false;
  290. m_bDestroyMakefileOnClose = true;
  291. m_pInputOutputSheet = new vgui::PropertySheet( this, "InputOutputSheet" );
  292. m_pInputOutputSheet->AddActionSignalTarget( this );
  293. m_pInputPage = new PropertyPage( m_pInputOutputSheet, "InputPage" );
  294. m_pOutputPage = new PropertyPage( m_pInputOutputSheet, "OutputPage" );
  295. m_pCompilePage = new PropertyPage( m_pInputOutputSheet, "CompilePage" );
  296. m_pOutputPreviewPage = new PropertyPage( m_pInputOutputSheet, "OutputPreviewPage" );
  297. m_pPropertiesSplitter = new vgui::Splitter( m_pInputPage, "PropertiesSplitter", SPLITTER_MODE_VERTICAL, 1 );
  298. vgui::Panel *pSplitterLeftSide = m_pPropertiesSplitter->GetChild( 0 );
  299. vgui::Panel *pSplitterRightSide = m_pPropertiesSplitter->GetChild( 1 );
  300. m_pDmePanel = new CDmePanel( pSplitterRightSide, "CompileOptions" );
  301. m_pDmePanel->AddActionSignalTarget( this );
  302. m_pOututPreviewPanel = new CDmePanel( m_pOutputPreviewPage, "OutputPreview", false );
  303. m_pOututPreviewPanel->AddActionSignalTarget( this );
  304. m_pSourcesList = new vgui::ListPanel( pSplitterLeftSide, "SourcesList" );
  305. m_pSourcesList->AddColumnHeader( 0, "type", "type", 100, 0 );
  306. m_pSourcesList->AddColumnHeader( 1, "file", "file", 52, 0 );
  307. m_pSourcesList->AddActionSignalTarget( this );
  308. m_pSourcesList->SetSortFunc( 0, TypeSortFunc );
  309. m_pSourcesList->SetSortFunc( 1, FileSortFunc );
  310. m_pSourcesList->SetSortColumn( 0 );
  311. // m_pSourcesList->SetSelectIndividualCells( true );
  312. m_pSourcesList->SetEmptyListText("No sources");
  313. // m_pSourcesList->SetDragEnabled( true );
  314. m_pOutputList = new vgui::ListPanel( m_pOutputPage, "OutputList" );
  315. m_pOutputList->AddColumnHeader( 0, "type", "type", 100, 0 );
  316. m_pOutputList->AddColumnHeader( 1, "file", "file", 52, 0 );
  317. m_pOutputList->AddActionSignalTarget( this );
  318. m_pOutputList->SetSortFunc( 0, TypeSortFunc );
  319. m_pOutputList->SetSortFunc( 1, FileSortFunc );
  320. m_pOutputList->SetSortColumn( 0 );
  321. m_pOutputList->SetEmptyListText("No outputs");
  322. m_pCompileOutput = new vgui::TextEntry( m_pCompilePage, "CompileOutput" );
  323. m_pCompileOutput->SetMultiline( true );
  324. m_pCompileOutput->SetVerticalScrollbar( true );
  325. m_pCompile = new vgui::Button( this, "CompileButton", "Compile", this, "OnCompile" );
  326. m_pPublish = new vgui::Button( this, "PublishButton", "Publish", this, "OnPublish" );
  327. m_pAbortCompile = new vgui::Button( this, "AbortCompileButton", "AbortCompile", this, "OnAbortCompile" );
  328. m_pCompileStatusBar = new CCompileStatusBar( this, "CompileStatus" );
  329. m_pInputPage->LoadControlSettingsAndUserConfig( "resource/assetbuilderinputpage.res" );
  330. m_pOutputPage->LoadControlSettingsAndUserConfig( "resource/assetbuilderoutputpage.res" );
  331. m_pCompilePage->LoadControlSettingsAndUserConfig( "resource/assetbuildercompilepage.res" );
  332. m_pOutputPreviewPage->LoadControlSettingsAndUserConfig( "resource/assetbuilderoutputpreviewpage.res" );
  333. // Load layout settings; has to happen before pinning occurs in code
  334. LoadControlSettingsAndUserConfig( "resource/assetbuilder.res" );
  335. // NOTE: Page adding happens *after* LoadControlSettingsAndUserConfig
  336. // because the layout of the sheet is correct at this point.
  337. m_pInputOutputSheet->AddPage( m_pInputPage, "Input" );
  338. m_pInputOutputSheet->AddPage( m_pOutputPage, "Output" );
  339. m_pInputOutputSheet->AddPage( m_pCompilePage, "Compile" );
  340. m_pInputOutputSheet->AddPage( m_pOutputPreviewPage, "Preview" );
  341. m_pCompile->SetEnabled( false );
  342. m_pPublish->SetEnabled( false );
  343. m_pAbortCompile->SetEnabled( false );
  344. }
  345. CAssetBuilder::~CAssetBuilder()
  346. {
  347. if ( m_bDestroyMakefileOnClose )
  348. {
  349. CleanupMakefile();
  350. }
  351. CleanupContextMenu();
  352. SaveUserConfig();
  353. }
  354. //-----------------------------------------------------------------------------
  355. // Default behavior is to destroy the makefile when we close
  356. //-----------------------------------------------------------------------------
  357. void CAssetBuilder::DestroyMakefileOnClose( bool bEnable )
  358. {
  359. m_bDestroyMakefileOnClose = bEnable;
  360. }
  361. //-----------------------------------------------------------------------------
  362. // Builds a unique list of file IDs
  363. //-----------------------------------------------------------------------------
  364. void CAssetBuilder::BuildFileIDList( CDmeMakefile *pMakeFile, CUtlVector<DmFileId_t> &fileIds )
  365. {
  366. if ( !pMakeFile )
  367. return;
  368. // NOTE: Not hugely efficient. If the CDmeDependencyMakefile starts
  369. // getting large, we can optimize this
  370. DmFileId_t id = pMakeFile->GetFileId();
  371. int nCount = fileIds.Count();
  372. int i;
  373. for ( i = 0; i < nCount; ++i )
  374. {
  375. if ( fileIds[i] == id )
  376. break;
  377. }
  378. if ( i == nCount )
  379. {
  380. fileIds.AddToTail( id );
  381. }
  382. int nSourceCount = pMakeFile->GetSourceCount();
  383. for ( int i = 0; i < nSourceCount; ++i )
  384. {
  385. CDmeSource *pSource = pMakeFile->GetSource(i);
  386. BuildFileIDList( pSource->GetDependentMakefile(), fileIds );
  387. }
  388. }
  389. //-----------------------------------------------------------------------------
  390. // Removes a makefile from memory
  391. //-----------------------------------------------------------------------------
  392. void CAssetBuilder::CleanupMakefile()
  393. {
  394. m_hMakefileStack.Clear();
  395. m_pDmePanel->SetDmeElement( NULL );
  396. m_pOututPreviewPanel->SetDmeElement( NULL );
  397. if ( !m_hRootMakefile.Get() )
  398. return;
  399. // First, build a list of unique file IDs
  400. CUtlVector<DmFileId_t> fileIds;
  401. BuildFileIDList( m_hRootMakefile, fileIds );
  402. CDisableUndoScopeGuard guard;
  403. m_hRootMakefile = NULL;
  404. int nCount = fileIds.Count();
  405. for ( int i = 0; i < nCount; ++i )
  406. {
  407. if ( fileIds[i] != DMFILEID_INVALID && g_pDataModel->GetFileName( fileIds[i] )[0] )
  408. {
  409. g_pDataModel->RemoveFileId( fileIds[i] );
  410. }
  411. }
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Marks the file as dirty (or not)
  415. //-----------------------------------------------------------------------------
  416. void CAssetBuilder::SetDirty()
  417. {
  418. PostActionSignal( new KeyValues( "DmeElementChanged" ) );
  419. }
  420. //-----------------------------------------------------------------------------
  421. // Returns the current makefile
  422. //-----------------------------------------------------------------------------
  423. CDmeMakefile *CAssetBuilder::GetMakeFile()
  424. {
  425. return m_hMakefile.Get();
  426. }
  427. CDmeMakefile *CAssetBuilder::GetRootMakeFile()
  428. {
  429. return m_hRootMakefile.Get();
  430. }
  431. //-----------------------------------------------------------------------------
  432. // Resets the lists; called when file name changes
  433. //-----------------------------------------------------------------------------
  434. void CAssetBuilder::Refresh()
  435. {
  436. RefreshSourceList();
  437. RefreshOutputList();
  438. }
  439. //-----------------------------------------------------------------------------
  440. // Resets the root makefile
  441. //-----------------------------------------------------------------------------
  442. void CAssetBuilder::SetRootMakefile( CDmeMakefile *pMakeFile )
  443. {
  444. CleanupMakefile();
  445. if ( pMakeFile )
  446. {
  447. m_hRootMakefile = pMakeFile;
  448. m_hMakefileStack.Push( m_hRootMakefile );
  449. }
  450. SetCurrentMakefile( pMakeFile );
  451. }
  452. //-----------------------------------------------------------------------------
  453. // Resets the current makefile
  454. //-----------------------------------------------------------------------------
  455. void CAssetBuilder::SetCurrentMakefile( CDmeMakefile *pMakeFile )
  456. {
  457. m_hMakefile = pMakeFile;
  458. m_pDmePanel->SetDmeElement( NULL );
  459. m_pOututPreviewPanel->SetDmeElement( pMakeFile, true, "DmeMakeFileOutputPreview" );
  460. RefreshSourceList();
  461. RefreshOutputList();
  462. // Lets the asset builder update the title bar
  463. PostActionSignal( new KeyValues( "UpdateFileName" ) );
  464. }
  465. //-----------------------------------------------------------------------------
  466. // Hook into the DME panel framework
  467. //-----------------------------------------------------------------------------
  468. void CAssetBuilder::SetDmeElement( CDmeMakefile *pMakeFile )
  469. {
  470. SetRootMakefile( pMakeFile );
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Refresh the source list
  474. //-----------------------------------------------------------------------------
  475. void CAssetBuilder::RefreshSourceList( )
  476. {
  477. m_pSourcesList->RemoveAll();
  478. if ( !m_hMakefile.Get() )
  479. return;
  480. DmeMakefileType_t *pSourceTypes = m_hMakefile->GetSourceTypes();
  481. for ( int i = 0; pSourceTypes[i].m_pTypeName; ++i )
  482. {
  483. CUtlVector< CDmeHandle< CDmeSource > > sources;
  484. m_hMakefile->GetSources( pSourceTypes[i].m_pTypeName, sources );
  485. int nCount = sources.Count();
  486. for ( int j = 0; j < nCount; ++j )
  487. {
  488. char pFullPath[MAX_PATH];
  489. m_hMakefile->GetSourceFullPath( sources[j], pFullPath, sizeof(pFullPath) );
  490. KeyValues *pItemKeys = new KeyValues( "node", "type", pSourceTypes[i].m_pHumanReadableName );
  491. pItemKeys->SetString( "file", pFullPath );
  492. pItemKeys->SetInt( "sourceTypeIndex", i );
  493. pItemKeys->SetInt( "index", j ); // for sorting in the listpanel
  494. SetElementKeyValue( pItemKeys, "dmeSource", sources[j] );
  495. m_pSourcesList->AddItem( pItemKeys, 0, false, false );
  496. }
  497. }
  498. m_pSourcesList->SortList();
  499. }
  500. //-----------------------------------------------------------------------------
  501. // Refreshes the output list
  502. //-----------------------------------------------------------------------------
  503. void CAssetBuilder::RefreshOutputList()
  504. {
  505. m_pOutputList->RemoveAll();
  506. m_pCompile->SetEnabled( false );
  507. m_pPublish->SetEnabled( false );
  508. if ( !m_hMakefile.Get() )
  509. return;
  510. CUtlVector<CUtlString> outputs;
  511. m_hMakefile->GetOutputs( outputs );
  512. int nCount = outputs.Count();
  513. for ( int j = 0; j < nCount; ++j )
  514. {
  515. KeyValues *pItemKeys = new KeyValues( "node", "type", "Output" );
  516. pItemKeys->SetString( "file", outputs[j] );
  517. pItemKeys->SetInt( "index", j );
  518. m_pOutputList->AddItem( pItemKeys, 0, false, false );
  519. }
  520. bool bEnabled = ( nCount > 0 ) && ( g_pDmeMakefileUtils != NULL );
  521. m_pCompile->SetEnabled( bEnabled );
  522. m_pPublish->SetEnabled( bEnabled );
  523. m_pOutputList->SortList();
  524. }
  525. //-----------------------------------------------------------------------------
  526. // Selects a particular source
  527. //-----------------------------------------------------------------------------
  528. void CAssetBuilder::SelectSource( CDmeSource *pSource )
  529. {
  530. int nItemID = m_pSourcesList->FirstItem();
  531. for ( ; nItemID != m_pSourcesList->InvalidItemID(); nItemID = m_pSourcesList->NextItem( nItemID ) )
  532. {
  533. KeyValues *kv = m_pSourcesList->GetItem( nItemID );
  534. if ( GetElementKeyValue< CDmeSource >( kv, "dmeSource" ) != pSource )
  535. continue;
  536. m_pSourcesList->SetSingleSelectedItem( nItemID );
  537. return;
  538. }
  539. }
  540. //-----------------------------------------------------------------------------
  541. // Called by the picker popped up in OnFileNew
  542. //-----------------------------------------------------------------------------
  543. void CAssetBuilder::OnPicked( KeyValues *kv )
  544. {
  545. const char *pValue = kv->GetString( "choice" );
  546. KeyValues *pContextKeys = kv->FindKey( "OnAddSource" );
  547. if ( pContextKeys )
  548. {
  549. OnSourceFileAdded( "", pValue );
  550. return;
  551. }
  552. CDisableUndoScopeGuard guard;
  553. CDmeMakefile *pMakeFile = GetElement< CDmeMakefile >( g_pDataModel->CreateElement( pValue, "unnamed", DMFILEID_INVALID ) );
  554. if ( !pMakeFile )
  555. return;
  556. DmeMakefileType_t *pType = pMakeFile->GetMakefileType();
  557. char pContext[MAX_PATH];
  558. Q_snprintf( pContext, sizeof(pContext), "asset_builder_session_%s", pType->m_pTypeName );
  559. char pStartingDir[MAX_PATH];
  560. pMakeFile->GetDefaultDirectory( pType->m_pDefaultDirectoryID, pStartingDir, sizeof(pStartingDir) );
  561. g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
  562. KeyValues *pDialogKeys = new KeyValues( "NewSourceFileSelected", "makefileType", pValue );
  563. FileOpenDialog *pDialog = new FileOpenDialog( this, "Select Asset Builder File Name", false, pDialogKeys );
  564. pDialog->SetStartDirectoryContext( pContext, pStartingDir );
  565. pDialog->AddFilter( pType->m_pFileFilter, pType->m_pFileFilterString, true );
  566. pDialog->AddActionSignalTarget( this );
  567. pDialog->DoModal( false );
  568. DestroyElement( pMakeFile );
  569. }
  570. //-----------------------------------------------------------------------------
  571. // Creates a new source file, hooks it in
  572. //-----------------------------------------------------------------------------
  573. void CAssetBuilder::OnNewSourceFile( )
  574. {
  575. KeyValues *pKeyValues = GetSelectedSourceKeyvalues();
  576. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  577. if ( !pSource )
  578. return;
  579. BuildAssetTypeList();
  580. PickerList_t typePickerList;
  581. PickerList_t &pickerList = BuildAssetSubTypeList( pSource->GetSourceMakefileTypes(), typePickerList );
  582. // Create a list indicating which type of asset to create
  583. CPickerFrame *pPicker = new CPickerFrame( this, "Select Sub-Asset Type", "Asset Type", "assetType" );
  584. pPicker->DoModal( pickerList );
  585. }
  586. //-----------------------------------------------------------------------------
  587. // Called when the button to add a file is clicked
  588. //-----------------------------------------------------------------------------
  589. void CAssetBuilder::OnAddSource( )
  590. {
  591. if ( !m_hMakefile.Get() )
  592. return;
  593. PickerList_t sourceType;
  594. DmeMakefileType_t *pSourceTypes = m_hMakefile->GetSourceTypes();
  595. for ( int i = 0; pSourceTypes[i].m_pTypeName; ++i )
  596. {
  597. if ( pSourceTypes[i].m_bIsSingleton )
  598. {
  599. if ( m_hMakefile->HasSourceOfType( pSourceTypes[i].m_pTypeName ) )
  600. continue;
  601. }
  602. int j = sourceType.AddToTail( );
  603. sourceType[j].m_pChoiceString = pSourceTypes[i].m_pHumanReadableName;
  604. sourceType[j].m_pChoiceValue = pSourceTypes[i].m_pTypeName;
  605. }
  606. if ( sourceType.Count() == 0 )
  607. return;
  608. KeyValues *pContextKeys = new KeyValues( "OnAddSource" );
  609. CPickerFrame *pPicker = new CPickerFrame( this, "Select Source Type", "Source Type", "sourceType" );
  610. pPicker->DoModal( sourceType, pContextKeys );
  611. }
  612. //-----------------------------------------------------------------------------
  613. // Returns the curerntly selected row
  614. //-----------------------------------------------------------------------------
  615. int CAssetBuilder::GetSelectedRow( )
  616. {
  617. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  618. return ( nItemID != -1 ) ? m_pSourcesList->GetItemCurrentRow( nItemID ) : -1;
  619. }
  620. //-----------------------------------------------------------------------------
  621. // Selects a particular row of the source list
  622. //-----------------------------------------------------------------------------
  623. void CAssetBuilder::SelectSourceListRow( int nRow )
  624. {
  625. int nVisibleRowCount = m_pSourcesList->GetItemCount();
  626. if ( nVisibleRowCount == 0 || nRow < 0 )
  627. return;
  628. if ( nRow >= nVisibleRowCount )
  629. {
  630. nRow = nVisibleRowCount - 1;
  631. }
  632. int nNewItemID = m_pSourcesList->GetItemIDFromRow( nRow );
  633. m_pSourcesList->SetSingleSelectedItem( nNewItemID );
  634. }
  635. //-----------------------------------------------------------------------------
  636. // Called when the button to remove a file is clicked
  637. //-----------------------------------------------------------------------------
  638. void CAssetBuilder::OnRemoveSource( )
  639. {
  640. int nCount = m_pSourcesList->GetSelectedItemsCount();
  641. if ( nCount == 0 || !m_hMakefile.Get() )
  642. return;
  643. int nRow = GetSelectedRow();
  644. Assert( nRow >= 0 );
  645. // Update the selection to be reasonable after deletion
  646. CDisableUndoScopeGuard guard;
  647. for ( int i = 0; i < nCount; ++i )
  648. {
  649. int nItemID = m_pSourcesList->GetSelectedItem( i );
  650. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  651. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  652. if ( pSource )
  653. {
  654. m_hMakefile->RemoveSource( pSource );
  655. DestroyElement( pSource );
  656. SetDirty( );
  657. }
  658. }
  659. RefreshSourceList();
  660. SelectSourceListRow( nRow );
  661. }
  662. //-----------------------------------------------------------------------------
  663. // Called to make a particular source the currently selected source
  664. //-----------------------------------------------------------------------------
  665. void CAssetBuilder::OnZoomInSource()
  666. {
  667. // Called to zoom into the currently selected source
  668. CDmeSource *pSource = GetSelectedSource( );
  669. if ( !pSource )
  670. return;
  671. CDmeMakefile *pChild = m_hMakefile->FindDependentMakefile( pSource );
  672. if ( pChild )
  673. {
  674. CDmeHandle< CDmeMakefile > hChild;
  675. hChild = pChild;
  676. m_hMakefileStack.Push( hChild );
  677. SetCurrentMakefile( pChild );
  678. }
  679. }
  680. //-----------------------------------------------------------------------------
  681. // Called to zoom out of a particular source
  682. //-----------------------------------------------------------------------------
  683. void CAssetBuilder::OnZoomOutSource()
  684. {
  685. // Called to zoom into the currently selected source
  686. if ( m_hMakefileStack.Count() <= 1 )
  687. return;
  688. CDmeMakefile *pOldParent = m_hMakefileStack.Top().Get();
  689. m_hMakefileStack.Pop( );
  690. CDmeMakefile *pParent = m_hMakefileStack.Top().Get();
  691. if ( pParent )
  692. {
  693. SetCurrentMakefile( pParent );
  694. CDmeSource *pSource = pParent->FindAssociatedSource( pOldParent );
  695. if ( pSource )
  696. {
  697. SelectSource( pSource );
  698. }
  699. }
  700. }
  701. //-----------------------------------------------------------------------------
  702. // Called when a key is typed
  703. //-----------------------------------------------------------------------------
  704. void CAssetBuilder::OnKeyCodeTyped( vgui::KeyCode code )
  705. {
  706. if ( code == KEY_DELETE )
  707. {
  708. OnRemoveSource();
  709. return;
  710. }
  711. if ( code == KEY_ENTER )
  712. {
  713. OnZoomInSource();
  714. return;
  715. }
  716. BaseClass::OnKeyCodeTyped( code );
  717. }
  718. //-----------------------------------------------------------------------------
  719. // Called when we're browsing for a source file and one was selected
  720. //-----------------------------------------------------------------------------
  721. void CAssetBuilder::OnSourceFileAdded( const char *pFileName, const char *pTypeName )
  722. {
  723. CDmeSource *pSource = NULL;
  724. {
  725. CDisableUndoScopeGuard guard;
  726. pSource = m_hMakefile->AddSource( pTypeName, pFileName );
  727. }
  728. SetDirty( );
  729. RefreshSourceList( );
  730. SelectSource( pSource );
  731. }
  732. //-----------------------------------------------------------------------------
  733. // Called when the file open dialog for browsing source files selects something
  734. //-----------------------------------------------------------------------------
  735. void CAssetBuilder::OnNewSourceFileSelected( const char *pFileName, KeyValues *kv )
  736. {
  737. int nCount = m_pSourcesList->GetSelectedItemsCount();
  738. if ( nCount != 1 || !m_hMakefile.Get() )
  739. return;
  740. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  741. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  742. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  743. if ( !pSource )
  744. return;
  745. const char *pMakeFileType = kv->GetString( "makefileType" );
  746. {
  747. CDisableUndoScopeGuard guard;
  748. m_hMakefile->SetSourceFullPath( pSource, pFileName );
  749. DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( pFileName );
  750. CDmeMakefile *pSourceMakeFile = CreateElement< CDmeMakefile >( pMakeFileType, pFileName, fileid );
  751. pSourceMakeFile->SetFileName( pFileName );
  752. m_hMakefile->SetAssociation( pSource, pSourceMakeFile );
  753. SetDirty( );
  754. }
  755. pKeyValues->SetString( "file", pFileName );
  756. m_pSourcesList->ApplyItemChanges( nItemID );
  757. m_pSourcesList->SortList();
  758. }
  759. //-----------------------------------------------------------------------------
  760. // Called when the file open dialog for browsing source files selects something
  761. //-----------------------------------------------------------------------------
  762. void CAssetBuilder::OnFileSelected( KeyValues *kv )
  763. {
  764. const char *pFileName = kv->GetString( "fullpath", NULL );
  765. if ( !pFileName )
  766. return;
  767. KeyValues *pDialogKeys = kv->FindKey( "SelectSourceFile" );
  768. if ( pDialogKeys )
  769. {
  770. OnSourceFileNameChanged( pFileName );
  771. return;
  772. }
  773. pDialogKeys = kv->FindKey( "NewSourceFileSelected" );
  774. if ( pDialogKeys )
  775. {
  776. if ( !g_pFullFileSystem->FileExists( pFileName ) )
  777. {
  778. OnNewSourceFileSelected( pFileName, pDialogKeys );
  779. }
  780. else
  781. {
  782. OnSourceFileNameChanged( pFileName );
  783. }
  784. return;
  785. }
  786. }
  787. //-----------------------------------------------------------------------------
  788. // Shows the source file browser
  789. //-----------------------------------------------------------------------------
  790. void CAssetBuilder::ShowSourceFileBrowser( const char *pTitle, DmeMakefileType_t *pSourceType, KeyValues *pDialogKeys )
  791. {
  792. char pContext[MAX_PATH];
  793. Q_snprintf( pContext, sizeof(pContext), "asset_builder_session_%s", pSourceType->m_pTypeName );
  794. char pStartingDir[MAX_PATH];
  795. m_hMakefile->GetDefaultDirectory( pSourceType->m_pDefaultDirectoryID, pStartingDir, sizeof(pStartingDir) );
  796. g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
  797. FileOpenDialog *pDialog = new FileOpenDialog( this, pTitle, true, pDialogKeys );
  798. pDialog->SetStartDirectoryContext( pContext, pStartingDir );
  799. pDialog->AddFilter( pSourceType->m_pFileFilter, pSourceType->m_pFileFilterString, true );
  800. pDialog->AddActionSignalTarget( this );
  801. pDialog->DoModal( false );
  802. }
  803. //-----------------------------------------------------------------------------
  804. // Called when the button to browse for a source file is clicked
  805. //-----------------------------------------------------------------------------
  806. void CAssetBuilder::OnBrowseSourceFile( )
  807. {
  808. KeyValues *pKeyValues = GetSelectedSourceKeyvalues();
  809. if ( !pKeyValues )
  810. return;
  811. int nSourceTypeIndex = pKeyValues->GetInt( "sourceTypeIndex", -1 );
  812. KeyValues *pDialogKeys = new KeyValues( "SelectSourceFile" );
  813. DmeMakefileType_t &sourceType = m_hMakefile->GetSourceTypes()[nSourceTypeIndex];
  814. ShowSourceFileBrowser( "Select Source File", &sourceType, pDialogKeys );
  815. }
  816. //-----------------------------------------------------------------------------
  817. // Command handler
  818. //-----------------------------------------------------------------------------
  819. void CAssetBuilder::OnCommand( const char *pCommand )
  820. {
  821. if ( !Q_stricmp( pCommand, "OnCompile" ) )
  822. {
  823. OnCompile();
  824. return;
  825. }
  826. if ( !Q_stricmp( pCommand, "OnAbortCompile" ) )
  827. {
  828. OnAbortCompile();
  829. return;
  830. }
  831. if ( !Q_stricmp( pCommand, "OnPublish" ) )
  832. {
  833. OnPublish();
  834. return;
  835. }
  836. BaseClass::OnCommand( pCommand );
  837. }
  838. //-----------------------------------------------------------------------------
  839. // Cleans up the context menu
  840. //-----------------------------------------------------------------------------
  841. void CAssetBuilder::CleanupContextMenu()
  842. {
  843. if ( m_hContextMenu.Get() )
  844. {
  845. m_hContextMenu->MarkForDeletion();
  846. m_hContextMenu = NULL;
  847. }
  848. }
  849. //-----------------------------------------------------------------------------
  850. // Called to open a context-sensitive menu for a particular menu item
  851. //-----------------------------------------------------------------------------
  852. void CAssetBuilder::OnOpenContextMenu( KeyValues *kv )
  853. {
  854. CleanupContextMenu();
  855. if ( !m_hMakefile.Get() )
  856. return;
  857. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  858. int nItemID = kv->GetInt( "itemID", -1 );
  859. if ( pPanel != m_pSourcesList )
  860. return;
  861. m_hContextMenu = new Menu( this, "ActionMenu" );
  862. m_hContextMenu->AddMenuItem( "Add...", new KeyValues( "AddSource" ), this );
  863. int nCount = m_pSourcesList->GetSelectedItemsCount();
  864. if ( nCount > 0 )
  865. {
  866. m_hContextMenu->AddMenuItem( "Remove", new KeyValues( "RemoveSource" ), this );
  867. }
  868. bool bShowZoomIn = false;
  869. bool bShowZoomOut = m_hMakefileStack.Count() > 1;
  870. bool bShowLoadSourceFile = false;
  871. bool bHasValidSourceFile = false;
  872. if ( nCount == 1 && nItemID != -1 )
  873. {
  874. KeyValues *kv = m_pSourcesList->GetItem( nItemID );
  875. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( kv, "dmeSource" );
  876. if ( pSource )
  877. {
  878. bHasValidSourceFile = pSource->GetRelativeFileName()[0] != 0;
  879. if ( m_hMakefile->FindDependentMakefile( pSource ) )
  880. {
  881. bShowZoomIn = true;
  882. }
  883. else
  884. {
  885. bShowLoadSourceFile = bHasValidSourceFile;
  886. }
  887. }
  888. }
  889. if ( bShowZoomIn || bShowZoomOut )
  890. {
  891. m_hContextMenu->AddSeparator();
  892. if ( bShowZoomIn )
  893. {
  894. m_hContextMenu->AddMenuItem( "Zoom In", new KeyValues( "ZoomInSource" ), this );
  895. }
  896. if ( bShowZoomOut )
  897. {
  898. m_hContextMenu->AddMenuItem( "Zoom Out", new KeyValues( "ZoomOutSource" ), this );
  899. }
  900. }
  901. if ( nCount == 1 )
  902. {
  903. m_hContextMenu->AddSeparator();
  904. m_hContextMenu->AddMenuItem( "New Source File...", new KeyValues( "NewSourceFile" ), this );
  905. m_hContextMenu->AddMenuItem( "Select Source File...", new KeyValues( "BrowseSourceFile" ), this );
  906. if ( bShowLoadSourceFile )
  907. {
  908. m_hContextMenu->AddMenuItem( "Load Source File", new KeyValues( "LoadSourceFile" ), this );
  909. }
  910. if ( bHasValidSourceFile )
  911. {
  912. m_hContextMenu->AddMenuItem( "Edit Source File", new KeyValues( "EditSourceFile" ), this );
  913. }
  914. }
  915. Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
  916. }
  917. //-----------------------------------------------------------------------------
  918. // Called when a list panel's selection changes
  919. //-----------------------------------------------------------------------------
  920. void CAssetBuilder::OnSourceItemSelectionChanged( )
  921. {
  922. int nCount = m_pSourcesList->GetSelectedItemsCount();
  923. if ( nCount != 1 )
  924. {
  925. m_pDmePanel->SetDmeElement( NULL );
  926. return;
  927. }
  928. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  929. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  930. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  931. m_pDmePanel->SetDmeElement( pSource );
  932. }
  933. //-----------------------------------------------------------------------------
  934. // Called when a list panel's selection changes
  935. //-----------------------------------------------------------------------------
  936. void CAssetBuilder::OnItemSelected( KeyValues *kv )
  937. {
  938. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  939. if ( pPanel == m_pSourcesList )
  940. {
  941. OnSourceItemSelectionChanged();
  942. return;
  943. }
  944. }
  945. //-----------------------------------------------------------------------------
  946. // Called when a list panel's selection changes
  947. //-----------------------------------------------------------------------------
  948. void CAssetBuilder::OnItemDeselected( KeyValues *kv )
  949. {
  950. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  951. if ( pPanel == m_pSourcesList )
  952. {
  953. OnSourceItemSelectionChanged();
  954. return;
  955. }
  956. }
  957. //-----------------------------------------------------------------------------
  958. // Returns the selected source (if there's only 1 source selected)
  959. //-----------------------------------------------------------------------------
  960. CDmeSource *CAssetBuilder::GetSelectedSource( )
  961. {
  962. int nCount = m_pSourcesList->GetSelectedItemsCount();
  963. if ( nCount != 1 || !m_hMakefile.Get() )
  964. return NULL;
  965. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  966. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  967. return GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  968. }
  969. KeyValues *CAssetBuilder::GetSelectedSourceKeyvalues( )
  970. {
  971. int nCount = m_pSourcesList->GetSelectedItemsCount();
  972. if ( nCount != 1 || !m_hMakefile.Get() )
  973. return NULL;
  974. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  975. return m_pSourcesList->GetItem( nItemID );
  976. }
  977. //-----------------------------------------------------------------------------
  978. // Called when the source file name changes
  979. //-----------------------------------------------------------------------------
  980. void CAssetBuilder::OnSourceFileNameChanged( const char *pFileName )
  981. {
  982. int nCount = m_pSourcesList->GetSelectedItemsCount();
  983. if ( nCount != 1 || !m_hMakefile.Get() )
  984. return;
  985. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  986. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  987. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  988. if ( !pSource )
  989. return;
  990. {
  991. CDisableUndoScopeGuard guard;
  992. m_hMakefile->SetSourceFullPath( pSource, pFileName );
  993. SetDirty( );
  994. }
  995. pKeyValues->SetString( "file", pFileName );
  996. m_pSourcesList->ApplyItemChanges( nItemID );
  997. m_pSourcesList->SortList();
  998. }
  999. //-----------------------------------------------------------------------------
  1000. // Called during compilation
  1001. //-----------------------------------------------------------------------------
  1002. void CAssetBuilder::OnLoadSourceFile()
  1003. {
  1004. CDmeSource *pSource = GetSelectedSource( );
  1005. if ( !pSource )
  1006. return;
  1007. char pFullPath[MAX_PATH];
  1008. m_hMakefile->GetSourceFullPath( pSource, pFullPath, sizeof(pFullPath) );
  1009. {
  1010. CDisableUndoScopeGuard guard;
  1011. CDmElement *pRoot;
  1012. CDmeMakefile *pMakeFile = ReadMakefile( pFullPath, &pRoot );
  1013. if ( !pMakeFile )
  1014. return;
  1015. // Successfully loaded a makefile. Set up the association.
  1016. m_hMakefile->SetAssociation( pSource, pMakeFile );
  1017. // Refresh the dme panel... setting association could provoke changes
  1018. m_pDmePanel->SetDmeElement( pSource, true );
  1019. }
  1020. }
  1021. //-----------------------------------------------------------------------------
  1022. // Called to open an external editor for this source file
  1023. //-----------------------------------------------------------------------------
  1024. void CAssetBuilder::OnEditSourceFile()
  1025. {
  1026. CDmeSource *pSource = GetSelectedSource( );
  1027. if ( pSource )
  1028. {
  1029. pSource->OpenEditor();
  1030. }
  1031. }
  1032. //-----------------------------------------------------------------------------
  1033. // Finishes compilation
  1034. //-----------------------------------------------------------------------------
  1035. void CAssetBuilder::FinishCompilation( CompilationState_t state )
  1036. {
  1037. // NOTE: compilation can cause the makefile to be completely
  1038. // rebuilt if it's sitting in the output file. Therefore,
  1039. // Detach the source preview panel from the source and refresh the
  1040. // source list to get it to correctly reconnect to the new source elements
  1041. m_pDmePanel->SetDmeElement( NULL );
  1042. int nRow = GetSelectedRow();
  1043. m_pOututPreviewPanel->SetDmeElement( m_hMakefile, true, "DmeMakeFileOutputPreview" );
  1044. m_bIsCompiling = false;
  1045. // NOTE: Sort of side-effecty. These two things must be done after
  1046. // m_pOututPreviewPanel->SetDmeElement, since that's what reloads the output element,
  1047. // which is also what can cause a reload of the makefile
  1048. RefreshSourceList();
  1049. SelectSourceListRow( nRow );
  1050. // Lets the asset builder update the title bar
  1051. // (compilation could have changed the dirty state if the makefile is in the file)
  1052. PostActionSignal( new KeyValues( "UpdateFileName" ) );
  1053. if ( state == COMPILATION_FAILED )
  1054. {
  1055. char pBuf[256];
  1056. Q_snprintf( pBuf, sizeof(pBuf), "Compilation Error (return code %d)", g_pDmeMakefileUtils->GetExitCode() );
  1057. m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_FAILED, pBuf );
  1058. }
  1059. else
  1060. {
  1061. m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_SUCCESSFUL, "Compile Successful!" );
  1062. }
  1063. }
  1064. //-----------------------------------------------------------------------------
  1065. // Called during compilation
  1066. //-----------------------------------------------------------------------------
  1067. void CAssetBuilder::OnTick()
  1068. {
  1069. BaseClass::OnTick();
  1070. if ( m_bIsCompiling )
  1071. {
  1072. int nLen = g_pDmeMakefileUtils->GetCompileOutputSize( );
  1073. char *pBuf = (char*)_alloca( nLen+1 );
  1074. CompilationState_t state = g_pDmeMakefileUtils->UpdateCompilation( pBuf, nLen );
  1075. if ( nLen > 0 )
  1076. {
  1077. m_pCompileOutput->InsertString( pBuf );
  1078. }
  1079. Assert( m_hMakefile.Get() );
  1080. if ( state != COMPILATION_NOT_COMPLETE )
  1081. {
  1082. FinishCompilation( state );
  1083. }
  1084. }
  1085. if ( !m_bIsCompiling )
  1086. {
  1087. m_pAbortCompile->SetEnabled( false );
  1088. vgui::ivgui()->RemoveTickSignal( GetVPanel() );
  1089. }
  1090. }
  1091. //-----------------------------------------------------------------------------
  1092. // Abort compile asset
  1093. //-----------------------------------------------------------------------------
  1094. void CAssetBuilder::OnAbortCompile()
  1095. {
  1096. if ( m_bIsCompiling )
  1097. {
  1098. g_pDmeMakefileUtils->AbortCurrentCompilation();
  1099. m_bIsCompiling = false;
  1100. m_pAbortCompile->SetEnabled( false );
  1101. m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_FAILED, "Compile Aborted" );
  1102. }
  1103. }
  1104. //-----------------------------------------------------------------------------
  1105. // Compile asset
  1106. //-----------------------------------------------------------------------------
  1107. void CAssetBuilder::OnCompile( )
  1108. {
  1109. if ( !m_hMakefile.Get() )
  1110. return;
  1111. OnAbortCompile();
  1112. m_pCompileOutput->SetText( "" );
  1113. g_pDmeMakefileUtils->PerformCompile( m_hMakefile, false );
  1114. m_bIsCompiling = true;
  1115. m_pAbortCompile->SetEnabled( true );
  1116. m_pCompileStatusBar->SetStatus( CCompileStatusBar::CURRENTLY_COMPILING, "Compiling..." );
  1117. vgui::ivgui()->AddTickSignal( GetVPanel(), 10 );
  1118. }
  1119. //-----------------------------------------------------------------------------
  1120. // Compile, then publish
  1121. //-----------------------------------------------------------------------------
  1122. void CAssetBuilder::OnPublish( )
  1123. {
  1124. if ( !m_hMakefile.Get() )
  1125. return;
  1126. OnAbortCompile();
  1127. m_pCompileOutput->SetText( "" );
  1128. g_pDmeMakefileUtils->PerformCompile( m_hMakefile, false );
  1129. m_bIsCompiling = true;
  1130. m_pAbortCompile->SetEnabled( true );
  1131. m_pCompileStatusBar->SetStatus( CCompileStatusBar::CURRENTLY_COMPILING, "Compiling..." );
  1132. vgui::ivgui()->AddTickSignal( GetVPanel(), 10 );
  1133. }
  1134. //-----------------------------------------------------------------------------
  1135. // Purpose: Constructor, destructor
  1136. //-----------------------------------------------------------------------------
  1137. CAssetBuilderFrame::CAssetBuilderFrame( vgui::Panel *pParent, const char *pTitle ) :
  1138. BaseClass( pParent, "AssetBuilderFrame" )
  1139. {
  1140. m_TitleString = pTitle;
  1141. SetMenuButtonVisible( true );
  1142. SetImages( "resource/downarrow" );
  1143. m_pAssetBuilder = new CAssetBuilder( this, "AssetBuilder" );
  1144. m_pAssetBuilder->AddActionSignalTarget( this );
  1145. vgui::Menu *pMenu = new vgui::Menu( NULL, "FileMenu" );
  1146. pMenu->AddMenuItem( "new", "#AssetBuilder_FileNew", new KeyValues( "FileNew" ), this );
  1147. pMenu->AddMenuItem( "open", "#AssetBuilder_FileOpen", new KeyValues( "FileOpen" ), this );
  1148. pMenu->AddMenuItem( "save", "#AssetBuilder_FileSave", new KeyValues( "FileSave" ), this );
  1149. pMenu->AddMenuItem( "saveas", "#AssetBuilder_FileSaveAs", new KeyValues( "FileSaveAs" ), this );
  1150. SetSysMenu( pMenu );
  1151. m_pFileOpenStateMachine = new vgui::FileOpenStateMachine( this, this );
  1152. m_pFileOpenStateMachine->AddActionSignalTarget( this );
  1153. // Load layout settings; has to happen before pinning occurs in code
  1154. LoadControlSettingsAndUserConfig( "resource/assetbuilderframe.res" );
  1155. UpdateFileName();
  1156. }
  1157. CAssetBuilderFrame::~CAssetBuilderFrame()
  1158. {
  1159. }
  1160. //-----------------------------------------------------------------------------
  1161. // Inherited from IFileOpenStateMachineClient
  1162. //-----------------------------------------------------------------------------
  1163. void CAssetBuilderFrame::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues )
  1164. {
  1165. // Compute starting directory
  1166. char pStartingDir[ MAX_PATH ];
  1167. GetModContentSubdirectory( "", pStartingDir, sizeof(pStartingDir) );
  1168. if ( bOpenFile )
  1169. {
  1170. // Clear out the existing makefile if we're opening a file
  1171. m_pAssetBuilder->SetRootMakefile( NULL );
  1172. pDialog->SetTitle( "Open Asset MakeFile", true );
  1173. }
  1174. else
  1175. {
  1176. pDialog->SetTitle( "Save Asset MakeFile As", true );
  1177. }
  1178. pDialog->SetStartDirectoryContext( "asset_browser_makefile", pStartingDir );
  1179. pDialog->AddFilter( "*.*", "All Files (*.*)", false );
  1180. pDialog->AddFilter( "*.dmx", "Asset MakeFiles (*.dmx)", true, "keyvalues2" );
  1181. }
  1182. bool CAssetBuilderFrame::OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
  1183. {
  1184. CDmElement *pRoot;
  1185. CDmeMakefile *pMakeFile = ReadMakefile( pFileName, &pRoot );
  1186. if ( !pMakeFile )
  1187. return false;
  1188. Reset( pMakeFile );
  1189. return true;
  1190. }
  1191. bool CAssetBuilderFrame::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
  1192. {
  1193. // Recompute relative paths for each source now that we know the file name
  1194. // NOTE: This also updates the name of the fileID in the datamodel system
  1195. CDmeMakefile *pMakefile = m_pAssetBuilder->GetMakeFile();
  1196. bool bOk;
  1197. {
  1198. CDisableUndoScopeGuard guard;
  1199. bOk = pMakefile->SetFileName( pFileName );
  1200. }
  1201. if ( !bOk )
  1202. {
  1203. vgui::MessageBox *pError = new vgui::MessageBox( "#AssetBuilder_CannotRenameSourceFiles", "#AssetBuilder_CannotRenameSourceFilesText", this );
  1204. pError->DoModal();
  1205. return false;
  1206. }
  1207. CDmElement *pRoot = GetElement< CDmElement >( g_pDataModel->GetFileRoot( pMakefile->GetFileId() ) );
  1208. if ( !pRoot )
  1209. {
  1210. pRoot = pMakefile;
  1211. }
  1212. bOk = g_pDataModel->SaveToFile( pFileName, NULL, g_pDataModel->GetDefaultEncoding( pFileFormat ), pFileFormat, pRoot );
  1213. m_pAssetBuilder->Refresh();
  1214. return bOk;
  1215. }
  1216. //-----------------------------------------------------------------------------
  1217. // Updates the file name
  1218. //-----------------------------------------------------------------------------
  1219. void CAssetBuilderFrame::UpdateFileName( )
  1220. {
  1221. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1222. if ( !pMakeFile )
  1223. {
  1224. SetTitle( m_TitleString.Get(), true );
  1225. return;
  1226. }
  1227. DmeMakefileType_t *pMakefileType = pMakeFile->GetMakefileType();
  1228. DmFileId_t fileId = pMakeFile->GetFileId();
  1229. const char *pFileName = ( fileId != DMFILEID_INVALID ) ? g_pDataModel->GetFileName( fileId ) : "<unnamed>";
  1230. if ( !pFileName || !pFileName[0] )
  1231. {
  1232. pFileName = "<unnamed>";
  1233. }
  1234. char pBuf[2*MAX_PATH];
  1235. if ( m_TitleString.Get() )
  1236. {
  1237. Q_snprintf( pBuf, sizeof(pBuf), "%s - %s - %s%s", m_TitleString.Get(), pMakefileType->m_pHumanReadableName, pFileName, pMakeFile->IsDirty() ? " *" : "" );
  1238. }
  1239. else
  1240. {
  1241. Q_snprintf( pBuf, sizeof(pBuf), "%s - s%s", pMakefileType->m_pHumanReadableName, pFileName, pMakeFile->IsDirty() ? " *" : "" );
  1242. }
  1243. SetTitle( pBuf, true );
  1244. }
  1245. //-----------------------------------------------------------------------------
  1246. // Marks the file as dirty (or not)
  1247. //-----------------------------------------------------------------------------
  1248. void CAssetBuilderFrame::SetDirty( bool bDirty )
  1249. {
  1250. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1251. if ( pMakeFile && ( pMakeFile->IsDirty() != bDirty ) )
  1252. {
  1253. pMakeFile->SetDirty( bDirty );
  1254. // Necessary because we draw a * if it's dirty before the name
  1255. UpdateFileName();
  1256. }
  1257. }
  1258. //-----------------------------------------------------------------------------
  1259. // Called when the asset builder changes something
  1260. //-----------------------------------------------------------------------------
  1261. void CAssetBuilderFrame::OnDmeElementChanged()
  1262. {
  1263. SetDirty( true );
  1264. }
  1265. //-----------------------------------------------------------------------------
  1266. // Resets the state
  1267. //-----------------------------------------------------------------------------
  1268. void CAssetBuilderFrame::Reset( CDmeMakefile *pMakeFile )
  1269. {
  1270. // NOTE: Don't need to call SetDirty because we call UpdateFileName below
  1271. m_pAssetBuilder->SetRootMakefile( pMakeFile );
  1272. UpdateFileName();
  1273. }
  1274. //-----------------------------------------------------------------------------
  1275. // Called when the file open dialog for selecting the new asset name is selected
  1276. //-----------------------------------------------------------------------------
  1277. void CAssetBuilderFrame::OnPerformFileNew( KeyValues *kv )
  1278. {
  1279. const char *pMakefileType = kv->GetString( "makefileType" );
  1280. const char *pFileName = kv->GetString( "fileName" );
  1281. CDmeMakefile *pMakeFile;
  1282. {
  1283. DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( pFileName );
  1284. CDisableUndoScopeGuard guard;
  1285. pMakeFile = CreateElement< CDmeMakefile >( pMakefileType, pFileName, fileid );
  1286. }
  1287. if ( !pMakeFile )
  1288. return;
  1289. pMakeFile->SetFileName( pFileName );
  1290. Reset( pMakeFile );
  1291. SetDirty( true );
  1292. }
  1293. //-----------------------------------------------------------------------------
  1294. // Called when the file open dialog for browsing source files selects something
  1295. //-----------------------------------------------------------------------------
  1296. void CAssetBuilderFrame::OnFileSelected( KeyValues *kv )
  1297. {
  1298. const char *pFileName = kv->GetString( "fullpath", NULL );
  1299. if ( !pFileName )
  1300. return;
  1301. KeyValues *pDialogKeys = kv->FindKey( "OnFileNew" );
  1302. if ( pDialogKeys )
  1303. {
  1304. KeyValues *pOkCommand = new KeyValues( "PerformFileNew", "makefileType", pDialogKeys->GetString( "makefileType" ) );
  1305. pOkCommand->SetString( "fileName", pFileName );
  1306. OverwriteFileDialog( this, pFileName, pOkCommand );
  1307. return;
  1308. }
  1309. }
  1310. //-----------------------------------------------------------------------------
  1311. // Called by the picker popped up in OnFileNew
  1312. //-----------------------------------------------------------------------------
  1313. void CAssetBuilderFrame::OnPicked( KeyValues *kv )
  1314. {
  1315. const char *pValue = kv->GetString( "choice" );
  1316. CDisableUndoScopeGuard guard;
  1317. CDmeMakefile *pMakeFile = GetElement< CDmeMakefile >( g_pDataModel->CreateElement( pValue, "unnamed", DMFILEID_INVALID ) );
  1318. if ( !pMakeFile )
  1319. return;
  1320. DmeMakefileType_t *pType = pMakeFile->GetMakefileType();
  1321. char pContext[MAX_PATH];
  1322. Q_snprintf( pContext, sizeof(pContext), "asset_builder_session_%s", pType->m_pTypeName );
  1323. char pStartingDir[MAX_PATH];
  1324. pMakeFile->GetDefaultDirectory( pType->m_pDefaultDirectoryID, pStartingDir, sizeof(pStartingDir) );
  1325. g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
  1326. char pTitle[MAX_PATH];
  1327. Q_snprintf( pTitle, sizeof(pTitle), "Select %s File Name", pType->m_pHumanReadableName );
  1328. KeyValues *pDialogKeys = new KeyValues( "OnFileNew", "makefileType", pValue );
  1329. FileOpenDialog *pDialog = new FileOpenDialog( this, pTitle, false, pDialogKeys );
  1330. pDialog->SetStartDirectoryContext( pContext, pStartingDir );
  1331. pDialog->AddFilter( pType->m_pFileFilter, pType->m_pFileFilterString, true );
  1332. pDialog->AddActionSignalTarget( this );
  1333. pDialog->DoModal( false );
  1334. DestroyElement( pMakeFile );
  1335. }
  1336. //-----------------------------------------------------------------------------
  1337. // Called by the file open state machine when an operation has completed
  1338. //-----------------------------------------------------------------------------
  1339. void CAssetBuilderFrame::OnFileStateMachineFinished( KeyValues *pKeyValues )
  1340. {
  1341. KeyValues *pNewFile = pKeyValues->FindKey( "FileNew" );
  1342. if ( pNewFile )
  1343. {
  1344. if ( pKeyValues->GetInt( "wroteFile", 0 ) != 0 )
  1345. {
  1346. SetDirty( false );
  1347. UpdateFileName();
  1348. }
  1349. if ( pKeyValues->GetInt( "completionState", FileOpenStateMachine::IN_PROGRESS ) == FileOpenStateMachine::SUCCESSFUL )
  1350. {
  1351. ShowNewAssetPicker();
  1352. }
  1353. return;
  1354. }
  1355. KeyValues *pSaveFile = pKeyValues->FindKey( "FileSave" );
  1356. if ( pSaveFile )
  1357. {
  1358. if ( pKeyValues->GetInt( "wroteFile", 0 ) != 0 )
  1359. {
  1360. SetDirty( false );
  1361. UpdateFileName();
  1362. }
  1363. return;
  1364. }
  1365. }
  1366. //-----------------------------------------------------------------------------
  1367. // Shows a picker for creating a new asset
  1368. //-----------------------------------------------------------------------------
  1369. void CAssetBuilderFrame::ShowNewAssetPicker( )
  1370. {
  1371. BuildAssetTypeList();
  1372. // Create a list indicating which type of asset to create
  1373. CPickerFrame *pPicker = new CPickerFrame( this, "Select Asset Type", "Asset Type", "assetType" );
  1374. pPicker->DoModal( s_AssetTypes );
  1375. }
  1376. //-----------------------------------------------------------------------------
  1377. // Creates a new file
  1378. //-----------------------------------------------------------------------------
  1379. void CAssetBuilderFrame::OnFileNew( )
  1380. {
  1381. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1382. if ( pMakeFile && pMakeFile->IsDirty() )
  1383. {
  1384. KeyValues *pContextKeyValues = new KeyValues( "FileNew" );
  1385. const char *pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
  1386. m_pFileOpenStateMachine->SaveFile( pContextKeyValues, pFileName, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY );
  1387. return;
  1388. }
  1389. ShowNewAssetPicker();
  1390. }
  1391. void CAssetBuilderFrame::OnFileOpen( )
  1392. {
  1393. int nFlags = 0;
  1394. const char *pFileName = NULL;
  1395. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1396. if ( pMakeFile && pMakeFile->IsDirty() )
  1397. {
  1398. nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
  1399. pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
  1400. }
  1401. KeyValues *pContextKeyValues = new KeyValues( "FileOpen" );
  1402. m_pFileOpenStateMachine->OpenFile( ASSET_FILE_FORMAT, pContextKeyValues, pFileName, NULL, nFlags );
  1403. }
  1404. void CAssetBuilderFrame::OnFileSave( )
  1405. {
  1406. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1407. if ( !pMakeFile )
  1408. return;
  1409. KeyValues *pContextKeyValues = new KeyValues( "FileSave" );
  1410. const char *pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
  1411. m_pFileOpenStateMachine->SaveFile( pContextKeyValues, pFileName, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS );
  1412. }
  1413. void CAssetBuilderFrame::OnFileSaveAs( )
  1414. {
  1415. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1416. if ( !pMakeFile )
  1417. return;
  1418. KeyValues *pContextKeyValues = new KeyValues( "FileSave" );
  1419. m_pFileOpenStateMachine->SaveFile( pContextKeyValues, NULL, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS );
  1420. }