soundrobj.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/soundrobj.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 1/16/02 10:21a $*
  29. * *
  30. * $Revision:: 4 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #if noWWAUDIO //(gth) removing dependency on wwaudio
  36. #include "soundrobj.h"
  37. #include "audiblesound.h"
  38. #include "sound3d.h"
  39. #include "wwaudio.h"
  40. #include "ffactory.h"
  41. #include "wwfile.h"
  42. #include "chunkio.h"
  43. #include "scene.h"
  44. //////////////////////////////////////////////////////////////////////////////////
  45. // Global variables
  46. //////////////////////////////////////////////////////////////////////////////////
  47. SoundRenderObjLoaderClass _SoundRenderObjLoader;
  48. //////////////////////////////////////////////////////////////////////////////////
  49. //
  50. // SoundRenderObjClass
  51. //
  52. //////////////////////////////////////////////////////////////////////////////////
  53. SoundRenderObjClass::SoundRenderObjClass (void)
  54. : Flags (FLAG_STOP_WHEN_HIDDEN),
  55. Sound (NULL),
  56. IsInitialized (false)
  57. {
  58. return ;
  59. }
  60. //////////////////////////////////////////////////////////////////////////////////
  61. //
  62. // SoundRenderObjClass
  63. //
  64. //////////////////////////////////////////////////////////////////////////////////
  65. SoundRenderObjClass::SoundRenderObjClass (const SoundRenderObjClass &src)
  66. : Flags (FLAG_STOP_WHEN_HIDDEN),
  67. Sound (NULL),
  68. IsInitialized (false)
  69. {
  70. (*this) = src;
  71. return ;
  72. }
  73. //////////////////////////////////////////////////////////////////////////////////
  74. //
  75. // ~SoundRenderObjClass
  76. //
  77. //////////////////////////////////////////////////////////////////////////////////
  78. SoundRenderObjClass::~SoundRenderObjClass (void)
  79. {
  80. //
  81. // Remove the old sound from the world (if necessary)
  82. //
  83. if (Sound != NULL) {
  84. Sound->Attach_To_Object (NULL);
  85. Sound->Remove_From_Scene ();
  86. REF_PTR_RELEASE (Sound);
  87. }
  88. return ;
  89. }
  90. //////////////////////////////////////////////////////////////////////////////////
  91. //
  92. // operator=
  93. //
  94. //////////////////////////////////////////////////////////////////////////////////
  95. const SoundRenderObjClass &
  96. SoundRenderObjClass::operator= (const SoundRenderObjClass &src)
  97. {
  98. //
  99. // Create a definition from the src sound object
  100. //
  101. AudibleSoundDefinitionClass definition;
  102. definition.Initialize_From_Sound (src.Sound);
  103. //
  104. // Create the internal sound object from the definition
  105. //
  106. Set_Sound (&definition);
  107. //
  108. // Copy the other misc settings
  109. //
  110. Name = src.Name;
  111. return *this;
  112. }
  113. //////////////////////////////////////////////////////////////////////////////////
  114. //
  115. // Set_Sound
  116. //
  117. //////////////////////////////////////////////////////////////////////////////////
  118. void
  119. SoundRenderObjClass::Set_Sound (AudibleSoundDefinitionClass *definition)
  120. {
  121. //
  122. // Remove the old sound from the world (if necessary)
  123. //
  124. if (Sound != NULL) {
  125. Sound->Remove_From_Scene ();
  126. REF_PTR_RELEASE (Sound);
  127. }
  128. //
  129. // Create the sound object from its definition
  130. //
  131. if (definition != NULL) {
  132. Sound = (AudibleSoundClass *)definition->Create ();
  133. }
  134. return ;
  135. }
  136. //////////////////////////////////////////////////////////////////////////////////
  137. //
  138. // On_Frame_Update
  139. //
  140. //////////////////////////////////////////////////////////////////////////////////
  141. void
  142. SoundRenderObjClass::On_Frame_Update (void)
  143. {
  144. //
  145. // Stop the sound from playing (if necessary)
  146. //
  147. if ( Sound != NULL &&
  148. Sound->Is_In_Scene () &&
  149. Sound->Is_Playing () == false)
  150. {
  151. Sound->Attach_To_Object (NULL);
  152. Sound->Remove_From_Scene ();
  153. }
  154. return ;
  155. }
  156. //////////////////////////////////////////////////////////////////////////////////
  157. //
  158. // Set_Hidden
  159. //
  160. //////////////////////////////////////////////////////////////////////////////////
  161. void
  162. SoundRenderObjClass::Set_Hidden (int onoff)
  163. {
  164. int before = Is_Not_Hidden_At_All ();
  165. RenderObjClass::Set_Hidden (onoff);
  166. //
  167. // If we've changed state, then update the visibility
  168. //
  169. if (IsInitialized == false || Is_Not_Hidden_At_All () != before) {
  170. IsInitialized = true;
  171. Update_On_Visibilty ();
  172. }
  173. return ;
  174. }
  175. //////////////////////////////////////////////////////////////////////////////////
  176. //
  177. // Set_Visible
  178. //
  179. //////////////////////////////////////////////////////////////////////////////////
  180. void
  181. SoundRenderObjClass::Set_Visible (int onoff)
  182. {
  183. int before = Is_Not_Hidden_At_All ();
  184. RenderObjClass::Set_Visible (onoff);
  185. //
  186. // If we've changed state, then update the visibility
  187. //
  188. if (IsInitialized == false || Is_Not_Hidden_At_All () != before) {
  189. IsInitialized = true;
  190. Update_On_Visibilty ();
  191. }
  192. return ;
  193. }
  194. //////////////////////////////////////////////////////////////////////////////////
  195. //
  196. // Set_Animation_Hidden
  197. //
  198. //////////////////////////////////////////////////////////////////////////////////
  199. void
  200. SoundRenderObjClass::Set_Animation_Hidden (int onoff)
  201. {
  202. int before = Is_Not_Hidden_At_All ();
  203. RenderObjClass::Set_Animation_Hidden (onoff);
  204. //
  205. // If we've changed state, then update the visibility
  206. //
  207. if (IsInitialized == false || Is_Not_Hidden_At_All () != before) {
  208. IsInitialized = true;
  209. Update_On_Visibilty ();
  210. }
  211. return ;
  212. }
  213. //////////////////////////////////////////////////////////////////////////////////
  214. //
  215. // Set_Force_Visible
  216. //
  217. //////////////////////////////////////////////////////////////////////////////////
  218. void
  219. SoundRenderObjClass::Set_Force_Visible (int onoff)
  220. {
  221. int before = Is_Not_Hidden_At_All ();
  222. RenderObjClass::Set_Force_Visible (onoff);
  223. //
  224. // If we've changed state, then update the visibility
  225. //
  226. if (IsInitialized == false || Is_Not_Hidden_At_All () != before) {
  227. IsInitialized = true;
  228. Update_On_Visibilty ();
  229. }
  230. return ;
  231. }
  232. //////////////////////////////////////////////////////////////////////////////////
  233. //
  234. // Update_On_Visibilty
  235. //
  236. //////////////////////////////////////////////////////////////////////////////////
  237. void
  238. SoundRenderObjClass::Update_On_Visibilty (void)
  239. {
  240. if (Sound == NULL) {
  241. return ;
  242. }
  243. //
  244. // Ensure our transform is correct
  245. //
  246. Validate_Transform ();
  247. //
  248. // Either add the sound object to the sound scene
  249. // or remove it from the sound scene depending
  250. // on the visibility state of the render object.
  251. //
  252. if ( Is_Not_Hidden_At_All () &&
  253. Sound->Is_In_Scene () == false &&
  254. Peek_Scene () != NULL)
  255. {
  256. //
  257. // Make sure the sound is properly attached to this render
  258. // object and then add it to the scene
  259. //
  260. Sound->Attach_To_Object (this);
  261. Sound->Add_To_Scene (true);
  262. } else if ((Is_Not_Hidden_At_All () == false) || (Peek_Scene () == NULL)) {
  263. //
  264. // Remove the sound from the scene (it will stop playing)
  265. //
  266. if ((Flags & FLAG_STOP_WHEN_HIDDEN) != 0 || (Peek_Scene () == NULL)) {
  267. Sound->Attach_To_Object (NULL);
  268. Sound->Remove_From_Scene ();
  269. }
  270. }
  271. return ;
  272. }
  273. //////////////////////////////////////////////////////////////////////////////////
  274. //
  275. // Get_Sound
  276. //
  277. //////////////////////////////////////////////////////////////////////////////////
  278. AudibleSoundClass *
  279. SoundRenderObjClass::Get_Sound (void) const
  280. {
  281. if (Sound != NULL) {
  282. Sound->Add_Ref ();
  283. }
  284. return Sound;
  285. }
  286. //////////////////////////////////////////////////////////////////////////////
  287. //
  288. // Set_Flag
  289. //
  290. //////////////////////////////////////////////////////////////////////////////
  291. void
  292. SoundRenderObjClass::Set_Flag (uint32 flag, bool onoff)
  293. {
  294. Flags &= ~flag;
  295. if (onoff) {
  296. Flags |= flag;
  297. }
  298. return ;
  299. }
  300. //////////////////////////////////////////////////////////////////////////////////
  301. //
  302. // Notify_Added
  303. //
  304. //////////////////////////////////////////////////////////////////////////////////
  305. void
  306. SoundRenderObjClass::Notify_Added (SceneClass *scene)
  307. {
  308. RenderObjClass::Notify_Added (scene);
  309. scene->Register (this, SceneClass::ON_FRAME_UPDATE);
  310. Update_On_Visibilty ();
  311. return ;
  312. }
  313. //////////////////////////////////////////////////////////////////////////////////
  314. //
  315. // Notify_Removed
  316. //
  317. //////////////////////////////////////////////////////////////////////////////////
  318. void
  319. SoundRenderObjClass::Notify_Removed (SceneClass *scene)
  320. {
  321. scene->Unregister (this, SceneClass::ON_FRAME_UPDATE);
  322. RenderObjClass::Notify_Removed (scene);
  323. Update_On_Visibilty ();
  324. return ;
  325. }
  326. //////////////////////////////////////////////////////////////////////////////////
  327. //
  328. // Set_Transform
  329. //
  330. //////////////////////////////////////////////////////////////////////////////////
  331. void
  332. SoundRenderObjClass::Set_Transform (const Matrix3D &tm)
  333. {
  334. RenderObjClass::Set_Transform (tm);
  335. if (IsInitialized == false) {
  336. IsInitialized = true;
  337. Update_On_Visibilty ();
  338. }
  339. return ;
  340. }
  341. //////////////////////////////////////////////////////////////////////////////////
  342. //
  343. // Set_Position
  344. //
  345. //////////////////////////////////////////////////////////////////////////////////
  346. void
  347. SoundRenderObjClass::Set_Position (const Vector3 &pos)
  348. {
  349. RenderObjClass::Set_Position (pos);
  350. if (IsInitialized == false) {
  351. IsInitialized = true;
  352. Update_On_Visibilty ();
  353. }
  354. return ;
  355. }
  356. //*********************************************************************************
  357. //
  358. // Start of SoundRenderObjDefClass
  359. //
  360. //*********************************************************************************
  361. //////////////////////////////////////////////////////////////////////////////////
  362. //
  363. // SoundRenderObjDefClass
  364. //
  365. //////////////////////////////////////////////////////////////////////////////////
  366. SoundRenderObjDefClass::SoundRenderObjDefClass (void)
  367. : Version (W3D_CURRENT_SOUNDROBJ_VERSION),
  368. Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN)
  369. {
  370. return ;
  371. }
  372. //////////////////////////////////////////////////////////////////////////////////
  373. //
  374. // SoundRenderObjDefClass
  375. //
  376. //////////////////////////////////////////////////////////////////////////////////
  377. SoundRenderObjDefClass::SoundRenderObjDefClass (SoundRenderObjClass &render_obj)
  378. : Version (W3D_CURRENT_SOUNDROBJ_VERSION),
  379. Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN)
  380. {
  381. Initialize (render_obj);
  382. return ;
  383. }
  384. //////////////////////////////////////////////////////////////////////////////////
  385. //
  386. // SoundRenderObjDefClass
  387. //
  388. //////////////////////////////////////////////////////////////////////////////////
  389. SoundRenderObjDefClass::SoundRenderObjDefClass (const SoundRenderObjDefClass &src)
  390. : Version (W3D_CURRENT_SOUNDROBJ_VERSION),
  391. Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN)
  392. {
  393. (*this) = src;
  394. return ;
  395. }
  396. //////////////////////////////////////////////////////////////////////////////////
  397. //
  398. // ~SoundRenderObjDefClass
  399. //
  400. //////////////////////////////////////////////////////////////////////////////////
  401. SoundRenderObjDefClass::~SoundRenderObjDefClass (void)
  402. {
  403. return ;
  404. }
  405. //////////////////////////////////////////////////////////////////////////////////
  406. //
  407. // operator=
  408. //
  409. //////////////////////////////////////////////////////////////////////////////////
  410. const SoundRenderObjDefClass &
  411. SoundRenderObjDefClass::operator= (const SoundRenderObjDefClass &src)
  412. {
  413. Definition = src.Definition;
  414. Version = src.Version;
  415. Name = src.Name;
  416. return (*this);
  417. }
  418. //////////////////////////////////////////////////////////////////////////////////
  419. //
  420. // Create
  421. //
  422. //////////////////////////////////////////////////////////////////////////////////
  423. RenderObjClass *
  424. SoundRenderObjDefClass::Create (void)
  425. {
  426. //
  427. // Allocate and initialize a new instance
  428. //
  429. SoundRenderObjClass *render_obj = W3DNEW SoundRenderObjClass;
  430. render_obj->Set_Name (Name);
  431. render_obj->Set_Sound (&Definition);
  432. render_obj->Set_Flags (Flags);
  433. return render_obj;
  434. }
  435. //////////////////////////////////////////////////////////////////////////////////
  436. //
  437. // Initialize
  438. //
  439. //////////////////////////////////////////////////////////////////////////////////
  440. void
  441. SoundRenderObjDefClass::Initialize (SoundRenderObjClass &render_obj)
  442. {
  443. //
  444. // Copy the settings from the sound object into our definition
  445. //
  446. Definition.Initialize_From_Sound (render_obj.Peek_Sound ());
  447. //
  448. // Copy the flags from the render object
  449. //
  450. Flags = (SoundRenderObjClass::FLAGS)render_obj.Get_Flags ();
  451. //
  452. // Copy the name
  453. //
  454. Name = render_obj.Get_Name ();
  455. return ;
  456. }
  457. ///////////////////////////////////////////////////////////////////////////////////
  458. //
  459. // Load
  460. //
  461. ///////////////////////////////////////////////////////////////////////////////////
  462. WW3DErrorType
  463. SoundRenderObjDefClass::Load_W3D (ChunkLoadClass &cload)
  464. {
  465. WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED;
  466. //
  467. // Attempt to read the different sections of the definition
  468. //
  469. if ((Read_Header (cload) == WW3D_ERROR_OK) &&
  470. (Read_Definition (cload) == WW3D_ERROR_OK))
  471. {
  472. retval = WW3D_ERROR_OK;
  473. }
  474. return retval;
  475. }
  476. //////////////////////////////////////////////////////////////////////////////////
  477. //
  478. // Save_W3D
  479. //
  480. //////////////////////////////////////////////////////////////////////////////////
  481. WW3DErrorType
  482. SoundRenderObjDefClass::Save_W3D (ChunkSaveClass &csave)
  483. {
  484. WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED;
  485. //
  486. // Begin a chunk that identifies a sound render object
  487. //
  488. if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ) == TRUE) {
  489. //
  490. // Attempt to save the different sections of the aggregate definition
  491. //
  492. if ((Write_Header (csave) == WW3D_ERROR_OK) &&
  493. (Write_Definition (csave) == WW3D_ERROR_OK))
  494. {
  495. retval = WW3D_ERROR_OK;
  496. }
  497. csave.End_Chunk ();
  498. }
  499. return retval;
  500. }
  501. ///////////////////////////////////////////////////////////////////////////////////
  502. //
  503. // Read_Header
  504. //
  505. ///////////////////////////////////////////////////////////////////////////////////
  506. WW3DErrorType
  507. SoundRenderObjDefClass::Read_Header (ChunkLoadClass &cload)
  508. {
  509. WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED;
  510. //
  511. // Is this the header chunk?
  512. //
  513. if (cload.Open_Chunk () &&
  514. (cload.Cur_Chunk_ID () == W3D_CHUNK_SOUNDROBJ_HEADER))
  515. {
  516. //
  517. // Read the header from the chunk
  518. //
  519. W3dSoundRObjHeaderStruct header = { 0 };
  520. if (cload.Read (&header, sizeof (header)) == sizeof (header)) {
  521. //
  522. // Copy the names from the header structure
  523. //
  524. Name = header.Name;
  525. Version = header.Version;
  526. Flags = (SoundRenderObjClass::FLAGS)header.Flags;
  527. retval = WW3D_ERROR_OK;
  528. }
  529. cload.Close_Chunk ();
  530. }
  531. return retval;
  532. }
  533. ///////////////////////////////////////////////////////////////////////////////////
  534. //
  535. // Read_Definition
  536. //
  537. ///////////////////////////////////////////////////////////////////////////////////
  538. WW3DErrorType
  539. SoundRenderObjDefClass::Read_Definition (ChunkLoadClass &cload)
  540. {
  541. WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED;
  542. //
  543. // Is this the right chunk?
  544. //
  545. if (cload.Open_Chunk () &&
  546. (cload.Cur_Chunk_ID () == W3D_CHUNK_SOUNDROBJ_DEFINITION))
  547. {
  548. //
  549. // Ask the definition to load its settings from the chunk
  550. //
  551. if (Definition.Load (cload)) {
  552. retval = WW3D_ERROR_OK;
  553. }
  554. cload.Close_Chunk ();
  555. }
  556. return retval;
  557. }
  558. ///////////////////////////////////////////////////////////////////////////////////
  559. //
  560. // Write_Header
  561. //
  562. ///////////////////////////////////////////////////////////////////////////////////
  563. WW3DErrorType
  564. SoundRenderObjDefClass::Write_Header (ChunkSaveClass &csave)
  565. {
  566. WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED;
  567. //
  568. // Begin a chunk that identifies the aggregate
  569. //
  570. if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ_HEADER) == TRUE) {
  571. //
  572. // Fill the header structure
  573. //
  574. W3dSoundRObjHeaderStruct header = { 0 };
  575. header.Version = W3D_CURRENT_AGGREGATE_VERSION;
  576. header.Flags = Flags;
  577. ::lstrcpyn (header.Name, (const char *)Name, sizeof (header.Name));
  578. header.Name[sizeof (header.Name) - 1] = 0;
  579. //
  580. // Write the header out to the chunk
  581. //
  582. if (csave.Write (&header, sizeof (header)) == sizeof (header)) {
  583. retval = WW3D_ERROR_OK;
  584. }
  585. // End the header chunk
  586. csave.End_Chunk ();
  587. }
  588. return retval;
  589. }
  590. ///////////////////////////////////////////////////////////////////////////////////
  591. //
  592. // Write_Definition
  593. //
  594. ///////////////////////////////////////////////////////////////////////////////////
  595. WW3DErrorType
  596. SoundRenderObjDefClass::Write_Definition (ChunkSaveClass &csave)
  597. {
  598. WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED;
  599. //
  600. // Save the definition to its own chunk
  601. //
  602. if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ_DEFINITION) == TRUE) {
  603. if (Definition.Save (csave)) {
  604. retval = WW3D_ERROR_OK;
  605. }
  606. csave.End_Chunk ();
  607. }
  608. return retval;
  609. }
  610. //*********************************************************************************
  611. //
  612. // Start of SoundRenderObjDefClass
  613. //
  614. //*********************************************************************************
  615. ///////////////////////////////////////////////////////////////////////////////////
  616. //
  617. // Load_W3D
  618. //
  619. ///////////////////////////////////////////////////////////////////////////////////
  620. PrototypeClass *
  621. SoundRenderObjLoaderClass::Load_W3D (ChunkLoadClass &cload)
  622. {
  623. SoundRenderObjPrototypeClass *prototype = NULL;
  624. //
  625. // Create a definition object
  626. //
  627. SoundRenderObjDefClass *definition = W3DNEW SoundRenderObjDefClass;
  628. if (definition != NULL) {
  629. //
  630. // Ask the definition object to load the sound data
  631. //
  632. if (definition->Load_W3D (cload) == WW3D_ERROR_OK) {
  633. //
  634. // Success! Create a prototype from the definition
  635. //
  636. prototype = W3DNEW SoundRenderObjPrototypeClass (definition);
  637. }
  638. REF_PTR_RELEASE (definition);
  639. }
  640. return prototype;
  641. }
  642. #endif // noWWAUDIO