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.

1300 lines
34 KiB

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