/* ** 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 . */ /*********************************************************************************************** *** 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 : WW3D * * * * $Archive:: /Commando/Code/ww3d2/soundrobj.cpp $* * * * Author:: Patrick Smith * * * * $Modtime:: 1/16/02 10:21a $* * * * $Revision:: 4 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "soundrobj.h" #include "audiblesound.h" #include "sound3d.h" #include "wwaudio.h" #include "ffactory.h" #include "wwfile.h" #include "chunkio.h" #include "scene.h" ////////////////////////////////////////////////////////////////////////////////// // Global variables ////////////////////////////////////////////////////////////////////////////////// SoundRenderObjLoaderClass _SoundRenderObjLoader; ////////////////////////////////////////////////////////////////////////////////// // // SoundRenderObjClass // ////////////////////////////////////////////////////////////////////////////////// SoundRenderObjClass::SoundRenderObjClass (void) : Flags (FLAG_STOP_WHEN_HIDDEN), Sound (NULL), IsInitialized (false) { return ; } ////////////////////////////////////////////////////////////////////////////////// // // SoundRenderObjClass // ////////////////////////////////////////////////////////////////////////////////// SoundRenderObjClass::SoundRenderObjClass (const SoundRenderObjClass &src) : Flags (FLAG_STOP_WHEN_HIDDEN), Sound (NULL), IsInitialized (false) { (*this) = src; return ; } ////////////////////////////////////////////////////////////////////////////////// // // ~SoundRenderObjClass // ////////////////////////////////////////////////////////////////////////////////// SoundRenderObjClass::~SoundRenderObjClass (void) { // // Remove the old sound from the world (if necessary) // if (Sound != NULL) { Sound->Attach_To_Object (NULL); Sound->Remove_From_Scene (); REF_PTR_RELEASE (Sound); } return ; } ////////////////////////////////////////////////////////////////////////////////// // // operator= // ////////////////////////////////////////////////////////////////////////////////// const SoundRenderObjClass & SoundRenderObjClass::operator= (const SoundRenderObjClass &src) { // // Create a definition from the src sound object // AudibleSoundDefinitionClass definition; definition.Initialize_From_Sound (src.Sound); // // Create the internal sound object from the definition // Set_Sound (&definition); // // Copy the other misc settings // Name = src.Name; return *this; } ////////////////////////////////////////////////////////////////////////////////// // // Set_Sound // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Set_Sound (AudibleSoundDefinitionClass *definition) { // // Remove the old sound from the world (if necessary) // if (Sound != NULL) { Sound->Remove_From_Scene (); REF_PTR_RELEASE (Sound); } // // Create the sound object from its definition // if (definition != NULL) { Sound = (AudibleSoundClass *)definition->Create (); } return ; } ////////////////////////////////////////////////////////////////////////////////// // // On_Frame_Update // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::On_Frame_Update (void) { // // Stop the sound from playing (if necessary) // if ( Sound != NULL && Sound->Is_In_Scene () && Sound->Is_Playing () == false) { Sound->Attach_To_Object (NULL); Sound->Remove_From_Scene (); } return ; } ////////////////////////////////////////////////////////////////////////////////// // // Set_Hidden // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Set_Hidden (int onoff) { int before = Is_Not_Hidden_At_All (); RenderObjClass::Set_Hidden (onoff); // // If we've changed state, then update the visibility // if (IsInitialized == false || Is_Not_Hidden_At_All () != before) { IsInitialized = true; Update_On_Visibilty (); } return ; } ////////////////////////////////////////////////////////////////////////////////// // // Set_Visible // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Set_Visible (int onoff) { int before = Is_Not_Hidden_At_All (); RenderObjClass::Set_Visible (onoff); // // If we've changed state, then update the visibility // if (IsInitialized == false || Is_Not_Hidden_At_All () != before) { IsInitialized = true; Update_On_Visibilty (); } return ; } ////////////////////////////////////////////////////////////////////////////////// // // Set_Animation_Hidden // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Set_Animation_Hidden (int onoff) { int before = Is_Not_Hidden_At_All (); RenderObjClass::Set_Animation_Hidden (onoff); // // If we've changed state, then update the visibility // if (IsInitialized == false || Is_Not_Hidden_At_All () != before) { IsInitialized = true; Update_On_Visibilty (); } return ; } ////////////////////////////////////////////////////////////////////////////////// // // Set_Force_Visible // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Set_Force_Visible (int onoff) { int before = Is_Not_Hidden_At_All (); RenderObjClass::Set_Force_Visible (onoff); // // If we've changed state, then update the visibility // if (IsInitialized == false || Is_Not_Hidden_At_All () != before) { IsInitialized = true; Update_On_Visibilty (); } return ; } ////////////////////////////////////////////////////////////////////////////////// // // Update_On_Visibilty // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Update_On_Visibilty (void) { if (Sound == NULL) { return ; } // // Ensure our transform is correct // Validate_Transform (); // // Either add the sound object to the sound scene // or remove it from the sound scene depending // on the visibility state of the render object. // if ( Is_Not_Hidden_At_All () && Sound->Is_In_Scene () == false && Peek_Scene () != NULL) { // // Make sure the sound is properly attached to this render // object and then add it to the scene // Sound->Attach_To_Object (this); Sound->Add_To_Scene (true); } else if ((Is_Not_Hidden_At_All () == false) || (Peek_Scene () == NULL)) { // // Remove the sound from the scene (it will stop playing) // if ((Flags & FLAG_STOP_WHEN_HIDDEN) != 0 || (Peek_Scene () == NULL)) { Sound->Attach_To_Object (NULL); Sound->Remove_From_Scene (); } } return ; } ////////////////////////////////////////////////////////////////////////////////// // // Get_Sound // ////////////////////////////////////////////////////////////////////////////////// AudibleSoundClass * SoundRenderObjClass::Get_Sound (void) const { if (Sound != NULL) { Sound->Add_Ref (); } return Sound; } ////////////////////////////////////////////////////////////////////////////// // // Set_Flag // ////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Set_Flag (uint32 flag, bool onoff) { Flags &= ~flag; if (onoff) { Flags |= flag; } return ; } ////////////////////////////////////////////////////////////////////////////////// // // Notify_Added // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Notify_Added (SceneClass *scene) { RenderObjClass::Notify_Added (scene); scene->Register (this, SceneClass::ON_FRAME_UPDATE); Update_On_Visibilty (); return ; } ////////////////////////////////////////////////////////////////////////////////// // // Notify_Removed // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Notify_Removed (SceneClass *scene) { scene->Unregister (this, SceneClass::ON_FRAME_UPDATE); RenderObjClass::Notify_Removed (scene); Update_On_Visibilty (); return ; } ////////////////////////////////////////////////////////////////////////////////// // // Set_Transform // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Set_Transform (const Matrix3D &tm) { RenderObjClass::Set_Transform (tm); if (IsInitialized == false) { IsInitialized = true; Update_On_Visibilty (); } return ; } ////////////////////////////////////////////////////////////////////////////////// // // Set_Position // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjClass::Set_Position (const Vector3 &pos) { RenderObjClass::Set_Position (pos); if (IsInitialized == false) { IsInitialized = true; Update_On_Visibilty (); } return ; } //********************************************************************************* // // Start of SoundRenderObjDefClass // //********************************************************************************* ////////////////////////////////////////////////////////////////////////////////// // // SoundRenderObjDefClass // ////////////////////////////////////////////////////////////////////////////////// SoundRenderObjDefClass::SoundRenderObjDefClass (void) : Version (W3D_CURRENT_SOUNDROBJ_VERSION), Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN) { return ; } ////////////////////////////////////////////////////////////////////////////////// // // SoundRenderObjDefClass // ////////////////////////////////////////////////////////////////////////////////// SoundRenderObjDefClass::SoundRenderObjDefClass (SoundRenderObjClass &render_obj) : Version (W3D_CURRENT_SOUNDROBJ_VERSION), Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN) { Initialize (render_obj); return ; } ////////////////////////////////////////////////////////////////////////////////// // // SoundRenderObjDefClass // ////////////////////////////////////////////////////////////////////////////////// SoundRenderObjDefClass::SoundRenderObjDefClass (const SoundRenderObjDefClass &src) : Version (W3D_CURRENT_SOUNDROBJ_VERSION), Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN) { (*this) = src; return ; } ////////////////////////////////////////////////////////////////////////////////// // // ~SoundRenderObjDefClass // ////////////////////////////////////////////////////////////////////////////////// SoundRenderObjDefClass::~SoundRenderObjDefClass (void) { return ; } ////////////////////////////////////////////////////////////////////////////////// // // operator= // ////////////////////////////////////////////////////////////////////////////////// const SoundRenderObjDefClass & SoundRenderObjDefClass::operator= (const SoundRenderObjDefClass &src) { Definition = src.Definition; Version = src.Version; Name = src.Name; return (*this); } ////////////////////////////////////////////////////////////////////////////////// // // Create // ////////////////////////////////////////////////////////////////////////////////// RenderObjClass * SoundRenderObjDefClass::Create (void) { // // Allocate and initialize a new instance // SoundRenderObjClass *render_obj = new SoundRenderObjClass; render_obj->Set_Name (Name); render_obj->Set_Sound (&Definition); render_obj->Set_Flags (Flags); return render_obj; } ////////////////////////////////////////////////////////////////////////////////// // // Initialize // ////////////////////////////////////////////////////////////////////////////////// void SoundRenderObjDefClass::Initialize (SoundRenderObjClass &render_obj) { // // Copy the settings from the sound object into our definition // Definition.Initialize_From_Sound (render_obj.Peek_Sound ()); // // Copy the flags from the render object // Flags = (SoundRenderObjClass::FLAGS)render_obj.Get_Flags (); // // Copy the name // Name = render_obj.Get_Name (); return ; } /////////////////////////////////////////////////////////////////////////////////// // // Load // /////////////////////////////////////////////////////////////////////////////////// WW3DErrorType SoundRenderObjDefClass::Load_W3D (ChunkLoadClass &cload) { WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED; // // Attempt to read the different sections of the definition // if ((Read_Header (cload) == WW3D_ERROR_OK) && (Read_Definition (cload) == WW3D_ERROR_OK)) { retval = WW3D_ERROR_OK; } return retval; } ////////////////////////////////////////////////////////////////////////////////// // // Save_W3D // ////////////////////////////////////////////////////////////////////////////////// WW3DErrorType SoundRenderObjDefClass::Save_W3D (ChunkSaveClass &csave) { WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED; // // Begin a chunk that identifies a sound render object // if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ) == TRUE) { // // Attempt to save the different sections of the aggregate definition // if ((Write_Header (csave) == WW3D_ERROR_OK) && (Write_Definition (csave) == WW3D_ERROR_OK)) { retval = WW3D_ERROR_OK; } csave.End_Chunk (); } return retval; } /////////////////////////////////////////////////////////////////////////////////// // // Read_Header // /////////////////////////////////////////////////////////////////////////////////// WW3DErrorType SoundRenderObjDefClass::Read_Header (ChunkLoadClass &cload) { WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED; // // Is this the header chunk? // if (cload.Open_Chunk () && (cload.Cur_Chunk_ID () == W3D_CHUNK_SOUNDROBJ_HEADER)) { // // Read the header from the chunk // W3dSoundRObjHeaderStruct header = { 0 }; if (cload.Read (&header, sizeof (header)) == sizeof (header)) { // // Copy the names from the header structure // Name = header.Name; Version = header.Version; Flags = (SoundRenderObjClass::FLAGS)header.Flags; retval = WW3D_ERROR_OK; } cload.Close_Chunk (); } return retval; } /////////////////////////////////////////////////////////////////////////////////// // // Read_Definition // /////////////////////////////////////////////////////////////////////////////////// WW3DErrorType SoundRenderObjDefClass::Read_Definition (ChunkLoadClass &cload) { WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED; // // Is this the right chunk? // if (cload.Open_Chunk () && (cload.Cur_Chunk_ID () == W3D_CHUNK_SOUNDROBJ_DEFINITION)) { // // Ask the definition to load its settings from the chunk // if (Definition.Load (cload)) { retval = WW3D_ERROR_OK; } cload.Close_Chunk (); } return retval; } /////////////////////////////////////////////////////////////////////////////////// // // Write_Header // /////////////////////////////////////////////////////////////////////////////////// WW3DErrorType SoundRenderObjDefClass::Write_Header (ChunkSaveClass &csave) { WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED; // // Begin a chunk that identifies the aggregate // if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ_HEADER) == TRUE) { // // Fill the header structure // W3dSoundRObjHeaderStruct header = { 0 }; header.Version = W3D_CURRENT_AGGREGATE_VERSION; header.Flags = Flags; ::lstrcpyn (header.Name, (const char *)Name, sizeof (header.Name)); header.Name[sizeof (header.Name) - 1] = 0; // // Write the header out to the chunk // if (csave.Write (&header, sizeof (header)) == sizeof (header)) { retval = WW3D_ERROR_OK; } // End the header chunk csave.End_Chunk (); } return retval; } /////////////////////////////////////////////////////////////////////////////////// // // Write_Definition // /////////////////////////////////////////////////////////////////////////////////// WW3DErrorType SoundRenderObjDefClass::Write_Definition (ChunkSaveClass &csave) { WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED; // // Save the definition to its own chunk // if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ_DEFINITION) == TRUE) { if (Definition.Save (csave)) { retval = WW3D_ERROR_OK; } csave.End_Chunk (); } return retval; } //********************************************************************************* // // Start of SoundRenderObjDefClass // //********************************************************************************* /////////////////////////////////////////////////////////////////////////////////// // // Load_W3D // /////////////////////////////////////////////////////////////////////////////////// PrototypeClass * SoundRenderObjLoaderClass::Load_W3D (ChunkLoadClass &cload) { SoundRenderObjPrototypeClass *prototype = NULL; // // Create a definition object // SoundRenderObjDefClass *definition = new SoundRenderObjDefClass; if (definition != NULL) { // // Ask the definition object to load the sound data // if (definition->Load_W3D (cload) == WW3D_ERROR_OK) { // // Success! Create a prototype from the definition // prototype = new SoundRenderObjPrototypeClass (definition); } REF_PTR_RELEASE (definition); } return prototype; }