diff --git a/direct/src/showbase/pandaSqueezer.py b/direct/src/showbase/pandaSqueezer.py index 06354bcb4f..e8c7aa4a50 100644 --- a/direct/src/showbase/pandaSqueezer.py +++ b/direct/src/showbase/pandaSqueezer.py @@ -41,7 +41,10 @@ def squeezePandaFiles(): l = getSqueezeableFiles() pandaSqueezeTool.squeeze("PandaModules", "PandaModulesUnsqueezed", l) - # Clean up the source files now that they've been squeezed. + # Clean up the source files now that they've been squeezed. If + # you don't like this behavior (e.g. if you want to inspect the + # generated files), use genPyCode -n to avoid squeezing + # altogether. for i in l: os.unlink(i) diff --git a/dtool/Config.pp b/dtool/Config.pp index e9460e3f7a..50efbcd866 100644 --- a/dtool/Config.pp +++ b/dtool/Config.pp @@ -312,6 +312,12 @@ #define VRPN_LIBS #defer HAVE_VRPN $[libtest $[VRPN_LPATH],$[VRPN_LIBS]] +// Is HELIX installed, and where? +#define HELIX_IPATH +#define HELIX_LPATH +#define HELIX_LIBS +#defer HAVE_HELIX $[libtest $[HELIX_LPATH],$[HELIX_LIBS]] + // Is ZLIB installed, and where? #define ZLIB_IPATH #define ZLIB_LPATH @@ -664,7 +670,7 @@ // How to generate a static C or C++ library. $[target] is the // name of the library to generate, and $[sources] is the list of .o // files that will go into the library. -#if $[eq $[PLATFORM], osx] +#if $[eq $[PLATFORM], osx] #defer STATIC_LIB_C libtool -static -o $[target] $[sources] #defer STATIC_LIB_C++ libtool -static -o $[target] $[sources] #else diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index 818be65e42..2e009d83cf 100644 --- a/dtool/LocalSetup.pp +++ b/dtool/LocalSetup.pp @@ -123,6 +123,9 @@ $[cdefine HAVE_NURBSPP] /* Define if we have VRPN installed. */ $[cdefine HAVE_VRPN] +/* Define if we have HELIX installed. */ +$[cdefine HAVE_HELIX] + /* Define if we have CG installed. */ $[cdefine HAVE_CG] diff --git a/dtool/Package.pp b/dtool/Package.pp index be346b9762..96c1fbd543 100644 --- a/dtool/Package.pp +++ b/dtool/Package.pp @@ -146,6 +146,11 @@ #set VRPN_LIBS $[VRPN_LIBS] #set HAVE_VRPN $[HAVE_VRPN] +#set HELIX_IPATH $[unixfilename $[HELIX_IPATH]] +#set HELIX_LPATH $[unixfilename $[HELIX_LPATH]] +#set HELIX_LIBS $[HELIX_LIBS] +#set HAVE_HELIX $[HAVE_HELIX] + #set ZLIB_IPATH $[unixfilename $[ZLIB_IPATH]] #set ZLIB_LPATH $[unixfilename $[ZLIB_LPATH]] #set ZLIB_LIBS $[ZLIB_LIBS] diff --git a/dtool/pptempl/Global.pp b/dtool/pptempl/Global.pp index af1d734866..f801426173 100644 --- a/dtool/pptempl/Global.pp +++ b/dtool/pptempl/Global.pp @@ -216,6 +216,13 @@ #define vrpn_libs $[VRPN_LIBS] #endif +#if $[HAVE_HELIX] + #define helix_ipath $[wildcard $[HELIX_IPATH]] + #define helix_lpath $[wildcard $[HELIX_LPATH]] + #define helix_cflags $[HELIX_CFLAGS] + #define helix_libs $[HELIX_LIBS] +#endif + #if $[HAVE_MIKMOD] #define mikmod_ipath $[wildcard $[MIKMOD_IPATH]] #define mikmod_lpath $[wildcard $[MIKMOD_LPATH]] diff --git a/dtool/src/parser-inc/Sources.pp b/dtool/src/parser-inc/Sources.pp index 85d63410e3..f4b0d22a08 100644 --- a/dtool/src/parser-inc/Sources.pp +++ b/dtool/src/parser-inc/Sources.pp @@ -2,6 +2,8 @@ algorithm deque ft2build.h iostream list map memory \ pair queue set stack stdcompare.h stdtypedefs.h \ string vector windows.h zlib.h md5.h files.h hex.h \ - nurbs.hh stddef.h krb5.h Python.h \ - Cg/cg.h Cg/cgGL.h + nurbs.hh stddef.h krb5.h MainHelix.h dllpath.h hxcom.h \ + hxcomm.h hxcore.h hxengin.h hxerror.h hxfiles.h hxtbuf.h \ + hxtbuff.h hxwin.h Python.h Cg/cg.h Cg/cgGL.h + diff --git a/panda/metalibs/panda/Sources.pp b/panda/metalibs/panda/Sources.pp index ffa3daf312..f6ad4345d9 100644 --- a/panda/metalibs/panda/Sources.pp +++ b/panda/metalibs/panda/Sources.pp @@ -17,7 +17,7 @@ parametrics pnm \ pnmimagetypes pnmimage sgattrib sgmanip sgraph sgraphutil \ switchnode pnmtext text tform tiff lerp loader putil \ - audio pgui pandabase + audio pgui pandabase helix #define LOCAL_LIBS \ downloader express pandabase diff --git a/panda/src/audio/audioManager.h b/panda/src/audio/audioManager.h index b78febfde0..64f0bd8ae9 100644 --- a/panda/src/audio/audioManager.h +++ b/panda/src/audio/audioManager.h @@ -49,7 +49,7 @@ PUBLISHED: virtual bool is_valid() = 0; // Get a sound: - virtual PT(AudioSound) get_sound(const string& file_name) = 0; + virtual PT(AudioSound) get_sound(const string& file_name, bool positional = false) = 0; PT(AudioSound) get_null_sound(); // Tell the AudioManager there is no need to keep this one cached. @@ -105,6 +105,45 @@ PUBLISHED: // this call may be for efficient on some implementations. virtual void stop_all_sounds() = 0; + // Changes to the positions of 3D spacialized sounds and the listener + // are all made at once when this method is called. It should be put + // in the main program loop. + virtual void audio_3d_update() = 0; + + // This controls the "set of ears" that listens to 3D spacialized sound + // px, py, pz are position coordinates. Can be NULL to ignore. + // vx, vy, vz are a velocity vector in UNITS PER SECOND (default: meters). Can be NULL to ignore. + // fx, fy and fz are the respective components of a unit forward-vector + // ux, uy and uz are the respective components of a unit up-vector + // These changes will NOT be invoked until audio_3d_update() is called. + virtual void audio_3d_set_listener_attributes(float px, float py, float pz, + float vx, float vy, float vz, + float fx, float fy, float fz, + float ux, float uy, float uz) = 0; + // Values should all default to NULL, so you can just pass the one you want to get. + virtual void audio_3d_get_listener_attributes(float px = NULL, float py = NULL, float pz = NULL, + float vx = NULL, float vy = NULL, float vz = NULL, + float fx = NULL, float fy = NULL, float fz = NULL, + float ux = NULL, float uy = NULL, float uz = NULL) = 0; + + // Control the "relative distance factor" for 3D spacialized audio. Default is 1.0 + // Fmod uses meters internally, so give a float in Units-per meter + // Don't know what Miles uses. + virtual void audio_3d_set_distance_factor(float factor) = 0; + virtual float audio_3d_get_distance_factor() const = 0; + + // Control the presence of the Doppler effect. Default is 1.0 + // Exaggerated Doppler, use >1.0 + // Diminshed Doppler, use <1.0 + virtual void audio_3d_set_doppler_factor(float factor) = 0; + virtual float audio_3d_get_doppler_factor() const = 0; + + // Exaggerate or diminish the effect of distance on sound. Default is 1.0 + // Faster drop off, use >1.0 + // Slower drop off, use <1.0 + virtual void audio_3d_set_drop_off_factor(float factor) = 0; + virtual float audio_3d_get_drop_off_factor() const = 0; + public: static void register_AudioManager_creator(Create_AudioManager_proc* proc); diff --git a/panda/src/audio/audioSound.h b/panda/src/audio/audioSound.h index 9df680e0a2..6ea9c727c3 100644 --- a/panda/src/audio/audioSound.h +++ b/panda/src/audio/audioSound.h @@ -95,6 +95,16 @@ PUBLISHED: // return: playing time in seconds. virtual float length() const = 0; + // Controls the position of this sound's emitter. + // px, py and pz are the emitter's position. + // vx, vy and vz are the emitter's velocity in UNITS PER SECOND (default: meters). + // You can pass NULL to either value for either function to ignore that value + // if you only want to set/get one of them for some reason. + virtual void set_3d_attributes(float px = NULL, float py = NULL, float pz = NULL, + float vx = NULL, float vy = NULL, float vz = NULL) = 0; + virtual void get_3d_attributes(float px = NULL, float py = NULL, float pz = NULL, + float vx = NULL, float vy = NULL, float vz = NULL) = 0; + enum SoundStatus { BAD, READY, PLAYING }; virtual SoundStatus status() const = 0; diff --git a/panda/src/audio/config_audio.cxx b/panda/src/audio/config_audio.cxx index 40a5da9e4b..b79f74744f 100644 --- a/panda/src/audio/config_audio.cxx +++ b/panda/src/audio/config_audio.cxx @@ -35,6 +35,20 @@ int audio_cache_limit float audio_volume =config_audio.GetFloat("audio-volume", 1.0f); +float audio_doppler_factor + =config_audio.GetFloat("audio-doppler-factor", 1.0f); + +float audio_distance_factor + =config_audio.GetFloat("audio-distance-factor", 1.0f); + +float audio_drop_off_factor + =config_audio.GetFloat("audio-drop-off-factor", 1.0f); + +// Guarantee this many channels on local sound card, or just +// play EVERYTHING in software. +int audio_min_hw_channels + =config_audio.GetInt("audio-min-hw-channels", 15); + bool audio_software_midi =config_audio.GetBool("audio-software-midi", false); diff --git a/panda/src/audio/config_audio.h b/panda/src/audio/config_audio.h index 650eb2bd80..372c654632 100644 --- a/panda/src/audio/config_audio.h +++ b/panda/src/audio/config_audio.h @@ -32,6 +32,12 @@ extern EXPCL_PANDA bool audio_active; extern EXPCL_PANDA int audio_cache_limit; extern EXPCL_PANDA float audio_volume; +extern EXPCL_PANDA float audio_doppler_factor; +extern EXPCL_PANDA float audio_distance_factor; +extern EXPCL_PANDA float audio_drop_off_factor; + +extern EXPCL_PANDA int audio_min_hw_channels; + extern EXPCL_PANDA bool audio_software_midi; extern EXPCL_PANDA string* audio_dls_file; diff --git a/panda/src/audio/nullAudioManager.cxx b/panda/src/audio/nullAudioManager.cxx index 127607d29f..17d3ce9fb0 100644 --- a/panda/src/audio/nullAudioManager.cxx +++ b/panda/src/audio/nullAudioManager.cxx @@ -19,6 +19,10 @@ #include "nullAudioManager.h" +//namespace { + //static const string blank=""; + //static float no_listener_attributes [] = {0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f}; +//} //////////////////////////////////////////////////////////////////// // Function: NullAudioManager::NullAudioManager @@ -56,7 +60,7 @@ is_valid() { // Description: //////////////////////////////////////////////////////////////////// PT(AudioSound) NullAudioManager:: -get_sound(const string&) { +get_sound(const string&, bool positional) { return get_null_sound(); } @@ -180,3 +184,96 @@ void NullAudioManager:: stop_all_sounds() { // intentionally blank. } + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_update +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void NullAudioManager:: +audio_3d_update() { + // intentionally blank. +} + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_set_listener_attributes +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void NullAudioManager:: +audio_3d_set_listener_attributes(float px, float py, float pz, float vx, float vy, float vz, float fx, float fy, float fz, float ux, float uy, float uz) { + // intentionally blank. +} + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_get_listener_attributes +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void NullAudioManager:: +audio_3d_get_listener_attributes(float px, float py, float pz, float vx, float vy, float vz, float fx, float fy, float fz, float ux, float uy, float uz) { + // intentionally blank. +} + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_set_distance_factor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void NullAudioManager:: +audio_3d_set_distance_factor(float factor) { + // intentionally blank. +} + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_get_distance_factor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +float NullAudioManager:: +audio_3d_get_distance_factor() const { + // intentionally blank. + return 0.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_set_doppler_factor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void NullAudioManager:: +audio_3d_set_doppler_factor(float factor) { + // intentionally blank. +} + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_get_doppler_factor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +float NullAudioManager:: +audio_3d_get_doppler_factor() const { + // intentionally blank. + return 0.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_set_drop_off_factor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void NullAudioManager:: +audio_3d_set_drop_off_factor(float factor) { + // intentionally blank. +} + +//////////////////////////////////////////////////////////////////// +// Function: NullAudioManager::audio_3d_get_drop_off_factor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +float NullAudioManager:: +audio_3d_get_drop_off_factor() const { + // intentionally blank. + return 0.0f; +} \ No newline at end of file diff --git a/panda/src/audio/nullAudioManager.h b/panda/src/audio/nullAudioManager.h index 7588253c4a..65b8a6b1b5 100644 --- a/panda/src/audio/nullAudioManager.h +++ b/panda/src/audio/nullAudioManager.h @@ -34,7 +34,7 @@ public: virtual bool is_valid(); - virtual PT(AudioSound) get_sound(const string&); + virtual PT(AudioSound) get_sound(const string&, bool positional = false); virtual void uncache_sound(const string&); virtual void clear_cache(); virtual void set_cache_limit(unsigned int); @@ -52,6 +52,26 @@ public: virtual void reduce_sounds_playing_to(unsigned int count); virtual void stop_all_sounds(); + + virtual void audio_3d_update(); + + virtual void audio_3d_set_listener_attributes(float px, float py, float pz, + float vx, float vy, float vz, + float fx, float fy, float fz, + float ux, float uy, float uz); + virtual void audio_3d_get_listener_attributes(float px = NULL, float py = NULL, float pz = NULL, + float vx = NULL, float vy = NULL, float vz = NULL, + float fx = NULL, float fy = NULL, float fz = NULL, + float ux = NULL, float uy = NULL, float uz = NULL); + + virtual void audio_3d_set_distance_factor(float factor); + virtual float audio_3d_get_distance_factor() const; + + virtual void audio_3d_set_doppler_factor(float factor); + virtual float audio_3d_get_doppler_factor() const; + + virtual void audio_3d_set_drop_off_factor(float factor); + virtual float audio_3d_get_drop_off_factor() const; }; #endif /* __NULL_AUDIO_MANAGER_H__ */ diff --git a/panda/src/audio/nullAudioSound.cxx b/panda/src/audio/nullAudioSound.cxx index 76f1af0439..7b23cbdad5 100644 --- a/panda/src/audio/nullAudioSound.cxx +++ b/panda/src/audio/nullAudioSound.cxx @@ -22,6 +22,7 @@ namespace { static const string blank=""; + static float no_attributes [] = {0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f}; } //////////////////////////////////////////////////////////////////// @@ -109,6 +110,14 @@ float NullAudioSound::length() const { return 0; } +void NullAudioSound::set_3d_attributes(float px, float py, float pz, float vx, float vy, float vz) { + // Intentionally blank. +} + +void NullAudioSound::get_3d_attributes(float px, float py, float pz, float vx, float vy, float vz) { + // Intentionally blank. +} + AudioSound::SoundStatus NullAudioSound::status() const { return AudioSound::READY; } diff --git a/panda/src/audio/nullAudioSound.h b/panda/src/audio/nullAudioSound.h index de26006dff..aef67a4537 100644 --- a/panda/src/audio/nullAudioSound.h +++ b/panda/src/audio/nullAudioSound.h @@ -62,6 +62,9 @@ public: float length() const; + void set_3d_attributes(float px, float py, float pz, float vx, float vy, float vz); + void get_3d_attributes(float px, float py, float pz, float vx, float vy, float vz); + AudioSound::SoundStatus status() const; // why protect the constructor?!? diff --git a/panda/src/audiotraits/Sources.pp b/panda/src/audiotraits/Sources.pp index 21f365ff37..a1210a7b46 100644 --- a/panda/src/audiotraits/Sources.pp +++ b/panda/src/audiotraits/Sources.pp @@ -26,7 +26,7 @@ #define BUILD_TARGET $[HAVE_FMOD] #define USE_PACKAGES fmod #define BUILDING_DLL BUILDING_FMOD_AUDIO - #define LOCAL_LIBS audio + #define LOCAL_LIBS audio event #define WIN_SYS_LIBS $[WIN_SYS_LIBS] user32.lib advapi32.lib winmm.lib #define COMBINED_SOURCES $[TARGET]_composite1.cxx diff --git a/panda/src/audiotraits/config_fmodAudio.cxx b/panda/src/audiotraits/config_fmodAudio.cxx index b5c6e9bfef..2df8d50f86 100644 --- a/panda/src/audiotraits/config_fmodAudio.cxx +++ b/panda/src/audiotraits/config_fmodAudio.cxx @@ -20,12 +20,6 @@ #ifdef HAVE_FMOD //[ -// Please remove this as part of updating fmod: -#error The fmod audio needs repair by the fmod implementers - - - - #include "config_fmodAudio.h" #include "fmodAudioManager.h" #include "fmodAudioSound.h" diff --git a/panda/src/audiotraits/fmodAudioManager.cxx b/panda/src/audiotraits/fmodAudioManager.cxx index 826503221b..a885007287 100644 --- a/panda/src/audiotraits/fmodAudioManager.cxx +++ b/panda/src/audiotraits/fmodAudioManager.cxx @@ -51,8 +51,18 @@ FmodAudioManager() { audio_debug("FmodAudioManager::FmodAudioManager()"); audio_debug(" audio_active="<set_active(_active); + audio_debug("GAH!"); _soundsOnLoan.insert(fmodAudioSound); + audio_debug("GIR!"); audioSound = fmodAudioSound; audio_debug(" returning 0x" << (void*)audioSound); assert(is_valid()); + audio_debug("GOO!"); return audioSound; } @@ -379,8 +417,8 @@ set_cache_limit(unsigned int count) { // Access: Public // Description: //////////////////////////////////////////////////////////////////// -int FmodAudioManager:: -get_cache_limit() { +unsigned int FmodAudioManager:: +get_cache_limit() const { audio_debug("FmodAudioManager::get_cache_limit() returning " <<_cache_limit); return _cache_limit; @@ -405,8 +443,16 @@ release_sound(FmodAudioSound* audioSound) { // Description: //////////////////////////////////////////////////////////////////// void FmodAudioManager:: -set_volume(float) { - // intentionally blank. +set_volume(float volume) { + audio_debug("FmodAudioManager::set_volume(volume="< 0) { - // SoundsPlaying::iterator sound = _sounds_playing.begin(); - // assert(sound != _sounds_playing.end()); - // (**sound).stop(); - //} + int limit = _sounds_playing.size() - count; + while (limit-- > 0) { + SoundsPlaying::iterator sound = _sounds_playing.begin(); + assert(sound != _sounds_playing.end()); + (**sound).stop(); + } } +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioManager::stop_a_sound +// Access: Public +// Description: Stop playback on one sound managed by this manager. +//////////////////////////////////////////////////////////////////// +//void FmodAudioManager:: +//stop_a_sound() { +// audio_debug("FmodAudioManager::stop_a_sound()"); +// AudioSet::size_type s=_soundsOnLoan.size() - 1; +// reduce_sounds_playing_to(s); + //if (s == _soundsOnLoan.size()) return true; + //return false; +//} + //////////////////////////////////////////////////////////////////// // Function: FmodAudioManager::stop_all_sounds // Access: Public @@ -493,12 +554,172 @@ reduce_sounds_playing_to(unsigned int count) { void FmodAudioManager:: stop_all_sounds() { audio_debug("FmodAudioManager::stop_all_sounds()"); - AudioSet::iterator i=_soundsOnLoan.begin(); - for (; i!=_soundsOnLoan.end(); ++i) { - if ((**i).status()==AudioSound::PLAYING) { - (**i).stop(); + reduce_sounds_playing_to(0); + //AudioSet::iterator i=_soundsOnLoan.begin(); + //for (; i!=_soundsOnLoan.end(); ++i) { + // if ((**i).status()==AudioSound::PLAYING) { + // (**i).stop(); + // } + //} +} + +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioManager::audio_3d_update +// Access: Public +// Description: Commit position changes to listener and all +// positioned sounds. Normally, you'd want to call this +// once per iteration of your main loop. +//////////////////////////////////////////////////////////////////// +void FmodAudioManager:: +audio_3d_update() { + audio_debug("FmodAudioManager::audio_3d_update()"); + //convert panda coordinates to fmod coordinates + float fmod_pos [] = {_listener_pos[0], _listener_pos[2], _listener_pos[1]}; + float fmod_vel [] = {_listener_vel[0], _listener_vel[2], _listener_vel[1]}; + float fmod_forward [] = {_listener_forward[0], _listener_forward[2], _listener_forward[1]}; + float fmod_up [] = {_listener_up[0], _listener_up[2], _listener_up[1]}; + + FSOUND_3D_Listener_SetAttributes(fmod_pos, fmod_vel, + fmod_forward[0], fmod_forward[1], fmod_forward[2], + fmod_up[0], fmod_up[1], fmod_up[2]); + FSOUND_Update(); +} + +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioManager::audio_3d_set_listener_attributes +// Access: Public +// Description: Set position of the "ear" that picks up 3d sounds +//////////////////////////////////////////////////////////////////// +void FmodAudioManager:: +audio_3d_set_listener_attributes(float px, float py, float pz, float vx, float vy, float vz, float fx, float fy, float fz, float ux, float uy, float uz) { + audio_debug("FmodAudioManager::audio_3d_set_listener_attributes()"); + + _listener_pos[0] = px; _listener_pos[1] = py; _listener_pos[2] = pz; + _listener_vel[0] = vx; _listener_vel[1] = vy; _listener_vel[2] = vz; + _listener_forward[0] = fx; _listener_forward[1] = fy; _listener_forward[2] = fz; + _listener_up[0] = ux; _listener_up[1] = uy; _listener_up[2] = uz; + + //FSOUND_3D_Listener_SetAttributes(_listener_pos, _listener_vel, fx, fz, fy, ux, uz, uy); +} + +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioManager::audio_3d_get_listener_attributes +// Access: Public +// Description: Get position of the "ear" that picks up 3d sounds +//////////////////////////////////////////////////////////////////// +void FmodAudioManager:: +audio_3d_get_listener_attributes(float px, float py, float pz, float vx, float vy, float vz, float fx, float fy, float fz, float ux, float uy, float uz) { + audio_error("audio3dGetListenerAttributes: currently unimplemented. Get the attributes of the attached object"); + //audio_debug("FmodAudioManager::audio_3d_get_listener_attributes()"); + // NOTE: swap the +y with the +z axis to convert between FMOD + // coordinates and Panda3D coordinates + //float temp; + //temp = py; + //py = pz; + //pz = temp; + + //temp = vy; + //vy = vz; + //vz = temp; + + //float pos [] = {px, py, pz}; + //float vel [] = {vx, vy, vz}; + //float front [] = {fx, fz, fy}; + //float up [] = {ux, uz, uy}; + + //FSOUND_3D_Listener_GetAttributes(pos, vel, &front[0], &front[1], &front[2], &up[0], &up[1], &up[2]); +} + + +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioManager::audio_3d_set_distance_factor +// Access: Public +// Description: Set units per meter (Fmod uses meters internally for +// its sound-spacialization calculations) +//////////////////////////////////////////////////////////////////// +void FmodAudioManager:: +audio_3d_set_distance_factor(float factor) { + audio_debug("FmodAudioManager::audio_3d_set_distance_factor(factor="<1.0 + // Diminshed Doppler, use <1.0 + virtual void audio_3d_set_doppler_factor(float factor); + virtual float audio_3d_get_doppler_factor() const; + + // Exaggerate or diminish the effect of distance on sound. Default is 1.0 + // Faster drop off, use >1.0 + // Slower drop off, use <1.0 + virtual void audio_3d_set_drop_off_factor(float factor); + virtual float audio_3d_get_drop_off_factor() const; + protected: // increment or decrement the refcount of the given file's cache entry. // sounds can only be uncached when their refcounts are zero. @@ -88,6 +129,10 @@ private: AudioSet _soundsOnLoan; unsigned int _concurrent_sound_limit; + typedef pset SoundsPlaying; + // The sounds from this manager that are currently playing + SoundsPlaying _sounds_playing; + // The Least Recently Used mechanism: typedef pdeque LRU; LRU _lru; @@ -98,6 +143,14 @@ private: static int _active_managers; bool _is_valid; bool _active; + float _volume; + float _listener_pos [3]; + float _listener_vel [3]; + float _listener_forward [3]; + float _listener_up [3]; + float _distance_factor; + float _doppler_factor; + float _drop_off_factor; char* load(const Filename& filename, size_t &size) const; diff --git a/panda/src/audiotraits/fmodAudioSound.cxx b/panda/src/audiotraits/fmodAudioSound.cxx index 7ee3ecee80..c3b20f9734 100644 --- a/panda/src/audiotraits/fmodAudioSound.cxx +++ b/panda/src/audiotraits/fmodAudioSound.cxx @@ -1,5 +1,6 @@ // Filename: fmodAudioSound.cxx // Created by: cort (January 22, 2003) +// Extended by: ben (October 22, 2003) // Prior system by: cary // //////////////////////////////////////////////////////////////////// @@ -20,6 +21,7 @@ #include "pandabase.h" #ifdef HAVE_FMOD //[ +#include "throw_event.h" #include "fmodAudioSound.h" #include "fmodAudioManager.h" @@ -32,25 +34,73 @@ #define fmod_audio_debug(x) ((void)0) #endif //] +//////////////////////////////////////////////////////////////////// +// Function: pandaFmodFinishedCallback_Stream +// Access: file scope +// Description: What happens when a sound ends (not reaches the end +// of a loop, but really ends). +//////////////////////////////////////////////////////////////////// +signed char +pandaFmodFinishedCallback_Stream( FSOUND_STREAM *audio, void *buff, int len, int p_sound ) { + FmodAudioSound* sound = (FmodAudioSound*)p_sound; + assert(sound); //sanity test + sound->finished(); + return true; //make signed char happy +} + +//////////////////////////////////////////////////////////////////// +// Function: panda_Fmod_finished_callback +// Access: file scope +// Description: Sets up a finish callback for a sound. +//////////////////////////////////////////////////////////////////// +void +panda_Fmod_finished_callback( FSOUND_STREAM *audio, FmodAudioSound* sound ) { + if ( !audio || !sound ) {//sanity test + return; + } + audio_debug("panda_Fmod_finished_callback(audio="<<((void*)audio) + <<", sound="<<((void*)sound)<<")"); + FSOUND_STREAMCALLBACK callback = pandaFmodFinishedCallback_Stream; + //actual stream, callback func, pointer to FmodAudioSound + FSOUND_Stream_SetEndCallback( audio, callback, (int)sound ); +} + +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioSound::FmodAudioSound +// Access: +// Description: constructor +//////////////////////////////////////////////////////////////////// FmodAudioSound:: FmodAudioSound(FmodAudioManager* manager, FSOUND_STREAM *audio_data, string file_name, float length) : _manager(manager), _audio(audio_data), _file_name(file_name), _volume(1.0f), _balance(0), _loop_count(1), _length(length), - _active(true), _paused(false), _channel(-1) { + _active(true), _paused(false), _bExclusive(false),_channel(-1) { + _pos[0] = 0.0f; _pos[1] = 0.0f; _pos[2] = 0.0f; + _vel[0] = 0.0f; _vel[1] = 0.0f; _vel[2] = 0.0f; nassertv(!file_name.empty()); nassertv(audio_data != NULL); - audio_debug("FmodAudioSound(manager=0x"<<(void*)&manager + fmod_audio_debug("FmodAudioSound(manager=0x"<<(void*)&manager <<", file_name="<stop(); _manager->release_sound(this); } - + +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioSound:: play +// Access: public +// Description: Play a sound +//////////////////////////////////////////////////////////////////// void FmodAudioSound:: play() { if (!_active) { @@ -60,11 +110,12 @@ play() { if (this->status() == AudioSound::PLAYING) { this->stop(); } - if (_manager->stop_a_sound()) { +if (_bExclusive) { // stop another sound that parent mgr is playing _manager->stop_all_sounds(); } + panda_Fmod_finished_callback( _audio, this ); // Play the stream, but start it paused so we can set the volume and // panning first. assert(_audio != NULL); @@ -81,6 +132,16 @@ play() { // Set panning. unsigned char new_balance = (unsigned char)( (_balance+1.0f)*0.5f*255.0f); FSOUND_SetPan(_channel, new_balance); + + // Set 3d attributes, if needed + if (FSOUND_Stream_GetMode(_audio) & FSOUND_HW3D) { + // Convert from Panda coordinates to Fmod coordinates + float fmod_pos [] = {_pos[0], _pos[2], _pos[1]}; + float fmod_vel [] = {_vel[0], _vel[2], _vel[1]}; + if(!FSOUND_3D_SetAttributes(_channel, fmod_pos, fmod_vel)) { + audio_error("Unable to set 3d attributes for "<<_file_name<<"!"); + } + } // Set looping -- unimplemented @@ -95,33 +156,103 @@ play() { } } +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioSound::stop +// Access: public +// Description: Stop a sound +//////////////////////////////////////////////////////////////////// void FmodAudioSound::stop() { - FSOUND_Stream_Stop(_audio); - _channel = -1; + if(!FSOUND_Stream_Stop(_audio)) { + audio_error("Stop failed!"); + } + _channel = -1; } +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioSound::finished +// Access: public +// Description: called by finishedCallback function when a sound +// terminates (but doesn't loop). +//////////////////////////////////////////////////////////////////// +void FmodAudioSound::finished() { + fmod_audio_debug("finished()"); + stop(); + if (!_finished_event.empty()) { + throw_event(_finished_event); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioSound::set_loop +// Access: public +// Description: Turns looping on and off +//////////////////////////////////////////////////////////////////// void FmodAudioSound::set_loop(bool loop) { - audio_error("FmodAudioSound::set_loop() -- not yet implemented"); fmod_audio_debug("set_loop() set to "<1 means loop that many times + // So _loop_count != 1 means we're looping + fmod_audio_debug("get_loop() returning "<<(_loop_count != 1)); + return (_loop_count != 1); } +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioSound::set_loop_count +// Access: public +// Description: +//////////////////////////////////////////////////////////////////// +void FmodAudioSound::set_loop_count(unsigned long loop_count) { + // Panda uses 0 to mean loop forever. + // Fmod uses negative numbers to mean loop forever. + // (0 means don't loop, 1 means play twice, etc.) + // We must convert! + + fmod_audio_debug("set_loop_count() set to "< #ifdef HAVE_FMOD //[ #include "audioSound.h" @@ -78,20 +78,36 @@ public: // return: playing time in seconds. float length() const; + // Controls the position of this sound's emitter. + // pos is a pointer to an xyz triplet of the emitter's position. + // vel is a pointer to an xyz triplet of the emitter's velocity. + // You can pass NULL to either value for either function to ignore that value + // if you only want to set/get one of them for some reason. + void set_3d_attributes(float px = NULL, float py = NULL, float pz = NULL, + float vx = NULL, float vy = NULL, float vz = NULL); + void get_3d_attributes(float px = NULL, float py = NULL, float pz = NULL, + float vx = NULL, float vy = NULL, float vz = NULL); + AudioSound::SoundStatus status() const; + void finished(); + protected: private: PT(FmodAudioManager) _manager; FSOUND_STREAM *_audio; string _file_name; + string _finished_event; float _volume; // 0..1.0 float _balance; // -1..1 + float _pos [3]; + float _vel [3]; unsigned long _loop_count; mutable float _length; // in seconds. bool _active; bool _paused; + bool _bExclusive; //stops all other sounds before playing when true int _channel; FmodAudioSound(FmodAudioManager* manager, FSOUND_STREAM *audio_data, diff --git a/panda/src/audiotraits/milesAudioSound.h b/panda/src/audiotraits/milesAudioSound.h index 2f2c9dda3a..80663a1788 100644 --- a/panda/src/audiotraits/milesAudioSound.h +++ b/panda/src/audiotraits/milesAudioSound.h @@ -108,6 +108,9 @@ public: // return: playing time in seconds. float length() const; + void set_3d_attributes(float* pos, float* vel); + void get_3d_attributes(float* pos, float* vel); + AudioSound::SoundStatus status() const; void finished(); diff --git a/panda/src/egg/eggTextureCollection.cxx b/panda/src/egg/eggTextureCollection.cxx index ac44342828..72fc70d50f 100644 --- a/panda/src/egg/eggTextureCollection.cxx +++ b/panda/src/egg/eggTextureCollection.cxx @@ -121,11 +121,11 @@ get_num_textures() const { // Access: Published // Description: Returns the nth EggTexture in the collection. //////////////////////////////////////////////////////////////////// -EggTexture EggTextureCollection:: +EggTexture *EggTextureCollection:: get_texture(int index) const { - nassertr(index >= 0 && index < (int)_ordered_textures.size(), EggTexture(0,0)); + nassertr(index >= 0 && index < (int)_ordered_textures.size(), NULL); - return *_ordered_textures[index]; + return _ordered_textures[index]; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/egg/eggTextureCollection.h b/panda/src/egg/eggTextureCollection.h index ab4c83ed8e..214e174143 100644 --- a/panda/src/egg/eggTextureCollection.h +++ b/panda/src/egg/eggTextureCollection.h @@ -66,7 +66,7 @@ PUBLISHED: bool is_empty() const; int get_num_textures() const; - EggTexture get_texture(int index) const; + EggTexture *get_texture(int index) const; public: EggGroupNode::iterator insert_textures(EggGroupNode *node); @@ -84,9 +84,9 @@ PUBLISHED: void uniquify_trefs(); void sort_by_tref(); +public: // Can be used to traverse all the textures in the collection, in // order as last sorted. -public: INLINE iterator begin() const; INLINE iterator end() const; INLINE bool empty() const; diff --git a/pandatool/src/progbase/programBase.cxx b/pandatool/src/progbase/programBase.cxx index 35f2c4747e..ebd9f839b0 100644 --- a/pandatool/src/progbase/programBase.cxx +++ b/pandatool/src/progbase/programBase.cxx @@ -215,6 +215,15 @@ show_text(const string &prefix, int indent_width, string text) { //////////////////////////////////////////////////////////////////// void ProgramBase:: parse_command_line(int argc, char *argv[]) { + + + // Setting this variable to zero reinitializes the options parser + // This is only necessary for processing multiple command lines in + // the same program (mainly the MaxToEgg converter plugin) + extern int optind; + optind = 0; + + _program_name = Filename::from_os_specific(argv[0]); int i; for (i = 1; i < argc; i++) {