effectparticle.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /**
  2. \brief Wrapper class for managing particles through SEffectManager
  3. */
  4. class EffectParticle : Effect
  5. {
  6. //! The main Particle effect that this Effect wrapper manages
  7. protected Particle m_ParticleObj;
  8. /** \name Generic data
  9. * Generic data for the particle
  10. */
  11. //@{
  12. //! The ID in the ParticleList to create Particle from
  13. protected int m_ParticleID;
  14. //! Orientation set by SetOrientation
  15. protected vector m_Orientation;
  16. //! Orientation setting to be used by the effect when the Effect starts
  17. protected bool m_ForceRotationRelativeToWorld;
  18. //@}
  19. /** \name DEPRECATED
  20. * Simply exist because of backwards compatibility, might have never been used
  21. */
  22. //@{
  23. protected vector m_ParticleOrientation;
  24. protected Object m_Object;
  25. //@}
  26. /**
  27. \brief ctor
  28. */
  29. void EffectParticle()
  30. {
  31. }
  32. /**
  33. \brief dtor
  34. */
  35. void ~EffectParticle()
  36. {
  37. }
  38. /**
  39. \brief init
  40. */
  41. override void InitEffect()
  42. {
  43. super.InitEffect();
  44. // Would be neat, but since particles are often already playing
  45. // BEFORE they are even registered as the particle for the Effect
  46. // Better to just keep that one I guess..
  47. // Event_OnStarted.Remove(Event_OnEffectStarted);
  48. // Will be called by the particle events
  49. Event_OnStopped.Remove(Event_OnEffectEnded);
  50. }
  51. /**
  52. \brief Override when getting debug information
  53. */
  54. override string GetDebugName()
  55. {
  56. string identifier;
  57. if (GetParticle())
  58. {
  59. identifier = GetParticle().GetDebugNameNative();
  60. }
  61. else
  62. {
  63. identifier = "NO_PARTICLE";
  64. }
  65. return string.Format("%1:%2:%3", super.GetDebugName(), m_ParticleID, identifier);
  66. }
  67. /**
  68. \brief Validation whether an effect truly started playing or if the Effect should stop as none is present
  69. \note Override this when inheriting to create own validation check
  70. \note Is called from Event_OnStarted invoker after Event_OnStarted has been performed
  71. */
  72. override void ValidateStart()
  73. {
  74. if (!GetParticle())
  75. {
  76. //ErrorEx(string.Format("No Particle started playing, stopping EffectParticle: %1", GetDebugName()), ErrorExSeverity.WARNING);
  77. Stop();
  78. }
  79. }
  80. /** \name EffectType
  81. Information about what type of effect the Effect is, without the need for casting
  82. */
  83. //@{
  84. /**
  85. \brief Get what type of effect the Effect is
  86. \return \p EffectType What type of effect the Effect is
  87. */
  88. override EffectType GetEffectType()
  89. {
  90. return EffectType.PARTICLE;
  91. }
  92. /**
  93. \brief Check whether the Effect is EffectParticle without casting
  94. \return \p bool Whether the Effect is EffectParticle
  95. */
  96. override bool IsParticle()
  97. {
  98. return true;
  99. }
  100. //@}
  101. /** \name Main particle
  102. Set or get the main particle which this Effect will manage
  103. */
  104. //@{
  105. /**
  106. \brief Sets the main particle which this Effect will manage
  107. \param p \p Particle Main particle which this Effect will manage
  108. */
  109. void SetParticle(Particle p)
  110. {
  111. // Unregister the events on the old
  112. if (m_ParticleObj)
  113. {
  114. ParticleEvents ope = m_ParticleObj.GetEvents();
  115. ope.Event_OnParticleStart.Remove(Event_OnEffectStarted);
  116. ope.Event_OnParticleStop.Remove(Event_OnEffectEnded);
  117. }
  118. // Assign the new main Particle
  119. m_ParticleObj = p;
  120. // Register the events on the new
  121. if (m_ParticleObj)
  122. {
  123. ParticleEvents npe = m_ParticleObj.GetEvents();
  124. npe.Event_OnParticleStart.Insert(Event_OnEffectStarted);
  125. // We will use Stop instead of End, as old particles were destroyed when they stopped
  126. // And this system kinda relies on that
  127. npe.Event_OnParticleStop.Insert(Event_OnEffectEnded);
  128. }
  129. }
  130. /**
  131. \brief Gets the main particle which this Effect is managing
  132. \return \p Particle Main particle which this Effect is managing
  133. */
  134. Particle GetParticle()
  135. {
  136. return m_ParticleObj;
  137. }
  138. //@}
  139. /** \name Playback
  140. * Methods to Play/Stop Effect
  141. * Generally, SEffectManager.Play methods are used instead of Start
  142. */
  143. //@{
  144. /**
  145. \brief Plays all elements this effect consists of
  146. \note Is called by SEffectManager.Play methods
  147. */
  148. override void Start()
  149. {
  150. if (m_ParticleID > 0)
  151. {
  152. vector pos = GetPosition();
  153. vector ori = GetOrientation();
  154. if (m_ParentObject)
  155. {
  156. pos = GetLocalPosition();
  157. ori = GetAttachedLocalOri();
  158. }
  159. SetParticle(ParticleManager.GetInstance().CreateParticle(m_ParticleID, pos, true, GetParent(), ori, IsParticleRotationRelativeToWorld()));
  160. }
  161. super.Start();
  162. }
  163. /**
  164. \brief Stops all elements this effect consists of
  165. \note Alternatively use SEffectManager.Stop( effect_id )
  166. */
  167. override void Stop()
  168. {
  169. if ( GetParticle() )
  170. {
  171. GetParticle().Stop();
  172. SetParticle(null);
  173. }
  174. super.Stop();
  175. }
  176. //@}
  177. /** \name Attach
  178. Helper methods for attaching to prent
  179. */
  180. //@{
  181. /**
  182. \brief Read Particle.AddAsChild
  183. */
  184. void AttachTo(Object obj, vector local_pos = "0 0 0", vector local_ori = "0 0 0", bool force_rotation_to_world = false)
  185. {
  186. // Update the cached variables...
  187. SetParent(obj);
  188. SetLocalPosition(local_pos);
  189. SetAttachedLocalOri(local_ori);
  190. ForceParticleRotationRelativeToWorld(force_rotation_to_world);
  191. // Now attach it
  192. AddAsChild(obj, local_pos, local_ori, force_rotation_to_world);
  193. }
  194. /**
  195. \brief Helper method to attach to parent using stored settings
  196. */
  197. void ReAttach()
  198. {
  199. // Skip the updating, as we are going to reuse what was set before
  200. AddAsChild( GetParent(), GetLocalPosition(), GetAttachedLocalOri(), IsParticleRotationRelativeToWorld());
  201. }
  202. /**
  203. \brief Helper method to attach to parent
  204. */
  205. protected void AddAsChild(Object obj, vector local_pos, vector local_ori, bool force_rotation_to_world)
  206. {
  207. Particle p = GetParticle();
  208. if (p)
  209. {
  210. p.AddAsChild(obj, local_pos, local_ori, force_rotation_to_world);
  211. }
  212. }
  213. //@}
  214. /** \name Events
  215. Various events that can be overriden for custom behaviour
  216. */
  217. //@{
  218. /**
  219. \brief Event which just simply exists (DEPRECATED)
  220. \warning Never called or used
  221. \note Use Event_OnStarted instead
  222. */
  223. void Event_OnPlayStart()
  224. {
  225. }
  226. /**
  227. \brief Event which just simply exists (DEPRECATED)
  228. \warning Never called or used
  229. \note Use Event_OnStarted instead
  230. */
  231. void Event_OnPlayStarted()
  232. {
  233. }
  234. //@}
  235. /** \name Generic API
  236. Setters and getters for generic data and properties
  237. */
  238. //@{
  239. /**
  240. \brief Sets the id of the particle to be used
  241. \note Only changes the cached variable, for immediate, use SetCurrentParticleID
  242. \param id \p int Particle ID registered in ParticleList
  243. */
  244. void SetParticleID( int id )
  245. {
  246. m_ParticleID = id;
  247. }
  248. /**
  249. \brief Gets the id of the particle to be used
  250. \warning Only gets the cached variable, for immediate effect use GetCurrent variant
  251. \return \p int Particle ID registered in ParticleList
  252. */
  253. int GetParticleID()
  254. {
  255. return m_ParticleID;
  256. }
  257. /**
  258. \brief Sets the id of the particle to be used
  259. \note Particle will not update immediately, but ParticleSource will
  260. \param id \p int Particle ID registered in ParticleList
  261. */
  262. void SetCurrentParticleID( int id )
  263. {
  264. m_ParticleID = id;
  265. Particle p = GetParticle();
  266. if (p)
  267. {
  268. p.SetSource(id);
  269. }
  270. }
  271. /**
  272. \brief Gets the current id of the managed Particle
  273. \return \p int Particle ID registered in ParticleList
  274. */
  275. int GetCurrentParticleID()
  276. {
  277. Particle p = GetParticle();
  278. if (p)
  279. {
  280. return p.GetParticleID();
  281. }
  282. else
  283. {
  284. return ParticleList.INVALID;
  285. }
  286. }
  287. /**
  288. \brief Set current parent of the managed Particle
  289. \param parent_obj \p Object The parent for the Particle
  290. \param updateCached \p bool Whether to update the cached variable
  291. */
  292. override void SetCurrentParent( Object parent_obj, bool updateCached = true )
  293. {
  294. super.SetCurrentParent(parent_obj, updateCached);
  295. ReAttach();
  296. }
  297. /**
  298. \brief Get the current parent of the managed Particle
  299. \return \p Object The currrent parent of the Particle
  300. */
  301. override Object GetCurrentParent()
  302. {
  303. Particle p = GetParticle();
  304. if (p)
  305. return Object.Cast(p.GetParent());
  306. else
  307. return super.GetParent();
  308. }
  309. /**
  310. \brief Set the current world position of the managed Particle
  311. \param pos \p vector The current world position for the Particle
  312. \param updateCached \p bool Whether to update the cached variable
  313. */
  314. override void SetCurrentPosition( vector pos, bool updateCached = true )
  315. {
  316. super.SetCurrentPosition(pos, updateCached);
  317. Particle p = GetParticle();
  318. if (p)
  319. p.SetPosition(pos);
  320. }
  321. /**
  322. \brief Get the current world position of the managed Particle
  323. \return \p vector The current world position of the managed Particle
  324. */
  325. override vector GetCurrentPosition()
  326. {
  327. Particle p = GetParticle();
  328. if (p)
  329. return p.GetPosition();
  330. else
  331. return super.GetPosition();
  332. }
  333. /**
  334. \brief Set the current local position of the managed Particle
  335. \param pos \p vector The current local position for the managed Particle
  336. \param updateCached \p bool Whether to update the cached variable
  337. */
  338. override void SetCurrentLocalPosition( vector pos, bool updateCached = true )
  339. {
  340. super.SetCurrentLocalPosition(pos, updateCached);
  341. Particle p = GetParticle();
  342. if (p)
  343. {
  344. Object parent = GetParent();
  345. if (parent)
  346. ReAttach();
  347. else
  348. p.SetPosition(pos);
  349. }
  350. }
  351. /**
  352. \brief Get the current local position of the managed Particle
  353. \return \p vector The current local position of the managed Particle
  354. */
  355. override vector GetCurrentLocalPosition()
  356. {
  357. Particle p = GetParticle();
  358. if (p)
  359. {
  360. Object parent = GetParent();
  361. if (parent)
  362. return parent.WorldToModel(p.GetPosition());
  363. else
  364. return p.GetPosition();
  365. }
  366. else
  367. return super.GetLocalPosition();
  368. }
  369. /**
  370. \brief Set orientation of the EffectParticle
  371. \warning Only sets the cached variable, for immediate effect use SetCurrent variant
  372. \param ori \p vector Orientation in degrees (yaw, pitch, roll)
  373. */
  374. void SetOrientation( vector ori )
  375. {
  376. m_Orientation = ori;
  377. }
  378. /**
  379. \brief Get the orientation of the EffectParticle
  380. \warning Only gets the cached variable, for immediate effect use GetCurrent variant
  381. \return \p vector The orientation of EffectParticle
  382. */
  383. vector GetOrientation()
  384. {
  385. return m_Orientation;
  386. }
  387. /**
  388. \brief Set the current orientation of the managed Particle
  389. \param ori \p vector Orientation in degrees (yaw, pitch, roll)
  390. */
  391. void SetCurrentOrientation( vector ori, bool updateCached = true )
  392. {
  393. if ( updateCached)
  394. SetOrientation(ori);
  395. Particle p = GetParticle();
  396. if (p)
  397. p.SetOrientation(ori);
  398. }
  399. /**
  400. \brief Get the current orientation of the managed Particle
  401. \return \p vector The current orientation of the managed Particle
  402. */
  403. vector GetCurrentOrientation()
  404. {
  405. Particle p = GetParticle();
  406. if (p)
  407. return p.GetOrientation();
  408. else
  409. return vector.Zero;
  410. }
  411. /**
  412. \brief Set orientation setting to be used by the effect when the Effect starts
  413. \warning Only caches it into a variable to be used by Start, does not live update when called afterwards
  414. \note There is no way to update this immediately
  415. \param state \p bool Whether to keep WS orientation when attaching it to parent
  416. */
  417. void ForceParticleRotationRelativeToWorld(bool state)
  418. {
  419. m_ForceRotationRelativeToWorld = state;
  420. }
  421. /**
  422. \brief Get the orientation setting to be used by the effect when the Effect starts
  423. \warning Only gets the cached variable, for immediate effect use IsParticleCurrentRotationRelativeToWorld
  424. \return \p bool Whether to keep WS orientation when attaching it to parent
  425. */
  426. bool IsParticleRotationRelativeToWorld()
  427. {
  428. Particle p = GetParticle();
  429. if (p)
  430. return p.IsHierarchyPositionOnly();
  431. else
  432. return m_ForceRotationRelativeToWorld;
  433. }
  434. /**
  435. \brief Get the current orientation setting to be used by the managed Particle
  436. \return \p bool Whether the managed Particle is only updating position from parent
  437. */
  438. bool IsParticleCurrentRotationRelativeToWorld()
  439. {
  440. Particle p = GetParticle();
  441. if (p)
  442. return p.IsHierarchyPositionOnly();
  443. else
  444. return false;
  445. }
  446. //@}
  447. /** \name DEPRECATED
  448. Methods which exist for backwards compatibility and are no longer in use or have never been in use
  449. */
  450. //@{
  451. /**
  452. \brief Was never called and probably should never be called
  453. \warning Emptied the functionality as it is relatively unsafe...
  454. */
  455. void CheckLifeSpan()
  456. {
  457. /*
  458. if ( !m_ParticleObj )
  459. {
  460. delete this;
  461. }
  462. OnCheckUpdate();
  463. */
  464. }
  465. void SetDecalOwner(Object o)
  466. {
  467. m_Object = o;
  468. }
  469. //@}
  470. }