afxEA_Sound.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  2. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  3. // Copyright (C) 2015 Faust Logic, Inc.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //
  23. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  24. #include <typeinfo>
  25. #include "afx/arcaneFX.h"
  26. #include "sfx/sfxSystem.h"
  27. #include "sfx/sfxSource.h"
  28. #include "sfx/sfxProfile.h"
  29. #include "afx/afxEffectDefs.h"
  30. #include "afx/afxEffectWrapper.h"
  31. #include "afx/afxChoreographer.h"
  32. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  33. // afxEA_Sound
  34. class afxEA_Sound : public afxEffectWrapper
  35. {
  36. typedef afxEffectWrapper Parent;
  37. SFXProfile* sound_prof;
  38. SFXDescription* sound_desc;
  39. SFXSource* sound_handle;
  40. void do_runtime_substitutions();
  41. public:
  42. /*C*/ afxEA_Sound();
  43. /*D*/ ~afxEA_Sound();
  44. virtual void ea_set_datablock(SimDataBlock*);
  45. virtual bool ea_start();
  46. virtual bool ea_update(F32 dt);
  47. virtual void ea_finish(bool was_stopped);
  48. virtual bool ea_is_enabled() { return true; }
  49. virtual void onDeleteNotify(SimObject*);
  50. };
  51. //~~~~~~~~~~~~~~~~~~~~//
  52. afxEA_Sound::afxEA_Sound()
  53. {
  54. sound_prof = 0;
  55. sound_desc = 0;
  56. sound_handle = 0;
  57. }
  58. afxEA_Sound::~afxEA_Sound()
  59. {
  60. if (sound_prof && sound_prof->isTempClone())
  61. delete sound_prof;
  62. sound_prof = 0;
  63. sound_desc = 0;
  64. sound_handle = 0;
  65. }
  66. void afxEA_Sound::ea_set_datablock(SimDataBlock* db)
  67. {
  68. sound_prof = dynamic_cast<SFXProfile*>(db);
  69. if (sound_prof)
  70. sound_desc = sound_prof->getDescription();
  71. }
  72. bool afxEA_Sound::ea_start()
  73. {
  74. if (!sound_prof)
  75. {
  76. Con::errorf("afxEA_Sound::ea_start() -- missing or incompatible AudioProfile.");
  77. return false;
  78. }
  79. if (!sound_desc)
  80. {
  81. Con::errorf("afxEA_Sound::ea_start() -- missing or incompatible AudioDescriptor.");
  82. return false;
  83. }
  84. do_runtime_substitutions();
  85. return true;
  86. }
  87. bool afxEA_Sound::ea_update(F32 dt)
  88. {
  89. if (!sound_handle)
  90. {
  91. sound_handle = SFX->createSource(sound_prof, &mUpdated_xfm, 0);
  92. if (sound_handle)
  93. sound_handle->play();
  94. }
  95. if (sound_handle)
  96. {
  97. sound_handle->setTransform(mUpdated_xfm);
  98. sound_handle->setVolume((mIn_scope) ? mUpdated_scale.x*mFade_value : 0.0f);
  99. deleteNotify(sound_handle);
  100. }
  101. return true;
  102. }
  103. void afxEA_Sound::ea_finish(bool was_stopped)
  104. {
  105. if (sound_handle)
  106. {
  107. sound_handle->stop();
  108. SFX_DELETE(sound_handle);
  109. }
  110. }
  111. void afxEA_Sound::do_runtime_substitutions()
  112. {
  113. sound_prof = sound_prof->cloneAndPerformSubstitutions(mChoreographer, mGroup_index);
  114. sound_desc = sound_prof->getDescription();
  115. }
  116. void afxEA_Sound::onDeleteNotify(SimObject* obj)
  117. {
  118. if (sound_handle == dynamic_cast<SFXSource*>(obj))
  119. sound_handle = 0;
  120. Parent::onDeleteNotify(obj);
  121. }
  122. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  123. class afxEA_SoundDesc : public afxEffectAdapterDesc, public afxEffectDefs
  124. {
  125. static afxEA_SoundDesc mDesc;
  126. public:
  127. virtual bool testEffectType(const SimDataBlock*) const;
  128. virtual bool requiresStop(const afxEffectWrapperData*, const afxEffectTimingData&) const;
  129. virtual bool runsOnServer(const afxEffectWrapperData*) const { return false; }
  130. virtual bool runsOnClient(const afxEffectWrapperData*) const { return true; }
  131. virtual void prepEffect(afxEffectWrapperData*) const;
  132. virtual afxEffectWrapper* create() const { return new afxEA_Sound; }
  133. };
  134. afxEA_SoundDesc afxEA_SoundDesc::mDesc;
  135. bool afxEA_SoundDesc::testEffectType(const SimDataBlock* db) const
  136. {
  137. // dynamic cast used here so that both SFXProfile and AudioProfile match
  138. return (dynamic_cast<const SFXProfile*>(db) != 0);
  139. }
  140. bool afxEA_SoundDesc::requiresStop(const afxEffectWrapperData* ew, const afxEffectTimingData& timing) const
  141. {
  142. SFXDescription* desc = ((SFXProfile*)ew->effect_data)->getDescription();
  143. return (desc && desc->mIsLooping) ? (timing.lifetime < 0) : false;
  144. }
  145. void afxEA_SoundDesc::prepEffect(afxEffectWrapperData* ew) const
  146. {
  147. if (ew->ewd_timing.lifetime < 0)
  148. {
  149. SFXProfile* snd = (SFXProfile*) ew->effect_data;
  150. SFXDescription* desc = snd->getDescription();
  151. if (desc && !desc->mIsLooping)
  152. {
  153. static bool test_for_audio = true;
  154. static bool can_get_audio_len = false;
  155. if (test_for_audio)
  156. {
  157. can_get_audio_len = true;
  158. test_for_audio = false;
  159. }
  160. if (can_get_audio_len)
  161. {
  162. SFXResource* sfx_rsrc = snd->getResource();
  163. if (sfx_rsrc)
  164. {
  165. ew->ewd_timing.lifetime = 0.001f*sfx_rsrc->getDuration();
  166. //Con::printf("SFX (%s) duration=%g", snd->mFilename, timing.lifetime);
  167. }
  168. }
  169. else
  170. {
  171. ew->ewd_timing.lifetime = 0;
  172. Con::printf("afxEA_SoundDesc::prepEffect() -- cannot get audio length from sound file.");
  173. }
  174. }
  175. }
  176. }
  177. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//