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

1375 lines
45 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Dialog used to edit properties of a particle system definition
  4. //
  5. //===========================================================================//
  6. #include "dme_controls/ParticleSystemPropertiesPanel.h"
  7. #include "tier1/keyvalues.h"
  8. #include "tier1/utlbuffer.h"
  9. #include "vgui/ivgui.h"
  10. #include "vgui_controls/button.h"
  11. #include "vgui_controls/listpanel.h"
  12. #include "vgui_controls/splitter.h"
  13. #include "vgui_controls/messagebox.h"
  14. #include "vgui_controls/combobox.h"
  15. #include "datamodel/dmelement.h"
  16. #include "movieobjects/dmeparticlesystemdefinition.h"
  17. #include "dme_controls/elementpropertiestree.h"
  18. #include "matsys_controls/picker.h"
  19. #include "dme_controls/dmecontrols_utils.h"
  20. #include "dme_controls/particlesystempanel.h"
  21. #include "dme_controls/dmepanel.h"
  22. // memdbgon must be the last include file in a .cpp file!!!
  23. #include <tier0/memdbgon.h>
  24. using namespace vgui;
  25. class CParticleFunctionTree: public vgui::TreeView
  26. {
  27. DECLARE_CLASS_SIMPLE( CParticleFunctionTree, vgui::TreeView );
  28. public:
  29. CParticleFunctionTree(Panel *parent, const char *panelName): TreeView(parent, panelName)
  30. {
  31. }
  32. virtual void GenerateContextMenu( int itemIndex, int x, int y )
  33. {
  34. PostActionSignal( new KeyValues("OpenContextMenu", "itemID", itemIndex ));
  35. }
  36. };
  37. //-----------------------------------------------------------------------------
  38. //
  39. // Purpose: Picker for particle functions
  40. //
  41. //-----------------------------------------------------------------------------
  42. class CParticleFunctionPickerFrame : public vgui::Frame
  43. {
  44. DECLARE_CLASS_SIMPLE( CParticleFunctionPickerFrame, vgui::Frame );
  45. public:
  46. CParticleFunctionPickerFrame( vgui::Panel *pParent, const char *pTitle );
  47. ~CParticleFunctionPickerFrame();
  48. // Sets the current scene + animation list
  49. void DoModal( CDmeParticleSystemDefinition *pParticleSystem, ParticleFunctionType_t type, KeyValues *pContextKeyValues );
  50. // Inherited from Frame
  51. virtual void OnCommand( const char *pCommand );
  52. private:
  53. // Refreshes the list of particle functions
  54. void RefreshParticleFunctions( CDmeParticleSystemDefinition *pDefinition, ParticleFunctionType_t type );
  55. void CleanUpMessage();
  56. MESSAGE_FUNC( OnTextChanged, "TextChanged" );
  57. vgui::ListPanel *m_pFunctionList;
  58. vgui::Button *m_pOpenButton;
  59. vgui::Button *m_pCancelButton;
  60. vgui::ComboBox *m_pFilterCombo;
  61. KeyValues *m_pContextKeyValues;
  62. };
  63. static int __cdecl ParticleFunctionNameSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
  64. {
  65. const char *string1 = item1.kv->GetString( "name" );
  66. const char *string2 = item2.kv->GetString( "name" );
  67. return Q_stricmp( string1, string2 );
  68. }
  69. CParticleFunctionPickerFrame::CParticleFunctionPickerFrame( vgui::Panel *pParent, const char *pTitle ) :
  70. BaseClass( pParent, "ParticleFunctionPickerFrame" )
  71. {
  72. SetDeleteSelfOnClose( true );
  73. m_pContextKeyValues = NULL;
  74. m_pFunctionList = new vgui::ListPanel( this, "ParticleFunctionList" );
  75. m_pFunctionList->AddColumnHeader( 0, "name", "Particle Function Name", 52, 0 );
  76. m_pFunctionList->SetSelectIndividualCells( false );
  77. m_pFunctionList->SetMultiselectEnabled( false );
  78. m_pFunctionList->SetEmptyListText( "No particle functions" );
  79. m_pFunctionList->AddActionSignalTarget( this );
  80. m_pFunctionList->SetSortFunc( 0, ParticleFunctionNameSortFunc );
  81. m_pFunctionList->SetSortColumn( 0 );
  82. m_pOpenButton = new vgui::Button( this, "OkButton", "#MessageBox_OK", this, "Ok" );
  83. m_pCancelButton = new vgui::Button( this, "CancelButton", "#MessageBox_Cancel", this, "Cancel" );
  84. m_pFilterCombo = new ComboBox(this, "FilterByOperatorType", 0, false);
  85. SetBlockDragChaining( true );
  86. LoadControlSettingsAndUserConfig( "resource/particlefunctionpicker.res" );
  87. SetTitle( pTitle, false );
  88. }
  89. CParticleFunctionPickerFrame::~CParticleFunctionPickerFrame()
  90. {
  91. CleanUpMessage();
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Refreshes the list of raw controls
  95. //-----------------------------------------------------------------------------
  96. void CParticleFunctionPickerFrame::RefreshParticleFunctions( CDmeParticleSystemDefinition *pParticleSystem, ParticleFunctionType_t type )
  97. {
  98. m_pFunctionList->RemoveAll();
  99. if ( !pParticleSystem )
  100. return;
  101. CUtlVector< IParticleOperatorDefinition *> &list = g_pParticleSystemMgr->GetAvailableParticleOperatorList( type );
  102. int nCount = list.Count();
  103. // Build a list of used operator IDs
  104. bool pUsedIDs[OPERATOR_ID_COUNT];
  105. memset( pUsedIDs, 0, sizeof(pUsedIDs) );
  106. uint32 allFilters = 0;
  107. int nFunctionCount = pParticleSystem->GetParticleFunctionCount( type );
  108. for ( int i = 0; i < nFunctionCount; ++i )
  109. {
  110. const char *pFunctionName = pParticleSystem->GetParticleFunction( type, i )->GetName();
  111. for ( int j = 0; j < nCount; ++j )
  112. {
  113. if ( Q_stricmp( pFunctionName, list[j]->GetName() ) )
  114. continue;
  115. if ( list[j]->GetId() >= 0 )
  116. {
  117. pUsedIDs[ list[j]->GetId() ] = true;
  118. }
  119. break;
  120. }
  121. }
  122. for ( int i = 0; i < nCount; ++i )
  123. {
  124. const char *pFunctionName = list[i]->GetName();
  125. uint32 filter = list[i]->GetFilter();
  126. bool disableItem = false;
  127. // Look to see if this is in a special operator group
  128. if ( list[i]->GetId() >= 0 )
  129. {
  130. // Disable ones that are already in the particle system
  131. if ( pUsedIDs[ list[i]->GetId() ] )
  132. disableItem = true;
  133. }
  134. if ( list[i]->GetId() == OPERATOR_SINGLETON )
  135. {
  136. // Disable ones that are already in the particle system
  137. if ( pParticleSystem->FindFunction( type, pFunctionName ) >= 0 )
  138. disableItem = true;
  139. }
  140. // Don't display obsolete operators
  141. if ( list[i]->IsObsolete() )
  142. continue;
  143. allFilters = allFilters | filter;
  144. KeyValues *kv = new KeyValues( "node", "name", pFunctionName );
  145. kv->SetInt( "typeNumber", type );
  146. kv->SetInt( "filters", filter );
  147. m_pFunctionList->AddItem( kv, 0, false, false );
  148. m_pFunctionList->SetItemDisabled( i, disableItem );
  149. }
  150. // Populate the combo box
  151. m_pFilterCombo->RemoveAll();
  152. for (int i = 0; i < FILTER_COUNT; ++i )
  153. {
  154. if ( (i == 0) || ( allFilters & ( 1 << i ) ) )
  155. {
  156. KeyValues *kv = new KeyValues( "Filter" );
  157. kv->SetInt( "filter", i);
  158. m_pFilterCombo->AddItem( g_pParticleSystemMgr->GetFilterName( (ParticleFilterType_t) i ), kv );
  159. }
  160. }
  161. m_pFilterCombo->ActivateItemByRow( 0 );
  162. m_pFunctionList->SortList();
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Filters the list
  166. //-----------------------------------------------------------------------------
  167. void CParticleFunctionPickerFrame::OnTextChanged( )
  168. {
  169. m_pFunctionList->SetAllVisible( true );
  170. int nCount = m_pFunctionList->GetItemCount();
  171. uint32 filter = 1 << m_pFilterCombo->GetActiveItemUserData()->GetInt( "filter", 0 );
  172. if (filter != 1)
  173. {
  174. for ( int i = 0; i < nCount; ++i )
  175. {
  176. // Hide items by filter type
  177. int currFilter = m_pFunctionList->GetItem(i)->GetInt( "filters", 0 );
  178. if ( ( (uint32) currFilter ) & filter )
  179. {
  180. m_pFunctionList->SetItemVisible( i, true );
  181. }
  182. else
  183. {
  184. m_pFunctionList->SetItemVisible( i, false );
  185. }
  186. }
  187. }
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Deletes the message
  191. //-----------------------------------------------------------------------------
  192. void CParticleFunctionPickerFrame::CleanUpMessage()
  193. {
  194. if ( m_pContextKeyValues )
  195. {
  196. m_pContextKeyValues->deleteThis();
  197. m_pContextKeyValues = NULL;
  198. }
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Sets the current scene + animation list
  202. //-----------------------------------------------------------------------------
  203. void CParticleFunctionPickerFrame::DoModal( CDmeParticleSystemDefinition *pParticleSystem, ParticleFunctionType_t type, KeyValues *pContextKeyValues )
  204. {
  205. CleanUpMessage();
  206. RefreshParticleFunctions( pParticleSystem, type );
  207. m_pContextKeyValues = pContextKeyValues;
  208. BaseClass::DoModal();
  209. }
  210. //-----------------------------------------------------------------------------
  211. // On command
  212. //-----------------------------------------------------------------------------
  213. void CParticleFunctionPickerFrame::OnCommand( const char *pCommand )
  214. {
  215. if ( !Q_stricmp( pCommand, "Ok" ) )
  216. {
  217. int nSelectedItemCount = m_pFunctionList->GetSelectedItemsCount();
  218. if ( nSelectedItemCount == 0 )
  219. return;
  220. Assert( nSelectedItemCount == 1 );
  221. int nItemID = m_pFunctionList->GetSelectedItem( 0 );
  222. KeyValues *pKeyValues = m_pFunctionList->GetItem( nItemID );
  223. if ( pKeyValues->GetInt( "disabled" ) == 1 )
  224. return;
  225. KeyValues *pActionKeys = new KeyValues( "ParticleFunctionPicked" );
  226. pActionKeys->SetString( "name", pKeyValues->GetString( "name" ) );
  227. pActionKeys->SetInt( "typeNumber", pKeyValues->GetInt("typeNumber") );
  228. if ( m_pContextKeyValues )
  229. {
  230. pActionKeys->AddSubKey( m_pContextKeyValues );
  231. // This prevents them from being deleted later
  232. m_pContextKeyValues = NULL;
  233. }
  234. PostActionSignal( pActionKeys );
  235. CloseModal();
  236. return;
  237. }
  238. if ( !Q_stricmp( pCommand, "Cancel" ) )
  239. {
  240. CloseModal();
  241. return;
  242. }
  243. BaseClass::OnCommand( pCommand );
  244. }
  245. //-----------------------------------------------------------------------------
  246. //
  247. // Purpose: Picker for child particle systems
  248. //
  249. //-----------------------------------------------------------------------------
  250. class CParticleChildrenPickerFrame : public vgui::Frame
  251. {
  252. DECLARE_CLASS_SIMPLE( CParticleChildrenPickerFrame, vgui::Frame );
  253. public:
  254. CParticleChildrenPickerFrame( vgui::Panel *pParent, const char *pTitle, IParticleSystemPropertiesPanelQuery *pQuery );
  255. ~CParticleChildrenPickerFrame();
  256. // Sets the current scene + animation list
  257. void DoModal( CDmeParticleSystemDefinition *pParticleSystem, KeyValues *pContextKeyValues );
  258. // Inherited from Frame
  259. virtual void OnCommand( const char *pCommand );
  260. private:
  261. // Refreshes the list of children particle systems
  262. void RefreshChildrenList( CDmeParticleSystemDefinition *pDefinition );
  263. void CleanUpMessage();
  264. IParticleSystemPropertiesPanelQuery *m_pQuery;
  265. vgui::ListPanel *m_pChildrenList;
  266. vgui::Button *m_pOpenButton;
  267. vgui::Button *m_pCancelButton;
  268. KeyValues *m_pContextKeyValues;
  269. };
  270. static int __cdecl ParticleChildrenNameSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
  271. {
  272. const char *string1 = item1.kv->GetString( "name" );
  273. const char *string2 = item2.kv->GetString( "name" );
  274. return Q_stricmp( string1, string2 );
  275. }
  276. CParticleChildrenPickerFrame::CParticleChildrenPickerFrame( vgui::Panel *pParent, const char *pTitle, IParticleSystemPropertiesPanelQuery *pQuery ) :
  277. BaseClass( pParent, "ParticleChildrenPickerFrame" ), m_pQuery( pQuery )
  278. {
  279. SetDeleteSelfOnClose( true );
  280. m_pContextKeyValues = NULL;
  281. m_pChildrenList = new vgui::ListPanel( this, "ParticleChildrenList" );
  282. m_pChildrenList->AddColumnHeader( 0, "name", "Particle System Name", 52, 0 );
  283. m_pChildrenList->SetSelectIndividualCells( false );
  284. m_pChildrenList->SetMultiselectEnabled( false );
  285. m_pChildrenList->SetEmptyListText( "No particle systems" );
  286. m_pChildrenList->AddActionSignalTarget( this );
  287. m_pChildrenList->SetSortFunc( 0, ParticleChildrenNameSortFunc );
  288. m_pChildrenList->SetSortColumn( 0 );
  289. m_pOpenButton = new vgui::Button( this, "OkButton", "#MessageBox_OK", this, "Ok" );
  290. m_pCancelButton = new vgui::Button( this, "CancelButton", "#MessageBox_Cancel", this, "Cancel" );
  291. SetBlockDragChaining( true );
  292. LoadControlSettingsAndUserConfig( "resource/particlechildrenpicker.res" );
  293. SetTitle( pTitle, false );
  294. }
  295. CParticleChildrenPickerFrame::~CParticleChildrenPickerFrame()
  296. {
  297. CleanUpMessage();
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Refreshes the list of raw controls
  301. //-----------------------------------------------------------------------------
  302. void CParticleChildrenPickerFrame::RefreshChildrenList( CDmeParticleSystemDefinition *pCurrentParticleSystem )
  303. {
  304. m_pChildrenList->RemoveAll();
  305. CUtlVector< CDmeParticleSystemDefinition* > definitions;
  306. if ( m_pQuery )
  307. {
  308. m_pQuery->GetKnownParticleDefinitions( definitions );
  309. }
  310. int nCount = definitions.Count();
  311. if ( nCount == 0 )
  312. return;
  313. for ( int i = 0; i < nCount; ++i )
  314. {
  315. CDmeParticleSystemDefinition *pParticleSystem = definitions[i];
  316. if ( pParticleSystem == pCurrentParticleSystem )
  317. continue;
  318. const char *pName = pParticleSystem->GetName();
  319. if ( !pName || !pName[0] )
  320. {
  321. pName = "<no name>";
  322. }
  323. KeyValues *kv = new KeyValues( "node" );
  324. kv->SetString( "name", pName );
  325. SetElementKeyValue( kv, "particleSystem", pParticleSystem );
  326. m_pChildrenList->AddItem( kv, 0, false, false );
  327. }
  328. m_pChildrenList->SortList();
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Deletes the message
  332. //-----------------------------------------------------------------------------
  333. void CParticleChildrenPickerFrame::CleanUpMessage()
  334. {
  335. if ( m_pContextKeyValues )
  336. {
  337. m_pContextKeyValues->deleteThis();
  338. m_pContextKeyValues = NULL;
  339. }
  340. }
  341. //-----------------------------------------------------------------------------
  342. // Sets the current scene + animation list
  343. //-----------------------------------------------------------------------------
  344. void CParticleChildrenPickerFrame::DoModal( CDmeParticleSystemDefinition *pParticleSystem, KeyValues *pContextKeyValues )
  345. {
  346. CleanUpMessage();
  347. RefreshChildrenList( pParticleSystem );
  348. m_pContextKeyValues = pContextKeyValues;
  349. BaseClass::DoModal();
  350. }
  351. //-----------------------------------------------------------------------------
  352. // On command
  353. //-----------------------------------------------------------------------------
  354. void CParticleChildrenPickerFrame::OnCommand( const char *pCommand )
  355. {
  356. if ( !Q_stricmp( pCommand, "Ok" ) )
  357. {
  358. int nSelectedItemCount = m_pChildrenList->GetSelectedItemsCount();
  359. if ( nSelectedItemCount == 0 )
  360. return;
  361. Assert( nSelectedItemCount == 1 );
  362. int nItemID = m_pChildrenList->GetSelectedItem( 0 );
  363. KeyValues *pKeyValues = m_pChildrenList->GetItem( nItemID );
  364. CDmeParticleSystemDefinition *pParticleSystem = GetElementKeyValue<CDmeParticleSystemDefinition>( pKeyValues, "particleSystem" );
  365. KeyValues *pActionKeys = new KeyValues( "ParticleChildPicked" );
  366. SetElementKeyValue( pActionKeys, "particleSystem", pParticleSystem );
  367. if ( m_pContextKeyValues )
  368. {
  369. pActionKeys->AddSubKey( m_pContextKeyValues );
  370. // This prevents them from being deleted later
  371. m_pContextKeyValues = NULL;
  372. }
  373. PostActionSignal( pActionKeys );
  374. CloseModal();
  375. return;
  376. }
  377. if ( !Q_stricmp( pCommand, "Cancel" ) )
  378. {
  379. CloseModal();
  380. return;
  381. }
  382. BaseClass::OnCommand( pCommand );
  383. }
  384. //-----------------------------------------------------------------------------
  385. // Browser of various particle functions
  386. //-----------------------------------------------------------------------------
  387. class CParticleFunctionBrowser : public vgui::EditablePanel
  388. {
  389. DECLARE_CLASS_SIMPLE( CParticleFunctionBrowser, vgui::EditablePanel );
  390. public:
  391. // constructor, destructor
  392. CParticleFunctionBrowser( vgui::Panel *pParent, const char *pName, IParticleSystemPropertiesPanelQuery *pQuery );
  393. virtual ~CParticleFunctionBrowser();
  394. // Inherited from Panel
  395. virtual void OnKeyCodeTyped( vgui::KeyCode code );
  396. void SetParticleFunctionProperties( CDmeElementPanel *pPanel );
  397. void SetParticleSystem( CDmeParticleSystemDefinition *pOp );
  398. void RefreshParticleFunctionList();
  399. void SelectDefaultFunction();
  400. // Called when a list panel's selection changes
  401. void RefreshParticleFunctionProperties( );
  402. MESSAGE_FUNC( DeleteSelectedFunctions, "Remove" );
  403. MESSAGE_FUNC( OnCopy, "OnCopy" );
  404. private:
  405. MESSAGE_FUNC_PARAMS( OnOpenContextMenu, "OpenContextMenu", kv );
  406. MESSAGE_FUNC_PARAMS( OnItemSelected, "TreeViewItemSelected", kv );
  407. MESSAGE_FUNC_PARAMS( OnItemDeselected, "TreeViewItemDeselected", kv );
  408. MESSAGE_FUNC_PARAMS( OnAdd, "Add", kv );
  409. MESSAGE_FUNC( OnRename, "Rename" );
  410. MESSAGE_FUNC( OnMoveUp, "MoveUp" );
  411. MESSAGE_FUNC( OnMoveDown, "MoveDown" );
  412. MESSAGE_FUNC_PARAMS( OnInputCompleted, "InputCompleted", kv );
  413. MESSAGE_FUNC_PARAMS( OnParticleFunctionPicked, "ParticleFunctionPicked", kv );
  414. MESSAGE_FUNC_PARAMS( OnParticleChildPicked, "ParticleChildPicked", kv );
  415. MESSAGE_FUNC( OnPasteFuncs, "PasteFuncs" );
  416. void RefreshParticleFunctionSubtree( ParticleFunctionType_t nFunction, const CUtlString &SelectedFuncName );
  417. void ClearTree( );
  418. // Cleans up the context menu
  419. void CleanupContextMenu();
  420. // Returns the selected particle function
  421. CDmeParticleFunction* GetSelectedFunction( );
  422. ParticleFunctionType_t GetSelectedFunctionType( );
  423. bool IsPropertiesSlotSelected( bool bOnly );
  424. // Returns the selected particle function
  425. CDmeParticleFunction* GetSelectedFunction( int nIndex );
  426. ParticleFunctionType_t GetSelectedFunctionType( int nIndex );
  427. // Select a particular particle function
  428. void SelectParticleFunction( CDmeParticleFunction *pFind );
  429. IParticleSystemPropertiesPanelQuery *m_pQuery;
  430. CDmeHandle< CDmeParticleSystemDefinition > m_hParticleSystem;
  431. CParticleFunctionTree *m_pFunctionTree;
  432. vgui::DHANDLE< vgui::Menu > m_hContextMenu;
  433. CDmeElementPanel *m_pParticleFunctionProperties;
  434. int m_FunctionRootTreeIndicies[PARTICLE_FUNCTION_COUNT];
  435. int m_nPropertiesRootTreeIndex;
  436. int m_FunctionTreeRoot;
  437. };
  438. //-----------------------------------------------------------------------------
  439. // Sort functions for list panel
  440. //-----------------------------------------------------------------------------
  441. static int __cdecl ParticleFunctionSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
  442. {
  443. int i1 = item1.kv->GetInt( "index" );
  444. int i2 = item2.kv->GetInt( "index" );
  445. return i1 - i2;
  446. }
  447. //-----------------------------------------------------------------------------
  448. // constructor, destructor
  449. //-----------------------------------------------------------------------------
  450. CParticleFunctionBrowser::CParticleFunctionBrowser( vgui::Panel *pParent, const char *pName, IParticleSystemPropertiesPanelQuery *pQuery ) :
  451. BaseClass( pParent, pName ), m_pQuery( pQuery )
  452. {
  453. SetKeyBoardInputEnabled( true );
  454. m_pFunctionTree = new CParticleFunctionTree( this, "FunctionTree" );
  455. LoadControlSettings( "resource/particlefunctionbrowser.res" );
  456. }
  457. CParticleFunctionBrowser::~CParticleFunctionBrowser()
  458. {
  459. CleanupContextMenu();
  460. }
  461. //-----------------------------------------------------------------------------
  462. // Cleans up the context menu
  463. //-----------------------------------------------------------------------------
  464. void CParticleFunctionBrowser::CleanupContextMenu()
  465. {
  466. if ( m_hContextMenu.Get() )
  467. {
  468. m_hContextMenu->MarkForDeletion();
  469. m_hContextMenu = NULL;
  470. }
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Selects a particular function by default
  474. //-----------------------------------------------------------------------------
  475. void CParticleFunctionBrowser::SelectDefaultFunction()
  476. {
  477. if ( m_pFunctionTree->GetSelectedItemCount() == 0 && m_pFunctionTree->GetItemCount() > 0 )
  478. {
  479. m_pFunctionTree->AddSelectedItem( m_nPropertiesRootTreeIndex, true );
  480. }
  481. }
  482. //-----------------------------------------------------------------------------
  483. // Sets the particle system properties panel
  484. //-----------------------------------------------------------------------------
  485. void CParticleFunctionBrowser::SetParticleFunctionProperties( CDmeElementPanel *pPanel )
  486. {
  487. m_pParticleFunctionProperties = pPanel;
  488. }
  489. //-----------------------------------------------------------------------------
  490. // Sets/gets the particle system
  491. //-----------------------------------------------------------------------------
  492. void CParticleFunctionBrowser::SetParticleSystem( CDmeParticleSystemDefinition *pParticleSystem )
  493. {
  494. if ( pParticleSystem != m_hParticleSystem.Get() )
  495. {
  496. m_hParticleSystem = pParticleSystem;
  497. RefreshParticleFunctionList();
  498. SelectDefaultFunction();
  499. }
  500. }
  501. //-----------------------------------------------------------------------------
  502. // Builds the particle function list for the particle system
  503. //-----------------------------------------------------------------------------
  504. void CParticleFunctionBrowser::RefreshParticleFunctionSubtree( ParticleFunctionType_t nFunction, const CUtlString &SelectedFuncName )
  505. {
  506. int nCount = m_hParticleSystem->GetParticleFunctionCount( nFunction );
  507. for ( int i = 0; i < nCount; ++i )
  508. {
  509. CDmeParticleFunction *pFunction = m_hParticleSystem->GetParticleFunction( nFunction, i );
  510. KeyValues *kv = new KeyValues( "node", "name", pFunction->GetName() );
  511. kv->SetString( "text", pFunction->GetName() );
  512. kv->SetString( "type", pFunction->GetFunctionType() );
  513. kv->SetInt( "typeNumber", nFunction );
  514. kv->SetInt( "index", i );
  515. SetElementKeyValue( kv, "particleFunction", pFunction );
  516. int nItemID = m_pFunctionTree->AddItem( kv, m_FunctionRootTreeIndicies[nFunction] );
  517. m_pFunctionTree->SetItemFgColor( nItemID, Color(255, 255, 255, 255) );
  518. if ( SelectedFuncName == pFunction->GetName() )
  519. {
  520. m_pFunctionTree->AddSelectedItem( nItemID, true );
  521. }
  522. }
  523. m_pFunctionTree->ExpandItem(m_FunctionRootTreeIndicies[nFunction],true);
  524. }
  525. void CParticleFunctionBrowser::ClearTree( )
  526. {
  527. m_pFunctionTree->RemoveAll();
  528. {
  529. KeyValues *pKV = new KeyValues("FunctionRoot");
  530. pKV->SetString( "Text", "System Properties" );
  531. pKV->SetInt( "typeNumber", -1 );
  532. pKV->SetBool( "isSystemProperties", true );
  533. pKV->SetInt( "index", -1 );
  534. m_nPropertiesRootTreeIndex = m_pFunctionTree->AddItem( pKV, -1 );
  535. m_pFunctionTree->SetItemFgColor( m_nPropertiesRootTreeIndex, Color(255, 255, 255, 255) );
  536. m_FunctionTreeRoot = m_nPropertiesRootTreeIndex;
  537. }
  538. for( int i = 0; i < PARTICLE_FUNCTION_COUNT; ++i )
  539. {
  540. KeyValues *pKV = new KeyValues("FunctionRoot");
  541. pKV->SetString( "Text", GetParticleFunctionTypeName(ParticleFunctionType_t(i)) );
  542. pKV->SetInt( "typeNumber", i );
  543. pKV->SetInt( "index", -1 );
  544. m_FunctionRootTreeIndicies[i] = m_pFunctionTree->AddItem( pKV, m_FunctionTreeRoot );
  545. m_pFunctionTree->SetItemFgColor( m_FunctionRootTreeIndicies[i], Color(96, 96, 96, 255) );
  546. }
  547. m_pFunctionTree->ExpandItem(m_FunctionTreeRoot,true);
  548. }
  549. void CParticleFunctionBrowser::RefreshParticleFunctionList()
  550. {
  551. CDmeParticleFunction* pSelectedFunc = GetSelectedFunction();
  552. CUtlString selectedFuncName = "";
  553. if ( pSelectedFunc )
  554. {
  555. selectedFuncName = pSelectedFunc->GetName();
  556. }
  557. ClearTree();
  558. if ( !m_hParticleSystem.Get() )
  559. {
  560. return;
  561. }
  562. for ( int i = 0; i < PARTICLE_FUNCTION_COUNT; ++i )
  563. {
  564. RefreshParticleFunctionSubtree(ParticleFunctionType_t(i), selectedFuncName);
  565. }
  566. }
  567. //-----------------------------------------------------------------------------
  568. // Returns the selected particle function
  569. //-----------------------------------------------------------------------------
  570. CDmeParticleFunction* CParticleFunctionBrowser::GetSelectedFunction( int nIndex )
  571. {
  572. if ( !m_hParticleSystem.Get() )
  573. return NULL;
  574. int nSelectedItemCount = m_pFunctionTree->GetSelectedItemCount();
  575. if ( nSelectedItemCount <= nIndex )
  576. return NULL;
  577. int nItemID = m_pFunctionTree->GetSelectedItem(nIndex);
  578. KeyValues *pKeyValues = m_pFunctionTree->GetItemData( nItemID );
  579. return GetElementKeyValue<CDmeParticleFunction>( pKeyValues, "particleFunction" );
  580. }
  581. ParticleFunctionType_t CParticleFunctionBrowser::GetSelectedFunctionType( int nIndex )
  582. {
  583. if ( !m_hParticleSystem.Get() )
  584. return PARTICLE_FUNCTION_COUNT; // invalid
  585. int nSelectedItemCount = m_pFunctionTree->GetSelectedItemCount();
  586. if ( nSelectedItemCount <= nIndex )
  587. return PARTICLE_FUNCTION_COUNT; // invalid
  588. int nItemID = m_pFunctionTree->GetSelectedItem( nIndex );
  589. KeyValues *pKeyValues = m_pFunctionTree->GetItemData( nItemID );
  590. return (ParticleFunctionType_t)pKeyValues->GetInt( "typeNumber" );
  591. }
  592. bool CParticleFunctionBrowser::IsPropertiesSlotSelected( bool bOnly )
  593. {
  594. int nSelectedItemCount = m_pFunctionTree->GetSelectedItemCount();
  595. if ( bOnly && nSelectedItemCount != 1 )
  596. return false;
  597. for ( int i = 0; i < nSelectedItemCount; ++i )
  598. {
  599. int nItemID = m_pFunctionTree->GetSelectedItem(i);
  600. KeyValues *pKeyValues = m_pFunctionTree->GetItemData( nItemID );
  601. if ( pKeyValues->GetBool( "isSystemProperties" ) )
  602. return true;
  603. }
  604. return false;
  605. }
  606. //-----------------------------------------------------------------------------
  607. // Returns the selected particle function
  608. //-----------------------------------------------------------------------------
  609. CDmeParticleFunction* CParticleFunctionBrowser::GetSelectedFunction( )
  610. {
  611. int nSelectedItemCount = m_pFunctionTree->GetSelectedItemCount();
  612. if ( nSelectedItemCount != 1 )
  613. return NULL;
  614. return GetSelectedFunction(0);
  615. }
  616. ParticleFunctionType_t CParticleFunctionBrowser::GetSelectedFunctionType( )
  617. {
  618. int nSelectedItemCount = m_pFunctionTree->GetSelectedItemCount();
  619. if ( nSelectedItemCount != 1 )
  620. return PARTICLE_FUNCTION_COUNT; // invalid
  621. return GetSelectedFunctionType(0);
  622. }
  623. void CParticleFunctionBrowser::OnMoveUp( )
  624. {
  625. CDmeParticleFunction* pFunction = GetSelectedFunction( );
  626. if ( !pFunction )
  627. return;
  628. ParticleFunctionType_t nType = GetSelectedFunctionType( );
  629. {
  630. CUndoScopeGuard guard( 0, NOTIFY_SETDIRTYFLAG, "Move Function Up", "Move Function Up" );
  631. m_hParticleSystem->MoveFunctionUp( nType, pFunction );
  632. }
  633. PostActionSignal( new KeyValues( "ParticleSystemModified" ) );
  634. }
  635. void CParticleFunctionBrowser::OnMoveDown( )
  636. {
  637. CDmeParticleFunction* pFunction = GetSelectedFunction( );
  638. if ( !pFunction )
  639. return;
  640. ParticleFunctionType_t nType = GetSelectedFunctionType( );
  641. {
  642. CUndoScopeGuard guard( 0, NOTIFY_SETDIRTYFLAG, "Move Function Down", "Move Function Down" );
  643. m_hParticleSystem->MoveFunctionDown( nType, pFunction );
  644. }
  645. PostActionSignal( new KeyValues( "ParticleSystemModified" ) );
  646. }
  647. //-----------------------------------------------------------------------------
  648. // Select a particular particle function
  649. //-----------------------------------------------------------------------------
  650. void CParticleFunctionBrowser::SelectParticleFunction( CDmeParticleFunction *pFind )
  651. {
  652. m_pFunctionTree->ClearSelection();
  653. for ( int nItemID = m_pFunctionTree->FirstItem(); nItemID != m_pFunctionTree->InvalidItemID(); nItemID = m_pFunctionTree->NextItem( nItemID ) )
  654. {
  655. KeyValues *kv = m_pFunctionTree->GetItemData( nItemID );
  656. CDmeParticleFunction *pFunction = GetElementKeyValue<CDmeParticleFunction>( kv, "particleFunction" );
  657. if ( pFunction == pFind )
  658. {
  659. m_pFunctionTree->AddSelectedItem( nItemID, true );
  660. break;
  661. }
  662. }
  663. }
  664. //-----------------------------------------------------------------------------
  665. // Add/remove functions
  666. //-----------------------------------------------------------------------------
  667. void CParticleFunctionBrowser::OnParticleChildPicked( KeyValues *pKeyValues )
  668. {
  669. CDmeParticleSystemDefinition *pParticleSystem = GetElementKeyValue<CDmeParticleSystemDefinition>( pKeyValues, "particleSystem" );
  670. if ( !pParticleSystem )
  671. return;
  672. CDmeParticleFunction *pFunction;
  673. {
  674. CUndoScopeGuard guard( 0, NOTIFY_SETDIRTYFLAG, "Add Particle System Child", "Add Particle System Child" );
  675. pFunction = m_hParticleSystem->AddChild( pParticleSystem );
  676. }
  677. PostActionSignal( new KeyValues( "ParticleSystemModified" ) );
  678. SelectParticleFunction( pFunction );
  679. }
  680. void CParticleFunctionBrowser::OnParticleFunctionPicked( KeyValues *pKeyValues )
  681. {
  682. ParticleFunctionType_t nParticleFuncType = (ParticleFunctionType_t)pKeyValues->GetInt( "typeNumber" );
  683. const char *pParticleFuncName = pKeyValues->GetString( "name" );
  684. CDmeParticleFunction *pFunction;
  685. {
  686. CUndoScopeGuard guard( 0, NOTIFY_SETDIRTYFLAG, "Add Particle Function", "Add Particle Function" );
  687. pFunction = m_hParticleSystem->AddOperator( nParticleFuncType, pParticleFuncName );
  688. }
  689. PostActionSignal( new KeyValues( "ParticleSystemModified" ) );
  690. SelectParticleFunction( pFunction );
  691. }
  692. void CParticleFunctionBrowser::OnAdd( KeyValues *pKeyValues )
  693. {
  694. ParticleFunctionType_t nParticleFuncType = (ParticleFunctionType_t)pKeyValues->GetInt( "typeNumber" );
  695. if ( nParticleFuncType != FUNCTION_CHILDREN )
  696. {
  697. CParticleFunctionPickerFrame *pPicker = new CParticleFunctionPickerFrame( this, "Select Particle Function" );
  698. pPicker->DoModal( m_hParticleSystem, nParticleFuncType, NULL );
  699. }
  700. else
  701. {
  702. CParticleChildrenPickerFrame *pPicker = new CParticleChildrenPickerFrame( this, "Select Child Particle Systems", m_pQuery );
  703. pPicker->DoModal( m_hParticleSystem, NULL );
  704. }
  705. }
  706. void CParticleFunctionBrowser::DeleteSelectedFunctions( )
  707. {
  708. int iSel = m_pFunctionTree->GetSelectedItem( 0 );
  709. {
  710. CUndoScopeGuard guard( 0, NOTIFY_SETDIRTYFLAG, "Remove Particle Function", "Remove Particle Function" );
  711. //
  712. // Build a list of objects to delete.
  713. //
  714. CUtlVector< CDmeParticleFunction* > itemsToDelete;
  715. CUtlVector< ParticleFunctionType_t > typesToDelete;
  716. int nCount = m_pFunctionTree->GetSelectedItemCount();
  717. for (int i = 0; i < nCount; i++)
  718. {
  719. CDmeParticleFunction *pParticleFunction = GetSelectedFunction( i );
  720. if ( pParticleFunction )
  721. {
  722. itemsToDelete.AddToTail( pParticleFunction );
  723. typesToDelete.AddToTail( GetSelectedFunctionType(i) );
  724. }
  725. }
  726. nCount = itemsToDelete.Count();
  727. for ( int i = 0; i < nCount; ++i )
  728. {
  729. m_hParticleSystem->RemoveFunction( typesToDelete[i], itemsToDelete[i] );
  730. }
  731. }
  732. PostActionSignal( new KeyValues( "ParticleSystemModified" ) );
  733. // Update the list box selection.
  734. if ( m_pFunctionTree->GetItemCount() > 0 )
  735. {
  736. m_pFunctionTree->AddSelectedItem( iSel, true );
  737. }
  738. else
  739. {
  740. m_pFunctionTree->ClearSelection();
  741. }
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Rename a particle function
  745. //-----------------------------------------------------------------------------
  746. void CParticleFunctionBrowser::OnInputCompleted( KeyValues *pKeyValues )
  747. {
  748. const char *pName = pKeyValues->GetString( "text" );
  749. CDmeParticleFunction *pFunction = GetSelectedFunction();
  750. {
  751. CUndoScopeGuard guard( 0, NOTIFY_SETDIRTYFLAG, "Rename Particle Function", "Rename Particle Function" );
  752. pFunction->SetName( pName );
  753. }
  754. PostActionSignal( new KeyValues( "ParticleSystemModified" ) );
  755. }
  756. //-----------------------------------------------------------------------------
  757. // Rename a particle function
  758. //-----------------------------------------------------------------------------
  759. void CParticleFunctionBrowser::OnRename()
  760. {
  761. int nSelectedItemCount = m_pFunctionTree->GetSelectedItemCount();
  762. if ( nSelectedItemCount != 1 )
  763. return;
  764. vgui::InputDialog *pInput = new vgui::InputDialog( this, "Rename Particle Function", "Enter new name of particle function" );
  765. pInput->SetMultiline( false );
  766. pInput->DoModal( );
  767. }
  768. //-----------------------------------------------------------------------------
  769. // Called when a list panel's selection changes
  770. //-----------------------------------------------------------------------------
  771. void CParticleFunctionBrowser::RefreshParticleFunctionProperties( )
  772. {
  773. if ( IsVisible() )
  774. {
  775. CDmeParticleFunction *pFunction = GetSelectedFunction();
  776. if ( pFunction )
  777. {
  778. m_pParticleFunctionProperties->SetTypeDictionary( pFunction->GetEditorTypeDictionary() );
  779. m_pParticleFunctionProperties->SetDmeElement( pFunction );
  780. }
  781. else if( IsPropertiesSlotSelected(true) )
  782. {
  783. if ( m_hParticleSystem.Get() )
  784. {
  785. m_pParticleFunctionProperties->SetTypeDictionary( m_hParticleSystem->GetEditorTypeDictionary() );
  786. }
  787. m_pParticleFunctionProperties->SetDmeElement( m_hParticleSystem );
  788. }
  789. // Notify the outside world so we can get helpers to render correctly in the preview
  790. KeyValues *pMessage = new KeyValues( "ParticleFunctionSelChanged" );
  791. SetElementKeyValue( pMessage, "function", pFunction );
  792. PostActionSignal( pMessage );
  793. }
  794. }
  795. //-----------------------------------------------------------------------------
  796. // Called when a list panel's selection changes
  797. //-----------------------------------------------------------------------------
  798. void CParticleFunctionBrowser::OnItemSelected( KeyValues *kv )
  799. {
  800. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  801. if ( pPanel == m_pFunctionTree )
  802. {
  803. RefreshParticleFunctionProperties();
  804. return;
  805. }
  806. }
  807. //-----------------------------------------------------------------------------
  808. // Called when a list panel's selection changes
  809. //-----------------------------------------------------------------------------
  810. void CParticleFunctionBrowser::OnItemDeselected( KeyValues *kv )
  811. {
  812. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  813. if ( pPanel == m_pFunctionTree )
  814. {
  815. RefreshParticleFunctionProperties();
  816. return;
  817. }
  818. }
  819. //-----------------------------------------------------------------------------
  820. // Called to open a context-sensitive menu for a particular menu item
  821. //-----------------------------------------------------------------------------
  822. bool WouldPasteParticleFunctions()
  823. {
  824. CUtlVector< KeyValues * > list;
  825. g_pDataModel->GetClipboardData( list );
  826. for ( int i = 0; i < list.Count(); ++i )
  827. {
  828. if ( V_strlen( list[i]->GetString( PARTICLE_CLIPBOARD_FUNCTIONS_STR ) ) )
  829. {
  830. return true;
  831. }
  832. }
  833. return false;
  834. }
  835. void CParticleFunctionBrowser::OnOpenContextMenu( KeyValues *kv )
  836. {
  837. CleanupContextMenu();
  838. if ( !m_hParticleSystem.Get() )
  839. return;
  840. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  841. if ( pPanel != m_pFunctionTree )
  842. return;
  843. int nSelectedItemCount = m_pFunctionTree->GetSelectedItemCount();
  844. m_hContextMenu = new vgui::Menu( this, "ActionMenu" );
  845. if ( nSelectedItemCount >= 1 )
  846. {
  847. m_hContextMenu->AddMenuItem( "#ParticleFunctionBrowser_Remove", new KeyValues( "Remove" ), this );
  848. m_hContextMenu->AddSeparator();
  849. }
  850. if ( nSelectedItemCount > 0 )
  851. {
  852. m_hContextMenu->AddMenuItem( "Copy Functions", new KeyValues( "OnCopy" ), this );
  853. }
  854. if ( WouldPasteParticleFunctions() )
  855. {
  856. m_hContextMenu->AddMenuItem( "Paste Functions", new KeyValues( "PasteFuncs" ), this );
  857. }
  858. if ( nSelectedItemCount == 1 )
  859. {
  860. m_hContextMenu->AddSeparator();
  861. int nType = m_pFunctionTree->GetItemData(m_pFunctionTree->GetSelectedItem(0))->GetInt("typeNumber");
  862. m_hContextMenu->AddMenuItem( "#ParticleFunctionBrowser_Add", new KeyValues( "Add", "typeNumber", nType ), this );
  863. // only rename/moveup/movedown for actual functions
  864. int nIndex = m_pFunctionTree->GetItemData(m_pFunctionTree->GetSelectedItem(0))->GetInt("index", -1);
  865. if ( nIndex != -1 )
  866. {
  867. m_hContextMenu->AddMenuItem( "#ParticleFunctionBrowser_Rename", new KeyValues( "Rename" ), this );
  868. m_hContextMenu->AddSeparator();
  869. m_hContextMenu->AddMenuItem( "#ParticleFunctionBrowser_MoveUp", new KeyValues( "MoveUp" ), this );
  870. m_hContextMenu->AddMenuItem( "#ParticleFunctionBrowser_MoveDown", new KeyValues( "MoveDown" ), this );
  871. }
  872. }
  873. vgui::Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
  874. }
  875. void CParticleFunctionBrowser::OnPasteFuncs( )
  876. {
  877. PostActionSignal( new KeyValues( "PasteFuncs" ) );
  878. }
  879. void CParticleFunctionBrowser::OnCopy( )
  880. {
  881. int nSelectedItemCount = m_pFunctionTree->GetSelectedItemCount();
  882. CUtlVector< KeyValues * > list;
  883. for ( int i = 0; i < nSelectedItemCount; ++i )
  884. {
  885. CDmeParticleFunction* pSelectedFunc = GetSelectedFunction(i);
  886. if ( !pSelectedFunc )
  887. continue;
  888. DmFileId_t tmpFileId = pSelectedFunc->GetFileId();
  889. pSelectedFunc->SetFileId( DMFILEID_INVALID, TD_NONE );
  890. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  891. if ( g_pDataModel->Serialize( buf, "keyvalues2", "pcf", pSelectedFunc->GetHandle() ) )
  892. {
  893. KeyValues *pData = new KeyValues( "Clipboard" );
  894. pData->SetString( PARTICLE_CLIPBOARD_FUNCTIONS_STR, (char*)buf.Base() );
  895. list.AddToTail( pData );
  896. }
  897. pSelectedFunc->SetFileId( tmpFileId, TD_NONE );
  898. }
  899. if ( IsPropertiesSlotSelected(false) )
  900. {
  901. CDmeParticleSystemDefinition* pCopySys = CreateElement<CDmeParticleSystemDefinition>( "tempcopy", DMFILEID_INVALID );
  902. pCopySys->OverrideAttributesFromOtherDefinition( m_hParticleSystem );
  903. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  904. if ( g_pDataModel->Serialize( buf, "keyvalues2", "pcf", pCopySys->GetHandle() ) )
  905. {
  906. KeyValues *pData = new KeyValues( "Clipboard" );
  907. pData->SetString( PARTICLE_CLIPBOARD_DEF_BODY_STR, (char*)buf.Base() );
  908. list.AddToTail( pData );
  909. }
  910. g_pDataModel->DestroyElement(pCopySys->GetHandle());
  911. }
  912. if ( list.Count() )
  913. {
  914. g_pDataModel->SetClipboardData( list );
  915. }
  916. }
  917. //-----------------------------------------------------------------------------
  918. // Purpose:
  919. //-----------------------------------------------------------------------------
  920. void CParticleFunctionBrowser::OnKeyCodeTyped( vgui::KeyCode code )
  921. {
  922. if ( code == KEY_DELETE )
  923. {
  924. DeleteSelectedFunctions();
  925. }
  926. else
  927. {
  928. BaseClass::OnKeyCodeTyped( code );
  929. }
  930. }
  931. //-----------------------------------------------------------------------------
  932. // Strings
  933. //-----------------------------------------------------------------------------
  934. ConVar pet_sort_attributes( "pet_sort_attributes", "1", FCVAR_NONE );
  935. //-----------------------------------------------------------------------------
  936. // Constructor
  937. //-----------------------------------------------------------------------------
  938. CParticleSystemPropertiesPanel::CParticleSystemPropertiesPanel( IParticleSystemPropertiesPanelQuery *pQuery, vgui::Panel* pParent )
  939. : BaseClass( pParent, "ParticleSystemPropertiesPanel" ), m_pQuery( pQuery )
  940. {
  941. SetKeyBoardInputEnabled( true );
  942. m_pSplitter = new vgui::Splitter( this, "Splitter", vgui::SPLITTER_MODE_VERTICAL, 1 );
  943. vgui::Panel *pSplitterLeftSide = m_pSplitter->GetChild( 0 );
  944. vgui::Panel *pSplitterRightSide = m_pSplitter->GetChild( 1 );
  945. m_pFunctionBrowserArea = new vgui::EditablePanel( pSplitterLeftSide, "FunctionBrowserArea" );
  946. m_pParticleFunctionProperties = new CDmeElementPanel( pSplitterRightSide, "FunctionProperties" );
  947. m_pParticleFunctionProperties->SetSortAttributesByName( pet_sort_attributes.GetBool() );
  948. m_pParticleFunctionProperties->SetAutoResize( vgui::Panel::PIN_TOPLEFT, vgui::Panel::AUTORESIZE_DOWNANDRIGHT, 6, 6, -6, -6 );
  949. m_pParticleFunctionProperties->AddActionSignalTarget( this );
  950. m_pParticleFunctionBrowser = new CParticleFunctionBrowser( m_pFunctionBrowserArea, "FunctionBrowser", m_pQuery );
  951. m_pParticleFunctionBrowser->SetParticleFunctionProperties( m_pParticleFunctionProperties );
  952. m_pParticleFunctionBrowser->AddActionSignalTarget( this );
  953. LoadControlSettings( "resource/particlesystempropertiespanel.res" );
  954. }
  955. //-----------------------------------------------------------------------------
  956. // Sets the particle system to look at
  957. //-----------------------------------------------------------------------------
  958. void CParticleSystemPropertiesPanel::SetParticleSystem( CDmeParticleSystemDefinition *pParticleSystem )
  959. {
  960. m_hParticleSystem = pParticleSystem;
  961. m_pParticleFunctionBrowser->SetParticleSystem( pParticleSystem );
  962. }
  963. CDmeParticleSystemDefinition *CParticleSystemPropertiesPanel::GetParticleSystem( )
  964. {
  965. return m_hParticleSystem;
  966. }
  967. //-----------------------------------------------------------------------------
  968. // Called when something changes in the dmeelement panel
  969. //-----------------------------------------------------------------------------
  970. void CParticleSystemPropertiesPanel::OnDmeElementChanged( KeyValues *pKeyValues )
  971. {
  972. int nNotifyFlags = pKeyValues->GetInt( "notifyFlags" );
  973. OnParticleSystemModified();
  974. if ( nNotifyFlags & ( NOTIFY_CHANGE_TOPOLOGICAL | NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE ) )
  975. {
  976. m_pParticleFunctionBrowser->RefreshParticleFunctionList();
  977. }
  978. PostActionSignal( new KeyValues( "ParticleSystemModified" ) );
  979. }
  980. void CParticleSystemPropertiesPanel::OnParticleSystemModifiedInternal()
  981. {
  982. OnParticleSystemModified();
  983. Refresh( false );
  984. PostActionSignal( new KeyValues( "ParticleSystemModified" ) );
  985. }
  986. void CParticleSystemPropertiesPanel::OnParticleFunctionSelChanged( KeyValues *pParams )
  987. {
  988. // Notify the outside world so we can get helpers to render correctly in the preview
  989. CDmeParticleFunction *pFunction = GetElementKeyValue<CDmeParticleFunction>( pParams, "function" );
  990. KeyValues *pMessage = new KeyValues( "ParticleFunctionSelChanged" );
  991. SetElementKeyValue( pMessage, "function", pFunction );
  992. PostActionSignal( pMessage );
  993. }
  994. void CParticleSystemPropertiesPanel::OnCopy()
  995. {
  996. m_pParticleFunctionBrowser->OnCopy();
  997. }
  998. void CParticleSystemPropertiesPanel::OnPasteFuncs()
  999. {
  1000. PostActionSignal( new KeyValues( "RequestPaste" ) );
  1001. }
  1002. //-----------------------------------------------------------------------------
  1003. // Refreshes display
  1004. //-----------------------------------------------------------------------------
  1005. void CParticleSystemPropertiesPanel::Refresh( bool bValuesOnly )
  1006. {
  1007. m_pParticleFunctionBrowser->RefreshParticleFunctionList();
  1008. m_pParticleFunctionProperties->Refresh( bValuesOnly ? CElementPropertiesTreeInternal::REFRESH_VALUES_ONLY :
  1009. CElementPropertiesTreeInternal::REFRESH_TREE_VIEW );
  1010. }
  1011. void CParticleSystemPropertiesPanel::DeleteSelectedFunctions( )
  1012. {
  1013. m_pParticleFunctionBrowser->DeleteSelectedFunctions();
  1014. }
  1015. //-----------------------------------------------------------------------------
  1016. // A little panel used as a DmePanel for particle systems
  1017. //-----------------------------------------------------------------------------
  1018. class CParticleSystemDmePanel : public vgui::EditablePanel
  1019. {
  1020. DECLARE_CLASS_SIMPLE( CParticleSystemDmePanel, vgui::EditablePanel );
  1021. public:
  1022. // constructor, destructor
  1023. CParticleSystemDmePanel( vgui::Panel *pParent, const char *pName );
  1024. virtual ~CParticleSystemDmePanel();
  1025. // Set the material to draw
  1026. void SetDmeElement( CDmeParticleSystemDefinition *pDef );
  1027. private:
  1028. MESSAGE_FUNC_INT( OnElementChangedExternally, "ElementChangedExternally", valuesOnly );
  1029. MESSAGE_FUNC( OnParticleSystemModified, "ParticleSystemModified" );
  1030. MESSAGE_FUNC_PARAMS( OnParticleFunctionSelChanged, "ParticleFunctionSelChanged", params );
  1031. MESSAGE_FUNC( OnPaste, "OnPaste" );
  1032. MESSAGE_FUNC( OnRequestPaste, "RequestPaste" );
  1033. KEYBINDING_FUNC_NODECLARE( edit_paste, KEY_V, vgui::MODIFIER_CONTROL, OnPaste, "#edit_paste_help", 0 );
  1034. vgui::Splitter *m_Splitter;
  1035. CParticleSystemPropertiesPanel *m_pProperties;
  1036. CParticleSystemPreviewPanel *m_pPreview;
  1037. };
  1038. //-----------------------------------------------------------------------------
  1039. // Dme panel connection
  1040. //-----------------------------------------------------------------------------
  1041. IMPLEMENT_DMEPANEL_FACTORY( CParticleSystemDmePanel, DmeParticleSystemDefinition, "DmeParticleSystemDefinitionEditor", "Particle System Editor", true );
  1042. //-----------------------------------------------------------------------------
  1043. // constructor, destructor
  1044. //-----------------------------------------------------------------------------
  1045. CParticleSystemDmePanel::CParticleSystemDmePanel( vgui::Panel *pParent, const char *pName ) :
  1046. BaseClass( pParent, pName )
  1047. {
  1048. m_Splitter = new vgui::Splitter( this, "Splitter", SPLITTER_MODE_HORIZONTAL, 1 );
  1049. vgui::Panel *pSplitterTopSide = m_Splitter->GetChild( 0 );
  1050. vgui::Panel *pSplitterBottomSide = m_Splitter->GetChild( 1 );
  1051. m_Splitter->SetAutoResize( PIN_TOPLEFT, AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
  1052. m_pProperties = new CParticleSystemPropertiesPanel( NULL, pSplitterBottomSide );
  1053. m_pProperties->AddActionSignalTarget( this );
  1054. m_pProperties->SetAutoResize( PIN_TOPLEFT, AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
  1055. m_pPreview = new CParticleSystemPreviewPanel( pSplitterTopSide, "Preview" );
  1056. m_pPreview->SetAutoResize( PIN_TOPLEFT, AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
  1057. }
  1058. CParticleSystemDmePanel::~CParticleSystemDmePanel()
  1059. {
  1060. }
  1061. //-----------------------------------------------------------------------------
  1062. // Layout
  1063. //-----------------------------------------------------------------------------
  1064. void CParticleSystemDmePanel::SetDmeElement( CDmeParticleSystemDefinition *pDef )
  1065. {
  1066. m_pProperties->SetParticleSystem( pDef );
  1067. m_pPreview->SetParticleSystem( pDef, true );
  1068. }
  1069. //-----------------------------------------------------------------------------
  1070. // Particle system modified externally to the editor
  1071. //-----------------------------------------------------------------------------
  1072. void CParticleSystemDmePanel::OnElementChangedExternally( int valuesOnly )
  1073. {
  1074. m_pProperties->Refresh( valuesOnly != 0 );
  1075. }
  1076. //-----------------------------------------------------------------------------
  1077. // Called when the selected particle function changes
  1078. //-----------------------------------------------------------------------------
  1079. void CParticleSystemDmePanel::OnParticleFunctionSelChanged( KeyValues *pParams )
  1080. {
  1081. CDmeParticleFunction *pFunction = GetElementKeyValue<CDmeParticleFunction>( pParams, "function" );
  1082. m_pPreview->SetParticleFunction( pFunction );
  1083. }
  1084. //-----------------------------------------------------------------------------
  1085. // Communicate to the owning DmePanel
  1086. //-----------------------------------------------------------------------------
  1087. void CParticleSystemDmePanel::OnParticleSystemModified()
  1088. {
  1089. PostActionSignal( new KeyValues( "DmeElementChanged" ) );
  1090. }
  1091. //-----------------------------------------------------------------------------
  1092. void CParticleSystemDmePanel::OnRequestPaste()
  1093. {
  1094. OnPaste();
  1095. }
  1096. void CParticleSystemDmePanel::OnPaste( )
  1097. {
  1098. CDmeParticleSystemDefinition *pEditingDef = m_pProperties->GetParticleSystem();
  1099. if ( !pEditingDef )
  1100. return;
  1101. CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Paste From Clipboard", "Paste From Clipboard" );
  1102. CUtlVector< KeyValues * > list;
  1103. g_pDataModel->GetClipboardData( list );
  1104. int nItems = list.Count();
  1105. for ( int i = 0; i < nItems; ++i )
  1106. {
  1107. CDmeParticleFunction *pFunc = ReadParticleClassFromKV<CDmeParticleFunction>( list[i], PARTICLE_CLIPBOARD_FUNCTIONS_STR );
  1108. if ( pFunc )
  1109. {
  1110. pEditingDef->AddCopyOfOperator( pFunc );
  1111. continue;
  1112. }
  1113. CDmeParticleSystemDefinition *pDef = ReadParticleClassFromKV<CDmeParticleSystemDefinition>( list[i], PARTICLE_CLIPBOARD_DEF_BODY_STR );
  1114. if ( pDef )
  1115. {
  1116. pEditingDef->OverrideAttributesFromOtherDefinition( pDef );
  1117. continue;
  1118. }
  1119. }
  1120. guard.Release();
  1121. }