Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1324 lines
34 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: Core Movie Maker UI API
  4. //
  5. //=============================================================================
  6. #include "commedittool.h"
  7. #include "vgui_controls/Menu.h"
  8. #include "tier1/KeyValues.h"
  9. #include "vgui/IInput.h"
  10. #include "vgui/KeyCode.h"
  11. #include "vgui_controls/FileOpenDialog.h"
  12. #include "vgui_controls/PropertySheet.h"
  13. #include "filesystem.h"
  14. #include "vgui/ilocalize.h"
  15. #include "dme_controls/elementpropertiestree.h"
  16. #include "tier0/icommandline.h"
  17. #include "materialsystem/imaterialsystem.h"
  18. #include "vguimatsurface/imatsystemsurface.h"
  19. #include "commeditdoc.h"
  20. #include "commentarynodebrowserpanel.h"
  21. #include "commentarypropertiespanel.h"
  22. #include "dme_controls/AttributeStringChoicePanel.h"
  23. #include "tier2/fileutils.h"
  24. #include "tier3/tier3.h"
  25. #include "vgui/ivgui.h"
  26. #include "toolutils/ConsolePage.h"
  27. using namespace vgui;
  28. enum
  29. {
  30. FILEOPEN_NEW_BSP,
  31. FILEOPEN_EXISTING_TXT,
  32. };
  33. const char *GetVGuiControlsModuleName()
  34. {
  35. return "CommEditTool";
  36. }
  37. //-----------------------------------------------------------------------------
  38. // Connect, disconnect
  39. //-----------------------------------------------------------------------------
  40. bool ConnectTools( CreateInterfaceFn factory )
  41. {
  42. return (materials != NULL) && (g_pMatSystemSurface != NULL) && (g_pMDLCache != NULL) && (studiorender != NULL) && (g_pMaterialSystemHardwareConfig != NULL);
  43. }
  44. void DisconnectTools( )
  45. {
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Singleton
  49. //-----------------------------------------------------------------------------
  50. CCommEditTool *g_pCommEditTool = NULL;
  51. void CreateTools()
  52. {
  53. g_pCommEditTool = new CCommEditTool();
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Constructor
  57. //-----------------------------------------------------------------------------
  58. CCommEditTool::CCommEditTool()
  59. {
  60. m_bInNodeDropMode = false;
  61. m_pMenuBar = NULL;
  62. m_pDoc = NULL;
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Init, shutdown
  66. //-----------------------------------------------------------------------------
  67. static const char *s_pDropClassName[ ] =
  68. {
  69. "point_commentary_node",
  70. "info_target",
  71. "info_remarkable"
  72. };
  73. bool CCommEditTool::Init( )
  74. {
  75. COMPILE_TIME_ASSERT( ARRAYSIZE( s_pDropClassName ) == DROP_MODE_COUNT );
  76. m_pDoc = NULL;
  77. m_RecentFiles.LoadFromRegistry( GetRegistryName() );
  78. // NOTE: This has to happen before BaseClass::Init
  79. g_pVGuiLocalize->AddFile( "resource/toolcommedit_%language%.txt" );
  80. if ( !BaseClass::Init( ) )
  81. return false;
  82. for ( int i = 0; i < DROP_MODE_COUNT; ++i )
  83. {
  84. char pTemp[256];
  85. Q_snprintf( pTemp, sizeof(pTemp), "preview %s", s_pDropClassName[i] );
  86. m_hPreviewEntity[i] = CreateElement<CDmeCommentaryNodeEntity>( pTemp, DMFILEID_INVALID );
  87. m_hPreviewEntity[i]->SetValue( "classname", s_pDropClassName[i] );
  88. }
  89. return true;
  90. }
  91. void CCommEditTool::Shutdown()
  92. {
  93. m_RecentFiles.SaveToRegistry( GetRegistryName() );
  94. for ( int i = 0; i < DROP_MODE_COUNT; ++i )
  95. {
  96. g_pDataModel->DestroyElement( m_hPreviewEntity[i] );
  97. m_hPreviewEntity[i] = NULL;
  98. }
  99. BaseClass::Shutdown();
  100. }
  101. //-----------------------------------------------------------------------------
  102. // returns the document
  103. //-----------------------------------------------------------------------------
  104. inline CCommEditDoc *CCommEditTool::GetDocument()
  105. {
  106. return m_pDoc;
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Tool activation/deactivation
  110. //-----------------------------------------------------------------------------
  111. void CCommEditTool::OnToolActivate()
  112. {
  113. BaseClass::OnToolActivate();
  114. enginetools->Command( "commentary 1\n" );
  115. }
  116. void CCommEditTool::OnToolDeactivate()
  117. {
  118. BaseClass::OnToolDeactivate();
  119. enginetools->Command( "commentary 0\n" );
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Enter mode where we preview dropping nodes
  123. //-----------------------------------------------------------------------------
  124. void CCommEditTool::EnterNodeDropMode()
  125. {
  126. // Can only do it in editor mode
  127. if ( IsGameInputEnabled() )
  128. return;
  129. m_bInNodeDropMode = true;
  130. m_nDropMode = DROP_MODE_COMMENTARY;
  131. SetMode( true, IsFullscreen() );
  132. {
  133. CDisableUndoScopeGuard guard;
  134. m_hPreviewEntity[DROP_MODE_COMMENTARY]->DrawInEngine( true );
  135. }
  136. SetMiniViewportText( "Left Click To Place Commentary\nRight Click To Toggle Modes\nESC to exit" );
  137. enginetools->Command( "noclip\n" );
  138. }
  139. void CCommEditTool::LeaveNodeDropMode()
  140. {
  141. Assert( m_bInNodeDropMode );
  142. m_bInNodeDropMode = false;
  143. SetMode( false, IsFullscreen() );
  144. {
  145. CDisableUndoScopeGuard guard;
  146. for ( int i = 0; i < DROP_MODE_COUNT; ++i )
  147. {
  148. m_hPreviewEntity[i]->DrawInEngine( false );
  149. }
  150. }
  151. SetMiniViewportText( NULL );
  152. enginetools->Command( "noclip\n" );
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Gets the position of the preview object
  156. //-----------------------------------------------------------------------------
  157. void CCommEditTool::GetPlacementInfo( Vector &vecOrigin, QAngle &angAngles )
  158. {
  159. // Places the placement objects
  160. float flFov;
  161. clienttools->GetLocalPlayerEyePosition( vecOrigin, angAngles, flFov );
  162. Vector vecForward;
  163. AngleVectors( angAngles, &vecForward );
  164. VectorMA( vecOrigin, 40.0f, vecForward, vecOrigin );
  165. // Eliminate pitch
  166. angAngles.x = 0.0f;
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Place the preview object before rendering
  170. //-----------------------------------------------------------------------------
  171. void CCommEditTool::ClientPreRender()
  172. {
  173. BaseClass::ClientPreRender();
  174. if ( !m_bInNodeDropMode )
  175. return;
  176. // Places the placement objects
  177. Vector vecOrigin;
  178. QAngle angAngles;
  179. GetPlacementInfo( vecOrigin, angAngles );
  180. CDisableUndoScopeGuard guard;
  181. for ( int i = 0; i < DROP_MODE_COUNT; ++i )
  182. {
  183. m_hPreviewEntity[i]->SetRenderOrigin( vecOrigin );
  184. m_hPreviewEntity[i]->SetRenderAngles( angAngles );
  185. }
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Let tool override key events (ie ESC and ~)
  189. //-----------------------------------------------------------------------------
  190. bool CCommEditTool::TrapKey( ButtonCode_t key, bool down )
  191. {
  192. // Don't hook keyboard if not topmost
  193. if ( !IsActiveTool() )
  194. return false; // didn't trap, continue processing
  195. if ( !m_bInNodeDropMode )
  196. {
  197. if ( !IsGameInputEnabled() && !IsFullscreen() && ( key == KEY_BACKQUOTE ) && down )
  198. {
  199. BringConsoleToFront();
  200. return true;
  201. }
  202. return BaseClass::TrapKey( key, down );
  203. }
  204. if ( !down )
  205. return false;
  206. if ( key == KEY_ESCAPE )
  207. {
  208. LeaveNodeDropMode();
  209. return true; // trapping this key, stop processing
  210. }
  211. if ( key == MOUSE_LEFT )
  212. {
  213. Vector vecOrigin;
  214. QAngle angAngles;
  215. GetPlacementInfo( vecOrigin, angAngles );
  216. switch( m_nDropMode )
  217. {
  218. case DROP_MODE_COMMENTARY:
  219. m_pDoc->AddNewCommentaryNode( vecOrigin, angAngles );
  220. break;
  221. case DROP_MODE_TARGET:
  222. m_pDoc->AddNewInfoTarget( vecOrigin, angAngles );
  223. break;
  224. case DROP_MODE_REMARKABLE:
  225. m_pDoc->AddNewInfoRemarkable( vecOrigin, angAngles );
  226. break;
  227. }
  228. return true; // trapping this key, stop processing
  229. }
  230. if ( key == MOUSE_RIGHT )
  231. {
  232. m_nDropMode = (DropNodeMode_t)( m_nDropMode + 1 );
  233. if ( m_nDropMode >= DROP_MODE_COUNT )
  234. {
  235. m_nDropMode = DROP_MODE_COMMENTARY;
  236. }
  237. switch( m_nDropMode )
  238. {
  239. case DROP_MODE_COMMENTARY:
  240. SetMiniViewportText( "Left Click To Place Commentary\nRight Click To Toggle Modes\nESC to exit" );
  241. break;
  242. case DROP_MODE_TARGET:
  243. SetMiniViewportText( "Left Click To Place Target\nRight Click To Toggle Modes\nESC to exit" );
  244. break;
  245. case DROP_MODE_REMARKABLE:
  246. SetMiniViewportText( "Left Click To Place Remarkable\nRight Click To Toggle Modes\nESC to exit" );
  247. break;
  248. }
  249. CDisableUndoScopeGuard guard;
  250. for ( int i = 0; i < DROP_MODE_COUNT; ++i )
  251. {
  252. m_hPreviewEntity[i]->DrawInEngine( i == m_nDropMode );
  253. }
  254. return true; // trapping this key, stop processing
  255. }
  256. return false; // didn't trap, continue processing
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Used to hook DME VMF entities into the render lists
  260. //-----------------------------------------------------------------------------
  261. void CCommEditTool::DrawCommentaryNodeEntitiesInEngine( bool bDrawInEngine )
  262. {
  263. if ( !m_pDoc )
  264. return;
  265. CDmrCommentaryNodeEntityList entities = m_pDoc->GetEntityList();
  266. if ( !entities.IsValid() )
  267. return;
  268. CDisableUndoScopeGuard guard;
  269. int nCount = entities.Count();
  270. for ( int i = 0; i < nCount; ++i )
  271. {
  272. CDmeCommentaryNodeEntity *pEntity = entities[i];
  273. Assert( pEntity );
  274. if ( pEntity )
  275. {
  276. pEntity->DrawInEngine( bDrawInEngine );
  277. }
  278. }
  279. }
  280. void CCommEditTool::ClientLevelInitPostEntity()
  281. {
  282. BaseClass::ClientLevelInitPostEntity();
  283. DrawCommentaryNodeEntitiesInEngine( true );
  284. AttachAllEngineEntities();
  285. }
  286. void CCommEditTool::ClientLevelShutdownPreEntity()
  287. {
  288. DrawCommentaryNodeEntitiesInEngine( false );
  289. BaseClass::ClientLevelShutdownPreEntity();
  290. }
  291. //-----------------------------------------------------------------------------
  292. // Derived classes can implement this to get a new scheme to be applied to this tool
  293. //-----------------------------------------------------------------------------
  294. vgui::HScheme CCommEditTool::GetToolScheme()
  295. {
  296. return vgui::scheme()->LoadSchemeFromFile( "Resource/BoxRocket.res", "BoxRocket" );
  297. }
  298. //-----------------------------------------------------------------------------
  299. //
  300. // The View menu
  301. //
  302. //-----------------------------------------------------------------------------
  303. class CCommEditViewMenuButton : public CToolMenuButton
  304. {
  305. DECLARE_CLASS_SIMPLE( CCommEditViewMenuButton, CToolMenuButton );
  306. public:
  307. CCommEditViewMenuButton( CCommEditTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget );
  308. virtual void OnShowMenu(vgui::Menu *menu);
  309. private:
  310. CCommEditTool *m_pTool;
  311. };
  312. CCommEditViewMenuButton::CCommEditViewMenuButton( CCommEditTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget )
  313. : BaseClass( parent, panelName, text, pActionSignalTarget )
  314. {
  315. m_pTool = parent;
  316. AddCheckableMenuItem( "properties", "#CommEditProperties", new KeyValues( "OnToggleProperties" ), pActionSignalTarget );
  317. AddCheckableMenuItem( "commentarynodebrowser", "#CommEditEntityReport", new KeyValues( "OnToggleEntityReport" ), pActionSignalTarget );
  318. AddCheckableMenuItem( "console", "#BxConsole", new KeyValues( "ToggleConsole" ), pActionSignalTarget );
  319. AddSeparator();
  320. AddMenuItem( "defaultlayout", "#CommEditViewDefault", new KeyValues( "OnDefaultLayout" ), pActionSignalTarget );
  321. SetMenu(m_pMenu);
  322. }
  323. void CCommEditViewMenuButton::OnShowMenu(vgui::Menu *menu)
  324. {
  325. BaseClass::OnShowMenu( menu );
  326. // Update the menu
  327. int id;
  328. CCommEditDoc *pDoc = m_pTool->GetDocument();
  329. if ( pDoc )
  330. {
  331. id = m_Items.Find( "properties" );
  332. m_pMenu->SetItemEnabled( id, true );
  333. Panel *p;
  334. p = m_pTool->GetProperties();
  335. Assert( p );
  336. m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false );
  337. id = m_Items.Find( "commentarynodebrowser" );
  338. m_pMenu->SetItemEnabled( id, true );
  339. p = m_pTool->GetCommentaryNodeBrowser();
  340. Assert( p );
  341. m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false );
  342. id = m_Items.Find( "console" );
  343. m_pMenu->SetItemEnabled( id, true );
  344. CConsolePage *console = m_pTool->GetConsole();
  345. m_pMenu->SetMenuItemChecked( id, console->GetParent() ? true : false );
  346. }
  347. else
  348. {
  349. id = m_Items.Find( "properties" );
  350. m_pMenu->SetItemEnabled( id, false );
  351. id = m_Items.Find( "commentarynodebrowser" );
  352. m_pMenu->SetItemEnabled( id, false );
  353. id = m_Items.Find( "console" );
  354. m_pMenu->SetItemEnabled( id, false );
  355. }
  356. }
  357. //-----------------------------------------------------------------------------
  358. //
  359. // The Tool menu
  360. //
  361. //-----------------------------------------------------------------------------
  362. class CCommEditToolMenuButton : public CToolMenuButton
  363. {
  364. DECLARE_CLASS_SIMPLE( CCommEditToolMenuButton, CToolMenuButton );
  365. public:
  366. CCommEditToolMenuButton( CCommEditTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget );
  367. virtual void OnShowMenu(vgui::Menu *menu);
  368. private:
  369. CCommEditTool *m_pTool;
  370. };
  371. CCommEditToolMenuButton::CCommEditToolMenuButton( CCommEditTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget )
  372. : BaseClass( parent, panelName, text, pActionSignalTarget )
  373. {
  374. m_pTool = parent;
  375. AddMenuItem( "addnewnodes", "#CommEditAddNewNodes", new KeyValues( "AddNewNodes" ), pActionSignalTarget, NULL, "CommEditAddNewNodes" );
  376. SetMenu(m_pMenu);
  377. }
  378. void CCommEditToolMenuButton::OnShowMenu(vgui::Menu *menu)
  379. {
  380. BaseClass::OnShowMenu( menu );
  381. // Update the menu
  382. int id;
  383. CCommEditDoc *pDoc = m_pTool->GetDocument();
  384. id = m_Items.Find( "addnewnodes" );
  385. m_pMenu->SetItemEnabled( id, pDoc != NULL );
  386. }
  387. //-----------------------------------------------------------------------------
  388. // Initializes the menu bar
  389. //-----------------------------------------------------------------------------
  390. vgui::MenuBar *CCommEditTool::CreateMenuBar( CBaseToolSystem *pParent )
  391. {
  392. m_pMenuBar = new CToolFileMenuBar( pParent, "Main Menu Bar" );
  393. // Sets info in the menu bar
  394. char title[ 64 ];
  395. ComputeMenuBarTitle( title, sizeof( title ) );
  396. m_pMenuBar->SetInfo( title );
  397. m_pMenuBar->SetToolName( GetToolName() );
  398. // Add menu buttons
  399. CToolMenuButton *pFileButton = CreateToolFileMenuButton( m_pMenuBar, "File", "&File", GetActionTarget(), this );
  400. CToolMenuButton *pEditButton = CreateToolEditMenuButton( this, "Edit", "&Edit", GetActionTarget() );
  401. CCommEditToolMenuButton *pToolButton = new CCommEditToolMenuButton( this, "CommEdit", "&CommEdit", GetActionTarget() );
  402. CCommEditViewMenuButton *pViewButton = new CCommEditViewMenuButton( this, "View", "&View", GetActionTarget() );
  403. CToolMenuButton *pSwitchButton = CreateToolSwitchMenuButton( m_pMenuBar, "Switcher", "&Tools", GetActionTarget() );
  404. m_pMenuBar->AddButton( pFileButton );
  405. m_pMenuBar->AddButton( pEditButton );
  406. m_pMenuBar->AddButton( pToolButton );
  407. m_pMenuBar->AddButton( pViewButton );
  408. m_pMenuBar->AddButton( pSwitchButton );
  409. return m_pMenuBar;
  410. }
  411. //-----------------------------------------------------------------------------
  412. // Updates the menu bar based on the current file
  413. //-----------------------------------------------------------------------------
  414. void CCommEditTool::UpdateMenuBar( )
  415. {
  416. if ( !m_pDoc )
  417. {
  418. m_pMenuBar->SetFileName( "#CommEditNoFile" );
  419. return;
  420. }
  421. const char *pTXTFile = m_pDoc->GetTXTFileName();
  422. if ( !pTXTFile[0] )
  423. {
  424. m_pMenuBar->SetFileName( "#CommEditNoFile" );
  425. return;
  426. }
  427. if ( m_pDoc->IsDirty() )
  428. {
  429. char sz[ 512 ];
  430. Q_snprintf( sz, sizeof( sz ), "* %s", pTXTFile );
  431. m_pMenuBar->SetFileName( sz );
  432. }
  433. else
  434. {
  435. m_pMenuBar->SetFileName( pTXTFile );
  436. }
  437. }
  438. //-----------------------------------------------------------------------------
  439. // Gets at tool windows
  440. //-----------------------------------------------------------------------------
  441. CCommentaryPropertiesPanel *CCommEditTool::GetProperties()
  442. {
  443. return m_hProperties.Get();
  444. }
  445. CCommentaryNodeBrowserPanel *CCommEditTool::GetCommentaryNodeBrowser()
  446. {
  447. return m_hCommentaryNodeBrowser.Get();
  448. }
  449. CConsolePage *CCommEditTool::GetConsole()
  450. {
  451. return m_hConsole;
  452. }
  453. //-----------------------------------------------------------------------------
  454. // Shows element properties
  455. //-----------------------------------------------------------------------------
  456. void CCommEditTool::ShowElementProperties( )
  457. {
  458. if ( !m_pDoc )
  459. return;
  460. // It should already exist
  461. Assert( m_hProperties.Get() );
  462. if ( m_hProperties.Get() )
  463. {
  464. m_hProperties->SetObject( m_hCurrentEntity );
  465. }
  466. }
  467. //-----------------------------------------------------------------------------
  468. // Destroys all tool windows
  469. //-----------------------------------------------------------------------------
  470. void CCommEditTool::ShowEntityInEntityProperties( CDmeCommentaryNodeEntity *pEntity )
  471. {
  472. Assert( m_hProperties.Get() );
  473. m_hCurrentEntity = pEntity;
  474. m_hProperties->SetObject( m_hCurrentEntity );
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Destroys all tool windows
  478. //-----------------------------------------------------------------------------
  479. void CCommEditTool::DestroyToolContainers()
  480. {
  481. int c = ToolWindow::GetToolWindowCount();
  482. for ( int i = c - 1; i >= 0 ; --i )
  483. {
  484. ToolWindow *kill = ToolWindow::GetToolWindow( i );
  485. delete kill;
  486. }
  487. }
  488. //-----------------------------------------------------------------------------
  489. // Sets up the default layout
  490. //-----------------------------------------------------------------------------
  491. void CCommEditTool::OnDefaultLayout()
  492. {
  493. int y = m_pMenuBar->GetTall();
  494. int usew, useh;
  495. GetSize( usew, useh );
  496. DestroyToolContainers();
  497. Assert( ToolWindow::GetToolWindowCount() == 0 );
  498. CCommentaryPropertiesPanel *properties = GetProperties();
  499. CCommentaryNodeBrowserPanel *pEntityReport = GetCommentaryNodeBrowser();
  500. CConsolePage *pConsole = GetConsole();
  501. // Need three containers
  502. ToolWindow *pPropertyWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, properties, "#CommEditProperties", false );
  503. ToolWindow *pEntityReportWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pEntityReport, "#CommEditEntityReport", false );
  504. ToolWindow *pMiniViewport = dynamic_cast< ToolWindow* >( GetMiniViewport() );
  505. pMiniViewport->AddPage( pConsole, "#BxConsole", false );
  506. int halfScreen = usew / 2;
  507. int bottom = useh - y;
  508. int sy = (bottom - y) / 2;
  509. SetMiniViewportBounds( halfScreen, y, halfScreen, sy - y );
  510. pEntityReportWindow->SetBounds( 0, y, halfScreen, bottom - y );
  511. pPropertyWindow->SetBounds( halfScreen, sy, halfScreen, bottom - sy );
  512. }
  513. void CCommEditTool::OnToggleProperties()
  514. {
  515. if ( m_hProperties.Get() )
  516. {
  517. ToggleToolWindow( m_hProperties.Get(), "#CommEditProperties" );
  518. }
  519. }
  520. void CCommEditTool::OnToggleEntityReport()
  521. {
  522. if ( m_hCommentaryNodeBrowser.Get() )
  523. {
  524. ToggleToolWindow( m_hCommentaryNodeBrowser.Get(), "#CommEditEntityReport" );
  525. }
  526. }
  527. void CCommEditTool::OnToggleConsole()
  528. {
  529. if ( m_hConsole.Get() )
  530. {
  531. ToggleToolWindow( m_hConsole.Get(), "#BxConsole" );
  532. }
  533. }
  534. void CCommEditTool::BringConsoleToFront()
  535. {
  536. CConsolePage *p = GetConsole();
  537. Panel *pPage = p->GetParent();
  538. if ( pPage == NULL )
  539. {
  540. OnToggleConsole();
  541. }
  542. else
  543. {
  544. ToolWindow *tw = dynamic_cast< ToolWindow * >( pPage->GetParent() );
  545. if ( tw )
  546. {
  547. if ( tw->GetActivePage() != p )
  548. {
  549. tw->SetActivePage( p );
  550. vgui::surface()->SetForegroundWindow( tw->GetVPanel() );
  551. p->TextEntryRequestFocus();
  552. }
  553. else
  554. {
  555. PropertySheet *pSheet = tw->GetPropertySheet();
  556. int nPageCount = pSheet->GetNumPages();
  557. int i;
  558. for ( i = 0; i < nPageCount; ++i )
  559. {
  560. if ( p == pSheet->GetPage(i) )
  561. break;
  562. }
  563. i = ( i + 1 ) % nPageCount;
  564. pSheet->SetActivePage( pSheet->GetPage(i) );
  565. }
  566. }
  567. }
  568. }
  569. //-----------------------------------------------------------------------------
  570. // Creates
  571. //-----------------------------------------------------------------------------
  572. void CCommEditTool::CreateTools( CCommEditDoc *doc )
  573. {
  574. if ( !m_hProperties.Get() )
  575. {
  576. m_hProperties = new CCommentaryPropertiesPanel( m_pDoc, this );
  577. }
  578. if ( !m_hCommentaryNodeBrowser.Get() )
  579. {
  580. m_hCommentaryNodeBrowser = new CCommentaryNodeBrowserPanel( m_pDoc, this, "CommentaryNodeBrowserPanel" );
  581. }
  582. if ( !m_hConsole.Get() )
  583. {
  584. m_hConsole = new CConsolePage( NULL, false );
  585. }
  586. RegisterToolWindow( m_hProperties );
  587. RegisterToolWindow( m_hCommentaryNodeBrowser );
  588. RegisterToolWindow( m_hConsole );
  589. }
  590. //-----------------------------------------------------------------------------
  591. // Initializes the tools
  592. //-----------------------------------------------------------------------------
  593. void CCommEditTool::InitTools()
  594. {
  595. ShowElementProperties();
  596. // FIXME: There are no tool windows here; how should this work?
  597. // These panels are saved
  598. windowposmgr->RegisterPanel( "properties", m_hProperties, false );
  599. windowposmgr->RegisterPanel( "commentarynodebrowser", m_hCommentaryNodeBrowser, false );
  600. windowposmgr->RegisterPanel( "Console", m_hConsole, false ); // No context menu
  601. if ( !windowposmgr->LoadPositions( "cfg/commedit.txt", this, &m_ToolWindowFactory, "CommEdit" ) )
  602. {
  603. OnDefaultLayout();
  604. }
  605. }
  606. void CCommEditTool::DestroyTools()
  607. {
  608. m_hCurrentEntity = NULL;
  609. int c = ToolWindow::GetToolWindowCount();
  610. for ( int i = c - 1; i >= 0 ; --i )
  611. {
  612. ToolWindow *kill = ToolWindow::GetToolWindow( i );
  613. delete kill;
  614. }
  615. UnregisterAllToolWindows();
  616. if ( m_hProperties.Get() )
  617. {
  618. windowposmgr->UnregisterPanel( m_hProperties.Get() );
  619. delete m_hProperties.Get();
  620. m_hProperties = NULL;
  621. }
  622. if ( m_hCommentaryNodeBrowser.Get() )
  623. {
  624. windowposmgr->UnregisterPanel( m_hCommentaryNodeBrowser.Get() );
  625. delete m_hCommentaryNodeBrowser.Get();
  626. m_hCommentaryNodeBrowser = NULL;
  627. }
  628. if ( m_hConsole.Get() )
  629. {
  630. windowposmgr->UnregisterPanel( m_hConsole.Get() );
  631. delete m_hConsole.Get();
  632. m_hConsole = NULL;
  633. }
  634. }
  635. void CCommEditTool::ShowToolWindow( Panel *tool, char const *toolName, bool visible )
  636. {
  637. Assert( tool );
  638. if ( tool->GetParent() == NULL && visible )
  639. {
  640. m_ToolWindowFactory.InstanceToolWindow( this, false, tool, toolName, false );
  641. }
  642. else if ( !visible )
  643. {
  644. ToolWindow *tw = dynamic_cast< ToolWindow * >( tool->GetParent()->GetParent() );
  645. Assert( tw );
  646. tw->RemovePage( tool );
  647. }
  648. }
  649. void CCommEditTool::ToggleToolWindow( Panel *tool, char const *toolName )
  650. {
  651. Assert( tool );
  652. if ( tool->GetParent() == NULL )
  653. {
  654. ShowToolWindow( tool, toolName, true );
  655. }
  656. else
  657. {
  658. ShowToolWindow( tool, toolName, false );
  659. }
  660. }
  661. //-----------------------------------------------------------------------------
  662. // Creates the action menu
  663. //-----------------------------------------------------------------------------
  664. vgui::Menu *CCommEditTool::CreateActionMenu( vgui::Panel *pParent )
  665. {
  666. vgui::Menu *pActionMenu = new Menu( pParent, "ActionMenu" );
  667. pActionMenu->AddMenuItem( "#ToolHide", new KeyValues( "Command", "command", "HideActionMenu" ), GetActionTarget() );
  668. return pActionMenu;
  669. }
  670. //-----------------------------------------------------------------------------
  671. // Inherited from IFileMenuCallbacks
  672. //-----------------------------------------------------------------------------
  673. int CCommEditTool::GetFileMenuItemsEnabled( )
  674. {
  675. int nFlags = FILE_ALL;
  676. if ( m_RecentFiles.IsEmpty() )
  677. {
  678. nFlags &= ~FILE_RECENT;
  679. }
  680. return nFlags;
  681. }
  682. void CCommEditTool::AddRecentFilesToMenu( vgui::Menu *pMenu )
  683. {
  684. m_RecentFiles.AddToMenu( pMenu, GetActionTarget(), "OnRecent" );
  685. }
  686. bool CCommEditTool::GetPerforceFileName( char *pFileName, int nMaxLen )
  687. {
  688. if ( !m_pDoc )
  689. return false;
  690. Q_strncpy( pFileName, m_pDoc->GetTXTFileName(), nMaxLen );
  691. return pFileName[0] != 0;
  692. }
  693. //-----------------------------------------------------------------------------
  694. // Purpose:
  695. // Input : -
  696. //-----------------------------------------------------------------------------
  697. void CCommEditTool::OnExit()
  698. {
  699. windowposmgr->SavePositions( "cfg/commedit.txt", "CommEdit" );
  700. enginetools->Command( "quit\n" );
  701. }
  702. //-----------------------------------------------------------------------------
  703. // Handle commands from the action menu and other menus
  704. //-----------------------------------------------------------------------------
  705. void CCommEditTool::OnCommand( const char *cmd )
  706. {
  707. if ( !V_stricmp( cmd, "HideActionMenu" ) )
  708. {
  709. if ( GetActionMenu() )
  710. {
  711. GetActionMenu()->SetVisible( false );
  712. }
  713. }
  714. else if ( const char *pSuffix = StringAfterPrefix( cmd, "OnRecent" ) )
  715. {
  716. int idx = Q_atoi( pSuffix );
  717. OpenFileFromHistory( idx );
  718. }
  719. else if ( const char *pSuffix = StringAfterPrefix( cmd, "OnTool" ) )
  720. {
  721. int idx = Q_atoi( pSuffix );
  722. enginetools->SwitchToTool( idx );
  723. }
  724. else if ( !V_stricmp( cmd, "OnUndo" ) )
  725. {
  726. OnUndo();
  727. }
  728. else if ( !V_stricmp( cmd, "OnRedo" ) )
  729. {
  730. OnRedo();
  731. }
  732. else if ( !V_stricmp( cmd, "OnDescribeUndo" ) )
  733. {
  734. OnDescribeUndo();
  735. }
  736. else
  737. {
  738. BaseClass::OnCommand( cmd );
  739. }
  740. }
  741. //-----------------------------------------------------------------------------
  742. // Command handlers
  743. //-----------------------------------------------------------------------------
  744. void CCommEditTool::OnNew()
  745. {
  746. int nFlags = 0;
  747. const char *pSaveFileName = NULL;
  748. if ( m_pDoc && m_pDoc->IsDirty() )
  749. {
  750. nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
  751. pSaveFileName = m_pDoc->GetTXTFileName();
  752. }
  753. // Bring up the file open dialog to choose a .bsp file
  754. OpenFile( "bsp", pSaveFileName, "txt", nFlags );
  755. }
  756. //-----------------------------------------------------------------------------
  757. // Called when the File->Open menu is selected
  758. //-----------------------------------------------------------------------------
  759. void CCommEditTool::OnOpen( )
  760. {
  761. int nFlags = 0;
  762. const char *pSaveFileName = NULL;
  763. if ( m_pDoc && m_pDoc->IsDirty() )
  764. {
  765. nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
  766. pSaveFileName = m_pDoc->GetTXTFileName();
  767. }
  768. OpenFile( "txt", pSaveFileName, "txt", nFlags );
  769. }
  770. bool CCommEditTool::OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
  771. {
  772. OnCloseNoSave();
  773. if ( !LoadDocument( pFileName ) )
  774. return false;
  775. m_RecentFiles.Add( pFileName, pFileFormat );
  776. m_RecentFiles.SaveToRegistry( GetRegistryName() );
  777. UpdateMenuBar();
  778. return true;
  779. }
  780. void CCommEditTool::Save()
  781. {
  782. if ( m_pDoc )
  783. {
  784. SaveFile( m_pDoc->GetTXTFileName(), "txt", FOSM_SHOW_PERFORCE_DIALOGS );
  785. }
  786. }
  787. void CCommEditTool::OnSaveAs()
  788. {
  789. if ( m_pDoc )
  790. {
  791. SaveFile( NULL, "txt", FOSM_SHOW_PERFORCE_DIALOGS );
  792. }
  793. }
  794. void CCommEditTool::OnRestartLevel()
  795. {
  796. enginetools->Command( "restart" );
  797. enginetools->Execute();
  798. CDmrCommentaryNodeEntityList entities = m_pDoc->GetEntityList();
  799. int nCount = entities.IsValid() ? entities.Count() : 0;
  800. for ( int i = 0; i < nCount; ++i )
  801. {
  802. CDmeCommentaryNodeEntity *pEntity = entities[i];
  803. Assert( pEntity );
  804. pEntity->MarkDirty( false );
  805. }
  806. }
  807. void CCommEditTool::SaveAndTest()
  808. {
  809. if ( m_pDoc && m_pDoc->IsDirty() )
  810. {
  811. SaveFile( m_pDoc->GetTXTFileName(), "txt", FOSM_SHOW_PERFORCE_DIALOGS,
  812. new KeyValues( "RestartLevel" ) );
  813. }
  814. else
  815. {
  816. OnRestartLevel();
  817. }
  818. }
  819. bool CCommEditTool::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
  820. {
  821. if ( !m_pDoc )
  822. return false;
  823. m_pDoc->SetTXTFileName( pFileName );
  824. m_pDoc->SaveToFile( );
  825. m_RecentFiles.Add( pFileName, pFileFormat );
  826. m_RecentFiles.SaveToRegistry( GetRegistryName() );
  827. UpdateMenuBar();
  828. return true;
  829. }
  830. void CCommEditTool::OnClose()
  831. {
  832. if ( m_pDoc && m_pDoc->IsDirty() )
  833. {
  834. SaveFile( m_pDoc->GetTXTFileName(), "txt", FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY,
  835. new KeyValues( "OnClose" ) );
  836. return;
  837. }
  838. OnCloseNoSave();
  839. }
  840. void CCommEditTool::OnCloseNoSave()
  841. {
  842. DestroyTools();
  843. if ( m_pDoc )
  844. {
  845. CAppNotifyScopeGuard sg( "CCommEditTool::OnCloseNoSave", 0 );
  846. delete m_pDoc;
  847. m_pDoc = NULL;
  848. if ( m_hProperties )
  849. {
  850. m_hProperties->SetObject( NULL );
  851. }
  852. }
  853. UpdateMenuBar( );
  854. }
  855. void CCommEditTool::CenterView( CDmeCommentaryNodeEntity *pEntity )
  856. {
  857. EntitySearchResult pPlayer = clienttools->GetLocalPlayer();
  858. Vector vecOrigin = pEntity->GetRenderOrigin();
  859. QAngle angles = pEntity->GetRenderAngles();
  860. Vector vecForward, vecUp, vecRight;
  861. AngleVectors( angles, &vecForward, &vecRight, &vecUp );
  862. VectorMA( vecOrigin, 40.0f, vecForward, vecOrigin );
  863. vecForward *= -1.0f;
  864. VectorAngles( vecForward, vecUp, angles );
  865. servertools->SnapPlayerToPosition( vecOrigin, angles, ( IClientEntity* )pPlayer );
  866. }
  867. void CCommEditTool::OnMarkNotDirty()
  868. {
  869. if ( m_pDoc )
  870. {
  871. m_pDoc->SetDirty( false );
  872. }
  873. }
  874. void CCommEditTool::AttachAllEngineEntities()
  875. {
  876. if ( !clienttools || !m_pDoc )
  877. return;
  878. for ( EntitySearchResult sr = clienttools->FirstEntity(); sr != NULL; sr = clienttools->NextEntity( sr ) )
  879. {
  880. if ( !sr )
  881. continue;
  882. HTOOLHANDLE handle = clienttools->AttachToEntity( sr );
  883. const char *pClassName = clienttools->GetClassname( handle );
  884. if ( Q_strcmp( pClassName, "class C_PointCommentaryNode" ) == 0 )
  885. {
  886. Vector vecOrigin = clienttools->GetAbsOrigin( handle );
  887. QAngle angAngles = clienttools->GetAbsAngles( handle );
  888. // Find the associated commentary node entry in our doc
  889. CDmeCommentaryNodeEntity *pNode = m_pDoc->GetCommentaryNodeForLocation( vecOrigin, angAngles );
  890. if ( pNode )
  891. {
  892. pNode->AttachToEngineEntity( handle );
  893. }
  894. }
  895. }
  896. }
  897. //-----------------------------------------------------------------------------
  898. // Show the save document query dialog
  899. //-----------------------------------------------------------------------------
  900. void CCommEditTool::OpenSpecificFile( const char *pFileName )
  901. {
  902. int nFlags = 0;
  903. const char *pSaveFileName = NULL;
  904. if ( m_pDoc )
  905. {
  906. // File is already open
  907. if ( !Q_stricmp( m_pDoc->GetTXTFileName(), pFileName ) )
  908. return;
  909. if ( m_pDoc->IsDirty() )
  910. {
  911. nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
  912. pSaveFileName = m_pDoc->GetTXTFileName();
  913. }
  914. else
  915. {
  916. OnCloseNoSave();
  917. }
  918. }
  919. OpenFile( pFileName, "txt", pSaveFileName, "txt", nFlags );
  920. }
  921. void CCommEditTool::OpenFileFromHistory( int slot )
  922. {
  923. const char *pFileName = m_RecentFiles.GetFile( slot );
  924. if ( !pFileName )
  925. return;
  926. OpenSpecificFile( pFileName );
  927. }
  928. //-----------------------------------------------------------------------------
  929. // Derived classes can implement this to get notified when files are saved/loaded
  930. //-----------------------------------------------------------------------------
  931. void CCommEditTool::OnFileOperationCompleted( const char *pFileType, bool bWroteFile, vgui::FileOpenStateMachine::CompletionState_t state, KeyValues *pContextKeyValues )
  932. {
  933. if ( bWroteFile )
  934. {
  935. OnMarkNotDirty();
  936. }
  937. if ( !pContextKeyValues )
  938. return;
  939. if ( state != FileOpenStateMachine::SUCCESSFUL )
  940. return;
  941. if ( !Q_stricmp( pContextKeyValues->GetName(), "OnClose" ) )
  942. {
  943. OnCloseNoSave();
  944. return;
  945. }
  946. if ( !Q_stricmp( pContextKeyValues->GetName(), "OnQuit" ) )
  947. {
  948. OnCloseNoSave();
  949. vgui::ivgui()->PostMessage( GetVPanel(), new KeyValues( "OnExit" ), 0 );
  950. return;
  951. }
  952. if ( !Q_stricmp( pContextKeyValues->GetName(), "OnUnload" ) )
  953. {
  954. enginetools->Command( "toolunload commedit -nosave\n" );
  955. return;
  956. }
  957. if ( !Q_stricmp( pContextKeyValues->GetName(), "RestartLevel" ) )
  958. {
  959. OnRestartLevel();
  960. return;
  961. }
  962. }
  963. //-----------------------------------------------------------------------------
  964. // Show the File browser dialog
  965. //-----------------------------------------------------------------------------
  966. void CCommEditTool::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues )
  967. {
  968. char pStartingDir[ MAX_PATH ];
  969. GetModSubdirectory( "maps", pStartingDir, sizeof(pStartingDir) );
  970. if ( !Q_stricmp( pFileFormat, "bsp" ) )
  971. {
  972. // Open a bsp file to create a new commentary file
  973. pDialog->SetTitle( "Choose BSP File", true );
  974. pDialog->SetStartDirectoryContext( "commedit_bsp_session", pStartingDir );
  975. pDialog->AddFilter( "*.bsp", "Valve BSP File (*.bsp)", true );
  976. }
  977. else
  978. {
  979. // Open existing commentary text files
  980. pDialog->SetTitle( "Choose Valve Commentary File", true );
  981. pDialog->SetStartDirectoryContext( "commedit_txt_session", pStartingDir );
  982. pDialog->AddFilter( "*.txt", "Valve Commentary File (*.txt)", true );
  983. }
  984. }
  985. //-----------------------------------------------------------------------------
  986. // Can we quit?
  987. //-----------------------------------------------------------------------------
  988. bool CCommEditTool::CanQuit( const char *pExitMsg )
  989. {
  990. if ( m_pDoc && m_pDoc->IsDirty() )
  991. {
  992. // Show Save changes Yes/No/Cancel and re-quit if hit yes/no
  993. SaveFile( m_pDoc->GetTXTFileName(), "txt", FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY, new KeyValues( pExitMsg ) );
  994. return false;
  995. }
  996. return true;
  997. }
  998. //-----------------------------------------------------------------------------
  999. // Various command handlers related to the Edit menu
  1000. //-----------------------------------------------------------------------------
  1001. void CCommEditTool::OnUndo()
  1002. {
  1003. CDisableUndoScopeGuard guard;
  1004. g_pDataModel->Undo();
  1005. }
  1006. void CCommEditTool::OnRedo()
  1007. {
  1008. CDisableUndoScopeGuard guard;
  1009. g_pDataModel->Redo();
  1010. }
  1011. void CCommEditTool::OnDescribeUndo()
  1012. {
  1013. CUtlVector< UndoInfo_t > list;
  1014. g_pDataModel->GetUndoInfo( list );
  1015. Msg( "%i operations in stack\n", list.Count() );
  1016. for ( int i = list.Count() - 1; i >= 0; --i )
  1017. {
  1018. UndoInfo_t& entry = list[ i ];
  1019. if ( entry.terminator )
  1020. {
  1021. Msg( "[ '%s' ] - %i operations\n", entry.undo, entry.numoperations );
  1022. }
  1023. Msg( " +%s\n", entry.desc );
  1024. }
  1025. }
  1026. //-----------------------------------------------------------------------------
  1027. // CommEdit menu items
  1028. //-----------------------------------------------------------------------------
  1029. void CCommEditTool::OnAddNewNodes()
  1030. {
  1031. if ( !m_pDoc )
  1032. return;
  1033. EnterNodeDropMode();
  1034. }
  1035. //-----------------------------------------------------------------------------
  1036. // Background
  1037. //-----------------------------------------------------------------------------
  1038. const char *CCommEditTool::GetLogoTextureName()
  1039. {
  1040. return NULL;
  1041. }
  1042. //-----------------------------------------------------------------------------
  1043. // Inherited from ICommEditDocCallback
  1044. //-----------------------------------------------------------------------------
  1045. void CCommEditTool::OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags )
  1046. {
  1047. if ( GetCommentaryNodeBrowser() )
  1048. {
  1049. GetCommentaryNodeBrowser()->UpdateEntityList();
  1050. }
  1051. UpdateMenuBar();
  1052. /*
  1053. if ( bRefreshUI && m_hProperties.Get() )
  1054. {
  1055. m_hProperties->Refresh();
  1056. }
  1057. */
  1058. }
  1059. //-----------------------------------------------------------------------------
  1060. // Loads up a new document
  1061. //-----------------------------------------------------------------------------
  1062. bool CCommEditTool::LoadDocument( const char *pDocName )
  1063. {
  1064. Assert( !m_pDoc );
  1065. DestroyTools();
  1066. m_pDoc = new CCommEditDoc( this );
  1067. if ( !m_pDoc->LoadFromFile( pDocName ) )
  1068. {
  1069. delete m_pDoc;
  1070. m_pDoc = NULL;
  1071. Warning( "Fatal error loading '%s'\n", pDocName );
  1072. return false;
  1073. }
  1074. ShowMiniViewport( true );
  1075. CreateTools( m_pDoc );
  1076. InitTools();
  1077. return true;
  1078. }
  1079. //-----------------------------------------------------------------------------
  1080. // Create the entities that are in our TXT file
  1081. //-----------------------------------------------------------------------------
  1082. const char* CCommEditTool::GetEntityData( const char *pActualEntityData )
  1083. {
  1084. // if ( !m_pDoc )
  1085. return pActualEntityData;
  1086. // return m_pDoc->GenerateEntityData( pActualEntityData );
  1087. }