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.

1284 lines
33 KiB

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