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.

781 lines
25 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmeparticlesystemdefinition.h"
  7. #include "datamodel/dmelementfactoryhelper.h"
  8. #include "movieobjects/dmeeditortypedictionary.h"
  9. #include "toolutils/enginetools_int.h"
  10. #include "tier1/keyvalues.h"
  11. #include "tier1/utlbuffer.h"
  12. #include "tier1/convar.h"
  13. #include "particles/particles.h"
  14. #include "dme_controls/attributeintchoicepanel.h"
  15. #include "dme_controls/attributeboolchoicepanel.h"
  16. #include "dme_controls/attributestringchoicepanel.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. //-----------------------------------------------------------------------------
  20. // Human readable string for the particle functions
  21. //-----------------------------------------------------------------------------
  22. static const char *s_pParticleFuncTypeName[PARTICLE_FUNCTION_COUNT] =
  23. {
  24. "Renderer", // FUNCTION_RENDERER = 0,
  25. "Operator", // FUNCTION_OPERATOR,
  26. "Initializer", // FUNCTION_INITIALIZER,
  27. "Emitter", // FUNCTION_EMITTER,
  28. "Children", // FUNCTION_CHILDREN,
  29. "ForceGenerator", // FUNCTION_FORCEGENERATOR
  30. "Constraint", // FUNCTION_CONSTRAINT
  31. };
  32. const char *GetParticleFunctionTypeName( ParticleFunctionType_t type )
  33. {
  34. return s_pParticleFuncTypeName[type];
  35. }
  36. //-----------------------------------------------------------------------------
  37. // Expose this class to the scene database
  38. //-----------------------------------------------------------------------------
  39. IMPLEMENT_ELEMENT_FACTORY_INSTALL_EXPLICITLY( DmeParticleFunction, CDmeParticleFunction );
  40. //-----------------------------------------------------------------------------
  41. // Purpose:
  42. //-----------------------------------------------------------------------------
  43. void CDmeParticleFunction::OnConstruction()
  44. {
  45. m_bSkipNextResolve = false;
  46. m_hTypeDictionary.Init( this, "type_dictionary", FATTRIB_DONTSAVE | FATTRIB_HIDDEN );
  47. }
  48. void CDmeParticleFunction::OnDestruction()
  49. {
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Construct an appropriate editor attribute info
  53. //-----------------------------------------------------------------------------
  54. static void CreateEditorAttributeInfo( CDmeEditorType *pEditorType, const char *pAttributeName, const char *pWidgetInfo )
  55. {
  56. if ( !pWidgetInfo )
  57. return;
  58. CCommand parse;
  59. parse.Tokenize( pWidgetInfo );
  60. if ( parse.ArgC() == 1 )
  61. {
  62. CDmeEditorAttributeInfo *pInfo = CreateElement< CDmeEditorAttributeInfo >( "field info", DMFILEID_INVALID );
  63. pEditorType->AddAttributeInfo( pAttributeName, pInfo );
  64. pInfo->m_Widget = parse[0];
  65. return;
  66. }
  67. if ( parse.ArgC() == 2 )
  68. {
  69. CDmeEditorChoicesInfo *pInfo = NULL;
  70. if ( !Q_stricmp( parse[0], "intchoice" ) )
  71. {
  72. pInfo = CreateElement< CDmeEditorIntChoicesInfo >( "field info", DMFILEID_INVALID );
  73. }
  74. if ( !Q_stricmp( parse[0], "boolchoice" ) )
  75. {
  76. pInfo = CreateElement< CDmeEditorBoolChoicesInfo >( "field info", DMFILEID_INVALID );
  77. }
  78. if ( !Q_stricmp( parse[0], "stringchoice" ) )
  79. {
  80. pInfo = CreateElement< CDmeEditorStringChoicesInfo >( "field info", DMFILEID_INVALID );
  81. }
  82. if ( !Q_stricmp( parse[0], "elementchoice" ) )
  83. {
  84. pInfo = CreateElement< CDmeEditorChoicesInfo >( "field info", DMFILEID_INVALID );
  85. }
  86. if ( pInfo )
  87. {
  88. pInfo->SetChoiceType( parse[1] );
  89. pEditorType->AddAttributeInfo( pAttributeName, pInfo );
  90. pInfo->m_Widget = parse[0];
  91. return;
  92. }
  93. }
  94. }
  95. //-----------------------------------------------------------------------------
  96. // Used for backward compat
  97. //-----------------------------------------------------------------------------
  98. void CDmeParticleFunction::AddMissingFields( const DmxElementUnpackStructure_t *pUnpack )
  99. {
  100. DestroyElement( m_hTypeDictionary, TD_DEEP );
  101. m_hTypeDictionary = CreateElement< CDmeEditorTypeDictionary >( "particleFunctionDict", DMFILEID_INVALID );
  102. CDmeEditorType *pEditorType = CreateElement< CDmeEditorType >( GetTypeString(), DMFILEID_INVALID );
  103. for ( ; pUnpack->m_pAttributeName; ++pUnpack )
  104. {
  105. CreateEditorAttributeInfo( pEditorType, pUnpack->m_pAttributeName, (const char *)pUnpack->m_pUserData );
  106. // Can happen if 'name' or 'functionName' is used
  107. if ( HasAttribute( pUnpack->m_pAttributeName ) )
  108. continue;
  109. CDmAttribute *pAttribute = AddAttribute( pUnpack->m_pAttributeName, pUnpack->m_AttributeType );
  110. if ( pUnpack->m_pDefaultString )
  111. {
  112. int nLen = Q_strlen( pUnpack->m_pDefaultString );
  113. CUtlBuffer bufParse( pUnpack->m_pDefaultString, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY );
  114. pAttribute->Unserialize( bufParse );
  115. }
  116. }
  117. m_hTypeDictionary->AddEditorType( pEditorType );
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Sets the particle operator
  121. //-----------------------------------------------------------------------------
  122. void CDmeParticleFunction::UpdateAttributes( const DmxElementUnpackStructure_t *pUnpack )
  123. {
  124. // Delete all old attributes
  125. CDmAttribute *pNext;
  126. for( CDmAttribute *pAttr = FirstAttribute(); pAttr; pAttr = pNext )
  127. {
  128. pNext = pAttr->NextAttribute();
  129. if ( pAttr->IsStandard() || pAttr->IsFlagSet( FATTRIB_EXTERNAL ) )
  130. continue;
  131. RemoveAttributeByPtr( pAttr );
  132. }
  133. AddMissingFields( pUnpack );
  134. }
  135. //-----------------------------------------------------------------------------
  136. // Marks a particle system as a new instance
  137. // This is basically a workaround to prevent newly-copied particle functions
  138. // from recompiling themselves a zillion times
  139. //-----------------------------------------------------------------------------
  140. void CDmeParticleFunction::MarkNewInstance()
  141. {
  142. m_bSkipNextResolve = true;
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Don't bother resolving during unserialization, the owning def will handle it
  146. //-----------------------------------------------------------------------------
  147. void CDmeParticleFunction::OnElementUnserialized()
  148. {
  149. BaseClass::OnElementUnserialized();
  150. MarkNewInstance();
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Recompiles the particle system when a change occurs
  154. //-----------------------------------------------------------------------------
  155. void CDmeParticleFunction::Resolve()
  156. {
  157. BaseClass::Resolve();
  158. if ( m_bSkipNextResolve )
  159. {
  160. m_bSkipNextResolve = false;
  161. return;
  162. }
  163. for( CDmAttribute* pAttr = FirstAttribute(); pAttr; pAttr = pAttr->NextAttribute() )
  164. {
  165. if ( !pAttr->IsFlagSet( FATTRIB_DIRTY ) )
  166. continue;
  167. // Find all CDmeParticleSystemDefinitions referring to this function
  168. DmAttributeReferenceIterator_t i = g_pDataModel->FirstAttributeReferencingElement( GetHandle() );
  169. while ( i != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID )
  170. {
  171. CDmAttribute *pAttribute = g_pDataModel->GetAttribute( i );
  172. // NOTE: This could cause the same particle system definition to recompile
  173. // multiple times if it refers to the same function multiple times,
  174. // but we don't expect that to happen, so we won't bother checking for it
  175. CDmeParticleSystemDefinition *pDef = CastElement<CDmeParticleSystemDefinition>( pAttribute->GetOwner() );
  176. if ( pDef && pDef->GetFileId() == GetFileId() )
  177. {
  178. pDef->RecompileParticleSystem();
  179. }
  180. i = g_pDataModel->NextAttributeReferencingElement( i );
  181. }
  182. break;
  183. }
  184. }
  185. //-----------------------------------------------------------------------------
  186. // Returns the editor type dictionary
  187. //-----------------------------------------------------------------------------
  188. CDmeEditorTypeDictionary* CDmeParticleFunction::GetEditorTypeDictionary()
  189. {
  190. return m_hTypeDictionary;
  191. }
  192. void CDmeParticleFunction::InstanceTypeDictionary()
  193. {
  194. if ( m_hTypeDictionary != DMELEMENT_HANDLE_INVALID )
  195. {
  196. m_hTypeDictionary = m_hTypeDictionary->Copy();
  197. }
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Expose this class to the scene database
  201. //-----------------------------------------------------------------------------
  202. IMPLEMENT_ELEMENT_FACTORY_INSTALL_EXPLICITLY( DmeParticleOperator, CDmeParticleOperator );
  203. //-----------------------------------------------------------------------------
  204. // Constructor, destructor
  205. //-----------------------------------------------------------------------------
  206. void CDmeParticleOperator::OnConstruction()
  207. {
  208. m_FunctionName.Init( this, "functionName" );
  209. }
  210. void CDmeParticleOperator::OnDestruction()
  211. {
  212. }
  213. //-----------------------------------------------------------------------------
  214. // Sets the particle operator
  215. //-----------------------------------------------------------------------------
  216. void CDmeParticleOperator::SetFunction( IParticleOperatorDefinition *pDefinition )
  217. {
  218. m_FunctionName = pDefinition->GetName();
  219. const DmxElementUnpackStructure_t *pUnpack = pDefinition->GetUnpackStructure();
  220. UpdateAttributes( pUnpack );
  221. }
  222. const char *CDmeParticleOperator::GetFunctionType() const
  223. {
  224. return m_FunctionName;
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Expose this class to the scene database
  228. //-----------------------------------------------------------------------------
  229. IMPLEMENT_ELEMENT_FACTORY_INSTALL_EXPLICITLY( DmeParticleChild, CDmeParticleChild );
  230. //-----------------------------------------------------------------------------
  231. // Constructor, destructor
  232. //-----------------------------------------------------------------------------
  233. void CDmeParticleChild::OnConstruction()
  234. {
  235. m_Child.Init( this, "child", FATTRIB_NEVERCOPY );
  236. /*
  237. CDmeEditorType *pEditorType = CreateElement< CDmeEditorType >( "DmeParticleChild", DMFILEID_INVALID );
  238. CDmeEditorAttributeInfo *pInfo = CreateElement< CDmeEditorAttributeInfo >( "field info", DMFILEID_INVALID );
  239. pEditorType->AddAttributeInfo( "child", pInfo );
  240. pInfo->m_Widget = "particle_picker";
  241. m_hTypeDictionary->AddEditorType( pEditorType );
  242. */
  243. }
  244. void CDmeParticleChild::OnDestruction()
  245. {
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Sets the particle system child
  249. //-----------------------------------------------------------------------------
  250. void CDmeParticleChild::SetChildParticleSystem( CDmeParticleSystemDefinition *pDef, IParticleOperatorDefinition *pDefinition )
  251. {
  252. // FIXME: Convert system name into a
  253. m_Child = pDef;
  254. const DmxElementUnpackStructure_t *pUnpack = pDefinition->GetUnpackStructure();
  255. UpdateAttributes( pUnpack );
  256. }
  257. const char *CDmeParticleChild::GetFunctionType() const
  258. {
  259. const CDmeParticleSystemDefinition *pChild = m_Child;
  260. return pChild ? pChild->GetName() : "";
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Expose this class to the scene database
  264. //-----------------------------------------------------------------------------
  265. IMPLEMENT_ELEMENT_FACTORY_INSTALL_EXPLICITLY( DmeParticleSystemDefinition, CDmeParticleSystemDefinition );
  266. //-----------------------------------------------------------------------------
  267. // Purpose:
  268. //-----------------------------------------------------------------------------
  269. void CDmeParticleSystemDefinition::OnConstruction()
  270. {
  271. m_ParticleFunction[FUNCTION_RENDERER].Init( this, "renderers" );
  272. m_ParticleFunction[FUNCTION_OPERATOR].Init( this, "operators" );
  273. m_ParticleFunction[FUNCTION_INITIALIZER].Init( this, "initializers" );
  274. m_ParticleFunction[FUNCTION_EMITTER].Init( this, "emitters" );
  275. m_ParticleFunction[FUNCTION_CHILDREN].Init( this, "children" );
  276. m_ParticleFunction[FUNCTION_FORCEGENERATOR].Init( this, "forces" );
  277. m_ParticleFunction[FUNCTION_CONSTRAINT].Init( this, "constraints" );
  278. m_bPreventNameBasedLookup.Init( this, "preventNameBasedLookup" );
  279. m_hTypeDictionary = CreateElement< CDmeEditorTypeDictionary >( "particleSystemDefinitionDict", DMFILEID_INVALID );
  280. CDmeEditorType *pEditorType = CreateElement< CDmeEditorType >( "DmeParticleSystemDefinition", DMFILEID_INVALID );
  281. const DmxElementUnpackStructure_t *pUnpack = g_pParticleSystemMgr->GetParticleSystemDefinitionUnpackStructure();
  282. for ( ; pUnpack->m_pAttributeName; ++pUnpack )
  283. {
  284. CreateEditorAttributeInfo( pEditorType, pUnpack->m_pAttributeName, (const char *)pUnpack->m_pUserData );
  285. CDmAttribute *pAttribute = AddAttribute( pUnpack->m_pAttributeName, pUnpack->m_AttributeType );
  286. if ( pUnpack->m_pDefaultString )
  287. {
  288. int nLen = MAX( 1, Q_strlen( pUnpack->m_pDefaultString ) );
  289. CUtlBuffer bufParse( pUnpack->m_pDefaultString, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY );
  290. pAttribute->Unserialize( bufParse );
  291. }
  292. }
  293. m_hTypeDictionary->AddEditorType( pEditorType );
  294. }
  295. void CDmeParticleSystemDefinition::OnDestruction()
  296. {
  297. DestroyElement( m_hTypeDictionary, TD_DEEP );
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Returns the editor type dictionary
  301. //-----------------------------------------------------------------------------
  302. CDmeEditorTypeDictionary* CDmeParticleSystemDefinition::GetEditorTypeDictionary()
  303. {
  304. return m_hTypeDictionary;
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Remove obsolete attributes
  308. //-----------------------------------------------------------------------------
  309. static void RemoveObsoleteAttributes( CDmElement *pElement, const DmxElementUnpackStructure_t *pUnpack )
  310. {
  311. // Delete all obsolete attributes
  312. CDmAttribute *pNext;
  313. for( CDmAttribute *pAttr = pElement->FirstAttribute(); pAttr; pAttr = pNext )
  314. {
  315. pNext = pAttr->NextAttribute();
  316. if ( pAttr->IsStandard() || pAttr->IsFlagSet( FATTRIB_EXTERNAL ) )
  317. continue;
  318. bool bFound = false;
  319. for ( const DmxElementUnpackStructure_t *pTrav = pUnpack; pTrav->m_pAttributeName; ++pTrav )
  320. {
  321. if ( !Q_stricmp( pTrav->m_pAttributeName, pAttr->GetName() ) )
  322. {
  323. bFound = true;
  324. break;
  325. }
  326. }
  327. if ( !bFound )
  328. {
  329. pElement->RemoveAttributeByPtr( pAttr );
  330. }
  331. }
  332. }
  333. // Remove all attributes from the element that are either:
  334. // A) Not in the unpack structure (eg. stale)
  335. // B) Equal to their default value
  336. static void CompactElement( CDmElement *pElement, const DmxElementUnpackStructure_t *pUnpack )
  337. {
  338. CDmAttribute *pNext;
  339. for( CDmAttribute *pAttr = pElement->FirstAttribute(); pAttr; pAttr = pNext )
  340. {
  341. pNext = pAttr->NextAttribute();
  342. if ( pAttr->IsStandard() || pAttr->IsFlagSet( FATTRIB_EXTERNAL ) )
  343. continue;
  344. const DmxElementUnpackStructure_t *pFoundUnpack = NULL;
  345. for ( const DmxElementUnpackStructure_t *pTrav = pUnpack; pTrav->m_pAttributeName; ++pTrav )
  346. {
  347. if ( !Q_stricmp( pTrav->m_pAttributeName, pAttr->GetName() ) )
  348. {
  349. pFoundUnpack = pTrav;
  350. break;
  351. }
  352. }
  353. if ( !pFoundUnpack )
  354. {
  355. // wasn't found in the unpack - attribute is stale
  356. pElement->RemoveAttributeByPtr( pAttr );
  357. }
  358. else if ( pFoundUnpack && pFoundUnpack->m_pDefaultString )
  359. {
  360. int nLen = Q_strlen( pFoundUnpack->m_pDefaultString );
  361. CUtlBuffer bufParse( pFoundUnpack->m_pDefaultString, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY );
  362. if ( pAttr->IsIdenticalToSerializedValue( bufParse ) )
  363. {
  364. // equal to the default value - safe to remove
  365. pElement->RemoveAttributeByPtr( pAttr );
  366. }
  367. }
  368. }
  369. }
  370. //-----------------------------------------------------------------------------
  371. // Used for automatic handling of backward compatability
  372. //-----------------------------------------------------------------------------
  373. void CDmeParticleSystemDefinition::OnElementUnserialized()
  374. {
  375. BaseClass::OnElementUnserialized();
  376. RemoveObsoleteAttributes( this, g_pParticleSystemMgr->GetParticleSystemDefinitionUnpackStructure() );
  377. // Add missing fields that are new
  378. for ( int i = 0; i < PARTICLE_FUNCTION_COUNT; ++i )
  379. {
  380. ParticleFunctionType_t type = (ParticleFunctionType_t)i;
  381. CUtlVector< IParticleOperatorDefinition *> &list = g_pParticleSystemMgr->GetAvailableParticleOperatorList( type );
  382. int nAvailType = list.Count();
  383. int nCount = GetParticleFunctionCount( type );
  384. for ( int j = 0; j < nCount; ++j )
  385. {
  386. CDmeParticleFunction *pFunction = GetParticleFunction( type, j );
  387. if ( i == FUNCTION_CHILDREN )
  388. {
  389. RemoveObsoleteAttributes( pFunction, list[0]->GetUnpackStructure() );
  390. pFunction->AddMissingFields( list[0]->GetUnpackStructure() );
  391. continue;
  392. }
  393. for ( int k = 0; k < nAvailType; ++k )
  394. {
  395. if ( Q_stricmp( pFunction->GetName(), list[k]->GetName() ) )
  396. continue;
  397. RemoveObsoleteAttributes( pFunction, list[k]->GetUnpackStructure() );
  398. pFunction->AddMissingFields( list[k]->GetUnpackStructure() );
  399. break;
  400. }
  401. }
  402. }
  403. }
  404. //-----------------------------------------------------------------------------
  405. // Check to see if any attributes changed
  406. //-----------------------------------------------------------------------------
  407. void CDmeParticleSystemDefinition::Resolve()
  408. {
  409. BaseClass::Resolve();
  410. for( CDmAttribute* pAttr = FirstAttribute(); pAttr; pAttr = pAttr->NextAttribute() )
  411. {
  412. if ( pAttr->IsFlagSet( FATTRIB_DIRTY ) )
  413. {
  414. RecompileParticleSystem();
  415. break;
  416. }
  417. }
  418. }
  419. //-----------------------------------------------------------------------------
  420. // Add, remove
  421. //-----------------------------------------------------------------------------
  422. CDmeParticleFunction* CDmeParticleSystemDefinition::AddOperator( ParticleFunctionType_t type, const char *pFunctionName )
  423. {
  424. CUtlVector< IParticleOperatorDefinition *> &list = g_pParticleSystemMgr->GetAvailableParticleOperatorList( type );
  425. int nCount = list.Count();
  426. for ( int i = 0; i < nCount; ++i )
  427. {
  428. if ( Q_stricmp( pFunctionName, list[i]->GetName() ) )
  429. continue;
  430. CDmeParticleOperator *pFunction = CreateElement< CDmeParticleOperator >( pFunctionName, GetFileId() );
  431. m_ParticleFunction[type].AddToTail( pFunction );
  432. pFunction->SetFunction( list[i] );
  433. return pFunction;
  434. }
  435. return NULL;
  436. }
  437. void CDmeParticleSystemDefinition::OverrideAttributesFromOtherDefinition( CDmeParticleSystemDefinition *pDef )
  438. {
  439. for ( const CDmAttribute *pAttr = pDef->FirstAttribute(); pAttr != NULL; pAttr = pAttr->NextAttribute() )
  440. {
  441. DmAttributeType_t type = pAttr->GetType();
  442. const char *pAttrName = pAttr->GetName();
  443. CDmAttribute *pCopyAttr = GetAttribute( pAttrName );
  444. if ( !V_stricmp( pAttrName, "name" ) )
  445. continue;
  446. if ( pCopyAttr == NULL )
  447. {
  448. pCopyAttr = AddAttribute( pAttrName, type );
  449. int flags = pAttr->GetFlags();
  450. Assert( ( flags & FATTRIB_EXTERNAL ) == 0 );
  451. flags &= ~FATTRIB_EXTERNAL;
  452. pCopyAttr->ClearFlags();
  453. pCopyAttr->AddFlag( flags );
  454. }
  455. // Temporarily remove the read-only flag from the copy while we copy into it
  456. bool bReadOnly = pCopyAttr->IsFlagSet( FATTRIB_READONLY );
  457. if ( bReadOnly )
  458. {
  459. pCopyAttr->RemoveFlag( FATTRIB_READONLY );
  460. }
  461. if ( type == AT_ELEMENT )
  462. {
  463. // nothing.
  464. }
  465. else if ( type == AT_ELEMENT_ARRAY )
  466. {
  467. // nothing.
  468. }
  469. else
  470. {
  471. pCopyAttr->SetValue( pAttr );
  472. }
  473. if ( bReadOnly )
  474. {
  475. pCopyAttr->AddFlag( FATTRIB_READONLY );
  476. }
  477. }
  478. }
  479. CDmeParticleFunction* CDmeParticleSystemDefinition::AddCopyOfOperator( CDmeParticleFunction *pFunc )
  480. {
  481. for ( int nType = 0; nType < PARTICLE_FUNCTION_COUNT; ++nType )
  482. {
  483. CUtlVector< IParticleOperatorDefinition *> &list = g_pParticleSystemMgr->GetAvailableParticleOperatorList( (ParticleFunctionType_t)nType );
  484. int nCount = list.Count();
  485. for ( int i = 0; i < nCount; ++i )
  486. {
  487. if ( nType == FUNCTION_CHILDREN )
  488. {
  489. if ( !pFunc->IsA<CDmeParticleChild>() )
  490. continue;
  491. }
  492. else
  493. {
  494. if ( Q_stricmp( pFunc->GetFunctionType(), list[i]->GetName() ) )
  495. continue;
  496. }
  497. CDmeParticleFunction *pCopy = pFunc->Copy(TD_SHALLOW);
  498. pCopy->SetFileId( GetFileId(), TD_SHALLOW );
  499. pCopy->InstanceTypeDictionary();
  500. m_ParticleFunction[nType].AddToTail( pCopy );
  501. return pCopy;
  502. }
  503. }
  504. return NULL;
  505. }
  506. CDmeParticleFunction* CDmeParticleSystemDefinition::AddChild( CDmeParticleSystemDefinition *pChild )
  507. {
  508. Assert( pChild );
  509. CUtlVector< IParticleOperatorDefinition *> &list = g_pParticleSystemMgr->GetAvailableParticleOperatorList( FUNCTION_CHILDREN );
  510. Assert( list.Count() == 1 );
  511. CDmeParticleChild *pFunction = CreateElement< CDmeParticleChild >( pChild->GetName(), GetFileId() );
  512. m_ParticleFunction[FUNCTION_CHILDREN].AddToTail( pFunction );
  513. pFunction->SetChildParticleSystem( pChild, list[0] );
  514. return pFunction;
  515. }
  516. void CDmeParticleSystemDefinition::RemoveFunction( ParticleFunctionType_t type, CDmeParticleFunction *pFunction )
  517. {
  518. int nIndex = FindFunction( type, pFunction );
  519. if ( nIndex >= 0 )
  520. {
  521. m_ParticleFunction[type].Remove(nIndex);
  522. }
  523. }
  524. //-----------------------------------------------------------------------------
  525. // Find
  526. //-----------------------------------------------------------------------------
  527. int CDmeParticleSystemDefinition::FindFunction( ParticleFunctionType_t type, CDmeParticleFunction *pParticleFunction )
  528. {
  529. int nCount = m_ParticleFunction[type].Count();
  530. for ( int i = 0; i < nCount; ++i )
  531. {
  532. if ( pParticleFunction == m_ParticleFunction[type][i] )
  533. return i;
  534. }
  535. return -1;
  536. }
  537. int CDmeParticleSystemDefinition::FindFunction( ParticleFunctionType_t type, const char *pFunctionName )
  538. {
  539. int nCount = m_ParticleFunction[type].Count();
  540. for ( int i = 0; i < nCount; ++i )
  541. {
  542. if ( !Q_stricmp( pFunctionName, m_ParticleFunction[type][i]->GetFunctionType() ) )
  543. return i;
  544. }
  545. return -1;
  546. }
  547. //-----------------------------------------------------------------------------
  548. // Iteration
  549. //-----------------------------------------------------------------------------
  550. int CDmeParticleSystemDefinition::GetParticleFunctionCount( ParticleFunctionType_t type ) const
  551. {
  552. return m_ParticleFunction[type].Count();
  553. }
  554. CDmeParticleFunction *CDmeParticleSystemDefinition::GetParticleFunction( ParticleFunctionType_t type, int nIndex )
  555. {
  556. return m_ParticleFunction[type][nIndex];
  557. }
  558. //-----------------------------------------------------------------------------
  559. // Reordering
  560. //-----------------------------------------------------------------------------
  561. void CDmeParticleSystemDefinition::MoveFunctionUp( ParticleFunctionType_t type, CDmeParticleFunction *pElement )
  562. {
  563. int nIndex = FindFunction( type, pElement );
  564. if ( nIndex > 0 )
  565. {
  566. m_ParticleFunction[type].Swap( nIndex, nIndex - 1 );
  567. }
  568. }
  569. void CDmeParticleSystemDefinition::MoveFunctionDown( ParticleFunctionType_t type, CDmeParticleFunction *pElement )
  570. {
  571. int nIndex = FindFunction( type, pElement );
  572. int nLastIndex = m_ParticleFunction[type].Count() - 1;
  573. if ( nIndex >= 0 && nIndex < nLastIndex )
  574. {
  575. m_ParticleFunction[type].Swap( nIndex, nIndex + 1 );
  576. }
  577. }
  578. //-----------------------------------------------------------------------------
  579. // Marks a particle system as a new instance
  580. // This is basically a workaround to prevent newly-copied particle functions
  581. // from recompiling themselves a zillion times
  582. //-----------------------------------------------------------------------------
  583. void CDmeParticleSystemDefinition::MarkNewInstance()
  584. {
  585. for ( int i = 0; i < PARTICLE_FUNCTION_COUNT; ++i )
  586. {
  587. int nCount = m_ParticleFunction[i].Count();
  588. for ( int j = 0; j < nCount; ++j )
  589. {
  590. m_ParticleFunction[i][j]->MarkNewInstance();
  591. }
  592. }
  593. }
  594. //-----------------------------------------------------------------------------
  595. // Recompiles the particle system when a change occurs
  596. //-----------------------------------------------------------------------------
  597. void CDmeParticleSystemDefinition::RecompileParticleSystem()
  598. {
  599. const char *pFileFormat = "pcf";
  600. const char *pEncoding = g_pDataModel->GetDefaultEncoding( pFileFormat );
  601. int nFlags = g_pDataModel->IsEncodingBinary( pEncoding ) ? 0 : CUtlBuffer::TEXT_BUFFER;
  602. CUtlBuffer buf( 0, 0, nFlags );
  603. if ( g_pDataModel->Serialize( buf, pEncoding, pFileFormat, GetHandle() ) )
  604. {
  605. g_pParticleSystemMgr->ReadParticleConfigFile( buf, true );
  606. }
  607. }
  608. void CDmeParticleSystemDefinition::RemoveInvalidFunctions()
  609. {
  610. for ( int f = 0; f < PARTICLE_FUNCTION_COUNT; ++f )
  611. {
  612. for ( int i = 0; i < m_ParticleFunction[f].Count(); )
  613. {
  614. CDmeParticleFunction* pFunc = m_ParticleFunction[f].Element(i);
  615. if ( pFunc == NULL )
  616. {
  617. m_ParticleFunction[f].Remove(i);
  618. }
  619. else
  620. {
  621. ++i;
  622. }
  623. }
  624. }
  625. }
  626. void CDmeParticleSystemDefinition::Compact()
  627. {
  628. // Traverse the entire definition and purge all the DM elements
  629. CompactElement( this, g_pParticleSystemMgr->GetParticleSystemDefinitionUnpackStructure() );
  630. for ( int i = 0; i < PARTICLE_FUNCTION_COUNT; ++i )
  631. {
  632. ParticleFunctionType_t type = (ParticleFunctionType_t)i;
  633. CUtlVector< IParticleOperatorDefinition *> &list = g_pParticleSystemMgr->GetAvailableParticleOperatorList( type );
  634. int nAvailType = list.Count();
  635. int nCount = GetParticleFunctionCount( type );
  636. for ( int j = 0; j < nCount; ++j )
  637. {
  638. CDmeParticleFunction *pFunction = GetParticleFunction( type, j );
  639. if ( i == FUNCTION_CHILDREN )
  640. {
  641. CompactElement( pFunction, list[0]->GetUnpackStructure() );
  642. continue;
  643. }
  644. for ( int k = 0; k < nAvailType; ++k )
  645. {
  646. if ( Q_stricmp( pFunction->GetName(), list[k]->GetName() ) )
  647. continue;
  648. CompactElement( pFunction, list[k]->GetUnpackStructure() );
  649. break;
  650. }
  651. }
  652. }
  653. }