MissionMusic.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. #include "MissionMusic.h"
  2. MissionMusic::Translate MissionMusic::actions[] =
  3. {
  4. {act_play_mission, ConstString("Start mission music")},
  5. {act_play_movie_p, ConstString("Start movie music, pause mission")},
  6. {act_play_movie_s, ConstString("Start movie music, stop mission")},
  7. {act_pause_movie, ConstString("Pause movie music")},
  8. {act_continue_movie, ConstString("Continue movie music")},
  9. {act_play_global, ConstString("Start global music")},
  10. {act_stop_all, ConstString("Stop all channels")}
  11. };
  12. MissionMusic::MissionMusic()
  13. {
  14. Assert(MusicService::ptr);
  15. musicName = null;
  16. action = act_error;
  17. }
  18. MissionMusic::~MissionMusic()
  19. {
  20. MusicService::ptr->StopMusic(s_mission, 0.0f);
  21. MusicService::ptr->StopMusic(s_movie, 0.0f);
  22. }
  23. //Инициализировать объект
  24. bool MissionMusic::Create(MOPReader & reader)
  25. {
  26. action = act_error;
  27. ConstString actStr = reader.Enum();
  28. for(dword i = 0; i < ARRSIZE(actions); i++)
  29. {
  30. if(actStr == actions[i].str)
  31. {
  32. action = (Action)actions[i].id;
  33. break;
  34. }
  35. }
  36. Assert(action != act_error);
  37. musicName = reader.String().c_str();
  38. fadeIn = reader.Float();
  39. fadeOut = reader.Float();
  40. volume = reader.Float();
  41. return true;
  42. }
  43. //Активировать/деактивировать объект
  44. void MissionMusic::Activate(bool isActive)
  45. {
  46. if(EditMode_IsOn()) return;
  47. if(isActive)
  48. {
  49. switch(action)
  50. {
  51. case act_play_mission:
  52. MusicService::ptr->StopMusic(s_movie, fadeOut);
  53. MusicService::ptr->StopMusic(s_global, fadeOut);
  54. if(MusicService::ptr->PlayMusic(s_mission, musicName, volume, fadeIn, fadeOut, false))
  55. {
  56. LogicDebug("Start mission music \"%s\" with fadein time %f, fadeout time %f.", musicName, fadeIn, fadeOut);
  57. }else{
  58. LogicDebugError("Can't start play mission music: \"%s\". Sound not found!", musicName);
  59. }
  60. break;
  61. case act_play_movie_p:
  62. MusicService::ptr->PauseMusic(s_mission, true);
  63. MusicService::ptr->StopMusic(s_global, fadeOut);
  64. MusicService::ptr->PauseMusic(s_movie, false);
  65. if(MusicService::ptr->PlayMusic(s_movie, musicName, volume, fadeIn, fadeOut, false))
  66. {
  67. LogicDebug("Pause mission music. Start movie music \"%s\" with fadein time %f, fadeout time %f.", musicName, fadeIn, fadeOut);
  68. }else{
  69. LogicDebugError("Can't start play movie music: \"%s\". Sound not found!", musicName);
  70. }
  71. break;
  72. case act_play_movie_s:
  73. MusicService::ptr->StopMusic(s_mission, fadeOut);
  74. MusicService::ptr->StopMusic(s_global, fadeOut);
  75. MusicService::ptr->PauseMusic(s_movie, false);
  76. if(MusicService::ptr->PlayMusic(s_movie, musicName, volume, fadeIn, fadeOut, false))
  77. {
  78. LogicDebug("Stop mission music. Start movie music \"%s\" with fadein time %f, fadeout time %f.", musicName, fadeIn, fadeOut);
  79. }else{
  80. LogicDebugError("Can't start play movie music: \"%s\". Sound not found!", musicName);
  81. }
  82. break;
  83. case act_pause_movie:
  84. MusicService::ptr->PauseMusic(s_movie, true);
  85. break;
  86. case act_continue_movie:
  87. MusicService::ptr->PauseMusic(s_movie, false);
  88. break;
  89. case act_play_global:
  90. MusicService::ptr->StopMusic(s_mission, fadeOut);
  91. MusicService::ptr->StopMusic(s_movie, fadeOut);
  92. if(MusicService::ptr->PlayMusic(s_global, musicName, volume, fadeIn, fadeOut, true))
  93. {
  94. LogicDebug("Stop mission music. Start global music \"%s\" with fadein time %f, fadeout time %f.", musicName, fadeIn, fadeOut);
  95. }else{
  96. LogicDebugError("Can't start play global music: \"%s\". Sound not found is global sound bank!", musicName);
  97. }
  98. case act_stop_all:
  99. MusicService::ptr->StopMusic(s_mission, fadeOut);
  100. MusicService::ptr->StopMusic(s_movie, fadeOut);
  101. MusicService::ptr->StopMusic(s_global, fadeOut);
  102. LogicDebug("Stop all music with fadeout time %f.", fadeOut);
  103. break;
  104. }
  105. }else{
  106. LogicDebug("Deactivate do nothing");
  107. }
  108. }
  109. #ifndef MIS_STOP_EDIT_FUNCS
  110. //Инициализировать объект
  111. bool MissionMusic::EditMode_Create(MOPReader & reader)
  112. {
  113. Create(reader);
  114. EditMode_Select(EditMode_IsSelect());
  115. return true;
  116. }
  117. //Инициализировать объект
  118. bool MissionMusic::EditMode_Update(MOPReader & reader)
  119. {
  120. return EditMode_Create(reader);
  121. }
  122. //Выделить объект
  123. void MissionMusic::EditMode_Select(bool isSelect)
  124. {
  125. MissionObject::EditMode_Select(isSelect);
  126. if(EditMode_IsSelect())
  127. {
  128. MusicService::ptr->PlayMusic(s_mission, musicName, volume, fadeIn, fadeOut, false);
  129. }else{
  130. MusicService::ptr->StopMusic(-1, 0.2f);
  131. }
  132. }
  133. //Перевести объект в спящий режим
  134. void MissionMusic::EditMode_Sleep(bool isSleep)
  135. {
  136. MissionObject::EditMode_Sleep(isSleep);
  137. MusicService::ptr->StopMusic(-1, 0.0f);
  138. }
  139. #endif
  140. MOP_BEGINLISTCG(MissionMusic, "Mission music", '1.00', 0x0, "Object present multislot music system in mission", "Effects")
  141. MOP_ENUMBEG("Action")
  142. for(dword i = 0; i < ARRSIZE(MissionMusic::actions); i++)
  143. {
  144. MOP_ENUMELEMENT(MissionMusic::actions[i].str.c_str())
  145. }
  146. MOP_ENUMEND
  147. MOP_ENUM("Action", "Action")
  148. MOP_STRING("Music name", "")
  149. MOP_FLOATEXC("Fadein", 1.0f, 0.0f, 10.0f, "Fade time for starting music in seconds")
  150. MOP_FLOATEXC("Fadeout", 1.0f, 0.0f, 10.0f, "Fade time for current playing music in seconds")
  151. MOP_FLOATEXC("Volume", 1.0f, 0.0f, 1.0f, "Additinal volume control");
  152. MOP_ENDLIST(MissionMusic)
  153. CREATE_SERVICE(MusicService, 1000)
  154. MusicService * MusicService::ptr = null;
  155. MusicService::MusicService()
  156. {
  157. Assert(!ptr);
  158. ptr = this;
  159. memset(slots, 0, sizeof(slots));
  160. }
  161. MusicService::~MusicService()
  162. {
  163. for(dword i = 0; i < MissionMusic::max_slots_count; i++)
  164. {
  165. Slot & slot = slots[i];
  166. RELEASE(slot.music);
  167. RELEASE(slot.fadeoutPlay);
  168. RELEASE(slot.musicScene);
  169. }
  170. Assert(ptr == this);
  171. ptr = null;
  172. }
  173. bool MusicService::Init()
  174. {
  175. ISoundService * ss = (ISoundService *)api->GetService("SoundService");
  176. if(!ss)
  177. {
  178. api->Storage().SetString("system.error", "MusicService not create, because SoundServece not created.");
  179. return false;
  180. }
  181. static const char * names[] =
  182. {
  183. "Mission music", //0
  184. "Movie music", //1
  185. "Global music" //2
  186. };
  187. memset(slots, 0, sizeof(slots));
  188. slots[MissionMusic::s_mission].name = names[0];
  189. slots[MissionMusic::s_movie].name = names[1];
  190. slots[MissionMusic::s_global].name = names[2];
  191. for(dword i = 0; i < MissionMusic::max_slots_count; i++)
  192. {
  193. Assert(names[i]);
  194. Slot & slot = slots[i];
  195. slot.musicScene = ss->CreateScene(names[i], _FL_);
  196. Assert(slot.musicScene);
  197. }
  198. api->SetEndFrameLevel(this, Core_DefaultExecuteLevel + 1);
  199. return true;
  200. }
  201. void MusicService::EndFrame(float dltTime)
  202. {
  203. for(dword i = 0; i < MissionMusic::max_slots_count; i++)
  204. {
  205. Slot & slot = slots[i];
  206. if(slot.music)
  207. {
  208. if(!slot.music->IsPlay())
  209. {
  210. slot.music->Release();
  211. slot.music = null;
  212. }
  213. }
  214. if(slot.fadeoutPlay)
  215. {
  216. if(!slot.fadeoutPlay->IsPlay())
  217. {
  218. slot.fadeoutPlay->Release();
  219. slot.fadeoutPlay = null;
  220. }
  221. }
  222. }
  223. }
  224. //Начать играть музыку
  225. bool MusicService::PlayMusic(long slotIndex, const char * name, float volume, float fadeInTime, float fadeOutTime, bool isCheckGlobal)
  226. {
  227. //Текущий слот
  228. Slot & playSlot = slots[slotIndex];
  229. //Если текущее состояние слота в паузе, не доигрываем хвост
  230. if(playSlot.musicScene->IsPause())
  231. {
  232. if(playSlot.fadeoutPlay)
  233. {
  234. playSlot.fadeoutPlay->Release();
  235. playSlot.fadeoutPlay = null;
  236. }
  237. //Музыка не изменилась, продолжаем играть текущую
  238. playSlot.musicScene->Resume();
  239. }
  240. //Проверяем текущую музыку на совпадение
  241. if(playSlot.music)
  242. {
  243. if(string::IsEqual(name, playSlot.music->GetName()))
  244. {
  245. return true;
  246. }
  247. }
  248. //Музыка меняеться, надо ставить текущую на фейд
  249. StopMusic(slotIndex, fadeOutTime);
  250. //Создаём новую музыку и начинаем проигрывать
  251. Assert(playSlot.musicScene);
  252. playSlot.music = playSlot.musicScene->Create(name, _FL_, false, false);
  253. if(!playSlot.music)
  254. {
  255. return false;
  256. }
  257. playSlot.music->SetVolume(volume);
  258. if(fadeInTime > 1e-3f)
  259. {
  260. playSlot.music->FadeIn(fadeInTime);
  261. }else{
  262. playSlot.music->Play();
  263. }
  264. return true;
  265. }
  266. //Пауза слота
  267. void MusicService::PauseMusic(long slotIndex, bool isPause)
  268. {
  269. //Текущий слот
  270. Slot & playSlot = slots[slotIndex];
  271. if(playSlot.musicScene->IsPause() == isPause)
  272. {
  273. //Ничего не меняеться
  274. return;
  275. }
  276. if(isPause)
  277. {
  278. playSlot.musicScene->Pause();
  279. RELEASE(playSlot.fadeoutPlay);
  280. }else{
  281. playSlot.musicScene->Resume();
  282. }
  283. }
  284. //Остановить музыку
  285. void MusicService::StopMusic(long slotIndex, float fadeOutTime)
  286. {
  287. if(slotIndex >= 0)
  288. {
  289. StopSlot(slotIndex, fadeOutTime);
  290. }else{
  291. for(dword i = 0; i < MissionMusic::max_slots_count; i++)
  292. {
  293. StopSlot(i, fadeOutTime);
  294. }
  295. }
  296. }
  297. void MusicService::StopSlot(long slotIndex, float fadeOutTime)
  298. {
  299. //Текущий слот
  300. Slot & playSlot = slots[slotIndex];
  301. //Мгновенная остановка
  302. if(fadeOutTime < 1e-3f)
  303. {
  304. if(playSlot.music)
  305. {
  306. playSlot.music->Release();
  307. playSlot.music = null;
  308. }
  309. if(playSlot.fadeoutPlay)
  310. {
  311. playSlot.fadeoutPlay->Release();
  312. playSlot.fadeoutPlay = null;
  313. }
  314. return;
  315. }
  316. //Отправляем текущую музыку на доигрывание
  317. if(playSlot.music)
  318. {
  319. if(playSlot.fadeoutPlay)
  320. {
  321. playSlot.fadeoutPlay->Release();
  322. playSlot.fadeoutPlay = null;
  323. }
  324. playSlot.fadeoutPlay = playSlot.music;
  325. playSlot.fadeoutPlay->FadeOut(fadeOutTime);
  326. playSlot.music = null;
  327. }
  328. if(playSlot.fadeoutPlay)
  329. {
  330. playSlot.fadeoutPlay->FadeOut(fadeOutTime);
  331. }
  332. }