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.

1078 lines
29 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Core Movie Maker UI API
  4. //
  5. //=============================================================================
  6. #include "pettool.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 "dme_controls/elementpropertiestree.h"
  15. #include "tier0/icommandline.h"
  16. #include "materialsystem/imaterialsystem.h"
  17. #include "VGuiMatSurface/IMatSystemSurface.h"
  18. #include "petdoc.h"
  19. #include "particlesystemdefinitionbrowser.h"
  20. #include "particlesystempropertiescontainer.h"
  21. #include "dme_controls/AttributeStringChoicePanel.h"
  22. #include "dme_controls/ParticleSystemPanel.h"
  23. #include "datamodel/dmelementfactoryhelper.h"
  24. #include "matsys_controls/picker.h"
  25. #include "tier2/fileutils.h"
  26. #include "tier3/tier3.h"
  27. #include "particles/particles.h"
  28. #include "dmserializers/idmserializers.h"
  29. #include "dme_controls/dmepanel.h"
  30. #include "vgui/ivgui.h"
  31. using namespace vgui;
  32. //-----------------------------------------------------------------------------
  33. // Methods needed by scenedatabase. They have to live here instead of toolutils
  34. // because this is a DLL but toolutils is only a static library
  35. //-----------------------------------------------------------------------------
  36. USING_DMEPANEL_FACTORY( CParticleSystemPreviewPanel, DmeParticleSystemDefinition );
  37. USING_DMEPANEL_FACTORY( CParticleSystemDmePanel, DmeParticleSystemDefinition );
  38. const char *GetVGuiControlsModuleName()
  39. {
  40. return "PetTool";
  41. }
  42. //-----------------------------------------------------------------------------
  43. // Connect, disconnect
  44. //-----------------------------------------------------------------------------
  45. bool ConnectTools( CreateInterfaceFn factory )
  46. {
  47. // Attach to the dmserializers instance of the particle system
  48. return (materials != NULL) && (g_pMatSystemSurface != NULL) && (g_pMDLCache != NULL) && (studiorender != NULL) && (g_pMaterialSystemHardwareConfig != NULL);
  49. }
  50. void DisconnectTools( )
  51. {
  52. }
  53. //-----------------------------------------------------------------------------
  54. // Singleton
  55. //-----------------------------------------------------------------------------
  56. CPetTool *g_pPetTool = NULL;
  57. void CreateTools()
  58. {
  59. g_pPetTool = new CPetTool();
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Constructor
  63. //-----------------------------------------------------------------------------
  64. CPetTool::CPetTool()
  65. {
  66. m_pMenuBar = NULL;
  67. m_pDoc = NULL;
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Init, shutdown
  71. //-----------------------------------------------------------------------------
  72. bool CPetTool::Init( )
  73. {
  74. m_hCurrentParticleSystem = NULL;
  75. m_pDoc = NULL;
  76. m_RecentFiles.LoadFromRegistry( GetRegistryName() );
  77. // NOTE: This has to happen before BaseClass::Init
  78. g_pVGuiLocalize->AddFile( "resource/toolpet_%language%.txt" );
  79. if ( !BaseClass::Init( ) )
  80. return false;
  81. CreateInterfaceFn factory;
  82. enginetools->GetClientFactory( factory );
  83. IParticleSystemQuery *pQuery = (IParticleSystemQuery*)factory( PARTICLE_SYSTEM_QUERY_INTERFACE_VERSION, NULL );
  84. g_pParticleSystemMgr->Init( pQuery );
  85. // tell particle mgr to add the default simulation + rendering ops
  86. g_pParticleSystemMgr->AddBuiltinSimulationOperators();
  87. g_pParticleSystemMgr->AddBuiltinRenderingOperators();
  88. // Create a directory for particles if it doesn't exist
  89. char pStartingDir[ MAX_PATH ];
  90. GetModSubdirectory( "particles", pStartingDir, sizeof(pStartingDir) );
  91. g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
  92. return true;
  93. }
  94. void CPetTool::Shutdown()
  95. {
  96. m_RecentFiles.SaveToRegistry( GetRegistryName() );
  97. BaseClass::Shutdown();
  98. }
  99. //-----------------------------------------------------------------------------
  100. // returns the document
  101. //-----------------------------------------------------------------------------
  102. CPetDoc *CPetTool::GetDocument()
  103. {
  104. return m_pDoc;
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Tool activation/deactivation
  108. //-----------------------------------------------------------------------------
  109. void CPetTool::OnToolActivate()
  110. {
  111. BaseClass::OnToolActivate();
  112. }
  113. void CPetTool::OnToolDeactivate()
  114. {
  115. BaseClass::OnToolDeactivate();
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Used to hook DME VMF entities into the render lists
  119. //-----------------------------------------------------------------------------
  120. void CPetTool::Think( bool finalTick )
  121. {
  122. BaseClass::Think( finalTick );
  123. if ( IsActiveTool() )
  124. {
  125. // Force resolve calls to happen
  126. // FIXME: Shouldn't this not have to happen here?
  127. CUtlVector< IDmeOperator* > operators;
  128. g_pDmElementFramework->SetOperators( operators );
  129. g_pDmElementFramework->Operate( true );
  130. g_pDmElementFramework->BeginEdit();
  131. }
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Derived classes can implement this to get a new scheme to be applied to this tool
  135. //-----------------------------------------------------------------------------
  136. vgui::HScheme CPetTool::GetToolScheme()
  137. {
  138. return vgui::scheme()->LoadSchemeFromFile( "Resource/BoxRocket.res", "BoxRocket" );
  139. }
  140. //-----------------------------------------------------------------------------
  141. //
  142. // The View menu
  143. //
  144. //-----------------------------------------------------------------------------
  145. class CPetViewMenuButton : public CToolMenuButton
  146. {
  147. DECLARE_CLASS_SIMPLE( CPetViewMenuButton, CToolMenuButton );
  148. public:
  149. CPetViewMenuButton( CPetTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget );
  150. virtual void OnShowMenu(vgui::Menu *menu);
  151. private:
  152. CPetTool *m_pTool;
  153. };
  154. CPetViewMenuButton::CPetViewMenuButton( CPetTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget )
  155. : BaseClass( parent, panelName, text, pActionSignalTarget )
  156. {
  157. m_pTool = parent;
  158. AddCheckableMenuItem( "properties", "#PetProperties", new KeyValues( "OnToggleProperties" ), pActionSignalTarget );
  159. AddCheckableMenuItem( "browser", "#PetParticleSystemBrowser", new KeyValues( "OnToggleParticleSystemBrowser" ), pActionSignalTarget );
  160. AddCheckableMenuItem( "particlepreview", "#PetParticlePreview", new KeyValues( "OnToggleParticlePreview" ), pActionSignalTarget );
  161. AddSeparator();
  162. AddMenuItem( "defaultlayout", "#PetViewDefault", new KeyValues( "OnDefaultLayout" ), pActionSignalTarget );
  163. SetMenu(m_pMenu);
  164. }
  165. void CPetViewMenuButton::OnShowMenu(vgui::Menu *menu)
  166. {
  167. BaseClass::OnShowMenu( menu );
  168. // Update the menu
  169. int id;
  170. CPetDoc *pDoc = m_pTool->GetDocument();
  171. if ( pDoc )
  172. {
  173. id = m_Items.Find( "properties" );
  174. m_pMenu->SetItemEnabled( id, true );
  175. Panel *p;
  176. p = m_pTool->GetProperties();
  177. Assert( p );
  178. m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false );
  179. id = m_Items.Find( "browser" );
  180. m_pMenu->SetItemEnabled( id, true );
  181. p = m_pTool->GetParticleSystemDefinitionBrowser();
  182. Assert( p );
  183. m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false );
  184. id = m_Items.Find( "particlepreview" );
  185. m_pMenu->SetItemEnabled( id, true );
  186. p = m_pTool->GetParticlePreview();
  187. Assert( p );
  188. m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false );
  189. }
  190. else
  191. {
  192. id = m_Items.Find( "properties" );
  193. m_pMenu->SetItemEnabled( id, false );
  194. id = m_Items.Find( "browser" );
  195. m_pMenu->SetItemEnabled( id, false );
  196. id = m_Items.Find( "particlepreview" );
  197. m_pMenu->SetItemEnabled( id, false );
  198. }
  199. }
  200. //-----------------------------------------------------------------------------
  201. //
  202. // The Tool menu
  203. //
  204. //-----------------------------------------------------------------------------
  205. class CPetToolMenuButton : public CToolMenuButton
  206. {
  207. DECLARE_CLASS_SIMPLE( CPetToolMenuButton, CToolMenuButton );
  208. public:
  209. CPetToolMenuButton( CPetTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget );
  210. virtual void OnShowMenu(vgui::Menu *menu);
  211. private:
  212. CPetTool *m_pTool;
  213. };
  214. CPetToolMenuButton::CPetToolMenuButton( CPetTool *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget )
  215. : BaseClass( parent, panelName, text, pActionSignalTarget )
  216. {
  217. m_pTool = parent;
  218. SetMenu(m_pMenu);
  219. }
  220. void CPetToolMenuButton::OnShowMenu(vgui::Menu *menu)
  221. {
  222. BaseClass::OnShowMenu( menu );
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Initializes the menu bar
  226. //-----------------------------------------------------------------------------
  227. vgui::MenuBar *CPetTool::CreateMenuBar( CBaseToolSystem *pParent )
  228. {
  229. m_pMenuBar = new CToolFileMenuBar( pParent, "Main Menu Bar" );
  230. // Sets info in the menu bar
  231. char title[ 64 ];
  232. ComputeMenuBarTitle( title, sizeof( title ) );
  233. m_pMenuBar->SetInfo( title );
  234. m_pMenuBar->SetToolName( GetToolName() );
  235. // Add menu buttons
  236. CToolMenuButton *pFileButton = CreateToolFileMenuButton( m_pMenuBar, "File", "&File", GetActionTarget(), this );
  237. CToolMenuButton *pEditButton = CreateToolEditMenuButton( this, "Edit", "&Edit", GetActionTarget() );
  238. CPetToolMenuButton *pToolButton = new CPetToolMenuButton( this, "Pet", "&Pet", GetActionTarget() );
  239. CPetViewMenuButton *pViewButton = new CPetViewMenuButton( this, "View", "&View", GetActionTarget() );
  240. CToolMenuButton *pSwitchButton = CreateToolSwitchMenuButton( m_pMenuBar, "Switcher", "&Tools", GetActionTarget() );
  241. pEditButton->AddMenuItem( "copy", "#BxEditCopy", new KeyValues( "OnCopy" ), GetActionTarget(), NULL, "edit_copy" );
  242. pEditButton->AddMenuItem( "paste", "#BxEditPaste", new KeyValues( "OnPaste" ), GetActionTarget(), NULL, "edit_paste" );
  243. pEditButton->MoveMenuItem( pEditButton->FindMenuItem( "paste" ), pEditButton->FindMenuItem( "editkeybindings" ) );
  244. pEditButton->MoveMenuItem( pEditButton->FindMenuItem( "copy" ), pEditButton->FindMenuItem( "paste" ) );
  245. pEditButton->AddSeparatorAfterItem( "paste" );
  246. m_pMenuBar->AddButton( pFileButton );
  247. m_pMenuBar->AddButton( pEditButton );
  248. m_pMenuBar->AddButton( pToolButton );
  249. m_pMenuBar->AddButton( pViewButton );
  250. m_pMenuBar->AddButton( pSwitchButton );
  251. return m_pMenuBar;
  252. }
  253. //-----------------------------------------------------------------------------
  254. // Updates the menu bar based on the current file
  255. //-----------------------------------------------------------------------------
  256. void CPetTool::UpdateMenuBar( )
  257. {
  258. if ( !m_pDoc )
  259. {
  260. m_pMenuBar->SetFileName( "#PetNoFile" );
  261. return;
  262. }
  263. const char *pFile = m_pDoc->GetFileName();
  264. if ( !pFile[0] )
  265. {
  266. m_pMenuBar->SetFileName( "#PetNoFile" );
  267. return;
  268. }
  269. if ( m_pDoc->IsDirty() )
  270. {
  271. char sz[ 512 ];
  272. Q_snprintf( sz, sizeof( sz ), "* %s", pFile );
  273. m_pMenuBar->SetFileName( sz );
  274. }
  275. else
  276. {
  277. m_pMenuBar->SetFileName( pFile );
  278. }
  279. }
  280. //-----------------------------------------------------------------------------
  281. // Gets at tool windows
  282. //-----------------------------------------------------------------------------
  283. CParticleSystemPropertiesContainer *CPetTool::GetProperties()
  284. {
  285. return m_hProperties.Get();
  286. }
  287. CParticleSystemDefinitionBrowser *CPetTool::GetParticleSystemDefinitionBrowser()
  288. {
  289. return m_hParticleSystemDefinitionBrowser.Get();
  290. }
  291. CParticleSystemPreviewPanel *CPetTool::GetParticlePreview()
  292. {
  293. return m_hParticlePreview.Get();
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Copy/paste
  297. //-----------------------------------------------------------------------------
  298. void CPetTool::OnCopy()
  299. {
  300. GetParticleSystemDefinitionBrowser()->CopyToClipboard();
  301. }
  302. void CPetTool::OnPaste()
  303. {
  304. GetParticleSystemDefinitionBrowser()->PasteFromClipboard();
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Sets/gets the current particle system
  308. //-----------------------------------------------------------------------------
  309. void CPetTool::SetCurrentParticleSystem( CDmeParticleSystemDefinition *pParticleSystem, bool bForceBrowserSelection )
  310. {
  311. if ( !m_pDoc )
  312. return;
  313. if ( m_hCurrentParticleSystem.Get() == pParticleSystem )
  314. return;
  315. m_hCurrentParticleSystem = pParticleSystem;
  316. if ( bForceBrowserSelection && m_hParticleSystemDefinitionBrowser.Get() )
  317. {
  318. m_hParticleSystemDefinitionBrowser->UpdateParticleSystemList();
  319. m_hParticleSystemDefinitionBrowser->SelectParticleSystem( pParticleSystem );
  320. }
  321. if ( m_hParticlePreview.Get() )
  322. {
  323. m_hParticlePreview->SetParticleSystem( pParticleSystem );
  324. }
  325. if ( m_hProperties.Get() )
  326. {
  327. m_hProperties->SetParticleSystem( m_hCurrentParticleSystem );
  328. }
  329. }
  330. CDmeParticleSystemDefinition* CPetTool::GetCurrentParticleSystem( void )
  331. {
  332. return m_hCurrentParticleSystem;
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Destroys all tool windows
  336. //-----------------------------------------------------------------------------
  337. void CPetTool::DestroyToolContainers()
  338. {
  339. int c = ToolWindow::GetToolWindowCount();
  340. for ( int i = c - 1; i >= 0 ; --i )
  341. {
  342. ToolWindow *kill = ToolWindow::GetToolWindow( i );
  343. delete kill;
  344. }
  345. }
  346. //-----------------------------------------------------------------------------
  347. // Sets up the default layout
  348. //-----------------------------------------------------------------------------
  349. void CPetTool::OnDefaultLayout()
  350. {
  351. int y = m_pMenuBar->GetTall();
  352. int usew, useh;
  353. GetSize( usew, useh );
  354. DestroyToolContainers();
  355. Assert( ToolWindow::GetToolWindowCount() == 0 );
  356. CParticleSystemPropertiesContainer *pProperties = GetProperties();
  357. CParticleSystemDefinitionBrowser *pParticleSystemBrowser = GetParticleSystemDefinitionBrowser();
  358. CParticleSystemPreviewPanel *pPreviewer = GetParticlePreview();
  359. // Need three containers
  360. ToolWindow *pPropertyWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pProperties, "#PetProperties", false );
  361. ToolWindow *pBrowserWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pParticleSystemBrowser, "#PetParticleSystemBrowser", false );
  362. ToolWindow *pPreviewWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pPreviewer, "#PetPreviewer", false );
  363. int halfScreen = usew / 2;
  364. int bottom = useh - y;
  365. int sy = (bottom - y) / 2;
  366. SetMiniViewportBounds( halfScreen, y, halfScreen, sy - y );
  367. pPreviewWindow->SetBounds( halfScreen, sy, halfScreen, bottom - sy );
  368. pBrowserWindow->SetBounds( 0, y, halfScreen, sy - y );
  369. pPropertyWindow->SetBounds( 0, sy, halfScreen, bottom - sy );
  370. }
  371. void CPetTool::OnToggleProperties()
  372. {
  373. if ( m_hProperties.Get() )
  374. {
  375. ToggleToolWindow( m_hProperties.Get(), "#PetProperties" );
  376. }
  377. }
  378. void CPetTool::OnToggleParticleSystemBrowser()
  379. {
  380. if ( m_hParticleSystemDefinitionBrowser.Get() )
  381. {
  382. ToggleToolWindow( m_hParticleSystemDefinitionBrowser.Get(), "#PetParticleSystemBrowser" );
  383. }
  384. }
  385. void CPetTool::OnToggleParticlePreview()
  386. {
  387. if ( m_hParticlePreview.Get() )
  388. {
  389. ToggleToolWindow( m_hParticlePreview.Get(), "#PetPreviewer" );
  390. }
  391. }
  392. //-----------------------------------------------------------------------------
  393. // Creates
  394. //-----------------------------------------------------------------------------
  395. void CPetTool::CreateTools( CPetDoc *doc )
  396. {
  397. if ( !m_hProperties.Get() )
  398. {
  399. m_hProperties = new CParticleSystemPropertiesContainer( m_pDoc, this );
  400. }
  401. if ( !m_hParticleSystemDefinitionBrowser.Get() )
  402. {
  403. m_hParticleSystemDefinitionBrowser = new CParticleSystemDefinitionBrowser( m_pDoc, this, "ParticleSystemDefinitionBrowser" );
  404. }
  405. if ( !m_hParticlePreview.Get() )
  406. {
  407. m_hParticlePreview = new CParticleSystemPreviewPanel( NULL, "Particle System Preview" );
  408. }
  409. RegisterToolWindow( m_hProperties );
  410. RegisterToolWindow( m_hParticleSystemDefinitionBrowser );
  411. RegisterToolWindow( m_hParticlePreview );
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Initializes the tools
  415. //-----------------------------------------------------------------------------
  416. void CPetTool::InitTools()
  417. {
  418. // FIXME: There are no tool windows here; how should this work?
  419. // These panels are saved
  420. windowposmgr->RegisterPanel( "properties", m_hProperties, false );
  421. windowposmgr->RegisterPanel( "particlesystemdefinitionbrowser", m_hParticleSystemDefinitionBrowser, false );
  422. windowposmgr->RegisterPanel( "previewpanel", m_hParticlePreview, false );
  423. if ( !windowposmgr->LoadPositions( "cfg/pet.txt", this, &m_ToolWindowFactory, "Pet" ) )
  424. {
  425. OnDefaultLayout();
  426. }
  427. }
  428. void CPetTool::DestroyTools()
  429. {
  430. SetCurrentParticleSystem( NULL );
  431. int c = ToolWindow::GetToolWindowCount();
  432. for ( int i = c - 1; i >= 0 ; --i )
  433. {
  434. ToolWindow *kill = ToolWindow::GetToolWindow( i );
  435. delete kill;
  436. }
  437. UnregisterAllToolWindows();
  438. if ( m_hProperties.Get() )
  439. {
  440. windowposmgr->UnregisterPanel( m_hProperties.Get() );
  441. delete m_hProperties.Get();
  442. m_hProperties = NULL;
  443. }
  444. if ( m_hParticleSystemDefinitionBrowser.Get() )
  445. {
  446. windowposmgr->UnregisterPanel( m_hParticleSystemDefinitionBrowser.Get() );
  447. delete m_hParticleSystemDefinitionBrowser.Get();
  448. m_hParticleSystemDefinitionBrowser = NULL;
  449. }
  450. if ( m_hParticlePreview.Get() )
  451. {
  452. windowposmgr->UnregisterPanel( m_hParticlePreview.Get() );
  453. delete m_hParticlePreview.Get();
  454. m_hParticlePreview = NULL;
  455. }
  456. }
  457. void CPetTool::ShowToolWindow( Panel *tool, char const *toolName, bool visible )
  458. {
  459. Assert( tool );
  460. if ( tool->GetParent() == NULL && visible )
  461. {
  462. m_ToolWindowFactory.InstanceToolWindow( this, false, tool, toolName, false );
  463. }
  464. else if ( !visible )
  465. {
  466. ToolWindow *tw = dynamic_cast< ToolWindow * >( tool->GetParent()->GetParent() );
  467. Assert( tw );
  468. tw->RemovePage( tool );
  469. }
  470. }
  471. void CPetTool::ToggleToolWindow( Panel *tool, char const *toolName )
  472. {
  473. Assert( tool );
  474. if ( tool->GetParent() == NULL )
  475. {
  476. ShowToolWindow( tool, toolName, true );
  477. }
  478. else
  479. {
  480. ShowToolWindow( tool, toolName, false );
  481. }
  482. }
  483. //-----------------------------------------------------------------------------
  484. // Creates the action menu
  485. //-----------------------------------------------------------------------------
  486. vgui::Menu *CPetTool::CreateActionMenu( vgui::Panel *pParent )
  487. {
  488. vgui::Menu *pActionMenu = new Menu( pParent, "ActionMenu" );
  489. pActionMenu->AddMenuItem( "#ToolHide", new KeyValues( "Command", "command", "HideActionMenu" ), GetActionTarget() );
  490. return pActionMenu;
  491. }
  492. //-----------------------------------------------------------------------------
  493. // Inherited from IFileMenuCallbacks
  494. //-----------------------------------------------------------------------------
  495. int CPetTool::GetFileMenuItemsEnabled( )
  496. {
  497. int nFlags = FILE_ALL;
  498. if ( m_RecentFiles.IsEmpty() )
  499. {
  500. nFlags &= ~(FILE_RECENT | FILE_CLEAR_RECENT);
  501. }
  502. return nFlags;
  503. }
  504. void CPetTool::AddRecentFilesToMenu( vgui::Menu *pMenu )
  505. {
  506. m_RecentFiles.AddToMenu( pMenu, GetActionTarget(), "OnRecent" );
  507. }
  508. bool CPetTool::GetPerforceFileName( char *pFileName, int nMaxLen )
  509. {
  510. if ( !m_pDoc )
  511. return false;
  512. Q_strncpy( pFileName, m_pDoc->GetFileName(), nMaxLen );
  513. return pFileName[0] != 0;
  514. }
  515. //-----------------------------------------------------------------------------
  516. // Purpose:
  517. // Input : -
  518. //-----------------------------------------------------------------------------
  519. void CPetTool::OnExit()
  520. {
  521. windowposmgr->SavePositions( "cfg/pet.txt", "Pet" );
  522. enginetools->Command( "quit\n" );
  523. }
  524. //-----------------------------------------------------------------------------
  525. // Handle commands from the action menu and other menus
  526. //-----------------------------------------------------------------------------
  527. void CPetTool::OnCommand( const char *cmd )
  528. {
  529. if ( !V_stricmp( cmd, "HideActionMenu" ) )
  530. {
  531. if ( GetActionMenu() )
  532. {
  533. GetActionMenu()->SetVisible( false );
  534. }
  535. }
  536. else if ( const char *pSuffix = StringAfterPrefix( cmd, "OnRecent" ) )
  537. {
  538. int idx = Q_atoi( pSuffix );
  539. OpenFileFromHistory( idx );
  540. }
  541. else if ( const char *pSuffix = StringAfterPrefix( cmd, "OnTool" ) )
  542. {
  543. int idx = Q_atoi( pSuffix );
  544. enginetools->SwitchToTool( idx );
  545. }
  546. else if ( !V_stricmp( cmd, "OnUndo" ) )
  547. {
  548. OnUndo();
  549. }
  550. else if ( !V_stricmp( cmd, "OnRedo" ) )
  551. {
  552. OnRedo();
  553. }
  554. else if ( !V_stricmp( cmd, "OnDescribeUndo" ) )
  555. {
  556. OnDescribeUndo();
  557. }
  558. else
  559. {
  560. BaseClass::OnCommand( cmd );
  561. }
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Command handlers
  565. //-----------------------------------------------------------------------------
  566. void CPetTool::PerformNew()
  567. {
  568. OnCloseNoSave();
  569. NewDocument();
  570. }
  571. void CPetTool::OnNew()
  572. {
  573. if ( m_pDoc && m_pDoc->IsDirty() )
  574. {
  575. SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY,
  576. new KeyValues( "OnNew" ) );
  577. return;
  578. }
  579. PerformNew();
  580. }
  581. //-----------------------------------------------------------------------------
  582. // Called when the File->Open menu is selected
  583. //-----------------------------------------------------------------------------
  584. void CPetTool::OnOpen( )
  585. {
  586. int nFlags = 0;
  587. const char *pSaveFileName = NULL;
  588. if ( m_pDoc && m_pDoc->IsDirty() )
  589. {
  590. nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
  591. pSaveFileName = m_pDoc->GetFileName();
  592. }
  593. OpenFile( PET_FILE_FORMAT, pSaveFileName, PET_FILE_FORMAT, nFlags );
  594. }
  595. bool CPetTool::OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
  596. {
  597. OnCloseNoSave();
  598. if ( !LoadDocument( pFileName ) )
  599. return false;
  600. m_RecentFiles.Add( pFileName, pFileFormat );
  601. m_RecentFiles.SaveToRegistry( GetRegistryName() );
  602. UpdateMenuBar();
  603. return true;
  604. }
  605. void CPetTool::Save()
  606. {
  607. if ( m_pDoc )
  608. {
  609. SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS );
  610. }
  611. }
  612. void CPetTool::OnSaveAs()
  613. {
  614. if ( m_pDoc )
  615. {
  616. SaveFile( NULL, PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS );
  617. }
  618. }
  619. void CPetTool::OnRestartLevel()
  620. {
  621. enginetools->Command( "restart" );
  622. enginetools->Execute();
  623. }
  624. void CPetTool::SaveAndTest()
  625. {
  626. if ( m_pDoc && m_pDoc->IsDirty() )
  627. {
  628. SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS,
  629. new KeyValues( "RestartLevel" ) );
  630. }
  631. else
  632. {
  633. OnRestartLevel();
  634. }
  635. }
  636. bool CPetTool::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
  637. {
  638. if ( !m_pDoc )
  639. return true;
  640. m_pDoc->SetFileName( pFileName );
  641. m_pDoc->SaveToFile( );
  642. m_RecentFiles.Add( pFileName, pFileFormat );
  643. m_RecentFiles.SaveToRegistry( GetRegistryName() );
  644. UpdateMenuBar();
  645. return true;
  646. }
  647. void CPetTool::OnClose()
  648. {
  649. if ( m_pDoc && m_pDoc->IsDirty() )
  650. {
  651. SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY,
  652. new KeyValues( "OnClose" ) );
  653. return;
  654. }
  655. OnCloseNoSave();
  656. }
  657. void CPetTool::OnCloseNoSave()
  658. {
  659. DestroyTools();
  660. if ( m_pDoc )
  661. {
  662. CAppNotifyScopeGuard sg( "CPetTool::OnCloseNoSave", NOTIFY_CHANGE_OTHER );
  663. delete m_pDoc;
  664. m_pDoc = NULL;
  665. if ( m_hProperties )
  666. {
  667. m_hProperties->SetParticleSystem( NULL );
  668. }
  669. }
  670. UpdateMenuBar( );
  671. }
  672. void CPetTool::OnMarkNotDirty()
  673. {
  674. if ( m_pDoc )
  675. {
  676. m_pDoc->SetDirty( false );
  677. }
  678. }
  679. //-----------------------------------------------------------------------------
  680. // Open a specific file
  681. //-----------------------------------------------------------------------------
  682. void CPetTool::OpenSpecificFile( const char *pFileName )
  683. {
  684. int nFlags = 0;
  685. const char *pSaveFileName = NULL;
  686. if ( m_pDoc )
  687. {
  688. // File is already open
  689. if ( !Q_stricmp( m_pDoc->GetFileName(), pFileName ) )
  690. return;
  691. if ( m_pDoc->IsDirty() )
  692. {
  693. nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
  694. pSaveFileName = m_pDoc->GetFileName();
  695. }
  696. else
  697. {
  698. OnCloseNoSave();
  699. }
  700. }
  701. OpenFile( pFileName, PET_FILE_FORMAT, pSaveFileName, PET_FILE_FORMAT, nFlags );
  702. }
  703. //-----------------------------------------------------------------------------
  704. // Show the save document query dialog
  705. //-----------------------------------------------------------------------------
  706. void CPetTool::OpenFileFromHistory( int slot )
  707. {
  708. const char *pFileName = m_RecentFiles.GetFile( slot );
  709. if ( !pFileName )
  710. return;
  711. OpenSpecificFile( pFileName );
  712. }
  713. //-----------------------------------------------------------------------------
  714. // Derived classes can implement this to get notified when files are saved/loaded
  715. //-----------------------------------------------------------------------------
  716. void CPetTool::OnFileOperationCompleted( const char *pFileType, bool bWroteFile, vgui::FileOpenStateMachine::CompletionState_t state, KeyValues *pContextKeyValues )
  717. {
  718. if ( bWroteFile )
  719. {
  720. OnMarkNotDirty();
  721. }
  722. if ( !pContextKeyValues )
  723. return;
  724. if ( state != FileOpenStateMachine::SUCCESSFUL )
  725. return;
  726. if ( !Q_stricmp( pContextKeyValues->GetName(), "OnNew" ) )
  727. {
  728. PerformNew();
  729. return;
  730. }
  731. if ( !Q_stricmp( pContextKeyValues->GetName(), "OnClose" ) )
  732. {
  733. OnCloseNoSave();
  734. return;
  735. }
  736. if ( !Q_stricmp( pContextKeyValues->GetName(), "OnQuit" ) )
  737. {
  738. OnCloseNoSave();
  739. vgui::ivgui()->PostMessage( GetVPanel(), new KeyValues( "OnExit" ), 0 );
  740. return;
  741. }
  742. if ( !Q_stricmp( pContextKeyValues->GetName(), "RestartLevel" ) )
  743. {
  744. OnRestartLevel();
  745. return;
  746. }
  747. }
  748. //-----------------------------------------------------------------------------
  749. // Show the File browser dialog
  750. //-----------------------------------------------------------------------------
  751. void CPetTool::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues )
  752. {
  753. char pStartingDir[ MAX_PATH ];
  754. GetModSubdirectory( "particles", pStartingDir, sizeof(pStartingDir) );
  755. // Open a bsp file to create a new commentary file
  756. pDialog->SetTitle( "Choose Particle Configuration File", true );
  757. pDialog->SetStartDirectoryContext( "pet_session", pStartingDir );
  758. pDialog->AddFilter( "*.pcf", "Particle Configuration File (*.pcf)", true );
  759. }
  760. //-----------------------------------------------------------------------------
  761. // Can we quit?
  762. //-----------------------------------------------------------------------------
  763. bool CPetTool::CanQuit()
  764. {
  765. if ( m_pDoc && m_pDoc->IsDirty() )
  766. {
  767. // Show Save changes Yes/No/Cancel and re-quit if hit yes/no
  768. SaveFile( m_pDoc->GetFileName(), PET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY,
  769. new KeyValues( "OnQuit" ) );
  770. return false;
  771. }
  772. return true;
  773. }
  774. //-----------------------------------------------------------------------------
  775. // Various command handlers related to the Edit menu
  776. //-----------------------------------------------------------------------------
  777. void CPetTool::OnUndo()
  778. {
  779. CDisableUndoScopeGuard guard;
  780. g_pDataModel->Undo();
  781. }
  782. void CPetTool::OnRedo()
  783. {
  784. CDisableUndoScopeGuard guard;
  785. g_pDataModel->Redo();
  786. }
  787. void CPetTool::OnDescribeUndo()
  788. {
  789. CUtlVector< UndoInfo_t > list;
  790. g_pDataModel->GetUndoInfo( list );
  791. Msg( "%i operations in stack\n", list.Count() );
  792. for ( int i = list.Count() - 1; i >= 0; --i )
  793. {
  794. UndoInfo_t& entry = list[ i ];
  795. if ( entry.terminator )
  796. {
  797. Msg( "[ '%s' ] - %i operations\n", entry.undo, entry.numoperations );
  798. }
  799. Msg( " +%s\n", entry.desc );
  800. }
  801. }
  802. //-----------------------------------------------------------------------------
  803. // Background
  804. //-----------------------------------------------------------------------------
  805. const char *CPetTool::GetLogoTextureName()
  806. {
  807. return NULL;
  808. }
  809. //-----------------------------------------------------------------------------
  810. // Inherited from IPetDocCallback
  811. //-----------------------------------------------------------------------------
  812. void CPetTool::OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags )
  813. {
  814. CDmeParticleSystemDefinition *pParticleSystem = GetCurrentParticleSystem();
  815. if ( m_pDoc && GetParticlePreview() && pParticleSystem )
  816. {
  817. m_pDoc->UpdateParticleDefinition( pParticleSystem );
  818. }
  819. if ( nNotifyFlags & NOTIFY_CHANGE_TOPOLOGICAL )
  820. {
  821. if ( GetParticleSystemDefinitionBrowser() )
  822. {
  823. GetParticleSystemDefinitionBrowser()->UpdateParticleSystemList();
  824. }
  825. }
  826. bool bRefreshProperties = ( nNotifySource != NOTIFY_SOURCE_PROPERTIES_TREE ) &&
  827. ( ( nNotifyFlags & ( NOTIFY_CHANGE_TOPOLOGICAL | NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE ) ) != 0 );
  828. bool bRefreshPropertyValues = ( nNotifySource != NOTIFY_SOURCE_PROPERTIES_TREE ) &&
  829. ( nNotifyFlags & NOTIFY_CHANGE_ATTRIBUTE_VALUE ) != 0;
  830. if ( bRefreshProperties || bRefreshPropertyValues )
  831. {
  832. if ( m_hProperties.Get() )
  833. {
  834. m_hProperties->Refresh( !bRefreshProperties );
  835. }
  836. }
  837. UpdateMenuBar();
  838. }
  839. //-----------------------------------------------------------------------------
  840. // Creates a new document
  841. //-----------------------------------------------------------------------------
  842. void CPetTool::NewDocument( )
  843. {
  844. Assert( !m_pDoc );
  845. DestroyTools();
  846. m_pDoc = new CPetDoc( this );
  847. m_pDoc->CreateNew( );
  848. ShowMiniViewport( true );
  849. CreateTools( m_pDoc );
  850. UpdateMenuBar( );
  851. InitTools();
  852. }
  853. //-----------------------------------------------------------------------------
  854. // Loads up a new document
  855. //-----------------------------------------------------------------------------
  856. bool CPetTool::LoadDocument( const char *pDocName )
  857. {
  858. Assert( !m_pDoc );
  859. DestroyTools();
  860. m_pDoc = new CPetDoc( this );
  861. if ( !m_pDoc->LoadFromFile( pDocName ) )
  862. {
  863. delete m_pDoc;
  864. m_pDoc = NULL;
  865. Warning( "Fatal error loading '%s'\n", pDocName );
  866. return false;
  867. }
  868. ShowMiniViewport( true );
  869. CreateTools( m_pDoc );
  870. UpdateMenuBar( );
  871. InitTools();
  872. // Let the other tools know we've loaded + therefore modified particle systems
  873. CUtlBuffer buf;
  874. g_pDataModel->Serialize( buf, "binary", PET_FILE_FORMAT, m_pDoc->GetRootObject()->GetHandle() );
  875. KeyValues *pMessage = new KeyValues( "ParticleSystemUpdated" );
  876. pMessage->SetPtr( "definitionBits", buf.Base() );
  877. pMessage->SetInt( "definitionSize", buf.TellMaxPut() );
  878. PostMessageToAllTools( pMessage );
  879. pMessage->deleteThis();
  880. return true;
  881. }