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.

2004 lines
44 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "workspacemanager.h"
  10. #include "workspacebrowser.h"
  11. #include "workspace.h"
  12. #include "statuswindow.h"
  13. #include "SoundEmitterSystem/isoundemittersystembase.h"
  14. #include "drawhelper.h"
  15. #include "InputProperties.h"
  16. #include "filesystem.h"
  17. #include "cmdlib.h"
  18. #include "project.h"
  19. #include "scene.h"
  20. #include <KeyValues.h>
  21. #include "utlbuffer.h"
  22. #include "iscenemanagersound.h"
  23. #include "soundentry.h"
  24. #include "vcdfile.h"
  25. #include "soundbrowser.h"
  26. #include "wavebrowser.h"
  27. #include "VSSProperties.h"
  28. #include "resource.h"
  29. #include "soundproperties.h"
  30. #include "waveproperties.h"
  31. #include "wavefile.h"
  32. #include "ifileloader.h"
  33. #include "MultipleRequest.h"
  34. #include <vgui/ILocalize.h>
  35. #include "tier3/tier3.h"
  36. char g_appTitle[] = "Source Engine SceneManager";
  37. static char g_appTitleFmt[] = "%s - SceneManager Workspace (%s)";
  38. static char g_appTitleFmtModified[] = "%s * - SceneManager Workspace (%s)";
  39. #define RECENT_FILES_FILE "scenemanager.rf"
  40. enum
  41. {
  42. // Menu options
  43. IDC_WSM_FILE_EXIT = 1000,
  44. IDC_WSM_FILE_WS_NEW,
  45. IDC_WSM_FILE_WS_OPEN,
  46. IDC_WSM_FILE_WS_CLOSE,
  47. IDC_WSM_FILE_WS_SAVE,
  48. IDC_WSM_FILE_WS_REFRESH,
  49. IDC_WSM_FILE_WS_VSSPROPERTIES,
  50. IDC_WSM_FILE_WS_CHECKOUT,
  51. IDC_WSM_FILE_WS_CHECKIN,
  52. IDC_WSM_FILE_SCENE_NEW, // + prompt for add to active project
  53. IDC_WSM_PROJECT_PRJ_NEW, // + Prompt for add to workspace
  54. IDC_WSM_PROJECT_PRJ_INSERT,
  55. IDC_WSM_PROJECT_PRJ_REMOVE,
  56. IDC_WSM_PROJECT_PRJ_MODIFYCOMMENTS,
  57. IDC_WSM_PROJECT_SCENE_NEW,
  58. IDC_WSM_SCENE_REMOVE,
  59. IDC_WSM_SOUNDENTRY_PLAY,
  60. IDC_WSM_SOUNDENTRY_TOGGLEVOICEDUCK,
  61. IDC_WSM_SOUNDENTRY_EDITTEXT,
  62. IDC_WSM_SOUNDENTRY_SHOWINBROWSERS,
  63. IDC_WSM_SOUNDENTRY_PROPERTIES,
  64. IDC_WSM_SCENE_VCD_ADD,
  65. IDC_WSM_SCENE_VCD_REMOVE,
  66. IDC_WSM_SCENE_EDIT_COMMENTS,
  67. IDC_WSM_VCD_EDIT_COMMENTS,
  68. IDC_WSM_SELECTION_CHECKOUT,
  69. IDC_WSM_SELECTION_CHECKIN,
  70. IDC_WSM_SELECTION_MOVEUP,
  71. IDC_WSM_SELECTION_MOVEDOWN,
  72. IDC_WSM_WAVEFILE_PROPERTIES,
  73. // Controls
  74. IDC_WS_BROWSER,
  75. IDC_WS_SOUNDBROWSER,
  76. IDC_WS_WAVEBROWSER,
  77. // These should be the final entriex
  78. IDC_WSM_FILE_RECENT_WORKSPACE_START = 1500,
  79. IDC_WSM_FILE_RECENT_WORKSPACE_END = 1510,
  80. IDC_WSM_OPTIONS_LANGUAGESTART = 1600,
  81. IDC_WSM_OPTIONS_LANGUAGEEND = 1600 + CC_NUM_LANGUAGES,
  82. };
  83. static CWorkspaceManager *g_pManager = NULL;
  84. CWorkspaceManager *GetWorkspaceManager()
  85. {
  86. Assert( g_pManager );
  87. return g_pManager;
  88. }
  89. class CWorkspaceWorkArea : public mxWindow
  90. {
  91. public:
  92. CWorkspaceWorkArea( mxWindow *parent )
  93. : mxWindow( parent, 0, 0, 0, 0, "" )
  94. {
  95. SceneManager_AddWindowStyle( this, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
  96. }
  97. virtual void redraw()
  98. {
  99. CDrawHelper helper( this, RGB( 200, 200, 200 ) );
  100. }
  101. };
  102. CWorkspaceManager::CWorkspaceManager()
  103. : mxWindow (0, 0, 0, 0, 0, g_appTitle, mxWindow::Normal)
  104. {
  105. m_lEnglishCaptionsFileChangeTime = -1L;
  106. m_nLanguageId = CC_ENGLISH;
  107. g_pManager = this;
  108. g_pStatusWindow = new CStatusWindow( this, 0, 0, 1024, 150, "" );
  109. g_pStatusWindow->setVisible( true );
  110. m_pWorkArea = new CWorkspaceWorkArea( this );
  111. Con_Printf( "Initializing\n" );
  112. Con_Printf( "CSoundEmitterSystemBase::Init()\n" );
  113. m_nRecentMenuItems = 0;
  114. // create menu stuff
  115. m_pMenuBar = new mxMenuBar (this);
  116. m_pFileMenu = new mxMenu ();
  117. m_pProjectMenu = new mxMenu ();
  118. m_pOptionsMenu = new mxMenu();
  119. {
  120. m_pMenuCloseCaptionLanguages = new mxMenu();
  121. for ( int i = 0; i < CC_NUM_LANGUAGES; i++ )
  122. {
  123. int id = IDC_WSM_OPTIONS_LANGUAGESTART + i;
  124. m_pMenuCloseCaptionLanguages->add( CSentence::NameForLanguage( i ), id );
  125. }
  126. // Check the first item
  127. m_pMenuCloseCaptionLanguages->setChecked( IDC_WSM_OPTIONS_LANGUAGESTART + CC_ENGLISH, true );
  128. m_pOptionsMenu->addMenu( "CC Language", m_pMenuCloseCaptionLanguages );
  129. }
  130. m_pMenuBar->addMenu ("File", m_pFileMenu );
  131. m_pMenuBar->addMenu( "Project", m_pProjectMenu );
  132. m_pMenuBar->addMenu ( "Options", m_pOptionsMenu );
  133. CreateFileMenu( m_pFileMenu );
  134. CreateProjectMenu( m_pProjectMenu );
  135. setMenuBar ( m_pMenuBar );
  136. Con_Printf( "Creating browser\n" );
  137. m_pBrowser = new CWorkspaceBrowser( m_pWorkArea, this, IDC_WS_BROWSER );
  138. m_pSoundBrowser = NULL;
  139. m_pWaveBrowser = NULL;
  140. int w = 1280;
  141. setBounds (10, 10, w, 960);
  142. setVisible (true);
  143. Con_Printf( "Creating wave browser\n" );
  144. m_pWaveBrowser = new CWaveBrowser( m_pWorkArea, this, IDC_WS_WAVEBROWSER );
  145. Con_Printf( "Creating sound browser\n" );
  146. m_pSoundBrowser = new CSoundBrowser( m_pWorkArea, this, IDC_WS_SOUNDBROWSER );
  147. GetBrowser()->SetWorkspace( NULL );
  148. // See if command line requested workspace
  149. // Default layout
  150. PerformLayout( true );
  151. LoadRecentFilesMenuFromDisk();
  152. }
  153. CWorkspaceManager::~CWorkspaceManager()
  154. {
  155. }
  156. bool CWorkspaceManager::Closing()
  157. {
  158. Con_Printf( "Checking for sound script changes...\n" );
  159. MultipleRequestChangeContext();
  160. // Save any changed sound script files
  161. int c = g_pSoundEmitterSystem->GetNumSoundScripts();
  162. for ( int i = 0; i < c; i++ )
  163. {
  164. if ( !g_pSoundEmitterSystem->IsSoundScriptDirty( i ) )
  165. continue;
  166. char const *scriptname = g_pSoundEmitterSystem->GetSoundScriptName( i );
  167. if ( !scriptname )
  168. continue;
  169. Assert( filesystem->FileExists( scriptname ) );
  170. bool save = true;
  171. if ( filesystem->FileExists( scriptname ) )
  172. {
  173. if ( !filesystem->IsFileWritable( scriptname ) )
  174. {
  175. int retval = MultipleRequest( va( "Check out '%s'?", scriptname ));
  176. // Cancel
  177. if ( retval == 2 )
  178. return false;
  179. if ( retval == 0 )
  180. {
  181. VSS_Checkout( scriptname );
  182. if ( !filesystem->IsFileWritable( scriptname ) )
  183. {
  184. mxMessageBox( NULL, va( "Aborting shutdown, %s, not writable!!", scriptname ), g_appTitle, MX_MB_OK );
  185. return false;
  186. }
  187. }
  188. else if ( retval == 1 )
  189. {
  190. // Don't save
  191. save = false;
  192. }
  193. }
  194. if ( filesystem->IsFileWritable( scriptname ) )
  195. {
  196. int retval = mxMessageBox( NULL, va( "Save changes to out '%s'?", scriptname ), g_appTitle, MX_MB_YESNOCANCEL );
  197. // Cancel
  198. if ( retval == 2 )
  199. return false;
  200. if ( retval == 0 )
  201. {
  202. if ( !filesystem->IsFileWritable( scriptname ) )
  203. {
  204. mxMessageBox( NULL, va( "Aborting shutdown, %s, not writable!!", scriptname ), g_appTitle, MX_MB_OK );
  205. return false;
  206. }
  207. }
  208. else if ( retval == 1 )
  209. {
  210. // Skip changes!!!
  211. save = false;
  212. }
  213. }
  214. }
  215. // Try and save it
  216. if ( !save )
  217. continue;
  218. g_pSoundEmitterSystem->SaveChangesToSoundScript( i );
  219. }
  220. return CloseWorkspace();
  221. }
  222. void CWorkspaceManager::OnDelete()
  223. {
  224. SaveRecentFilesMenuToDisk();
  225. }
  226. void CWorkspaceManager::CreateFileMenu( mxMenu *m )
  227. {
  228. m->add ("&New Workspace", IDC_WSM_FILE_WS_NEW );
  229. m->addSeparator();
  230. m->add ("Open &Workspace...", IDC_WSM_FILE_WS_OPEN );
  231. m->add ("Sa&ve Workspace", IDC_WSM_FILE_WS_SAVE );
  232. m->add ("Close Wor&kspace", IDC_WSM_FILE_WS_CLOSE );
  233. m->addSeparator();
  234. m->add ("&Create New Scene...", IDC_WSM_FILE_SCENE_NEW );
  235. m->addSeparator();
  236. m->add( "V&SS Properties...", IDC_WSM_FILE_WS_VSSPROPERTIES );
  237. m->addSeparator();
  238. m->add( "Refresh\tF5", IDC_WSM_FILE_WS_REFRESH );
  239. m->addSeparator();
  240. m_pRecentFileMenu = new mxMenu ();
  241. m->addMenu ("Recent Files", m_pRecentFileMenu);
  242. m->addSeparator();
  243. m->add ("E&xit", IDC_WSM_FILE_EXIT );
  244. }
  245. void CWorkspaceManager::UpdateMenus()
  246. {
  247. CWorkspace *ws = GetBrowser()->GetWorkspace();
  248. ITreeItem *item = GetBrowser()->GetSelectedItem();
  249. bool hasworkspace = ws != NULL ? true : false;
  250. //bool workspacedirty = ws && ws->IsDirty() ? true : false;
  251. bool hasproject = item && item->GetProject() ? true : false;
  252. m_pMenuBar->setEnabled( IDC_WSM_FILE_WS_SAVE, true );
  253. m_pMenuBar->setEnabled( IDC_WSM_FILE_WS_CLOSE, hasworkspace );
  254. if ( hasproject )
  255. {
  256. m_pMenuBar->modify( IDC_WSM_FILE_SCENE_NEW, IDC_WSM_FILE_SCENE_NEW, va( "&Create Scene in '%s'", item->GetProject()->GetName() ) );
  257. }
  258. else
  259. {
  260. m_pMenuBar->modify( IDC_WSM_FILE_SCENE_NEW, IDC_WSM_FILE_SCENE_NEW, "&Create New Scene..." );
  261. }
  262. m_pMenuBar->setEnabled( IDC_WSM_FILE_SCENE_NEW, hasproject );
  263. }
  264. void CWorkspaceManager::CreateProjectMenu( mxMenu *m )
  265. {
  266. m->add ("Create New Project...", IDC_WSM_PROJECT_PRJ_NEW );
  267. m->addSeparator();
  268. m->add ("Insert Project...", IDC_WSM_PROJECT_PRJ_INSERT );
  269. m->add ("Remove Project...", IDC_WSM_PROJECT_PRJ_REMOVE );
  270. m->addSeparator();
  271. m->add ("Properties...", IDC_WSM_PROJECT_PRJ_MODIFYCOMMENTS );
  272. }
  273. CWorkspaceBrowser *CWorkspaceManager::GetBrowser()
  274. {
  275. return m_pBrowser;
  276. }
  277. CSoundBrowser *CWorkspaceManager::GetSoundBrowser()
  278. {
  279. return m_pSoundBrowser;
  280. }
  281. CWaveBrowser *CWorkspaceManager::GetWaveBrowser()
  282. {
  283. return m_pWaveBrowser;
  284. }
  285. int CWorkspaceManager::GetMaxRecentFiles() const
  286. {
  287. return IDC_WSM_FILE_RECENT_WORKSPACE_END - IDC_WSM_FILE_RECENT_WORKSPACE_START;
  288. }
  289. #define MAX_FPS 250.0f
  290. #define MIN_TIMESTEP ( 1.0f / MAX_FPS )
  291. double realtime = 0.0f;
  292. void CWorkspaceManager::Think( float dt )
  293. {
  294. sound->Update( dt );
  295. int c = fileloader->ProcessCompleted();
  296. if ( c > 0 )
  297. {
  298. RefreshBrowsers();
  299. Con_Printf( "Thread loaded %i sounds\n", c );
  300. }
  301. }
  302. void CWorkspaceManager::Frame( void )
  303. {
  304. static bool recursion_guard = false;
  305. static double prev = 0.0;
  306. double curr = (double) mx::getTickCount () / 1000.0;
  307. double dt = ( curr - prev );
  308. if ( recursion_guard )
  309. return;
  310. recursion_guard = true;
  311. // clamp to MAX_FPS
  312. if ( dt >= 0.0 && dt < MIN_TIMESTEP )
  313. {
  314. Sleep( max( 0, (int)( ( MIN_TIMESTEP - dt ) * 1000.0f ) ) );
  315. recursion_guard = false;
  316. return;
  317. }
  318. if ( prev != 0.0 )
  319. {
  320. dt = min( 0.1, dt );
  321. Think( dt );
  322. realtime += dt;
  323. }
  324. prev = curr;
  325. recursion_guard = false;
  326. }
  327. int CWorkspaceManager::handleEvent( mxEvent *event )
  328. {
  329. int iret = 0;
  330. switch ( event->event )
  331. {
  332. default:
  333. break;
  334. case mxEvent::Activate:
  335. {
  336. if (event->action)
  337. {
  338. mx::setIdleWindow( this );
  339. // Force reload of localization data
  340. OnChangeLanguage( GetLanguageId(), true );
  341. }
  342. else
  343. {
  344. mx::setIdleWindow( 0 );
  345. }
  346. iret = 1;
  347. }
  348. break;
  349. case mxEvent::Idle:
  350. {
  351. iret = 1;
  352. Frame();
  353. }
  354. break;
  355. case mxEvent::KeyUp:
  356. {
  357. if ( event->key == VK_F5 )
  358. {
  359. RefreshBrowsers();
  360. }
  361. }
  362. break;
  363. case mxEvent::Action:
  364. {
  365. iret = 1;
  366. switch ( event->action )
  367. {
  368. default:
  369. {
  370. if ( event->action >= IDC_WSM_FILE_RECENT_WORKSPACE_START &&
  371. event->action < IDC_WSM_FILE_RECENT_WORKSPACE_END )
  372. {
  373. OnRecentWorkspace( event->action - IDC_WSM_FILE_RECENT_WORKSPACE_START );
  374. }
  375. else if ( event->action >= IDC_WSM_OPTIONS_LANGUAGESTART &&
  376. event->action < IDC_WSM_OPTIONS_LANGUAGEEND )
  377. {
  378. OnChangeLanguage( event->action - IDC_WSM_OPTIONS_LANGUAGESTART );
  379. }
  380. else
  381. {
  382. iret = 0;
  383. }
  384. }
  385. break;
  386. case IDC_WSM_FILE_EXIT:
  387. {
  388. mx::quit();
  389. }
  390. break;
  391. case IDC_WSM_FILE_WS_REFRESH:
  392. {
  393. RefreshBrowsers();
  394. }
  395. break;
  396. case IDC_WSM_FILE_WS_NEW:
  397. {
  398. OnNewWorkspace();
  399. }
  400. break;
  401. case IDC_WSM_FILE_WS_OPEN:
  402. {
  403. OnOpenWorkspace();
  404. }
  405. break;
  406. case IDC_WSM_FILE_WS_CLOSE:
  407. {
  408. OnCloseWorkspace();
  409. }
  410. break;
  411. case IDC_WSM_FILE_WS_SAVE:
  412. {
  413. OnSaveWorkspace();
  414. }
  415. break;
  416. case IDC_WSM_FILE_WS_VSSPROPERTIES:
  417. {
  418. OnChangeVSSProperites();
  419. }
  420. break;
  421. case IDC_WSM_FILE_WS_CHECKOUT:
  422. {
  423. OnCheckoutWorkspace();
  424. }
  425. break;
  426. case IDC_WSM_FILE_WS_CHECKIN:
  427. {
  428. OnCheckinWorkspace();
  429. }
  430. break;
  431. case IDC_WSM_PROJECT_PRJ_NEW:
  432. {
  433. OnNewProject();
  434. }
  435. break;
  436. case IDC_WSM_PROJECT_PRJ_INSERT:
  437. {
  438. OnInsertProject();
  439. }
  440. break;
  441. case IDC_WSM_PROJECT_PRJ_REMOVE:
  442. {
  443. OnRemoveProject();
  444. }
  445. break;
  446. case IDC_WSM_PROJECT_PRJ_MODIFYCOMMENTS:
  447. {
  448. OnModifyProjectComments();
  449. }
  450. break;
  451. case IDC_WSM_PROJECT_SCENE_NEW:
  452. {
  453. OnNewScene();
  454. }
  455. break;
  456. case IDC_WSM_SOUNDENTRY_PLAY:
  457. {
  458. OnSoundPlay();
  459. }
  460. break;
  461. case IDC_WSM_SOUNDENTRY_TOGGLEVOICEDUCK:
  462. {
  463. OnSoundToggleVoiceDuck();
  464. }
  465. break;
  466. case IDC_WSM_SOUNDENTRY_EDITTEXT:
  467. {
  468. OnSoundEditText();
  469. }
  470. break;
  471. case IDC_WSM_SOUNDENTRY_PROPERTIES:
  472. {
  473. OnSoundProperties();
  474. }
  475. break;
  476. case IDC_WSM_SCENE_VCD_ADD:
  477. {
  478. OnSceneAddVCD();
  479. }
  480. break;
  481. case IDC_WSM_SCENE_VCD_REMOVE:
  482. {
  483. OnSceneRemoveVCD();
  484. }
  485. break;
  486. case IDC_WSM_SCENE_EDIT_COMMENTS:
  487. {
  488. OnModifySceneComments();
  489. }
  490. break;
  491. case IDC_WSM_VCD_EDIT_COMMENTS:
  492. {
  493. OnModifyVCDComments();
  494. }
  495. break;
  496. case IDC_WSM_SCENE_REMOVE:
  497. {
  498. OnRemoveScene();
  499. }
  500. break;
  501. case IDC_WSM_SOUNDENTRY_SHOWINBROWSERS:
  502. {
  503. OnSoundShowInBrowsers();
  504. }
  505. break;
  506. case IDC_WSM_SELECTION_CHECKOUT:
  507. {
  508. OnCheckout();
  509. }
  510. break;
  511. case IDC_WSM_SELECTION_CHECKIN:
  512. {
  513. OnCheckin();
  514. }
  515. break;
  516. case IDC_WSM_SELECTION_MOVEUP:
  517. {
  518. OnMoveUp();
  519. }
  520. break;
  521. case IDC_WSM_SELECTION_MOVEDOWN:
  522. {
  523. OnMoveDown();
  524. }
  525. break;
  526. case IDC_WSM_WAVEFILE_PROPERTIES:
  527. {
  528. OnWaveProperties();
  529. }
  530. break;
  531. }
  532. }
  533. break;
  534. case mxEvent::Size:
  535. {
  536. iret = 1;
  537. PerformLayout( false );
  538. }
  539. break;
  540. }
  541. return iret;
  542. }
  543. //-----------------------------------------------------------------------------
  544. // Purpose:
  545. //-----------------------------------------------------------------------------
  546. void CWorkspaceManager::PerformLayout( bool movebrowsers )
  547. {
  548. int width = w2();
  549. int height = h2();
  550. int statush = 100;
  551. m_pWorkArea->setBounds( 0, 0, width, height - statush );
  552. if ( movebrowsers )
  553. {
  554. GetBrowser()->setBounds( 0, 0, m_pWorkArea->w2(), m_pWorkArea->h2() / 3 );
  555. if ( GetSoundBrowser() )
  556. {
  557. GetSoundBrowser()->setBounds( 0, m_pWorkArea->h2() / 3, m_pWorkArea->w2(), m_pWorkArea->h2() / 3 );
  558. }
  559. if ( GetWaveBrowser() )
  560. {
  561. GetWaveBrowser()->setBounds( 0, 2 * m_pWorkArea->h2() / 3, m_pWorkArea->w2(), m_pWorkArea->h2() / 3 );
  562. }
  563. }
  564. g_pStatusWindow->setBounds( 0, height - statush, width, statush );
  565. }
  566. //-----------------------------------------------------------------------------
  567. // Purpose:
  568. // Output : Returns true on success, false on failure.
  569. //-----------------------------------------------------------------------------
  570. bool CWorkspaceManager::CloseWorkspace()
  571. {
  572. CWorkspace *ws = GetBrowser()->GetWorkspace();
  573. if ( !ws )
  574. return true;
  575. if ( !ws->CanClose() )
  576. return false;
  577. delete ws;
  578. SetWorkspace( NULL );
  579. return true;
  580. }
  581. //-----------------------------------------------------------------------------
  582. // Purpose:
  583. //-----------------------------------------------------------------------------
  584. void CWorkspaceManager::OnUpdateTitle( void )
  585. {
  586. CWorkspace *ws = GetBrowser()->GetWorkspace();
  587. char szTitle[ 256 ];
  588. if ( ws )
  589. {
  590. char const *fmt = g_appTitleFmt;
  591. if ( ws->IsDirty() )
  592. {
  593. fmt = g_appTitleFmtModified;
  594. }
  595. Q_snprintf( szTitle, sizeof( szTitle ), fmt, ws->GetName(), CSentence::NameForLanguage( m_nLanguageId ) );
  596. }
  597. else
  598. {
  599. Q_snprintf( szTitle, sizeof( szTitle ), g_appTitle );
  600. }
  601. setLabel( szTitle );
  602. UpdateMenus();
  603. }
  604. //-----------------------------------------------------------------------------
  605. // Purpose:
  606. // Input : *ws -
  607. //-----------------------------------------------------------------------------
  608. void CWorkspaceManager::SetWorkspace( CWorkspace *ws )
  609. {
  610. GetBrowser()->SetWorkspace( ws );
  611. OnUpdateTitle();
  612. }
  613. //-----------------------------------------------------------------------------
  614. // Purpose:
  615. //-----------------------------------------------------------------------------
  616. void CWorkspaceManager::OnNewWorkspace()
  617. {
  618. // Show file io
  619. const char *fullpath = mxGetSaveFileName(
  620. 0,
  621. ".",
  622. "*.vsw" );
  623. if ( !fullpath || !fullpath[ 0 ] )
  624. return;
  625. // Strip game directory and slash
  626. char workspace_name[ 512 ];
  627. filesystem->FullPathToRelativePath( fullpath, workspace_name, sizeof( workspace_name ) );
  628. Q_StripExtension( workspace_name, workspace_name, sizeof( workspace_name ) );
  629. Q_DefaultExtension( workspace_name, ".vsw", sizeof( workspace_name ) );
  630. if ( filesystem->FileExists( workspace_name ) )
  631. {
  632. Con_Printf( "%s exists already!\n", workspace_name );
  633. Assert( 0 );
  634. return;
  635. }
  636. LoadWorkspace( workspace_name );
  637. }
  638. void CWorkspaceManager::AddFileToRecentWorkspaceList( char const *filename )
  639. {
  640. int i;
  641. int c = m_RecentFiles.Count();
  642. for ( i = 0; i < c; i++ )
  643. {
  644. if (!Q_stricmp( m_RecentFiles[i].filename, filename ))
  645. break;
  646. }
  647. // swap existing recent file
  648. if ( i < c )
  649. {
  650. RecentFile rf = m_RecentFiles[0];
  651. m_RecentFiles[ 0 ] = m_RecentFiles[ i ];
  652. m_RecentFiles[ i ] = rf;
  653. }
  654. // insert recent file
  655. else
  656. {
  657. RecentFile rf;
  658. Q_strcpy( rf.filename, filename );
  659. m_RecentFiles.AddToHead( rf );
  660. }
  661. while( m_RecentFiles.Count() > GetMaxRecentFiles() )
  662. {
  663. m_RecentFiles.Remove( m_RecentFiles.Count() - 1 );
  664. }
  665. UpdateRecentFilesMenu();
  666. }
  667. void CWorkspaceManager::LoadRecentFilesMenuFromDisk()
  668. {
  669. KeyValues *kv = new KeyValues( "recentfiles" );
  670. if ( kv->LoadFromFile( filesystem, RECENT_FILES_FILE ) )
  671. {
  672. for ( KeyValues *sub = kv->GetFirstSubKey(); sub; sub = sub->GetNextKey() )
  673. {
  674. RecentFile rf;
  675. Q_strncpy( rf.filename, sub->GetString(), sizeof( rf ) );
  676. m_RecentFiles.AddToTail( rf );
  677. }
  678. }
  679. kv->deleteThis();
  680. UpdateRecentFilesMenu();
  681. }
  682. void CWorkspaceManager::AutoLoad( char const *workspace )
  683. {
  684. if ( workspace )
  685. {
  686. LoadWorkspace( workspace );
  687. }
  688. else
  689. {
  690. if ( m_RecentFiles.Count() > 0 )
  691. {
  692. LoadWorkspace( m_RecentFiles[ 0 ].filename );
  693. }
  694. }
  695. }
  696. void CWorkspaceManager::SaveRecentFilesMenuToDisk()
  697. {
  698. int i;
  699. int c = m_RecentFiles.Count();
  700. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  701. buf.Printf( "recentfiles\n{\n" );
  702. for ( i = 0; i < c; i++ )
  703. {
  704. buf.Printf( "\t\"%i\"\t\"%s\"\n", i + 1, m_RecentFiles[ i ].filename );
  705. }
  706. buf.Printf( "}\n" );
  707. char const *recentfiles = RECENT_FILES_FILE;
  708. // Write it out baby
  709. FileHandle_t fh = filesystem->Open( recentfiles, "wt" );
  710. if (fh)
  711. {
  712. filesystem->Write( buf.Base(), buf.TellPut(), fh );
  713. filesystem->Close(fh);
  714. }
  715. else
  716. {
  717. Con_Printf( "CWorkspace::SaveRecentFilesMenuToDisk: Unable to write file %s!!!\n", recentfiles );
  718. }
  719. }
  720. void CWorkspaceManager::UpdateRecentFilesMenu()
  721. {
  722. int c = m_RecentFiles.Count();
  723. while ( c > m_nRecentMenuItems )
  724. {
  725. m_pRecentFileMenu->add( "(empty)", IDC_WSM_FILE_RECENT_WORKSPACE_START + m_nRecentMenuItems++ );
  726. }
  727. for (int i = 0; i < c; i++)
  728. {
  729. m_pMenuBar->modify (IDC_WSM_FILE_RECENT_WORKSPACE_START + i, IDC_WSM_FILE_RECENT_WORKSPACE_START + i, m_RecentFiles[i].filename );
  730. }
  731. }
  732. void CWorkspaceManager::LoadWorkspace( char const *filename )
  733. {
  734. if ( !CloseWorkspace() )
  735. return;
  736. Con_Printf( "Loading workspace %s\n", filename );
  737. CWorkspace *wks = new CWorkspace( filename );
  738. SetWorkspace( wks );
  739. AddFileToRecentWorkspaceList( filename );
  740. OnUpdateTitle();
  741. UpdateMenus();
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Purpose:
  745. //-----------------------------------------------------------------------------
  746. void CWorkspaceManager::OnOpenWorkspace()
  747. {
  748. // Show file io
  749. const char *fullpath = mxGetOpenFileName(
  750. 0,
  751. ".",
  752. "*.vsw" );
  753. if ( !fullpath || !fullpath[ 0 ] )
  754. return;
  755. // Strip game directory and slash
  756. char workspace_name[ 512 ];
  757. filesystem->FullPathToRelativePath( fullpath, workspace_name, sizeof( workspace_name ) );
  758. LoadWorkspace( workspace_name );
  759. }
  760. //-----------------------------------------------------------------------------
  761. // Purpose:
  762. //-----------------------------------------------------------------------------
  763. void CWorkspaceManager::OnCloseWorkspace()
  764. {
  765. if ( !CloseWorkspace() )
  766. return;
  767. Con_Printf( "Closed workspace\n" );
  768. }
  769. //-----------------------------------------------------------------------------
  770. // Purpose:
  771. //-----------------------------------------------------------------------------
  772. void CWorkspaceManager::OnSaveWorkspace()
  773. {
  774. CWorkspace *ws = GetBrowser()->GetWorkspace();
  775. if ( ws )
  776. {
  777. ws->SaveChanges();
  778. OnUpdateTitle();
  779. }
  780. }
  781. //-----------------------------------------------------------------------------
  782. // Purpose:
  783. //-----------------------------------------------------------------------------
  784. void CWorkspaceManager::OnNewProject()
  785. {
  786. Con_Printf( "OnNewProject()\n" );
  787. // Show file io
  788. const char *fullpath = mxGetSaveFileName(
  789. 0,
  790. ".",
  791. "*.vsp" );
  792. if ( !fullpath || !fullpath[ 0 ] )
  793. return;
  794. // Strip game directory and slash
  795. char project_name[ 512 ];
  796. filesystem->FullPathToRelativePath( fullpath, project_name, sizeof( project_name ) );
  797. Q_StripExtension( project_name, project_name, sizeof( project_name ) );
  798. Q_DefaultExtension( project_name, ".vsp", sizeof( project_name ) );
  799. if ( filesystem->FileExists( project_name ) )
  800. {
  801. Con_Printf( "%s exists already!\n", project_name );
  802. Assert( 0 );
  803. return;
  804. }
  805. CWorkspace *ws = GetBrowser()->GetWorkspace();
  806. if ( !ws )
  807. {
  808. // Create one on the fly
  809. char workspace_name[ 512 ];
  810. Q_StripExtension( project_name, workspace_name, sizeof( workspace_name ) );
  811. Q_DefaultExtension( workspace_name, ".vsw", sizeof( workspace_name ) );
  812. if ( !filesystem->FileExists( workspace_name ) )
  813. {
  814. int retval = mxMessageBox( NULL, va( "Automatically create workspace %s?", workspace_name ), g_appTitle, MX_MB_YESNOCANCEL );
  815. if ( retval != 0 )
  816. {
  817. Con_Printf( "Canceling project creation\n" );
  818. return;
  819. }
  820. }
  821. else
  822. {
  823. Con_Printf( "Found workspace '%s', automatically loading...\n", workspace_name );
  824. }
  825. LoadWorkspace( workspace_name );
  826. ws = GetBrowser()->GetWorkspace();
  827. }
  828. if ( ws && ws->FindProjectFile( project_name ) )
  829. {
  830. Con_Printf( "Project %s already exists in workspace\n", project_name );
  831. return;
  832. }
  833. // Create a new project and add it into current workspace
  834. CProject *proj = new CProject( ws, project_name );
  835. Assert( proj );
  836. Assert( ws );
  837. if ( ws )
  838. {
  839. GetBrowser()->AddProject( proj );
  840. }
  841. OnUpdateTitle();
  842. }
  843. //-----------------------------------------------------------------------------
  844. // Purpose:
  845. //-----------------------------------------------------------------------------
  846. void CWorkspaceManager::OnInsertProject()
  847. {
  848. Con_Printf( "OnInsertProject()\n" );
  849. // Show file io
  850. const char *fullpath = mxGetOpenFileName(
  851. 0,
  852. ".",
  853. "*.vsp" );
  854. if ( !fullpath || !fullpath[ 0 ] )
  855. return;
  856. // Strip game directory and slash
  857. char project_name[ 512 ];
  858. filesystem->FullPathToRelativePath( fullpath, project_name, sizeof( project_name ) );
  859. Q_StripExtension( project_name, project_name, sizeof( project_name ) );
  860. Q_DefaultExtension( project_name, ".vsp", sizeof( project_name ) );
  861. CWorkspace *ws = GetBrowser()->GetWorkspace();
  862. if ( !ws )
  863. {
  864. // Create one on the fly
  865. char workspace_name[ 512 ];
  866. Q_StripExtension( project_name, workspace_name, sizeof( workspace_name ) );
  867. Q_DefaultExtension( workspace_name, ".vsw", sizeof( workspace_name ) );
  868. if ( !filesystem->FileExists( workspace_name ) )
  869. {
  870. int retval = mxMessageBox( NULL, va( "Automatically create workspace %s?", workspace_name ), g_appTitle, MX_MB_YESNOCANCEL );
  871. if ( retval != 0 )
  872. {
  873. Con_Printf( "Canceling project creation\n" );
  874. return;
  875. }
  876. }
  877. else
  878. {
  879. Con_Printf( "Found workspace '%s', automatically loading...\n", workspace_name );
  880. }
  881. LoadWorkspace( workspace_name );
  882. ws = GetBrowser()->GetWorkspace();
  883. }
  884. if ( ws && ws->FindProjectFile( project_name ) )
  885. {
  886. Con_Printf( "Project %s already exists in workspace\n", project_name );
  887. return;
  888. }
  889. // Create a new project and add it into current workspace
  890. CProject *proj = new CProject( ws, project_name );
  891. Assert( proj );
  892. Assert( ws );
  893. if ( ws )
  894. {
  895. GetBrowser()->AddProject( proj );
  896. }
  897. OnUpdateTitle();
  898. }
  899. //-----------------------------------------------------------------------------
  900. // Purpose:
  901. //-----------------------------------------------------------------------------
  902. void CWorkspaceManager::OnRemoveProject()
  903. {
  904. Con_Printf( "OnRemoveProject()\n" );
  905. ITreeItem *item = GetBrowser()->GetSelectedItem();
  906. if ( !item )
  907. return;
  908. CProject *project = item->GetProject();
  909. if ( !project )
  910. {
  911. Con_Printf( "Can't remove project, item is not a project\n" );
  912. return;
  913. }
  914. CWorkspace *ws = GetBrowser()->GetWorkspace();
  915. if ( !ws )
  916. {
  917. Con_Printf( "Can't remove project '%s', no current workspace?!\n",
  918. project->GetName() );
  919. return;
  920. }
  921. ws->RemoveProject( project );
  922. Con_Printf( "Removed project '%s'\n", project->GetName() );
  923. delete project;
  924. GetBrowser()->PopulateTree();
  925. OnUpdateTitle();
  926. }
  927. void CWorkspaceManager::OnRemoveScene()
  928. {
  929. Con_Printf( "OnRemoveScene()\n" );
  930. ITreeItem *item = GetBrowser()->GetSelectedItem();
  931. if ( !item )
  932. return;
  933. CScene *scene = item->GetScene();
  934. if ( !scene )
  935. {
  936. Con_Printf( "Can't remove scene, item is not a scene\n" );
  937. return;
  938. }
  939. CProject *project = scene->GetOwnerProject();
  940. if ( !project )
  941. {
  942. Con_Printf( "Can't remove scene '%s', no current owner project?!\n",
  943. scene->GetName() );
  944. return;
  945. }
  946. project->RemoveScene( scene );
  947. Con_Printf( "Removed scene '%s'\n", scene->GetName() );
  948. delete scene;
  949. GetBrowser()->PopulateTree();
  950. OnUpdateTitle();
  951. }
  952. void CWorkspaceManager::OnNewScene()
  953. {
  954. Con_Printf( "OnNewScene()\n" );
  955. ITreeItem *item = GetBrowser()->GetSelectedItem();
  956. if ( !item )
  957. return;
  958. CProject *project = item->GetProject();
  959. if ( !project )
  960. {
  961. Con_Printf( "Can't add new scene, selected item is not a project\n" );
  962. return;
  963. }
  964. CInputParams params;
  965. memset( &params, 0, sizeof( params ) );
  966. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Create scene in '%s'", project->GetName() );
  967. Q_strcpy( params.m_szPrompt, "Scene Name:" );
  968. Q_strcpy( params.m_szInputText, "" );
  969. if ( !InputProperties( &params ) )
  970. return;
  971. if ( !params.m_szInputText[ 0 ] )
  972. {
  973. Con_Printf( "You must name the scene!\n" );
  974. return;
  975. }
  976. CScene *scene = new CScene( project, params.m_szInputText );
  977. Assert( scene );
  978. project->AddScene( scene );
  979. Con_Printf( "Added scene '%s' to project '%s'\n", scene->GetName(),
  980. project->GetName() );
  981. GetBrowser()->PopulateTree();
  982. OnUpdateTitle();
  983. }
  984. //-----------------------------------------------------------------------------
  985. // Purpose:
  986. //-----------------------------------------------------------------------------
  987. void CWorkspaceManager::OnModifyProjectComments()
  988. {
  989. Con_Printf( "OnModifyProjectComments()\n" );
  990. ITreeItem *item = GetBrowser()->GetSelectedItem();
  991. if ( !item )
  992. return;
  993. CProject *project = item->GetProject();
  994. if ( !project )
  995. {
  996. Con_Printf( "Can't modify comments, item is not a project\n" );
  997. return;
  998. }
  999. CInputParams params;
  1000. memset( &params, 0, sizeof( params ) );
  1001. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Edit comments for '%s'", project->GetName() );
  1002. Q_strcpy( params.m_szPrompt, "Comments:" );
  1003. Q_strncpy( params.m_szInputText, project->GetComments(), sizeof( params.m_szInputText ) );
  1004. if ( !InputProperties( &params ) )
  1005. return;
  1006. if ( !Q_strcmp( params.m_szInputText, project->GetComments() ) )
  1007. return;
  1008. project->SetComments( params.m_szInputText );
  1009. GetBrowser()->PopulateTree();
  1010. OnUpdateTitle();
  1011. }
  1012. //-----------------------------------------------------------------------------
  1013. // Purpose:
  1014. // Input : index -
  1015. //-----------------------------------------------------------------------------
  1016. void CWorkspaceManager::OnRecentWorkspace( int index )
  1017. {
  1018. if ( index < 0 || index >= m_RecentFiles.Count() )
  1019. return;
  1020. LoadWorkspace( m_RecentFiles[ index ].filename );
  1021. }
  1022. int CWorkspaceManager::GetLanguageId() const
  1023. {
  1024. return m_nLanguageId;
  1025. }
  1026. void CWorkspaceManager::OnChangeLanguage( int lang_index, bool force /* = false */ )
  1027. {
  1028. bool changed = m_nLanguageId != lang_index;
  1029. m_nLanguageId = lang_index;
  1030. if ( changed || force )
  1031. {
  1032. // Update the menu
  1033. for ( int i = 0; i < CC_NUM_LANGUAGES; i++ )
  1034. {
  1035. int id = IDC_WSM_OPTIONS_LANGUAGESTART + i;
  1036. m_pMenuCloseCaptionLanguages->setChecked( id, i == m_nLanguageId );
  1037. }
  1038. bool filechanged = false;
  1039. char const *suffix = CSentence::NameForLanguage( lang_index );
  1040. if ( Q_stricmp( suffix, "unknown_language" ) )
  1041. {
  1042. char fn[ MAX_PATH ];
  1043. Q_snprintf( fn, sizeof( fn ), "resource/closecaption_%s.txt", suffix );
  1044. long filetimestamp = filesystem->GetFileTime( fn );
  1045. if ( filesystem->FileExists( fn ) )
  1046. {
  1047. if ( m_lEnglishCaptionsFileChangeTime != filetimestamp )
  1048. {
  1049. filechanged = true;
  1050. m_lEnglishCaptionsFileChangeTime = filetimestamp;
  1051. //Con_Printf( "Reloading close caption data from '%s'\n", fn );
  1052. g_pVGuiLocalize->RemoveAll();
  1053. g_pVGuiLocalize->AddFile( fn );
  1054. }
  1055. }
  1056. else
  1057. {
  1058. Con_Printf( "CWorkspaceManager::OnChangeLanguage Warning, can't find localization file %s\n", fn );
  1059. }
  1060. }
  1061. if ( !force || filechanged )
  1062. {
  1063. // Update all text for items.
  1064. RefreshBrowsers();
  1065. OnUpdateTitle();
  1066. }
  1067. }
  1068. }
  1069. void CWorkspaceManager::OnDoubleClicked( ITreeItem *item )
  1070. {
  1071. CSoundEntry *s = item->GetSoundEntry();
  1072. if ( s )
  1073. {
  1074. s->Play();
  1075. return;
  1076. }
  1077. }
  1078. void CWorkspaceManager::OnSoundPlay()
  1079. {
  1080. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1081. if ( item->GetSoundEntry() )
  1082. {
  1083. item->GetSoundEntry()->Play();
  1084. }
  1085. else if ( item->GetWaveFile() )
  1086. {
  1087. item->GetWaveFile()->Play();
  1088. }
  1089. }
  1090. void CWorkspaceManager::OnSoundToggleVoiceDuck()
  1091. {
  1092. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1093. if ( item->GetWaveFile() )
  1094. {
  1095. item->GetWaveFile()->ToggleVoiceDucking();
  1096. }
  1097. }
  1098. void CWorkspaceManager::OnSoundEditText()
  1099. {
  1100. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1101. if ( !item )
  1102. return;
  1103. CWaveFile *s = item->GetWaveFile();
  1104. if ( !s )
  1105. return;
  1106. CInputParams params;
  1107. memset( &params, 0, sizeof( params ) );
  1108. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Edit text of '%s'", s->GetName() );
  1109. Q_strcpy( params.m_szPrompt, "Sentence text:" );
  1110. V_strcpy_safe( params.m_szInputText, s->GetSentenceText() );
  1111. if ( !InputProperties( &params ) )
  1112. return;
  1113. if ( !Q_stricmp( params.m_szInputText, s->GetSentenceText() ) )
  1114. {
  1115. return;
  1116. }
  1117. s->SetSentenceText( params.m_szInputText );
  1118. GetBrowser()->PopulateTree();
  1119. OnUpdateTitle();
  1120. }
  1121. // Scene entries
  1122. void CWorkspaceManager::OnSceneAddVCD()
  1123. {
  1124. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1125. if ( !item )
  1126. return;
  1127. CScene *scene = item->GetScene();
  1128. if ( !scene )
  1129. return;
  1130. // Show file io
  1131. const char *fullpath = mxGetOpenFileName(
  1132. 0,
  1133. ".",
  1134. "*.vcd" );
  1135. if ( !fullpath || !fullpath[ 0 ] )
  1136. return;
  1137. // Strip game directory and slash
  1138. char vcd_name[ 512 ];
  1139. filesystem->FullPathToRelativePath( fullpath, vcd_name, sizeof( vcd_name ) );
  1140. Q_StripExtension( vcd_name, vcd_name, sizeof( vcd_name ) );
  1141. Q_DefaultExtension( vcd_name, ".vcd", sizeof( vcd_name ) );
  1142. if ( scene->FindVCD( vcd_name ) )
  1143. {
  1144. Con_Printf( "File '%s' is already in scene '%s'\n", vcd_name, scene->GetName() );
  1145. return;
  1146. }
  1147. CVCDFile *vcd = new CVCDFile( scene, vcd_name );
  1148. scene->AddVCD( vcd );
  1149. GetBrowser()->PopulateTree();
  1150. OnUpdateTitle();
  1151. }
  1152. void CWorkspaceManager::OnModifySceneComments()
  1153. {
  1154. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1155. if ( !item )
  1156. return;
  1157. CScene *scene = item->GetScene();
  1158. if ( !scene )
  1159. return;
  1160. CInputParams params;
  1161. memset( &params, 0, sizeof( params ) );
  1162. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Edit comments for '%s'", scene->GetName() );
  1163. Q_strcpy( params.m_szPrompt, "Comments:" );
  1164. Q_strncpy( params.m_szInputText, scene->GetComments(), sizeof( params.m_szInputText ) );
  1165. if ( !InputProperties( &params ) )
  1166. return;
  1167. if ( !Q_strcmp( params.m_szInputText, scene->GetComments() ) )
  1168. return;
  1169. scene->SetComments( params.m_szInputText );
  1170. GetBrowser()->PopulateTree();
  1171. OnUpdateTitle();
  1172. }
  1173. void CWorkspaceManager::OnModifyVCDComments()
  1174. {
  1175. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1176. if ( !item )
  1177. return;
  1178. CVCDFile *file = item->GetVCDFile();
  1179. if ( !file )
  1180. return;
  1181. CInputParams params;
  1182. memset( &params, 0, sizeof( params ) );
  1183. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Edit comments for '%s'", file->GetName() );
  1184. Q_strcpy( params.m_szPrompt, "Comments:" );
  1185. Q_strncpy( params.m_szInputText, file->GetComments(), sizeof( params.m_szInputText ) );
  1186. if ( !InputProperties( &params ) )
  1187. return;
  1188. if ( !Q_strcmp( params.m_szInputText, file->GetComments() ) )
  1189. return;
  1190. file->SetComments( params.m_szInputText );
  1191. GetBrowser()->PopulateTree();
  1192. OnUpdateTitle();
  1193. }
  1194. void CWorkspaceManager::OnSceneRemoveVCD()
  1195. {
  1196. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1197. if ( !item )
  1198. return;
  1199. CVCDFile *file = item->GetVCDFile();
  1200. if ( !file )
  1201. return;
  1202. CScene *scene = file->GetOwnerScene();
  1203. if ( !scene )
  1204. return;
  1205. scene->RemoveVCD( file );
  1206. GetBrowser()->PopulateTree();
  1207. OnUpdateTitle();
  1208. }
  1209. void CWorkspaceManager::ShowContextMenu( int x, int y, ITreeItem *p )
  1210. {
  1211. CWorkspace *w = p->GetWorkspace();
  1212. if ( w )
  1213. {
  1214. ShowContextMenu_Workspace( x, y, w );
  1215. return;
  1216. }
  1217. CProject *proj = p->GetProject();
  1218. if ( proj )
  1219. {
  1220. ShowContextMenu_Project( x, y, proj );
  1221. return;
  1222. }
  1223. CScene *scene = p->GetScene();
  1224. if ( scene )
  1225. {
  1226. ShowContextMenu_Scene( x, y, scene );
  1227. return;
  1228. }
  1229. CVCDFile *vcd = p->GetVCDFile();
  1230. if ( vcd )
  1231. {
  1232. ShowContextMenu_VCD( x, y, vcd );
  1233. return;
  1234. }
  1235. CSoundEntry *sound = p->GetSoundEntry();
  1236. if ( sound )
  1237. {
  1238. ShowContextMenu_SoundEntry( x, y, sound );
  1239. return;
  1240. }
  1241. CWaveFile *wave = p->GetWaveFile();
  1242. if ( wave )
  1243. {
  1244. ShowContextMenu_WaveFile( x, y, wave );
  1245. return;
  1246. }
  1247. Con_Printf( "unknown tree item type\n" );
  1248. Assert( 0 );
  1249. }
  1250. void CWorkspaceManager::ShowContextMenu_Workspace( int x, int y, CWorkspace *ws )
  1251. {
  1252. if ( !ws )
  1253. return;
  1254. // New project and insert project
  1255. mxPopupMenu *pop = new mxPopupMenu();
  1256. pop->add ("Create New Project...", IDC_WSM_PROJECT_PRJ_NEW );
  1257. pop->add ("Insert Project...", IDC_WSM_PROJECT_PRJ_INSERT );
  1258. pop->addSeparator();
  1259. pop->add( "VSS Properties...", IDC_WSM_FILE_WS_VSSPROPERTIES );
  1260. if ( !filesystem->IsFileWritable( ws->GetFileName() ) )
  1261. {
  1262. pop->add( va( "Checkout '%s'", ws->GetName() ), IDC_WSM_SELECTION_CHECKOUT );
  1263. }
  1264. else
  1265. {
  1266. pop->add( va( "Checkin '%s'", ws->GetName() ), IDC_WSM_SELECTION_CHECKIN );
  1267. }
  1268. pop->popup( this, x, y );
  1269. }
  1270. void CWorkspaceManager::ShowContextMenu_Project( int x, int y, CProject *project )
  1271. {
  1272. // New scene, edit comments
  1273. mxPopupMenu *pop = new mxPopupMenu();
  1274. pop->add ("Create New Scene...", IDC_WSM_PROJECT_SCENE_NEW );
  1275. pop->addSeparator();
  1276. pop->add ("Remove Project...", IDC_WSM_PROJECT_PRJ_REMOVE );
  1277. pop->addSeparator();
  1278. pop->add( "Edit comments...", IDC_WSM_PROJECT_PRJ_MODIFYCOMMENTS );
  1279. if ( !project->IsFirstChild() || !project->IsLastChild() )
  1280. {
  1281. pop->addSeparator();
  1282. if( !project->IsFirstChild() )
  1283. {
  1284. pop->add( va( "Move '%s' Up", project->GetName() ), IDC_WSM_SELECTION_MOVEUP );
  1285. }
  1286. if( !project->IsLastChild() )
  1287. {
  1288. pop->add( va( "Move '%s' Down", project->GetName() ), IDC_WSM_SELECTION_MOVEDOWN );
  1289. }
  1290. }
  1291. pop->addSeparator();
  1292. if ( !filesystem->IsFileWritable( project->GetFileName() ) )
  1293. {
  1294. pop->add( va( "Checkout '%s'", project->GetName() ), IDC_WSM_SELECTION_CHECKOUT );
  1295. }
  1296. else
  1297. {
  1298. pop->add( va( "Checkin '%s'", project->GetName() ), IDC_WSM_SELECTION_CHECKIN );
  1299. }
  1300. pop->popup( this, x, y );
  1301. }
  1302. void CWorkspaceManager::ShowContextMenu_Scene( int x, int y, CScene *scene )
  1303. {
  1304. // New scene, edit comments
  1305. mxPopupMenu *pop = new mxPopupMenu();
  1306. pop->add( va( "Add VCD to '%s'...", scene->GetName() ), IDC_WSM_SCENE_VCD_ADD );
  1307. pop->addSeparator();
  1308. pop->add ("Remove Scene", IDC_WSM_SCENE_REMOVE );
  1309. pop->addSeparator();
  1310. pop->add( va( "Edit comments..." ), IDC_WSM_SCENE_EDIT_COMMENTS );
  1311. if ( !scene->IsFirstChild() || !scene->IsLastChild() )
  1312. {
  1313. pop->addSeparator();
  1314. if( !scene->IsFirstChild() )
  1315. {
  1316. pop->add( va( "Move '%s' Up", scene->GetName() ), IDC_WSM_SELECTION_MOVEUP );
  1317. }
  1318. if( !scene->IsLastChild() )
  1319. {
  1320. pop->add( va( "Move '%s' Down", scene->GetName() ), IDC_WSM_SELECTION_MOVEDOWN );
  1321. }
  1322. }
  1323. pop->popup( this, x, y );
  1324. }
  1325. void CWorkspaceManager::ShowContextMenu_VCD( int x, int y, CVCDFile *vcd )
  1326. {
  1327. // New scene, edit comments
  1328. mxPopupMenu *pop = new mxPopupMenu();
  1329. pop->add( va( "Remove VCD" ), IDC_WSM_SCENE_VCD_REMOVE );
  1330. pop->addSeparator();
  1331. pop->add( va( "Edit comments..." ), IDC_WSM_VCD_EDIT_COMMENTS );
  1332. if ( !vcd->IsFirstChild() || !vcd->IsLastChild() )
  1333. {
  1334. pop->addSeparator();
  1335. if( !vcd->IsFirstChild() )
  1336. {
  1337. pop->add( va( "Move '%s' Up", vcd->GetName() ), IDC_WSM_SELECTION_MOVEUP );
  1338. }
  1339. if( !vcd->IsLastChild() )
  1340. {
  1341. pop->add( va( "Move '%s' Down", vcd->GetName() ), IDC_WSM_SELECTION_MOVEDOWN );
  1342. }
  1343. }
  1344. pop->addSeparator();
  1345. if ( !filesystem->IsFileWritable( vcd->GetName() ) )
  1346. {
  1347. pop->add( va( "Checkout '%s'", vcd->GetName() ), IDC_WSM_SELECTION_CHECKOUT );
  1348. }
  1349. else
  1350. {
  1351. pop->add( va( "Checkin '%s'", vcd->GetName() ), IDC_WSM_SELECTION_CHECKIN );
  1352. }
  1353. pop->popup( this, x, y );
  1354. }
  1355. void CWorkspaceManager::ShowContextMenu_SoundEntry( int x, int y, CSoundEntry *entry )
  1356. {
  1357. // New scene, edit comments
  1358. mxPopupMenu *pop = new mxPopupMenu();
  1359. pop->add ("&Play", IDC_WSM_SOUNDENTRY_PLAY );
  1360. // pop->add( "&Jump To", IDC_WSM_SOUNDENTRY_SHOWINBROWSERS );
  1361. pop->addSeparator();
  1362. pop->add( "Properties...", IDC_WSM_SOUNDENTRY_PROPERTIES );
  1363. pop->popup( this, x, y );
  1364. }
  1365. void CWorkspaceManager::ShowContextMenu_WaveFile( int x, int y, CWaveFile *entry )
  1366. {
  1367. // New scene, edit comments
  1368. mxPopupMenu *pop = new mxPopupMenu();
  1369. pop->add ("&Play", IDC_WSM_SOUNDENTRY_PLAY );
  1370. // pop->add( "&Jump To", IDC_WSM_SOUNDENTRY_SHOWINBROWSERS );
  1371. if ( entry->GetVoiceDuck() )
  1372. {
  1373. pop->add ("Disable &voice duck", IDC_WSM_SOUNDENTRY_TOGGLEVOICEDUCK );
  1374. }
  1375. else
  1376. {
  1377. pop->add ("Enable &voice duck", IDC_WSM_SOUNDENTRY_TOGGLEVOICEDUCK );
  1378. }
  1379. pop->add( "&Edit sentence text...", IDC_WSM_SOUNDENTRY_EDITTEXT );
  1380. pop->addSeparator();
  1381. if ( !filesystem->IsFileWritable( entry->GetFileName() ) )
  1382. {
  1383. pop->add( va( "Checkout '%s'", entry->GetName() ), IDC_WSM_SELECTION_CHECKOUT );
  1384. }
  1385. else
  1386. {
  1387. pop->add( va( "Checkin '%s'", entry->GetName() ), IDC_WSM_SELECTION_CHECKIN );
  1388. }
  1389. pop->addSeparator();
  1390. pop->add( "Properties...", IDC_WSM_WAVEFILE_PROPERTIES );
  1391. pop->popup( this, x, y );
  1392. }
  1393. void CWorkspaceManager::OnChangeVSSProperites()
  1394. {
  1395. CWorkspace *ws = GetBrowser()->GetWorkspace();
  1396. if ( !ws )
  1397. {
  1398. return;
  1399. }
  1400. CVSSParams params;
  1401. memset( &params, 0, sizeof( params ) );
  1402. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "VSS Properites" );
  1403. V_strcpy_safe( params.m_szUserName, ws->GetVSSUserName() );
  1404. V_strcpy_safe( params.m_szProject, ws->GetVSSProject() );
  1405. if ( !VSSProperties( &params ) )
  1406. return;
  1407. if ( !params.m_szUserName[ 0 ] )
  1408. {
  1409. Con_Printf( "You must enter a user name\n" );
  1410. return;
  1411. }
  1412. if ( !params.m_szProject[ 0 ] )
  1413. {
  1414. Con_Printf( "You must enter a project name\n" );
  1415. return;
  1416. }
  1417. ws->SetVSSUserName( params.m_szUserName );
  1418. ws->SetVSSProject( params.m_szProject );
  1419. ws->SetDirty( true );
  1420. Con_Printf( "VSS user = '%s', project = '%s'\n",
  1421. ws->GetVSSUserName(), ws->GetVSSProject() );
  1422. }
  1423. void CWorkspaceManager::OnCheckoutWorkspace()
  1424. {
  1425. CWorkspace *ws = GetBrowser()->GetWorkspace();
  1426. if ( !ws )
  1427. {
  1428. return;
  1429. }
  1430. ws->Checkout();
  1431. }
  1432. void CWorkspaceManager::OnCheckinWorkspace()
  1433. {
  1434. CWorkspace *ws = GetBrowser()->GetWorkspace();
  1435. if ( !ws )
  1436. {
  1437. return;
  1438. }
  1439. ws->Checkin();
  1440. }
  1441. #define CX_ICON 16
  1442. #define CY_ICON 16
  1443. HIMAGELIST CWorkspaceManager::CreateImageList()
  1444. {
  1445. HIMAGELIST list;
  1446. list = ImageList_Create( CX_ICON, CY_ICON,
  1447. FALSE, NUM_IMAGES, 0 );
  1448. // Load the icon resources, and add the icons to the image list.
  1449. HICON hicon;
  1450. int slot;
  1451. #if defined( DBGFLAG_ASSERT )
  1452. int c = 0;
  1453. #endif
  1454. hicon = LoadIcon( GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WORKSPACE));
  1455. slot = ImageList_AddIcon(list, hicon);
  1456. Assert( slot == c++ );
  1457. DeleteObject( hicon );
  1458. hicon = LoadIcon( GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WORKSPACE_CHECKEDOUT));
  1459. slot = ImageList_AddIcon(list, hicon);
  1460. Assert( slot == c++ );
  1461. DeleteObject( hicon );
  1462. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_PROJECT));
  1463. slot = ImageList_AddIcon(list, hicon);
  1464. Assert( slot == c++ );
  1465. DeleteObject( hicon );
  1466. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_PROJECT_CHECKEDOUT));
  1467. slot = ImageList_AddIcon(list, hicon);
  1468. Assert( slot == c++ );
  1469. DeleteObject( hicon );
  1470. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SCENE));
  1471. slot = ImageList_AddIcon(list, hicon);
  1472. Assert( slot == c++ );
  1473. DeleteObject( hicon );
  1474. // hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SCENE_CHECKEDOUT));
  1475. // slot = ImageList_AddIcon(list, hicon);
  1476. // Assert( slot == c++ );
  1477. // DeleteObject( hicon );
  1478. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_VCD));
  1479. slot = ImageList_AddIcon(list, hicon);
  1480. Assert( slot == c++ );
  1481. DeleteObject( hicon );
  1482. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_VCD_CHECKEDOUT ));
  1483. slot = ImageList_AddIcon(list, hicon);
  1484. Assert( slot == c++ );
  1485. DeleteObject( hicon );
  1486. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WAV));
  1487. slot = ImageList_AddIcon(list, hicon);
  1488. Assert( slot == c++ );
  1489. DeleteObject( hicon );
  1490. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WAV_CHECKEDOUT));
  1491. slot = ImageList_AddIcon(list, hicon);
  1492. Assert( slot == c++ );
  1493. DeleteObject( hicon );
  1494. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SPEAK));
  1495. slot = ImageList_AddIcon(list, hicon);
  1496. Assert( slot == c++ );
  1497. DeleteObject( hicon );
  1498. hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SPEAK_CHECKEDOUT));
  1499. slot = ImageList_AddIcon(list, hicon);
  1500. Assert( slot == c++ );
  1501. DeleteObject( hicon );
  1502. return list;
  1503. }
  1504. //-----------------------------------------------------------------------------
  1505. // Purpose:
  1506. //-----------------------------------------------------------------------------
  1507. void CWorkspaceManager::RefreshBrowsers()
  1508. {
  1509. if ( GetBrowser() )
  1510. {
  1511. GetBrowser()->PopulateTree();
  1512. }
  1513. if ( GetSoundBrowser() )
  1514. {
  1515. GetSoundBrowser()->RepopulateTree();
  1516. }
  1517. if ( GetWaveBrowser() )
  1518. {
  1519. GetWaveBrowser()->RepopulateTree();
  1520. }
  1521. }
  1522. void CWorkspaceManager::OnSoundShowInBrowsers()
  1523. {
  1524. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1525. if ( !item )
  1526. return;
  1527. CSoundEntry *se = item->GetSoundEntry();
  1528. if ( se )
  1529. {
  1530. GetSoundBrowser()->JumpToItem( se );
  1531. return;
  1532. }
  1533. CWaveFile *wave = item->GetWaveFile();
  1534. if ( wave )
  1535. {
  1536. GetWaveBrowser()->JumpToItem( wave );
  1537. if ( wave->GetOwnerSoundEntry() )
  1538. {
  1539. GetSoundBrowser()->JumpToItem( wave->GetOwnerSoundEntry() );
  1540. }
  1541. }
  1542. }
  1543. void CWorkspaceManager::OnCheckout()
  1544. {
  1545. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1546. if ( !item )
  1547. return;
  1548. item->Checkout();
  1549. GetBrowser()->PopulateTree();
  1550. OnUpdateTitle();
  1551. }
  1552. void CWorkspaceManager::OnCheckin()
  1553. {
  1554. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1555. if ( !item )
  1556. return;
  1557. item->Checkin();
  1558. GetBrowser()->PopulateTree();
  1559. OnUpdateTitle();
  1560. }
  1561. void CWorkspaceManager::OnMoveUp()
  1562. {
  1563. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1564. if ( !item )
  1565. return;
  1566. ITreeItem *parent = item->GetParentItem();
  1567. if ( !parent )
  1568. return;
  1569. parent->MoveChildUp( item );
  1570. parent->SetDirty( true );
  1571. GetBrowser()->PopulateTree();
  1572. OnUpdateTitle();
  1573. GetBrowser()->JumpTo( item );
  1574. }
  1575. void CWorkspaceManager::OnMoveDown()
  1576. {
  1577. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1578. if ( !item )
  1579. return;
  1580. ITreeItem *parent = item->GetParentItem();
  1581. if ( !parent )
  1582. return;
  1583. parent->MoveChildDown( item );
  1584. parent->SetDirty( true );
  1585. GetBrowser()->PopulateTree();
  1586. OnUpdateTitle();
  1587. GetBrowser()->JumpTo( item );
  1588. }
  1589. void CWorkspaceManager::SetWorkspaceDirty()
  1590. {
  1591. CWorkspace *ws = GetBrowser()->GetWorkspace();
  1592. if ( ws )
  1593. {
  1594. ws->SetDirty( true );
  1595. }
  1596. OnUpdateTitle();
  1597. }
  1598. //-----------------------------------------------------------------------------
  1599. // Purpose:
  1600. //-----------------------------------------------------------------------------
  1601. void CWorkspaceManager::OnSoundProperties()
  1602. {
  1603. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1604. if ( !item )
  1605. return;
  1606. CSoundEntry *entry = item->GetSoundEntry();
  1607. if ( !entry )
  1608. return;
  1609. CSoundParams params;
  1610. memset( &params, 0, sizeof( params ) );
  1611. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Sound Properties" );
  1612. params.items.AddToTail( entry );
  1613. SoundProperties( &params );
  1614. }
  1615. //-----------------------------------------------------------------------------
  1616. // Purpose:
  1617. //-----------------------------------------------------------------------------
  1618. void CWorkspaceManager::OnWaveProperties()
  1619. {
  1620. ITreeItem *item = GetBrowser()->GetSelectedItem();
  1621. if ( !item )
  1622. return;
  1623. CWaveFile *wave = item->GetWaveFile();
  1624. if ( !wave )
  1625. return;
  1626. CWaveParams params;
  1627. memset( &params, 0, sizeof( params ) );
  1628. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Wave Properties" );
  1629. params.items.AddToTail( wave );
  1630. WaveProperties( &params );
  1631. }