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.

1725 lines
54 KiB

  1. //========= Copyright 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. vgui::surface()->DrawSetTextureFile( m_CompilingId, "vgui/progressbar", true, false );
  75. }
  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" ) );
  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" ) );
  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" ) );
  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->SetDeleteSelfOnClose( true );
  567. pDialog->AddActionSignalTarget( this );
  568. pDialog->DoModal( false );
  569. DestroyElement( pMakeFile );
  570. }
  571. //-----------------------------------------------------------------------------
  572. // Creates a new source file, hooks it in
  573. //-----------------------------------------------------------------------------
  574. void CAssetBuilder::OnNewSourceFile( )
  575. {
  576. KeyValues *pKeyValues = GetSelectedSourceKeyvalues();
  577. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  578. if ( !pSource )
  579. return;
  580. BuildAssetTypeList();
  581. PickerList_t typePickerList;
  582. PickerList_t &pickerList = BuildAssetSubTypeList( pSource->GetSourceMakefileTypes(), typePickerList );
  583. // Create a list indicating which type of asset to create
  584. CPickerFrame *pPicker = new CPickerFrame( this, "Select Sub-Asset Type", "Asset Type", "assetType" );
  585. pPicker->DoModal( pickerList );
  586. }
  587. //-----------------------------------------------------------------------------
  588. // Called when the button to add a file is clicked
  589. //-----------------------------------------------------------------------------
  590. void CAssetBuilder::OnAddSource( )
  591. {
  592. if ( !m_hMakefile.Get() )
  593. return;
  594. PickerList_t sourceType;
  595. DmeMakefileType_t *pSourceTypes = m_hMakefile->GetSourceTypes();
  596. for ( int i = 0; pSourceTypes[i].m_pTypeName; ++i )
  597. {
  598. if ( pSourceTypes[i].m_bIsSingleton )
  599. {
  600. if ( m_hMakefile->HasSourceOfType( pSourceTypes[i].m_pTypeName ) )
  601. continue;
  602. }
  603. int j = sourceType.AddToTail( );
  604. sourceType[j].m_pChoiceString = pSourceTypes[i].m_pHumanReadableName;
  605. sourceType[j].m_pChoiceValue = pSourceTypes[i].m_pTypeName;
  606. }
  607. if ( sourceType.Count() == 0 )
  608. return;
  609. KeyValues *pContextKeys = new KeyValues( "OnAddSource" );
  610. CPickerFrame *pPicker = new CPickerFrame( this, "Select Source Type", "Source Type", "sourceType" );
  611. pPicker->DoModal( sourceType, pContextKeys );
  612. }
  613. //-----------------------------------------------------------------------------
  614. // Returns the curerntly selected row
  615. //-----------------------------------------------------------------------------
  616. int CAssetBuilder::GetSelectedRow( )
  617. {
  618. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  619. return ( nItemID != -1 ) ? m_pSourcesList->GetItemCurrentRow( nItemID ) : -1;
  620. }
  621. //-----------------------------------------------------------------------------
  622. // Selects a particular row of the source list
  623. //-----------------------------------------------------------------------------
  624. void CAssetBuilder::SelectSourceListRow( int nRow )
  625. {
  626. int nVisibleRowCount = m_pSourcesList->GetItemCount();
  627. if ( nVisibleRowCount == 0 || nRow < 0 )
  628. return;
  629. if ( nRow >= nVisibleRowCount )
  630. {
  631. nRow = nVisibleRowCount - 1;
  632. }
  633. int nNewItemID = m_pSourcesList->GetItemIDFromRow( nRow );
  634. m_pSourcesList->SetSingleSelectedItem( nNewItemID );
  635. }
  636. //-----------------------------------------------------------------------------
  637. // Called when the button to remove a file is clicked
  638. //-----------------------------------------------------------------------------
  639. void CAssetBuilder::OnRemoveSource( )
  640. {
  641. int nCount = m_pSourcesList->GetSelectedItemsCount();
  642. if ( nCount == 0 || !m_hMakefile.Get() )
  643. return;
  644. int nRow = GetSelectedRow();
  645. Assert( nRow >= 0 );
  646. // Update the selection to be reasonable after deletion
  647. CDisableUndoScopeGuard guard;
  648. for ( int i = 0; i < nCount; ++i )
  649. {
  650. int nItemID = m_pSourcesList->GetSelectedItem( i );
  651. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  652. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  653. if ( pSource )
  654. {
  655. m_hMakefile->RemoveSource( pSource );
  656. DestroyElement( pSource );
  657. SetDirty( );
  658. }
  659. }
  660. RefreshSourceList();
  661. SelectSourceListRow( nRow );
  662. }
  663. //-----------------------------------------------------------------------------
  664. // Called to make a particular source the currently selected source
  665. //-----------------------------------------------------------------------------
  666. void CAssetBuilder::OnZoomInSource()
  667. {
  668. // Called to zoom into the currently selected source
  669. CDmeSource *pSource = GetSelectedSource( );
  670. if ( !pSource )
  671. return;
  672. CDmeMakefile *pChild = m_hMakefile->FindDependentMakefile( pSource );
  673. if ( pChild )
  674. {
  675. CDmeHandle< CDmeMakefile > hChild;
  676. hChild = pChild;
  677. m_hMakefileStack.Push( hChild );
  678. SetCurrentMakefile( pChild );
  679. }
  680. }
  681. //-----------------------------------------------------------------------------
  682. // Called to zoom out of a particular source
  683. //-----------------------------------------------------------------------------
  684. void CAssetBuilder::OnZoomOutSource()
  685. {
  686. // Called to zoom into the currently selected source
  687. if ( m_hMakefileStack.Count() <= 1 )
  688. return;
  689. CDmeMakefile *pOldParent = m_hMakefileStack.Top().Get();
  690. m_hMakefileStack.Pop( );
  691. CDmeMakefile *pParent = m_hMakefileStack.Top().Get();
  692. if ( pParent )
  693. {
  694. SetCurrentMakefile( pParent );
  695. CDmeSource *pSource = pParent->FindAssociatedSource( pOldParent );
  696. if ( pSource )
  697. {
  698. SelectSource( pSource );
  699. }
  700. }
  701. }
  702. //-----------------------------------------------------------------------------
  703. // Called when a key is typed
  704. //-----------------------------------------------------------------------------
  705. void CAssetBuilder::OnKeyCodeTyped( vgui::KeyCode code )
  706. {
  707. if ( code == KEY_DELETE )
  708. {
  709. OnRemoveSource();
  710. return;
  711. }
  712. if ( code == KEY_ENTER )
  713. {
  714. OnZoomInSource();
  715. return;
  716. }
  717. BaseClass::OnKeyCodeTyped( code );
  718. }
  719. //-----------------------------------------------------------------------------
  720. // Called when we're browsing for a source file and one was selected
  721. //-----------------------------------------------------------------------------
  722. void CAssetBuilder::OnSourceFileAdded( const char *pFileName, const char *pTypeName )
  723. {
  724. CDmeSource *pSource = NULL;
  725. {
  726. CDisableUndoScopeGuard guard;
  727. pSource = m_hMakefile->AddSource( pTypeName, pFileName );
  728. }
  729. SetDirty( );
  730. RefreshSourceList( );
  731. SelectSource( pSource );
  732. }
  733. //-----------------------------------------------------------------------------
  734. // Called when the file open dialog for browsing source files selects something
  735. //-----------------------------------------------------------------------------
  736. void CAssetBuilder::OnNewSourceFileSelected( const char *pFileName, KeyValues *kv )
  737. {
  738. int nCount = m_pSourcesList->GetSelectedItemsCount();
  739. if ( nCount != 1 || !m_hMakefile.Get() )
  740. return;
  741. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  742. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  743. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  744. if ( !pSource )
  745. return;
  746. const char *pMakeFileType = kv->GetString( "makefileType" );
  747. {
  748. CDisableUndoScopeGuard guard;
  749. m_hMakefile->SetSourceFullPath( pSource, pFileName );
  750. DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( pFileName );
  751. CDmeMakefile *pSourceMakeFile = CreateElement< CDmeMakefile >( pMakeFileType, pFileName, fileid );
  752. pSourceMakeFile->SetFileName( pFileName );
  753. m_hMakefile->SetAssociation( pSource, pSourceMakeFile );
  754. SetDirty( );
  755. }
  756. pKeyValues->SetString( "file", pFileName );
  757. m_pSourcesList->ApplyItemChanges( nItemID );
  758. m_pSourcesList->SortList();
  759. }
  760. //-----------------------------------------------------------------------------
  761. // Called when the file open dialog for browsing source files selects something
  762. //-----------------------------------------------------------------------------
  763. void CAssetBuilder::OnFileSelected( KeyValues *kv )
  764. {
  765. const char *pFileName = kv->GetString( "fullpath", NULL );
  766. if ( !pFileName )
  767. return;
  768. KeyValues *pDialogKeys = kv->FindKey( "SelectSourceFile" );
  769. if ( pDialogKeys )
  770. {
  771. OnSourceFileNameChanged( pFileName );
  772. return;
  773. }
  774. pDialogKeys = kv->FindKey( "NewSourceFileSelected" );
  775. if ( pDialogKeys )
  776. {
  777. if ( !g_pFullFileSystem->FileExists( pFileName ) )
  778. {
  779. OnNewSourceFileSelected( pFileName, pDialogKeys );
  780. }
  781. else
  782. {
  783. OnSourceFileNameChanged( pFileName );
  784. }
  785. return;
  786. }
  787. }
  788. //-----------------------------------------------------------------------------
  789. // Shows the source file browser
  790. //-----------------------------------------------------------------------------
  791. void CAssetBuilder::ShowSourceFileBrowser( const char *pTitle, DmeMakefileType_t *pSourceType, KeyValues *pDialogKeys )
  792. {
  793. char pContext[MAX_PATH];
  794. Q_snprintf( pContext, sizeof(pContext), "asset_builder_session_%s", pSourceType->m_pTypeName );
  795. char pStartingDir[MAX_PATH];
  796. m_hMakefile->GetDefaultDirectory( pSourceType->m_pDefaultDirectoryID, pStartingDir, sizeof(pStartingDir) );
  797. g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
  798. FileOpenDialog *pDialog = new FileOpenDialog( this, pTitle, true, pDialogKeys );
  799. pDialog->SetStartDirectoryContext( pContext, pStartingDir );
  800. pDialog->AddFilter( pSourceType->m_pFileFilter, pSourceType->m_pFileFilterString, true );
  801. pDialog->SetDeleteSelfOnClose( true );
  802. pDialog->AddActionSignalTarget( this );
  803. pDialog->DoModal( false );
  804. }
  805. //-----------------------------------------------------------------------------
  806. // Called when the button to browse for a source file is clicked
  807. //-----------------------------------------------------------------------------
  808. void CAssetBuilder::OnBrowseSourceFile( )
  809. {
  810. KeyValues *pKeyValues = GetSelectedSourceKeyvalues();
  811. if ( !pKeyValues )
  812. return;
  813. int nSourceTypeIndex = pKeyValues->GetInt( "sourceTypeIndex", -1 );
  814. KeyValues *pDialogKeys = new KeyValues( "SelectSourceFile" );
  815. DmeMakefileType_t &sourceType = m_hMakefile->GetSourceTypes()[nSourceTypeIndex];
  816. ShowSourceFileBrowser( "Select Source File", &sourceType, pDialogKeys );
  817. }
  818. //-----------------------------------------------------------------------------
  819. // Command handler
  820. //-----------------------------------------------------------------------------
  821. void CAssetBuilder::OnCommand( const char *pCommand )
  822. {
  823. if ( !Q_stricmp( pCommand, "OnCompile" ) )
  824. {
  825. OnCompile();
  826. return;
  827. }
  828. if ( !Q_stricmp( pCommand, "OnAbortCompile" ) )
  829. {
  830. OnAbortCompile();
  831. return;
  832. }
  833. if ( !Q_stricmp( pCommand, "OnPublish" ) )
  834. {
  835. OnPublish();
  836. return;
  837. }
  838. BaseClass::OnCommand( pCommand );
  839. }
  840. //-----------------------------------------------------------------------------
  841. // Cleans up the context menu
  842. //-----------------------------------------------------------------------------
  843. void CAssetBuilder::CleanupContextMenu()
  844. {
  845. if ( m_hContextMenu.Get() )
  846. {
  847. m_hContextMenu->MarkForDeletion();
  848. m_hContextMenu = NULL;
  849. }
  850. }
  851. //-----------------------------------------------------------------------------
  852. // Called to open a context-sensitive menu for a particular menu item
  853. //-----------------------------------------------------------------------------
  854. void CAssetBuilder::OnOpenContextMenu( KeyValues *kv )
  855. {
  856. CleanupContextMenu();
  857. if ( !m_hMakefile.Get() )
  858. return;
  859. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  860. int nItemID = kv->GetInt( "itemID", -1 );
  861. if ( pPanel != m_pSourcesList )
  862. return;
  863. m_hContextMenu = new Menu( this, "ActionMenu" );
  864. m_hContextMenu->AddMenuItem( "Add...", new KeyValues( "AddSource" ), this );
  865. int nCount = m_pSourcesList->GetSelectedItemsCount();
  866. if ( nCount > 0 )
  867. {
  868. m_hContextMenu->AddMenuItem( "Remove", new KeyValues( "RemoveSource" ), this );
  869. }
  870. bool bShowZoomIn = false;
  871. bool bShowZoomOut = m_hMakefileStack.Count() > 1;
  872. bool bShowLoadSourceFile = false;
  873. bool bHasValidSourceFile = false;
  874. if ( nCount == 1 && nItemID != -1 )
  875. {
  876. KeyValues *kv = m_pSourcesList->GetItem( nItemID );
  877. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( kv, "dmeSource" );
  878. if ( pSource )
  879. {
  880. bHasValidSourceFile = pSource->GetRelativeFileName()[0] != 0;
  881. if ( m_hMakefile->FindDependentMakefile( pSource ) )
  882. {
  883. bShowZoomIn = true;
  884. }
  885. else
  886. {
  887. bShowLoadSourceFile = bHasValidSourceFile;
  888. }
  889. }
  890. }
  891. if ( bShowZoomIn || bShowZoomOut )
  892. {
  893. m_hContextMenu->AddSeparator();
  894. if ( bShowZoomIn )
  895. {
  896. m_hContextMenu->AddMenuItem( "Zoom In", new KeyValues( "ZoomInSource" ), this );
  897. }
  898. if ( bShowZoomOut )
  899. {
  900. m_hContextMenu->AddMenuItem( "Zoom Out", new KeyValues( "ZoomOutSource" ), this );
  901. }
  902. }
  903. if ( nCount == 1 )
  904. {
  905. m_hContextMenu->AddSeparator();
  906. m_hContextMenu->AddMenuItem( "New Source File...", new KeyValues( "NewSourceFile" ), this );
  907. m_hContextMenu->AddMenuItem( "Select Source File...", new KeyValues( "BrowseSourceFile" ), this );
  908. if ( bShowLoadSourceFile )
  909. {
  910. m_hContextMenu->AddMenuItem( "Load Source File", new KeyValues( "LoadSourceFile" ), this );
  911. }
  912. if ( bHasValidSourceFile )
  913. {
  914. m_hContextMenu->AddMenuItem( "Edit Source File", new KeyValues( "EditSourceFile" ), this );
  915. }
  916. }
  917. Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
  918. }
  919. //-----------------------------------------------------------------------------
  920. // Called when a list panel's selection changes
  921. //-----------------------------------------------------------------------------
  922. void CAssetBuilder::OnSourceItemSelectionChanged( )
  923. {
  924. int nCount = m_pSourcesList->GetSelectedItemsCount();
  925. if ( nCount != 1 )
  926. {
  927. m_pDmePanel->SetDmeElement( NULL );
  928. return;
  929. }
  930. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  931. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  932. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  933. m_pDmePanel->SetDmeElement( pSource );
  934. }
  935. //-----------------------------------------------------------------------------
  936. // Called when a list panel's selection changes
  937. //-----------------------------------------------------------------------------
  938. void CAssetBuilder::OnItemSelected( KeyValues *kv )
  939. {
  940. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  941. if ( pPanel == m_pSourcesList )
  942. {
  943. OnSourceItemSelectionChanged();
  944. return;
  945. }
  946. }
  947. //-----------------------------------------------------------------------------
  948. // Called when a list panel's selection changes
  949. //-----------------------------------------------------------------------------
  950. void CAssetBuilder::OnItemDeselected( KeyValues *kv )
  951. {
  952. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  953. if ( pPanel == m_pSourcesList )
  954. {
  955. OnSourceItemSelectionChanged();
  956. return;
  957. }
  958. }
  959. //-----------------------------------------------------------------------------
  960. // Returns the selected source (if there's only 1 source selected)
  961. //-----------------------------------------------------------------------------
  962. CDmeSource *CAssetBuilder::GetSelectedSource( )
  963. {
  964. int nCount = m_pSourcesList->GetSelectedItemsCount();
  965. if ( nCount != 1 || !m_hMakefile.Get() )
  966. return NULL;
  967. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  968. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  969. return GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  970. }
  971. KeyValues *CAssetBuilder::GetSelectedSourceKeyvalues( )
  972. {
  973. int nCount = m_pSourcesList->GetSelectedItemsCount();
  974. if ( nCount != 1 || !m_hMakefile.Get() )
  975. return NULL;
  976. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  977. return m_pSourcesList->GetItem( nItemID );
  978. }
  979. //-----------------------------------------------------------------------------
  980. // Called when the source file name changes
  981. //-----------------------------------------------------------------------------
  982. void CAssetBuilder::OnSourceFileNameChanged( const char *pFileName )
  983. {
  984. int nCount = m_pSourcesList->GetSelectedItemsCount();
  985. if ( nCount != 1 || !m_hMakefile.Get() )
  986. return;
  987. int nItemID = m_pSourcesList->GetSelectedItem( 0 );
  988. KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
  989. CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
  990. if ( !pSource )
  991. return;
  992. {
  993. CDisableUndoScopeGuard guard;
  994. m_hMakefile->SetSourceFullPath( pSource, pFileName );
  995. SetDirty( );
  996. }
  997. pKeyValues->SetString( "file", pFileName );
  998. m_pSourcesList->ApplyItemChanges( nItemID );
  999. m_pSourcesList->SortList();
  1000. }
  1001. //-----------------------------------------------------------------------------
  1002. // Called during compilation
  1003. //-----------------------------------------------------------------------------
  1004. void CAssetBuilder::OnLoadSourceFile()
  1005. {
  1006. CDmeSource *pSource = GetSelectedSource( );
  1007. if ( !pSource )
  1008. return;
  1009. char pFullPath[MAX_PATH];
  1010. m_hMakefile->GetSourceFullPath( pSource, pFullPath, sizeof(pFullPath) );
  1011. {
  1012. CDisableUndoScopeGuard guard;
  1013. CDmElement *pRoot;
  1014. CDmeMakefile *pMakeFile = ReadMakefile( pFullPath, &pRoot );
  1015. if ( !pMakeFile )
  1016. return;
  1017. // Successfully loaded a makefile. Set up the association.
  1018. m_hMakefile->SetAssociation( pSource, pMakeFile );
  1019. // Refresh the dme panel... setting association could provoke changes
  1020. m_pDmePanel->SetDmeElement( pSource, true );
  1021. }
  1022. }
  1023. //-----------------------------------------------------------------------------
  1024. // Called to open an external editor for this source file
  1025. //-----------------------------------------------------------------------------
  1026. void CAssetBuilder::OnEditSourceFile()
  1027. {
  1028. CDmeSource *pSource = GetSelectedSource( );
  1029. if ( pSource )
  1030. {
  1031. pSource->OpenEditor();
  1032. }
  1033. }
  1034. //-----------------------------------------------------------------------------
  1035. // Finishes compilation
  1036. //-----------------------------------------------------------------------------
  1037. void CAssetBuilder::FinishCompilation( CompilationState_t state )
  1038. {
  1039. // NOTE: compilation can cause the makefile to be completely
  1040. // rebuilt if it's sitting in the output file. Therefore,
  1041. // Detach the source preview panel from the source and refresh the
  1042. // source list to get it to correctly reconnect to the new source elements
  1043. m_pDmePanel->SetDmeElement( NULL );
  1044. int nRow = GetSelectedRow();
  1045. m_pOututPreviewPanel->SetDmeElement( m_hMakefile, true, "DmeMakeFileOutputPreview" );
  1046. m_bIsCompiling = false;
  1047. // NOTE: Sort of side-effecty. These two things must be done after
  1048. // m_pOututPreviewPanel->SetDmeElement, since that's what reloads the output element,
  1049. // which is also what can cause a reload of the makefile
  1050. RefreshSourceList();
  1051. SelectSourceListRow( nRow );
  1052. // Lets the asset builder update the title bar
  1053. // (compilation could have changed the dirty state if the makefile is in the file)
  1054. PostActionSignal( new KeyValues( "UpdateFileName" ) );
  1055. if ( state == COMPILATION_FAILED )
  1056. {
  1057. char pBuf[256];
  1058. Q_snprintf( pBuf, sizeof(pBuf), "Compilation Error (return code %d)", g_pDmeMakefileUtils->GetExitCode() );
  1059. m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_FAILED, pBuf );
  1060. }
  1061. else
  1062. {
  1063. m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_SUCCESSFUL, "Compile Successful!" );
  1064. }
  1065. }
  1066. //-----------------------------------------------------------------------------
  1067. // Called during compilation
  1068. //-----------------------------------------------------------------------------
  1069. void CAssetBuilder::OnTick()
  1070. {
  1071. BaseClass::OnTick();
  1072. if ( m_bIsCompiling )
  1073. {
  1074. int nLen = g_pDmeMakefileUtils->GetCompileOutputSize( );
  1075. char *pBuf = (char*)_alloca( nLen+1 );
  1076. CompilationState_t state = g_pDmeMakefileUtils->UpdateCompilation( pBuf, nLen );
  1077. if ( nLen > 0 )
  1078. {
  1079. m_pCompileOutput->InsertString( pBuf );
  1080. }
  1081. Assert( m_hMakefile.Get() );
  1082. if ( state != COMPILATION_NOT_COMPLETE )
  1083. {
  1084. FinishCompilation( state );
  1085. }
  1086. }
  1087. if ( !m_bIsCompiling )
  1088. {
  1089. m_pAbortCompile->SetEnabled( false );
  1090. vgui::ivgui()->RemoveTickSignal( GetVPanel() );
  1091. }
  1092. }
  1093. //-----------------------------------------------------------------------------
  1094. // Abort compile asset
  1095. //-----------------------------------------------------------------------------
  1096. void CAssetBuilder::OnAbortCompile()
  1097. {
  1098. if ( m_bIsCompiling )
  1099. {
  1100. g_pDmeMakefileUtils->AbortCurrentCompilation();
  1101. m_bIsCompiling = false;
  1102. m_pAbortCompile->SetEnabled( false );
  1103. m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_FAILED, "Compile Aborted" );
  1104. }
  1105. }
  1106. //-----------------------------------------------------------------------------
  1107. // Compile asset
  1108. //-----------------------------------------------------------------------------
  1109. void CAssetBuilder::OnCompile( )
  1110. {
  1111. if ( !m_hMakefile.Get() )
  1112. return;
  1113. OnAbortCompile();
  1114. m_pCompileOutput->SetText( "" );
  1115. g_pDmeMakefileUtils->PerformCompile( m_hMakefile, false );
  1116. m_bIsCompiling = true;
  1117. m_pAbortCompile->SetEnabled( true );
  1118. m_pCompileStatusBar->SetStatus( CCompileStatusBar::CURRENTLY_COMPILING, "Compiling..." );
  1119. vgui::ivgui()->AddTickSignal( GetVPanel(), 10 );
  1120. }
  1121. //-----------------------------------------------------------------------------
  1122. // Compile, then publish
  1123. //-----------------------------------------------------------------------------
  1124. void CAssetBuilder::OnPublish( )
  1125. {
  1126. if ( !m_hMakefile.Get() )
  1127. return;
  1128. OnAbortCompile();
  1129. m_pCompileOutput->SetText( "" );
  1130. g_pDmeMakefileUtils->PerformCompile( m_hMakefile, false );
  1131. m_bIsCompiling = true;
  1132. m_pAbortCompile->SetEnabled( true );
  1133. m_pCompileStatusBar->SetStatus( CCompileStatusBar::CURRENTLY_COMPILING, "Compiling..." );
  1134. vgui::ivgui()->AddTickSignal( GetVPanel(), 10 );
  1135. }
  1136. //-----------------------------------------------------------------------------
  1137. // Purpose: Constructor, destructor
  1138. //-----------------------------------------------------------------------------
  1139. CAssetBuilderFrame::CAssetBuilderFrame( vgui::Panel *pParent, const char *pTitle ) :
  1140. BaseClass( pParent, "AssetBuilderFrame" )
  1141. {
  1142. m_TitleString = pTitle;
  1143. SetMenuButtonVisible( true );
  1144. SetImages( "resource/downarrow" );
  1145. m_pAssetBuilder = new CAssetBuilder( this, "AssetBuilder" );
  1146. m_pAssetBuilder->AddActionSignalTarget( this );
  1147. vgui::Menu *pMenu = new vgui::Menu( NULL, "FileMenu" );
  1148. pMenu->AddMenuItem( "new", "#AssetBuilder_FileNew", new KeyValues( "FileNew" ), this );
  1149. pMenu->AddMenuItem( "open", "#AssetBuilder_FileOpen", new KeyValues( "FileOpen" ), this );
  1150. pMenu->AddMenuItem( "save", "#AssetBuilder_FileSave", new KeyValues( "FileSave" ), this );
  1151. pMenu->AddMenuItem( "saveas", "#AssetBuilder_FileSaveAs", new KeyValues( "FileSaveAs" ), this );
  1152. SetSysMenu( pMenu );
  1153. m_pFileOpenStateMachine = new vgui::FileOpenStateMachine( this, this );
  1154. m_pFileOpenStateMachine->AddActionSignalTarget( this );
  1155. // Load layout settings; has to happen before pinning occurs in code
  1156. LoadControlSettingsAndUserConfig( "resource/assetbuilderframe.res" );
  1157. UpdateFileName();
  1158. }
  1159. CAssetBuilderFrame::~CAssetBuilderFrame()
  1160. {
  1161. }
  1162. //-----------------------------------------------------------------------------
  1163. // Inherited from IFileOpenStateMachineClient
  1164. //-----------------------------------------------------------------------------
  1165. void CAssetBuilderFrame::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues )
  1166. {
  1167. // Compute starting directory
  1168. char pStartingDir[ MAX_PATH ];
  1169. GetModContentSubdirectory( "", pStartingDir, sizeof(pStartingDir) );
  1170. if ( bOpenFile )
  1171. {
  1172. // Clear out the existing makefile if we're opening a file
  1173. m_pAssetBuilder->SetRootMakefile( NULL );
  1174. pDialog->SetTitle( "Open Asset MakeFile", true );
  1175. }
  1176. else
  1177. {
  1178. pDialog->SetTitle( "Save Asset MakeFile As", true );
  1179. }
  1180. pDialog->SetStartDirectoryContext( "asset_browser_makefile", pStartingDir );
  1181. pDialog->AddFilter( "*.*", "All Files (*.*)", false );
  1182. pDialog->AddFilter( "*.dmx", "Asset MakeFiles (*.dmx)", true, "keyvalues2" );
  1183. }
  1184. bool CAssetBuilderFrame::OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
  1185. {
  1186. CDmElement *pRoot;
  1187. CDmeMakefile *pMakeFile = ReadMakefile( pFileName, &pRoot );
  1188. if ( !pMakeFile )
  1189. return false;
  1190. Reset( pMakeFile );
  1191. return true;
  1192. }
  1193. bool CAssetBuilderFrame::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
  1194. {
  1195. // Recompute relative paths for each source now that we know the file name
  1196. // NOTE: This also updates the name of the fileID in the datamodel system
  1197. CDmeMakefile *pMakefile = m_pAssetBuilder->GetMakeFile();
  1198. bool bOk;
  1199. {
  1200. CDisableUndoScopeGuard guard;
  1201. bOk = pMakefile->SetFileName( pFileName );
  1202. }
  1203. if ( !bOk )
  1204. {
  1205. vgui::MessageBox *pError = new vgui::MessageBox( "#AssetBuilder_CannotRenameSourceFiles", "#AssetBuilder_CannotRenameSourceFilesText", this );
  1206. pError->DoModal();
  1207. return false;
  1208. }
  1209. CDmElement *pRoot = GetElement< CDmElement >( g_pDataModel->GetFileRoot( pMakefile->GetFileId() ) );
  1210. if ( !pRoot )
  1211. {
  1212. pRoot = pMakefile;
  1213. }
  1214. bOk = g_pDataModel->SaveToFile( pFileName, NULL, g_pDataModel->GetDefaultEncoding( pFileFormat ), pFileFormat, pRoot );
  1215. m_pAssetBuilder->Refresh();
  1216. return bOk;
  1217. }
  1218. //-----------------------------------------------------------------------------
  1219. // Updates the file name
  1220. //-----------------------------------------------------------------------------
  1221. void CAssetBuilderFrame::UpdateFileName( )
  1222. {
  1223. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1224. if ( !pMakeFile )
  1225. {
  1226. SetTitle( m_TitleString.Get(), true );
  1227. return;
  1228. }
  1229. DmeMakefileType_t *pMakefileType = pMakeFile->GetMakefileType();
  1230. DmFileId_t fileId = pMakeFile->GetFileId();
  1231. const char *pFileName = ( fileId != DMFILEID_INVALID ) ? g_pDataModel->GetFileName( fileId ) : "<unnamed>";
  1232. if ( !pFileName || !pFileName[0] )
  1233. {
  1234. pFileName = "<unnamed>";
  1235. }
  1236. char pBuf[2*MAX_PATH];
  1237. if ( m_TitleString.Get() )
  1238. {
  1239. Q_snprintf( pBuf, sizeof(pBuf), "%s - %s - %s%s", m_TitleString.Get(), pMakefileType->m_pHumanReadableName, pFileName, pMakeFile->IsDirty() ? " *" : "" );
  1240. }
  1241. else
  1242. {
  1243. Q_snprintf( pBuf, sizeof(pBuf), "%s - %s%s", pMakefileType->m_pHumanReadableName, pFileName, pMakeFile->IsDirty() ? " *" : "" );
  1244. }
  1245. SetTitle( pBuf, true );
  1246. }
  1247. //-----------------------------------------------------------------------------
  1248. // Marks the file as dirty (or not)
  1249. //-----------------------------------------------------------------------------
  1250. void CAssetBuilderFrame::SetDirty( bool bDirty )
  1251. {
  1252. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1253. if ( pMakeFile && ( pMakeFile->IsDirty() != bDirty ) )
  1254. {
  1255. pMakeFile->SetDirty( bDirty );
  1256. // Necessary because we draw a * if it's dirty before the name
  1257. UpdateFileName();
  1258. }
  1259. }
  1260. //-----------------------------------------------------------------------------
  1261. // Called when the asset builder changes something
  1262. //-----------------------------------------------------------------------------
  1263. void CAssetBuilderFrame::OnDmeElementChanged()
  1264. {
  1265. SetDirty( true );
  1266. }
  1267. //-----------------------------------------------------------------------------
  1268. // Resets the state
  1269. //-----------------------------------------------------------------------------
  1270. void CAssetBuilderFrame::Reset( CDmeMakefile *pMakeFile )
  1271. {
  1272. // NOTE: Don't need to call SetDirty because we call UpdateFileName below
  1273. m_pAssetBuilder->SetRootMakefile( pMakeFile );
  1274. UpdateFileName();
  1275. }
  1276. //-----------------------------------------------------------------------------
  1277. // Called when the file open dialog for selecting the new asset name is selected
  1278. //-----------------------------------------------------------------------------
  1279. void CAssetBuilderFrame::OnPerformFileNew( KeyValues *kv )
  1280. {
  1281. const char *pMakefileType = kv->GetString( "makefileType" );
  1282. const char *pFileName = kv->GetString( "fileName" );
  1283. CDmeMakefile *pMakeFile;
  1284. {
  1285. DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( pFileName );
  1286. CDisableUndoScopeGuard guard;
  1287. pMakeFile = CreateElement< CDmeMakefile >( pMakefileType, pFileName, fileid );
  1288. }
  1289. if ( !pMakeFile )
  1290. return;
  1291. pMakeFile->SetFileName( pFileName );
  1292. Reset( pMakeFile );
  1293. SetDirty( true );
  1294. }
  1295. //-----------------------------------------------------------------------------
  1296. // Called when the file open dialog for browsing source files selects something
  1297. //-----------------------------------------------------------------------------
  1298. void CAssetBuilderFrame::OnFileSelected( KeyValues *kv )
  1299. {
  1300. const char *pFileName = kv->GetString( "fullpath", NULL );
  1301. if ( !pFileName )
  1302. return;
  1303. KeyValues *pDialogKeys = kv->FindKey( "OnFileNew" );
  1304. if ( pDialogKeys )
  1305. {
  1306. KeyValues *pOkCommand = new KeyValues( "PerformFileNew", "makefileType", pDialogKeys->GetString( "makefileType" ) );
  1307. pOkCommand->SetString( "fileName", pFileName );
  1308. OverwriteFileDialog( this, pFileName, pOkCommand );
  1309. return;
  1310. }
  1311. }
  1312. //-----------------------------------------------------------------------------
  1313. // Called by the picker popped up in OnFileNew
  1314. //-----------------------------------------------------------------------------
  1315. void CAssetBuilderFrame::OnPicked( KeyValues *kv )
  1316. {
  1317. const char *pValue = kv->GetString( "choice" );
  1318. CDisableUndoScopeGuard guard;
  1319. CDmeMakefile *pMakeFile = GetElement< CDmeMakefile >( g_pDataModel->CreateElement( pValue, "unnamed" ) );
  1320. if ( !pMakeFile )
  1321. return;
  1322. DmeMakefileType_t *pType = pMakeFile->GetMakefileType();
  1323. char pContext[MAX_PATH];
  1324. Q_snprintf( pContext, sizeof(pContext), "asset_builder_session_%s", pType->m_pTypeName );
  1325. char pStartingDir[MAX_PATH];
  1326. pMakeFile->GetDefaultDirectory( pType->m_pDefaultDirectoryID, pStartingDir, sizeof(pStartingDir) );
  1327. g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
  1328. char pTitle[MAX_PATH];
  1329. Q_snprintf( pTitle, sizeof(pTitle), "Select %s File Name", pType->m_pHumanReadableName );
  1330. KeyValues *pDialogKeys = new KeyValues( "OnFileNew", "makefileType", pValue );
  1331. FileOpenDialog *pDialog = new FileOpenDialog( this, pTitle, false, pDialogKeys );
  1332. pDialog->SetStartDirectoryContext( pContext, pStartingDir );
  1333. pDialog->AddFilter( pType->m_pFileFilter, pType->m_pFileFilterString, true );
  1334. pDialog->SetDeleteSelfOnClose( true );
  1335. pDialog->AddActionSignalTarget( this );
  1336. pDialog->DoModal( false );
  1337. DestroyElement( pMakeFile );
  1338. }
  1339. //-----------------------------------------------------------------------------
  1340. // Called by the file open state machine when an operation has completed
  1341. //-----------------------------------------------------------------------------
  1342. void CAssetBuilderFrame::OnFileStateMachineFinished( KeyValues *pKeyValues )
  1343. {
  1344. KeyValues *pNewFile = pKeyValues->FindKey( "FileNew" );
  1345. if ( pNewFile )
  1346. {
  1347. if ( pKeyValues->GetInt( "wroteFile", 0 ) != 0 )
  1348. {
  1349. SetDirty( false );
  1350. UpdateFileName();
  1351. }
  1352. if ( pKeyValues->GetInt( "completionState", FileOpenStateMachine::IN_PROGRESS ) == FileOpenStateMachine::SUCCESSFUL )
  1353. {
  1354. ShowNewAssetPicker();
  1355. }
  1356. return;
  1357. }
  1358. KeyValues *pSaveFile = pKeyValues->FindKey( "FileSave" );
  1359. if ( pSaveFile )
  1360. {
  1361. if ( pKeyValues->GetInt( "wroteFile", 0 ) != 0 )
  1362. {
  1363. SetDirty( false );
  1364. UpdateFileName();
  1365. }
  1366. return;
  1367. }
  1368. }
  1369. //-----------------------------------------------------------------------------
  1370. // Shows a picker for creating a new asset
  1371. //-----------------------------------------------------------------------------
  1372. void CAssetBuilderFrame::ShowNewAssetPicker( )
  1373. {
  1374. BuildAssetTypeList();
  1375. // Create a list indicating which type of asset to create
  1376. CPickerFrame *pPicker = new CPickerFrame( this, "Select Asset Type", "Asset Type", "assetType" );
  1377. pPicker->DoModal( s_AssetTypes );
  1378. }
  1379. //-----------------------------------------------------------------------------
  1380. // Creates a new file
  1381. //-----------------------------------------------------------------------------
  1382. void CAssetBuilderFrame::OnFileNew( )
  1383. {
  1384. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1385. if ( pMakeFile && pMakeFile->IsDirty() )
  1386. {
  1387. KeyValues *pContextKeyValues = new KeyValues( "FileNew" );
  1388. const char *pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
  1389. m_pFileOpenStateMachine->SaveFile( pContextKeyValues, pFileName, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY );
  1390. return;
  1391. }
  1392. ShowNewAssetPicker();
  1393. }
  1394. void CAssetBuilderFrame::OnFileOpen( )
  1395. {
  1396. int nFlags = 0;
  1397. const char *pFileName = NULL;
  1398. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1399. if ( pMakeFile && pMakeFile->IsDirty() )
  1400. {
  1401. nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
  1402. pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
  1403. }
  1404. KeyValues *pContextKeyValues = new KeyValues( "FileOpen" );
  1405. m_pFileOpenStateMachine->OpenFile( ASSET_FILE_FORMAT, pContextKeyValues, pFileName, NULL, nFlags );
  1406. }
  1407. void CAssetBuilderFrame::OnFileSave( )
  1408. {
  1409. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1410. if ( !pMakeFile )
  1411. return;
  1412. KeyValues *pContextKeyValues = new KeyValues( "FileSave" );
  1413. const char *pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
  1414. m_pFileOpenStateMachine->SaveFile( pContextKeyValues, pFileName, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS );
  1415. }
  1416. void CAssetBuilderFrame::OnFileSaveAs( )
  1417. {
  1418. CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
  1419. if ( !pMakeFile )
  1420. return;
  1421. KeyValues *pContextKeyValues = new KeyValues( "FileSave" );
  1422. m_pFileOpenStateMachine->SaveFile( pContextKeyValues, NULL, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS );
  1423. }