| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : WWAudio *
- * *
- * $Archive:: /Commando/Code/WWAudio/SoundSceneObj.cpp $*
- * *
- * $Modtime:: 11/02/01 11:58a $*
- * *
- * $Revision:: 16 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "SoundSceneObj.h"
- #include "camera.h"
- #include "rendobj.h"
- #include "persistfactory.h"
- #include "SoundChunkIDs.h"
- #include "utils.h"
- //////////////////////////////////////////////////////////////////////////////////
- // Save/Load constants
- //////////////////////////////////////////////////////////////////////////////////
- enum
- {
- CHUNKID_VARIABLES = 0x03270459,
- CHUNKID_BASE_CLASS
- };
- enum
- {
- VARID_ATTACHED_OBJ = 0x01,
- VARID_ATTACHED_BONE,
- VARID_USER_DATA,
- VARID_USER_OBJ,
- VARID_ID
- };
- //////////////////////////////////////////////////////////////////////////////////
- // Static member initialization
- //////////////////////////////////////////////////////////////////////////////////
- DynamicVectorClass<SoundSceneObjClass *> SoundSceneObjClass::m_GlobalSoundList;
- uint32 SoundSceneObjClass::m_NextAvailableID = SOUND_OBJ_START_ID;
- CriticalSectionClass SoundSceneObjClass::m_IDListMutex;
- //////////////////////////////////////////////////////////////////////////////////
- // Mutex managment
- //////////////////////////////////////////////////////////////////////////////////
- /*
- class HandleMgrClass
- {
- public:
- HandleMgrClass (void) { SoundSceneObjClass::m_IDListMutex = ::CreateMutex (NULL, FALSE, NULL); }
- ~HandleMgrClass (void) { ::CloseHandle (SoundSceneObjClass::m_IDListMutex); }
- };
- HandleMgrClass _GlobalMutexHandleMgr;
- */
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // SoundSceneObjClass
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- SoundSceneObjClass::SoundSceneObjClass (void)
- : m_Scene (NULL),
- m_PhysWrapper (NULL),
- m_pCallback (NULL),
- m_AttachedObject (NULL),
- m_UserData (0),
- m_UserObj (NULL),
- m_ID (SOUND_OBJ_DEFAULT_ID),
- m_RegisteredEvents (AudioCallbackClass::EVENT_NONE)
- {
- m_ID = m_NextAvailableID ++;
- Register_Sound_Object (this);
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // SoundSceneObjClass
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- SoundSceneObjClass::SoundSceneObjClass (const SoundSceneObjClass &src)
- : m_Scene (NULL),
- m_PhysWrapper (NULL),
- m_pCallback (NULL),
- m_AttachedObject (NULL),
- m_UserData (0),
- m_UserObj (NULL),
- m_ID (SOUND_OBJ_DEFAULT_ID),
- m_RegisteredEvents (AudioCallbackClass::EVENT_NONE)
- {
- m_ID = m_NextAvailableID ++;
- (*this) = src;
- Register_Sound_Object (this);
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // ~SoundSceneObjClass
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- SoundSceneObjClass::~SoundSceneObjClass (void)
- {
- Register_Callback (AudioCallbackClass::EVENT_NONE, NULL);
- REF_PTR_RELEASE (m_UserObj);
- REF_PTR_RELEASE (m_AttachedObject);
- Unregister_Sound_Object (this);
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // operator=
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- const SoundSceneObjClass &
- SoundSceneObjClass::operator= (const SoundSceneObjClass &src)
- {
- m_Scene = src.m_Scene;
- m_pCallback = src.m_pCallback;
- m_RegisteredEvents = src.m_RegisteredEvents;
- Attach_To_Object (src.m_AttachedObject, src.m_AttachedBone);
-
- PersistClass::operator= ((const PersistClass &)src);
- return (*this);
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Attach_To_Object
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- SoundSceneObjClass::Attach_To_Object
- (
- RenderObjClass * render_obj,
- const char * bone_name
- )
- {
- REF_PTR_SET (m_AttachedObject, render_obj);
- if (m_AttachedObject != NULL && bone_name != NULL) {
- m_AttachedBone = m_AttachedObject->Get_Bone_Index (bone_name);
- } else {
- m_AttachedBone = -1;
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Attach_To_Object
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- SoundSceneObjClass::Attach_To_Object
- (
- RenderObjClass * render_obj,
- int bone_index
- )
- {
- if (m_AttachedObject != render_obj || m_AttachedBone != bone_index) {
-
- //
- // Record the attachment
- //
- REF_PTR_SET (m_AttachedObject, render_obj);
- m_AttachedBone = bone_index;
- //
- // Update the transform
- //
- Apply_Auto_Position ();
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Apply_Auto_Position
- //
- //////////////////////////////////////////////////////////////////////////////
- void
- SoundSceneObjClass::Apply_Auto_Position (void)
- {
- // If the sound is attached to an object, then update its transform
- // based on this link.
- if (m_AttachedObject != NULL) {
-
- // Determine which transform to use
- Matrix3D transform (1);
- if (m_AttachedBone >= 0) {
- transform = m_AttachedObject->Get_Bone_Transform (m_AttachedBone);
- } else {
- transform = m_AttachedObject->Get_Transform ();
-
- //
- // Convert the camera's transform to an object transform
- //
- if (m_AttachedObject->Class_ID () == RenderObjClass::CLASSID_CAMERA) {
- Matrix3D cam_to_world (Vector3 (0, 0, -1), Vector3 (-1, 0, 0), Vector3 (0, 1, 0), Vector3 (0, 0, 0));
- transform = transform * cam_to_world;
- }
- }
- // Update the sound's transform
- Set_Transform (transform);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Save
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- SoundSceneObjClass::Save (ChunkSaveClass &csave)
- {
- csave.Begin_Chunk (CHUNKID_BASE_CLASS);
- PersistClass::Save (csave);
- csave.End_Chunk ();
- csave.Begin_Chunk (CHUNKID_VARIABLES);
- WRITE_MICRO_CHUNK (csave, VARID_ATTACHED_OBJ, m_AttachedObject);
- WRITE_MICRO_CHUNK (csave, VARID_ATTACHED_BONE, m_AttachedBone);
- WRITE_MICRO_CHUNK (csave, VARID_USER_DATA, m_UserData);
- WRITE_MICRO_CHUNK (csave, VARID_USER_OBJ, m_UserObj);
- WRITE_MICRO_CHUNK (csave, VARID_ID, m_ID);
- csave.End_Chunk ();
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Load
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- SoundSceneObjClass::Load (ChunkLoadClass &cload)
- {
- uint32 id = SOUND_OBJ_DEFAULT_ID;
- while (cload.Open_Chunk ()) {
- switch (cload.Cur_Chunk_ID ()) {
- case CHUNKID_BASE_CLASS:
- PersistClass::Load (cload);
- break;
- case CHUNKID_VARIABLES:
- {
- //
- // Read all the variables from their micro-chunks
- //
- while (cload.Open_Micro_Chunk ()) {
- switch (cload.Cur_Micro_Chunk_ID ()) {
- READ_MICRO_CHUNK (cload, VARID_ATTACHED_OBJ, m_AttachedObject);
- READ_MICRO_CHUNK (cload, VARID_ATTACHED_BONE, m_AttachedBone);
- READ_MICRO_CHUNK (cload, VARID_USER_DATA, m_UserData);
- READ_MICRO_CHUNK (cload, VARID_USER_OBJ, m_UserObj);
- READ_MICRO_CHUNK (cload, VARID_ID, id);
- }
- cload.Close_Micro_Chunk ();
- }
- }
- break;
- }
- cload.Close_Chunk ();
- }
- //
- // Set the ID (this will cause the sound object to
- // be re-inserted in the master sorted list)
- //
- if (id != SOUND_OBJ_DEFAULT_ID) {
- Set_ID (id);
- }
- //
- // Max sure the next available ID is the largest ID in existence
- //
- m_NextAvailableID = max (m_NextAvailableID, m_ID + 1);
- //
- // We need to 'swizzle' the attached object pointer. We saved the pointer's
- // value, and need to map it (hopefully) to the new value.
- //
- if (m_AttachedObject != NULL) {
- SaveLoadSystemClass::Request_Ref_Counted_Pointer_Remap ((RefCountClass **)&m_AttachedObject);
- }
-
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // On_Frame_Update
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- SoundSceneObjClass::On_Frame_Update (unsigned int /*milliseconds*/)
- {
- Apply_Auto_Position ();
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Set_ID
- //
- //////////////////////////////////////////////////////////////////////////////////
- void
- SoundSceneObjClass::Set_ID (uint32 id)
- {
- //
- // Remove the sound object from our sorted list
- //
- Unregister_Sound_Object (this);
- //
- // Change the sound object's ID
- //
- m_ID = id;
- //
- // Reinsert the sound object in our sorted list
- //
- Register_Sound_Object (this);
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Register_Sound_Object
- //
- //////////////////////////////////////////////////////////////////////////////////
- void
- SoundSceneObjClass::Register_Sound_Object (SoundSceneObjClass *sound_obj)
- {
- int sound_id = sound_obj->Get_ID ();
- CriticalSectionClass::LockClass lock(m_IDListMutex);
- //
- // Special case a non-ID
- //
- if (sound_id == SOUND_OBJ_DEFAULT_ID) {
- m_GlobalSoundList.Insert (0, sound_obj);
- } else {
- //
- // Check to ensure the object isn't already in the list
- //
- int index = 0;
- if (Find_Sound_Object (sound_id, &index) == false) {
- //
- // Insert the object into the list
- //
- m_GlobalSoundList.Insert (index, sound_obj);
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Unregister_Sound_Object
- //
- //////////////////////////////////////////////////////////////////////////////////
- void
- SoundSceneObjClass::Unregister_Sound_Object (SoundSceneObjClass *sound_obj)
- {
- CriticalSectionClass::LockClass lock(m_IDListMutex);
- //
- // Try to find the object in the list
- //
- int index = 0;
- if (Find_Sound_Object (sound_obj->Get_ID (), &index)) {
-
- //
- // Remove the object from the list
- //
- m_GlobalSoundList.Delete (index);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Find_Sound_Object
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- SoundSceneObjClass::Find_Sound_Object (uint32 id_to_find, int *index)
- {
- CriticalSectionClass::LockClass lock(m_IDListMutex);
- bool found = false;
- (*index) = 0;
- int min_index = 0;
- int max_index = m_GlobalSoundList.Count () - 1;
-
- //
- // Keep looping until we've closed the window of possiblity
- //
- bool keep_going = (max_index >= min_index);
- while (keep_going) {
- //
- // Calculate what slot we are currently looking at
- //
- int curr_index = min_index + ((max_index - min_index) / 2);
- uint32 curr_id = m_GlobalSoundList[curr_index]->Get_ID ();
- //
- // Did we find the right slot?
- //
- if (id_to_find == curr_id) {
- (*index) = curr_index;
- keep_going = false;
- found = true;
- } else {
- //
- // Stop if we've narrowed the window to one entry
- //
- keep_going = (max_index > min_index);
- //
- // Move the window to the appropriate side
- // of the test index.
- //
- if (id_to_find < curr_id) {
- max_index = curr_index - 1;
- (*index) = curr_index;
- } else {
- min_index = curr_index + 1;
- (*index) = curr_index + 1;
- }
- }
- }
- return found;
- }
|