particlesource.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. //! Flags to pass to ParticleSource.SetParticleAutoDestroyFlags
  2. enum ParticleAutoDestroyFlags
  3. {
  4. //! No automatic destroying
  5. NONE,
  6. //! Destroy when the Particle ends (looping particle never ends)
  7. ON_END,
  8. //! Destroy when particle stops
  9. ON_STOP,
  10. //! ON_END | ON_STOP
  11. ALL,
  12. }
  13. //! Flags to pass to ParticleSource.PlayParticleEx
  14. enum PlayParticleFlags
  15. {
  16. //! No flags
  17. NONE,
  18. // Is just a placeholder for now
  19. }
  20. //! Flags to pass to ParticleSource.StopParticle
  21. enum StopParticleFlags
  22. {
  23. //! No flags
  24. NONE,
  25. //! Reset state after stopping
  26. RESET,
  27. /**
  28. \brief Flag will make the particle stop immediately, taking it out of simulation and clearing VISIBLE flag
  29. * \note By default the particle will gradually fade
  30. * \note Note that when using IMMEDIATE, it is possible to call PlayParticle and it will resume from the moment it stopped
  31. * Which is not possible by default, as the gradual fade is accomplished by nulling the lifetime
  32. */
  33. IMMEDIATE,
  34. //! Is default behaviour, but can be used in conjuction with IMMEDIATE which hides it when this flag is not present
  35. VISIBLE,
  36. //! (SPF_IMMEDIATE | SPF_VISIBLE) "Freezes" the particle while keeping it visible
  37. PAUSE,
  38. }
  39. //! Mode for GetParticle
  40. enum EGetParticleMode
  41. {
  42. //! Full path with ext ("graphics/particles/smoking_barrel_small.ptc")
  43. FULL,
  44. //! Full path without ext ("graphics/particles/smoking_barrel_small")
  45. NO_EXT,
  46. //! Filename only ("smoking_barrel_small")
  47. FILE,
  48. }
  49. enum ParticlePropertiesFlags
  50. {
  51. NONE,
  52. //! Makes the particle start playing immediately after being created
  53. PLAY_ON_CREATION,
  54. //! Only applicable when there is a parent, this will force the localOri to be in world space instead of local
  55. FORCE_WORLD_ROT,
  56. //! By default, a particle unparents when it ends, this disables this behaviour
  57. KEEP_PARENT_ON_END,
  58. };
  59. //! Properties while creating a ParticleSource
  60. class ParticleProperties
  61. {
  62. /**
  63. *\brief Constructor (ctor)
  64. * \param localPos \p vector Local position of particle, if no parent this is world position
  65. * \param flags \p int See ParticlePropertiesFlags
  66. * \param parent \p Object The parent that the ParticleSource will be added to as a child
  67. * \param localOri \p vector Local orientation of particle, if no parent this is world orientation
  68. * \param owner \p Class The owning instance for this particle, as long as it exists, this particle will not be reused (unless flagged)
  69. * Important when for example virtual is enabled
  70. * since if the particle owner has been deleted, the virtual should not be converted
  71. * Only fill in owner if necessary, for example when the owner is reusing the same particle after storing it
  72. */
  73. void ParticleProperties(vector localPos, int flags, Object parent = null, vector localOri = vector.Zero, Class owner = null)
  74. {
  75. }
  76. //! dtor
  77. void ~ParticleProperties()
  78. {
  79. }
  80. /** \name Data access
  81. Methods to retrieve the data in script
  82. */
  83. //@{
  84. proto Object GetParent();
  85. proto Class GetOwner();
  86. proto vector GetLocalPos();
  87. proto vector GetLocalOri();
  88. proto int GetPPFlags();
  89. proto bool IsPlayOnCreation();
  90. proto bool IsForceWorldRotation();
  91. proto bool IsKeepParentOnEnd();
  92. //@}
  93. }
  94. typedef array<ref ParticleProperties> ParticlePropertiesArray;
  95. typedef array<ParticleSource> ParticleSourceArray;
  96. /**
  97. *\brief Entity which has the particle instance as an ObjectComponent
  98. * \note Unfortunately the native methods are private and have a script wrapper
  99. * This is because of backwards compatibility with the old Particle and to avoid confusion
  100. * As we should continue to use Particle for consistency, as it is too deeply rooted in script
  101. * Which means switching is no longer possible due to it being harmful for already existing mods
  102. * Even though using the ParticleSource directly would be preferred
  103. *
  104. * \note Some variables from Particle are invalid on this level, those marked DEPRECATED by Particle are still DEPRECATED here
  105. * m_ParticleID; //!< INVALID - Use GetParticleID() instead
  106. * m_Lifetime; //!< INVALID - No EOnFrame, so no use for it
  107. * m_IsPlaying; //!< VALID - Set through events - IsParticlePlaying() is still better
  108. * m_IsRepeat; //!< INVALID - Use IsRepeat() instead
  109. * m_MarkedForDeletion; //!< INVALID - No EOnFrame, so no use for it
  110. * Wiggle API variables are still used for Wiggle API
  111. * m_ParentObject; //!< VALID - Set through events - Or use GetParticleParent() or GetParent()
  112. * m_ParticleEffect; //!< VALID - Not in the same usage as Particle, as it will always be 'this', never null
  113. */
  114. class ParticleSource : Particle
  115. {
  116. //! ctor
  117. void ParticleSource()
  118. {
  119. m_ParticleEffect = this;
  120. }
  121. //! dtor
  122. void ~ParticleSource()
  123. {
  124. }
  125. //! Empty - Only needed for Particle
  126. override protected void ParticleInit() {}
  127. /**
  128. \brief Enables the particle to automatically clean up itself when ending or stopping
  129. \note Is enabled by default (ALL)
  130. \note Looping particles never end
  131. \note ParticleSource belonging to a ParticleManager will ignore these
  132. \param flags \p ParticleAutoDestroyFlags Flags enabling when the particle should be auto destroyed
  133. */
  134. proto native void SetParticleAutoDestroyFlags(ParticleAutoDestroyFlags flags);
  135. /**
  136. \brief Disables the particle automatically cleaning up itself when ending or stopping
  137. */
  138. void DisableAutoDestroy()
  139. {
  140. SetParticleAutoDestroyFlags(ParticleAutoDestroyFlags.NONE);
  141. }
  142. /**
  143. \brief Gets the currently set ParticleAutoDestroyFlags flags set on this ParticleSource
  144. \return \p int Currently set ParticleAutoDestroyFlags flags set on this ParticleSource
  145. */
  146. proto native int GetParticleAutoDestroyFlags();
  147. /** \name Create a particle (static)
  148. Helper static methods to create/attach/play a ParticleSource on one line
  149. */
  150. //@{
  151. /**
  152. \brief Create function
  153. \param id \p int Particle ID registered in ParticleList
  154. \param pos \p vector Position of ParticleSource in LS (WS when no parent)
  155. \param playOnCreation \p bool Whether to play immediately after creation (Optional)
  156. \param parent \p Object Parent Object which will child the ParticleSource (Optional)
  157. \param ori \p vector Orientation of ParticleSource in LS (WS when no parent) (Pitch, Yaw, Roll in degrees) (Optional)
  158. \param forceWorldRotation \p bool Forces orientation to rotate relative to the world and not with the parent (Optional)
  159. \param owner \p Class The owning instance for this particle (Optional)
  160. \return \p ParticleSource Created particle instance when successful
  161. */
  162. static ParticleSource CreateParticle( int id, vector pos, bool playOnCreation = false, Object parent = null, vector ori = vector.Zero, bool forceWorldRotation = false, Class owner = null )
  163. {
  164. int flags = ParticlePropertiesFlags.NONE;
  165. if (playOnCreation)
  166. {
  167. flags = flags | ParticlePropertiesFlags.PLAY_ON_CREATION;
  168. }
  169. if (forceWorldRotation)
  170. {
  171. flags = flags | ParticlePropertiesFlags.FORCE_WORLD_ROT;
  172. }
  173. return CreateParticleEx(id, pos, flags, parent, ori, owner);
  174. }
  175. /**
  176. \brief Master create function
  177. \param id \p int Particle ID registered in ParticleList
  178. \param pos \p vector Position of ParticleSource in LS (WS when no parent)
  179. \param flags \p int See ParticlePropertiesFlags (Optional)
  180. \param parent \p Object Parent Object which will child the ParticleSource (Optional)
  181. \param ori \p vector Orientation of ParticleSource in LS (WS when no parent) (Pitch, Yaw, Roll in degrees) (Optional)
  182. \param owner \p Class The owning instance for this particle (Optional)
  183. \return \p ParticleSource Created particle instance when successful
  184. */
  185. static ParticleSource CreateParticleEx( int id, vector pos, int flags = ParticlePropertiesFlags.NONE, Object parent = null, vector ori = vector.Zero, Class owner = null )
  186. {
  187. string particlePath = ParticleList.GetParticleFullPath(id);
  188. if (particlePath == "") // There is already an error inside of ParticleList signaling this
  189. {
  190. ErrorEx(string.Format("Could not create ParticleSource as particle id %1 is invalid.", id));
  191. return null;
  192. }
  193. vector localPos = pos;
  194. if (parent)
  195. pos = parent.GetPosition();
  196. ParticleSource p = ParticleSource.Cast( GetGame().CreateObjectEx("ParticleSource", pos, ECE_LOCAL) );
  197. p.SetParticle(particlePath);
  198. ParticleProperties props = new ParticleProperties(localPos, flags, parent, ori, owner);
  199. p.ApplyProperties(props);
  200. return p;
  201. }
  202. /**
  203. \brief Creates a particle emitter and attaches it on the given object
  204. \param particle_id \p int Particle ID registered in ParticleList
  205. \param parent_obj \p Object Instance on which this particle will be attached
  206. \param local_pos \p vector Attachment position local to the parent (Optional)
  207. \param local_ori \p vector Orientation local to the parent (Pitch, Yaw, Roll in degrees) (Optional)
  208. \param force_world_rotation \p bool Forces particle's orientation to rotate relative to the world and not with the object (Optional)
  209. \return \p Particle Created particle instance
  210. */
  211. override static Particle CreateOnObject(
  212. int particle_id,
  213. Object parent_obj,
  214. vector local_pos = "0 0 0",
  215. vector local_ori = "0 0 0",
  216. bool force_world_rotation = false )
  217. {
  218. return CreateParticle(particle_id, local_pos, false, parent_obj, local_ori, force_world_rotation);
  219. }
  220. /**
  221. \brief Legacy function for backwards compatibility
  222. */
  223. override static Particle Create( int particle_id, Object parent_obj, vector local_pos = "0 0 0", vector local_ori = "0 0 0" )
  224. {
  225. return CreateOnObject( particle_id, parent_obj, local_pos, local_ori);
  226. }
  227. /**
  228. \brief Creates a particle emitter on the given position
  229. \param particle_id \p int Particle ID registered in ParticleList
  230. \param global_pos \p Vector Position where the particel will be created
  231. \param global_ori \p vector Orientation (Pitch, Yawn, Roll in degrees) (Optional)
  232. \param force_world_rotation \p bool Has absolutely no effect here as there is no parent
  233. \return \p Particle Created particle instance
  234. */
  235. override static Particle CreateInWorld( int particle_id, vector global_pos, vector global_ori = "0 0 0", bool force_world_rotation = false )
  236. {
  237. return CreateParticle(particle_id, global_pos, false, null, global_ori, force_world_rotation);
  238. }
  239. /**
  240. \brief Legacy function for backwards compatibility with 1.01 and below
  241. */
  242. override static ParticleSource Create( int particle_id, vector global_pos, vector global_ori = "0 0 0" )
  243. {
  244. return CreateInWorld( particle_id, global_pos, global_ori );
  245. }
  246. //@}
  247. /** \name Static play on creation
  248. You can use the following Play(...) functions to create and activate a particle in 1 line of your script.
  249. */
  250. //@{
  251. /**
  252. \brief Creates a particle emitter, attaches it on the given object and activates it
  253. \param particle_id \p int Particle ID registered in ParticleList
  254. \param parent_obj \p Object Instance on which this particle will be attached
  255. \param local_pos \p vector Attachment position local to the parent (Optional)
  256. \param local_ori \p vector Orientation local to the parent (Pitch, Yaw, Roll in degrees) (Optional)
  257. \param force_world_rotation \p bool Forces particle's orientation to rotate relative to the world and not with the object (Optional)
  258. \return \p Particle Created particle instance
  259. */
  260. override static Particle PlayOnObject(int particle_id, Object parent_obj, vector local_pos = "0 0 0", vector local_ori = "0 0 0", bool force_world_rotation = false )
  261. {
  262. return CreateParticle(particle_id, local_pos, true, parent_obj, local_ori, force_world_rotation);
  263. }
  264. /**
  265. \brief Legacy function for backwards compatibility with 1.01 and below
  266. */
  267. override static Particle Play( int particle_id, Object parent_obj, vector local_pos = "0 0 0", vector local_ori = "0 0 0" )
  268. {
  269. return PlayOnObject( particle_id, parent_obj, local_pos, local_ori);
  270. }
  271. /**
  272. \brief Creates a particle emitter on the given position and activates it
  273. \param particle_id \p int Particle ID registered in ParticleList
  274. \param global_pos \p Vector Position where the particel will be created
  275. \return \p Particle Created particle instance
  276. */
  277. override static Particle PlayInWorld( int particle_id, vector global_pos)
  278. {
  279. return CreateParticle(particle_id, global_pos, true);
  280. }
  281. /**
  282. \brief Legacy function for backwards compatibility with 1.01 and below
  283. */
  284. override static Particle Play( int particle_id, vector global_pos)
  285. {
  286. return PlayInWorld( particle_id, global_pos);
  287. }
  288. //@}
  289. /** \name Playback
  290. Methods regarding playing/stopping of particle
  291. */
  292. //@{
  293. /**
  294. \brief Method to tell the particle to start playing
  295. \note Will call OnParticleStart when successful
  296. \return \p bool Whether the particle successfully started
  297. */
  298. private proto bool PlayParticleNative(int flags);
  299. /**
  300. \brief Method to tell the particle to start playing
  301. \param particle_id \p int Particle ID registered in ParticleList to start playing
  302. \return \p bool Whether the particle successfully started
  303. */
  304. override bool PlayParticleEx(int particle_id = -1, int flags = 0)
  305. {
  306. if ( particle_id > -1 )
  307. {
  308. // Here we can just do it directly
  309. // While with the old system it will not work when the particle is already created
  310. SetParticleByID(particle_id);
  311. }
  312. return PlayParticleNative(flags);
  313. }
  314. /**
  315. \brief Method to tell the particle to stop playing
  316. \note The particle is not immediately stopped by default, instead it will gradually fade
  317. * If this is however desired, then pass in StopParticleFlags.IMMEDIATE
  318. \param flags \p int Flags to pass to the stopping (StopParticleFlags)
  319. \return \p bool Whether the particle successfully stopped
  320. */
  321. private proto bool StopParticleNative(int flags);
  322. /**
  323. \brief Method to tell the particle to stop playing
  324. \param flags \p int Flags to pass to the stopping (StopParticleFlags)
  325. \return \p bool Whether the particle successfully stopped
  326. */
  327. override bool StopParticle(int flags = 0)
  328. {
  329. return StopParticleNative(flags);
  330. }
  331. /**
  332. \brief Method to tell the particle to reset
  333. \return \p bool Whether the particle successfully reset
  334. */
  335. private proto native bool ResetParticleNative();
  336. /**
  337. \brief Method to tell the particle to reset
  338. \return \p bool Whether the particle successfully reset
  339. */
  340. override bool ResetParticle()
  341. {
  342. return ResetParticleNative();
  343. }
  344. /**
  345. \brief Method to tell the particle to restart (reset + play)
  346. \return \p bool Whether the particle successfully restarted
  347. */
  348. private proto native bool RestartParticleNative();
  349. /**
  350. \brief Method to tell the particle to restart (reset + play)
  351. \return \p bool Whether the particle successfully restarted
  352. */
  353. override bool RestartParticle()
  354. {
  355. return RestartParticleNative();
  356. }
  357. /**
  358. \brief Ask if the particle is still playing
  359. \return \p bool Whether the particle is playing
  360. */
  361. private proto bool IsParticlePlayingNative();
  362. /**
  363. \brief Ask if the particle is still playing
  364. \return \p bool Whether the particle is playing
  365. */
  366. override bool IsParticlePlaying()
  367. {
  368. return IsParticlePlayingNative();
  369. }
  370. //@}
  371. /** \name SetParticle
  372. Methods that set the particle to be used
  373. */
  374. //@{
  375. /**
  376. \brief Assigns a particle to the ParticleSource
  377. \param path \p string Path of particle effect
  378. \return \p bool Whether the creating and assigning of particle was successful
  379. */
  380. private proto native bool SetParticleNative(string path);
  381. /**
  382. \brief Assigns a particle to the ParticleSource
  383. \note Intentionally private, as it is best to use 'SetParticleByID' instead from script, because ParticleList
  384. \param path \p string Path of particle effect
  385. \return \p bool Whether the creating and assigning of particle was successful
  386. */
  387. private bool SetParticle(string path)
  388. {
  389. return SetParticleNative(path);
  390. }
  391. /**
  392. \brief Assigns a particle to the ParticleSource
  393. \param id \p int ID of particle registered in ParticleList
  394. \return \p bool Whether the creating and assigning of particle was successful
  395. */
  396. bool SetParticleByID(int id)
  397. {
  398. return SetParticle(ParticleList.GetParticleFullPath(id));
  399. }
  400. /**
  401. \brief Sets particle id
  402. \note Purely here for backwards compatibility with Particle
  403. \param particle_id \p int Particle ID registered in ParticleList to start playing
  404. */
  405. override void SetSource(int particle_id)
  406. {
  407. SetParticleByID(particle_id);
  408. }
  409. //@}
  410. /** \name GetParticle
  411. Methods that get the particle assigned
  412. */
  413. //@{
  414. /**
  415. \brief Gets the path to the currently assigned particle
  416. \param path \p string Path of particle effect
  417. \param mode \p EGetParticleMode What path to return
  418. \return \p bool Whether the path is filled in or not
  419. */
  420. private proto bool GetParticleNative(out string path, EGetParticleMode mode);
  421. /**
  422. \brief Gets the path to the currently assigned particle
  423. \param path \p string Path of particle effect
  424. \param mode \p EGetParticleMode What path to return
  425. \return \p bool Whether the path is filled in or not
  426. */
  427. bool GetParticle(out string path, EGetParticleMode mode)
  428. {
  429. return GetParticleNative(path, mode);
  430. }
  431. /**
  432. \brief Gets the ParticleList ID of the currently assigned particle
  433. \return \p int ID of particle registered in ParticleList
  434. */
  435. override int GetParticleID()
  436. {
  437. string path;
  438. if (GetParticle(path, EGetParticleMode.FILE))
  439. return ParticleList.GetParticleIDByName(path);
  440. else
  441. return -1;
  442. }
  443. /**
  444. \brief Gets the ParticleList ID of the currently assigned particle
  445. \note This is because the new GetParticleID will only work when every particle file name has a unique name
  446. * In case this is not the case, then this method is what one will want to use
  447. \return \p int ID of particle registered in ParticleList
  448. */
  449. int GetParticleIDLegacy()
  450. {
  451. string path;
  452. if (GetParticle(path, EGetParticleMode.NO_EXT))
  453. return ParticleList.GetParticleID(path);
  454. else
  455. return -1;
  456. }
  457. //@}
  458. /** \name Apply properties
  459. Methods to apply properties to the particle
  460. */
  461. //@{
  462. /**
  463. \brief Applies the properties given to the ParticleSource
  464. \note Already handles proper reparenting
  465. \param properties \p ParticleProperties The properties to apply
  466. \return \p bool Whether the properties were successfully applied
  467. */
  468. private proto native bool ApplyPropertiesNative(ParticleProperties properties);
  469. /**
  470. \brief Applies the properties given to the ParticleSource
  471. \param properties \p ParticleProperties The properties to apply
  472. \return \p bool Whether the properties were successfully applied
  473. */
  474. bool ApplyProperties(ParticleProperties properties)
  475. {
  476. return ApplyPropertiesNative(properties);
  477. }
  478. //@}
  479. /** \name Properties and state
  480. Obtain information or set properties regarding the state of the Particle
  481. */
  482. //@{
  483. /**
  484. \brief Returns direct particle effect entity
  485. \note Backwards compatibility with Particle, here it is the Object itself
  486. \return \p Object The Object with the particle component (this)
  487. */
  488. override Object GetDirectParticleEffect()
  489. {
  490. return this;
  491. }
  492. /**
  493. \brief Returns the parent of this Particle if there is one
  494. \return \p Object The parent or null if there is none
  495. */
  496. override Object GetParticleParent()
  497. {
  498. return Object.Cast(GetParent());
  499. }
  500. /**
  501. \brief Returns if there is any particle active
  502. \return \p bool Whether there is any particle active
  503. */
  504. private proto bool HasActiveParticleNative();
  505. /**
  506. \brief Returns if there is any particle active
  507. \return \p bool Whether there is any particle active
  508. */
  509. override bool HasActiveParticle()
  510. {
  511. return HasActiveParticleNative();
  512. }
  513. /**
  514. \brief Returns the total count of active particles in all emitors
  515. \note Internally does a sum, HasActiveParticle is better for a quick check
  516. \return \p int Total count of active particles
  517. */
  518. private proto int GetParticleCountNative();
  519. /**
  520. \brief Returns the total count of active particles in all emitors
  521. \note Internally does a sum, HasActiveParticle is better for a quick check
  522. \return \p int Total count of active particles
  523. */
  524. override int GetParticleCount()
  525. {
  526. return GetParticleCountNative();
  527. }
  528. /**
  529. \brief Returns whether there is a repeating particle
  530. \return \p bool whether there is a repeating particle
  531. */
  532. private proto bool IsRepeatNative();
  533. /**
  534. \brief Returns whether there is a repeating particle
  535. \return \p bool whether there is a repeating particle
  536. */
  537. override bool IsRepeat()
  538. {
  539. return IsRepeatNative();
  540. }
  541. /**
  542. \brief Returns the approx. max lifetime
  543. \return \p float The largest lifetime sum among the emitors
  544. */
  545. private proto float GetMaxLifetimeNative();
  546. /**
  547. \brief Returns the approx. max lifetime
  548. \return \p float The largest lifetime sum among the emitors
  549. */
  550. override float GetMaxLifetime()
  551. {
  552. return GetMaxLifetimeNative();
  553. }
  554. /**
  555. \brief Get the owner of this ParticleSource
  556. \return \p Class The owner or null
  557. */
  558. proto native Class GetOwner();
  559. /**
  560. \brief Set the owner of this ParticleSource
  561. \param \p Class The owner or null
  562. */
  563. proto native void SetOwner(Class owner);
  564. /**
  565. \brief null the owner of this ParticleSource
  566. */
  567. proto native void Orphan();
  568. //@}
  569. /** \name Owning ParticleManager
  570. Methods regarding the owner
  571. */
  572. //@{
  573. /**
  574. \brief Get the ParticleManager the ParticleSource belongs to if any
  575. \return \p ParticleManager The ParticleManager which created the ParticleSource or null
  576. */
  577. proto native ParticleManager GetParticleManager();
  578. /**
  579. \brief Get the index of this ParticleSource in the owning ParticleManager
  580. \return \p int The index in the pool in the owning ParticleManager, -1 if no owner
  581. */
  582. proto native int GetIndex();
  583. //@}
  584. /** \name Static counter API
  585. Gives counter information for the class
  586. */
  587. //@{
  588. /**
  589. \brief Gets the ID for the ParticleSource
  590. \note Different every restart, as it is the nth instance created since the start of the program
  591. \return \p int ID for the ParticleSource
  592. */
  593. proto int GetCountID();
  594. /**
  595. \brief Gets the amount of ParticleSource that have been created since the start of the program
  596. \return \p int Amount of ParticleSource that have been created since the start of the program
  597. */
  598. proto native static int GetStaticCount();
  599. /**
  600. \brief Gets the amount of ParticleSource that are currently existing
  601. \return \p int Amount of ParticleSource that are currently existing
  602. */
  603. proto native static int GetStaticActiveCount();
  604. //@}
  605. /** \name Events
  606. * ParticleBase events
  607. * For ParticleSource, these are handed on C++ side
  608. * For more information, read ParticleEvents
  609. */
  610. //@{
  611. /**
  612. \brief Event when the particle receives a parent
  613. */
  614. override protected void OnParticleParented(IEntity parent)
  615. {
  616. m_ParentObject = Object.Cast(parent);
  617. super.OnParticleParented(parent);
  618. }
  619. /**
  620. \brief Event when the particle is orphaned
  621. */
  622. override protected void OnParticleUnParented(IEntity parent)
  623. {
  624. m_ParentObject = null;
  625. // Since we have lost the parent, we will need to refresh the wiggle
  626. // As it uses a cached local position, which is now no longer correct
  627. if (!m_WiggleProcessing && IsWiggling())
  628. {
  629. float randomAngle = m_MaxOriWiggle;
  630. float randomInterval = m_MaxOriInterval;
  631. m_DefaultPos = m_DefaultWorldPos;
  632. m_DefaultOri = m_DefaultWorldOri;
  633. StopWiggle();
  634. SetWiggle(randomAngle, randomInterval);
  635. }
  636. super.OnParticleUnParented(parent);
  637. }
  638. /**
  639. \brief Event when the particle stops
  640. */
  641. override protected void OnParticleStop()
  642. {
  643. if (IsWiggling())
  644. {
  645. StopWiggle();
  646. delete m_RandomizeOri;
  647. }
  648. super.OnParticleStop();
  649. }
  650. //@}
  651. /** \name Misc backwards compatibility helpers
  652. Helpers for misc backwards compatibility functionality
  653. */
  654. //@{
  655. /**
  656. \brief Attaches this particle onto some object. If null value is provided then the particle will be detached from the current parent.
  657. \note Unlike Particle, you are free to use AddChild/RemoveChild instead of this one if you know what you are doing
  658. \param parent \p Object Parent onto which this particle will be attached
  659. \param local_pos \p vector Attachment position local to the parent (optional)
  660. \param local_ori \p vector Orientation local to the parent (Pitch, Yawn, Roll in degrees) (Optional)
  661. \param force_rotation_to_world \p bool Force rotation to be in WS (Optional)
  662. */
  663. override void AddAsChild(Object parent, vector local_pos = "0 0 0", vector local_ori = "0 0 0", bool force_rotation_to_world = false)
  664. {
  665. int flags = ParticlePropertiesFlags.NONE;
  666. if (force_rotation_to_world)
  667. flags = ParticlePropertiesFlags.FORCE_WORLD_ROT;
  668. ParticleProperties props = new ParticleProperties(local_pos, flags, parent, local_ori);
  669. ApplyProperties(props);
  670. }
  671. //@}
  672. /** \name Parameter API
  673. Helpful methods for getting or setting parameters
  674. */
  675. //@{
  676. /**
  677. \brief Set the value of a parameter of all emitors in the particle
  678. \param parameter \p int The parameter to apply the new value to (enum EmitorParam)
  679. \param value \p float The value to apply
  680. */
  681. override void SetParticleParam(int parameter_id, float value )
  682. {
  683. SetParticleParm(this, -1, parameter_id, value);
  684. }
  685. /**
  686. \brief Set the value of a parameter of an emitor in the particle
  687. \param emitter \p int The emitter to apply the new value to, -1 for all emitter
  688. \param parameter \p int The parameter to apply the new value to (enum EmitorParam)
  689. \param value \p float The value to apply
  690. */
  691. override void SetParameter(int emitter, int parameter, float value)
  692. {
  693. SetParticleParm(this, emitter, parameter, value);
  694. }
  695. /**
  696. \brief Get the value of a parameter of an emitor in the particle
  697. \param emitter \p int The emitor to get the value from
  698. \param parameter \p int The parameter to get the value from (enum EmitorParam)
  699. \param value \p float The value
  700. */
  701. override void GetParameter(int emitter, int parameter, out float value)
  702. {
  703. GetParticleParm(this, emitter, parameter, value);
  704. }
  705. /**
  706. \brief Get the value of a parameter of an emitor in the particle
  707. \param emitter \p int The emitor to get the value from
  708. \param parameter \p int The parameter to get the value from (enum EmitorParam)
  709. \return \p float The value
  710. */
  711. override float GetParameterEx(int emitter, int parameter)
  712. {
  713. float value;
  714. GetParticleParm(this, emitter, parameter, value);
  715. return value;
  716. }
  717. /**
  718. \brief Scales the given parameter on all emitors relatively to their ORIGINAL value.
  719. \param parameter_id \p int The parameter to adjust (enum EmitorParam)
  720. \param coef \p float The multiplier to apply
  721. */
  722. override void ScaleParticleParamFromOriginal(int parameter_id, float coef )
  723. {
  724. int emitors = GetParticleEmitorCount(this);
  725. for (int i = 0; i < emitors; ++i)
  726. {
  727. float value;
  728. GetParticleParmOriginal(this, i, parameter_id, value);
  729. SetParticleParm(this, i, parameter_id, value * coef);
  730. }
  731. }
  732. /**
  733. \brief Scales the given parameter on all emitors relatively to their CURRENT value.
  734. \param parameter_id \p int The parameter to adjust (enum EmitorParam)
  735. \param coef \p float The multiplier to apply
  736. */
  737. override void ScaleParticleParam(int parameter_id, float coef )
  738. {
  739. int emitors = GetParticleEmitorCount(this);
  740. for (int i = 0; i < emitors; ++i)
  741. {
  742. float value;
  743. GetParticleParm(this, i, parameter_id, value);
  744. SetParticleParm(this, i, parameter_id, value * coef);
  745. }
  746. }
  747. /**
  748. \brief Increments the value of the given parameter relatively from the ORIGINAL value.
  749. \note It's a simple sum, so negative value decrements
  750. \param parameter_id \p int The parameter to adjust (enum EmitorParam)
  751. \param value \p float The value to sum
  752. */
  753. override void IncrementParticleParamFromOriginal(int parameter_id, float value )
  754. {
  755. int emitors = GetParticleEmitorCount(this);
  756. for (int i = 0; i < emitors; ++i)
  757. {
  758. float param;
  759. GetParticleParmOriginal(this, i, parameter_id, param);
  760. SetParticleParm(this, i, parameter_id, param + value);
  761. }
  762. }
  763. /**
  764. \brief Increments the value of the given parameter relatively from the CURRENT value.
  765. \note It's a simple sum, so negative value decrements
  766. \param parameter_id \p int The parameter to adjust (enum EmitorParam)
  767. \param value \p float The value to sum
  768. */
  769. override void IncrementParticleParam(int parameter_id, float value )
  770. {
  771. int emitors = GetParticleEmitorCount(this);
  772. for (int i = 0; i < emitors; ++i)
  773. {
  774. float param;
  775. GetParticleParm(this, i, parameter_id, param);
  776. SetParticleParm(this, i, parameter_id, param + value);
  777. }
  778. }
  779. //@}
  780. /** \name Wiggle API
  781. Settings to make the Particle wiggle
  782. */
  783. //@{
  784. /**
  785. \brief Makes the particle change direction by random_angle every random_interval seconds.
  786. \note This does not actually work on Particle with no parent, it should on ParticleSource
  787. \param random_angle \p float Will be the range [-random_angle, random_angle[ to wiggle between
  788. \param random_interval \p float Will be the time range [0, random_interval] to wiggle next time
  789. */
  790. override void SetWiggle(float random_angle, float random_interval)
  791. {
  792. if (random_angle != 0 || random_interval != 0)
  793. {
  794. if (IsWiggling())
  795. {
  796. m_MaxOriWiggle = random_angle;
  797. m_MaxOriInterval = random_interval;
  798. return;
  799. }
  800. // We need the position to be accurate before storing it
  801. Update();
  802. // These are only ever used within the Wiggle API
  803. // To restore the properties after wiggling
  804. // So let's only set them within the Wiggle API c:
  805. m_DefaultPos = GetLocalPosition();
  806. m_DefaultOri = GetLocalYawPitchRoll();
  807. m_DefaultWorldPos = GetWorldPosition();
  808. m_DefaultWorldOri = GetYawPitchRoll();
  809. m_ForceOrientationRelativeToWorld = IsHierarchyPositionOnly();
  810. }
  811. super.SetWiggle(random_angle, random_interval);
  812. }
  813. /**
  814. \brief Stops randomized wiggle
  815. */
  816. override void StopWiggle()
  817. {
  818. bool wiggling = IsWiggling();
  819. super.StopWiggle();
  820. if (wiggling)
  821. {
  822. // Restore pre-wiggle orientation
  823. int flags = ParticlePropertiesFlags.NONE;
  824. if (m_ForceOrientationRelativeToWorld)
  825. flags = ParticlePropertiesFlags.FORCE_WORLD_ROT;
  826. ParticleProperties prop = new ParticleProperties(m_DefaultPos, flags, GetParticleParent(), m_DefaultOri, GetOwner());
  827. ApplyProperties(prop);
  828. }
  829. }
  830. /**
  831. \brief Randomizes a new orientation and applies it
  832. */
  833. override private void RandomizeOrientation()
  834. {
  835. if (ToDelete())
  836. return;
  837. m_WiggleProcessing = true;
  838. if ( !m_RandomizeOri.IsRunning() )
  839. m_RandomizeOri.Run( Math.RandomFloat(0, m_MaxOriInterval) , this, "RandomizeOrientation", null, false);
  840. int flags = ParticlePropertiesFlags.NONE;
  841. if (m_ForceOrientationRelativeToWorld)
  842. flags = ParticlePropertiesFlags.FORCE_WORLD_ROT;
  843. ParticleProperties prop = new ParticleProperties(m_DefaultPos, flags, GetParticleParent(), m_DefaultOri + RandWiggleVector(), GetOwner());
  844. ApplyProperties(prop);
  845. m_WiggleProcessing = false;
  846. }
  847. //@}
  848. /** \name Misc Particle specific helpers
  849. Functionality specific for Particle, so we empty them here
  850. */
  851. //@{
  852. //! Empty
  853. override private void UpdateState() { ErrorEx("Should not be in use on ParticleSource."); }
  854. //! Empty
  855. override private void DestroyParticleEffect() { ErrorEx("Should not be in use on ParticleSource."); }
  856. //! Empty
  857. override private void CreateParticleEffect() { ErrorEx("Should not be in use on ParticleSource."); }
  858. //! Empty
  859. override protected void EOnFrame(IEntity other, float timeSlice) { ErrorEx("Should not be in use on ParticleSource."); }
  860. //! Empty
  861. override private void OnCheckAutoDelete() { ErrorEx("Should not be in use on ParticleSource."); }
  862. //! Empty
  863. override private void OnToDelete() { ErrorEx("Should not be in use on ParticleSource."); }
  864. //@}
  865. }