new updates from CMU

This commit is contained in:
David Rose 2004-08-06 00:10:20 +00:00
parent d26d443f9d
commit b4eb31344f
25 changed files with 826 additions and 65 deletions

View File

@ -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)

View File

@ -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

View File

@ -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]

View File

@ -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]

View File

@ -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]]

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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?!?

View File

@ -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

View File

@ -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"

View File

@ -51,8 +51,18 @@ FmodAudioManager() {
audio_debug("FmodAudioManager::FmodAudioManager()");
audio_debug(" audio_active="<<audio_active);
audio_debug(" audio_volume="<<audio_volume);
_active = audio_active;
_volume = audio_volume;
//positional audio data
_listener_pos[0] = 0.0f; _listener_pos[1] = 0.0f; _listener_pos[2] = 0.0f;
_listener_vel[0] = 0.0f; _listener_vel[1] = 0.0f; _listener_vel[2] = 0.0f;
_listener_forward[0] = 0.0f; _listener_forward[1] = 1.0f; _listener_forward[2] = 0.0f;
_listener_up[0] = 0.0f; _listener_up[1] = 0.0f; _listener_up[2] = 1.0f;
_distance_factor = audio_distance_factor;
_doppler_factor = audio_doppler_factor;
_drop_off_factor = audio_drop_off_factor;
_cache_limit = audio_cache_limit;
_concurrent_sound_limit = 0;
@ -68,8 +78,13 @@ FmodAudioManager() {
_is_valid = false;
break;
}
// If the local system doesn't have enough hardware channels,
// Don't even bother trying to use hardware effects. Play EVERYTHING in software.
audio_debug("Setting minimum hardware channels(min="<<audio_min_hw_channels<<")");
FSOUND_SetMinHardwareChannels(audio_min_hw_channels);
if (FSOUND_Init(44100, 32, 0) == 0) {
if (FSOUND_Init(audio_output_rate, audio_cache_limit, 0) == 0) {
audio_error("Fmod initialization failure.");
_is_valid = false;
break;
@ -78,6 +93,10 @@ FmodAudioManager() {
while(0); // curious -- why is there a non-loop here?
}
// set 3D sound characteristics as they are given in the configrc
audio_3d_set_doppler_factor(audio_doppler_factor);
audio_3d_set_distance_factor(audio_distance_factor);
audio_3d_set_drop_off_factor(audio_drop_off_factor);
// increment regardless of whether an error has occured -- the
// destructor will do the right thing.
++_active_managers;
@ -137,7 +156,7 @@ is_valid() {
// Description:
////////////////////////////////////////////////////////////////////
PT(AudioSound) FmodAudioManager::
get_sound(const string &file_name) {
get_sound(const string &file_name, bool positional) {
audio_debug("FmodAudioManager::get_sound(file_name=\""<<file_name<<"\")");
if(!is_valid()) {
@ -200,6 +219,21 @@ get_sound(const string &file_name) {
// FMOD v4.0!
FSOUND_STREAM *stream = NULL;
int flags = FSOUND_LOADMEMORY | FSOUND_MPEGACCURATE;
// 3D sounds have to be mono. Forcing stereo streams
// to be mono will create a speed hit.
if (positional) {
flags |= FSOUND_HW3D | FSOUND_FORCEMONO;
} else {
flags |= FSOUND_2D;
}
if (audio_output_bits == 8) {
flags |= FSOUND_8BITS;
} else if (audio_output_bits == 16) {
flags |= FSOUND_16BITS;
}
if (audio_output_channels == 1) {
flags |= FSOUND_FORCEMONO;
}
string os_path = path.to_os_specific();
string suffix = downcase(path.get_extension());
@ -223,12 +257,16 @@ get_sound(const string &file_name) {
PT(AudioSound) audioSound = 0;
PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, stream, path,
length);
audio_debug("BOO!");
fmodAudioSound->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="<<volume<<")");
if (_volume!=volume) {
_volume = volume;
// Tell our AudioSounds to adjust:
AudioSet::iterator i=_soundsOnLoan.begin();
for (; i!=_soundsOnLoan.end(); ++i) {
(**i).set_volume((**i).get_volume());
}
}
}
////////////////////////////////////////////////////////////////////
@ -415,14 +461,15 @@ set_volume(float) {
// Description:
////////////////////////////////////////////////////////////////////
float FmodAudioManager::
get_volume() {
return 0;
get_volume() const {
audio_debug("FmodAudioManager::get_volume() returning "<<_volume);
return _volume;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::set_active
// Access: Public
// Description:
// Description: turn on/off
////////////////////////////////////////////////////////////////////
void FmodAudioManager::
set_active(bool active) {
@ -444,7 +491,8 @@ set_active(bool active) {
// Description:
////////////////////////////////////////////////////////////////////
bool FmodAudioManager::
get_active() {
get_active() const {
audio_debug("FmodAudioManager::get_active() returning "<<_active);
return _active;
}
@ -476,15 +524,28 @@ get_concurrent_sound_limit() const {
////////////////////////////////////////////////////////////////////
void FmodAudioManager::
reduce_sounds_playing_to(unsigned int count) {
// This is an example from Miles audio, this should be done for fmod:
//int limit = _sounds_playing.size() - count;
//while (limit-- > 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="<<factor<<")");
if (factor<0.0) {
audio_debug("Recieved value below 0.0. Clamping to 0.0.");
factor = 0.0;
}
}
if (_distance_factor != factor){
_distance_factor = factor;
FSOUND_3D_SetDistanceFactor(_distance_factor);
}
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::audio_3d_get_distance_factor
// Access: Public
// Description: Gets units per meter (Fmod uses meters internally for
// its sound-spacialization calculations)
////////////////////////////////////////////////////////////////////
float FmodAudioManager::
audio_3d_get_distance_factor() const {
audio_debug("FmodAudioManager::audio_3d_get_distance_factor()");
return _distance_factor;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::audio_3d_set_doppler_factor
// Access: Public
// Description: Exaggerates or diminishes the Doppler effect.
// Defaults to 1.0
////////////////////////////////////////////////////////////////////
void FmodAudioManager::
audio_3d_set_doppler_factor(float factor) {
audio_debug("FmodAudioManager::audio_3d_set_doppler_factor(factor="<<factor<<")");
if (factor<0.0) {
audio_debug("Recieved value below 0.0. Clamping to 0.0.");
factor = 0.0;
}
if (_doppler_factor != factor) {
_doppler_factor = factor;
FSOUND_3D_SetDopplerFactor(_doppler_factor);
}
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::audio_3d_get_doppler_factor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
float FmodAudioManager::
audio_3d_get_doppler_factor() const {
audio_debug("FmodAudioManager::audio_3d_get_doppler_factor()");
return _doppler_factor;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::audio_3d_set_drop_off_factor
// Access: Public
// Description: Control the effect distance has on audability.
// Defaults to 1.0
////////////////////////////////////////////////////////////////////
void FmodAudioManager::
audio_3d_set_drop_off_factor(float factor) {
audio_debug("FmodAudioManager::audio_3d_set_drop_off_factor("<<factor<<")");
if (factor<0.0) {
audio_debug("Recieved value below 0.0. Clamping to 0.0");
factor = 0.0;
}
if (_drop_off_factor != factor) {
_drop_off_factor = factor;
FSOUND_3D_SetRolloffFactor(_drop_off_factor);
}
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::audio_3d_get_drop_off_factor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
float FmodAudioManager::
audio_3d_get_drop_off_factor() const {
audio_debug("FmodAudioManager::audio_3d_get_drop_off_factor()");
return _drop_off_factor;
}
////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,6 @@
// Filename: fmodAudioManager.h
// Created by: cort (January 22, 2003)
// Extended by: ben (October 22, 2003)
// Prior system by: cary
//
////////////////////////////////////////////////////////////////////
@ -43,11 +44,11 @@ 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 count);
virtual int get_cache_limit();
virtual unsigned int get_cache_limit() const;
// Indicates that the given sound was the most recently used.
void most_recently_used(const string& path);
@ -56,18 +57,58 @@ public:
void uncache_a_sound();
virtual void set_volume(float);
virtual float get_volume();
virtual float get_volume() const;
virtual void set_active(bool);
virtual bool get_active();
virtual bool get_active() const;
virtual void set_concurrent_sound_limit(unsigned int limit = 0);
virtual unsigned int get_concurrent_sound_limit() const;
virtual void reduce_sounds_playing_to(unsigned int count);
//virtual void stop_a_sound();
virtual void stop_all_sounds();
// 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();
// 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 xy, float xz,
float fx, float fy, float fz,
float ux, float uy, float uz);
// 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);
// 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);
virtual float audio_3d_get_distance_factor() const;
// 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);
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<FmodAudioSound* > SoundsPlaying;
// The sounds from this manager that are currently playing
SoundsPlaying _sounds_playing;
// The Least Recently Used mechanism:
typedef pdeque<string> 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;

View File

@ -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="<<file_name<<")");
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::~FmodAudioSound
// Access: public
// Description: destructor
////////////////////////////////////////////////////////////////////
FmodAudioSound::
~FmodAudioSound() {
fmod_audio_debug("~FmodAudioSound()");
this->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 "<<loop);
unsigned int mode = FSOUND_Stream_GetMode(_audio);
if (loop) {
// turn looping on
FSOUND_Stream_SetMode(_audio, mode | FSOUND_LOOP_NORMAL);
} else {
// turn looping off if and only if it is on
if (FSOUND_LOOP_NORMAL == (mode & FSOUND_LOOP_NORMAL)) {
FSOUND_Stream_SetMode(_audio, mode ^ FSOUND_LOOP_NORMAL);
}
}
// default to loop infinitely
_loop_count = loop ? 0 : 1;
FSOUND_Stream_SetLoopCount(_audio, _loop_count - 1);
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_loop
// Access: public
// Description: Returns whether looping is on or off
////////////////////////////////////////////////////////////////////
bool FmodAudioSound::get_loop() const {
fmod_audio_debug("get_loop() returning "<<(_loop_count==0));
return (_loop_count == 0);
}
void FmodAudioSound::set_loop_count(unsigned long loop_count) {
audio_error("FmodAudioSound::set_loop_count() -- not yet implemented");
fmod_audio_debug("set_loop_count() set to "<<loop_count);
_loop_count = loop_count;
// 0 means loop forever,
// >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 "<<loop_count);
if (loop_count < 0) {
fmod_audio_debug("Value out of bounds. Default to loop infinitely.");
loop_count = 0;
}
_loop_count = loop_count;
loop_count -= 1;
FSOUND_Stream_SetLoopCount(_audio, loop_count);
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_loop_count
// Access: public
// Description:
////////////////////////////////////////////////////////////////////
unsigned long FmodAudioSound::get_loop_count() const {
fmod_audio_debug("get_loop_count() returning "<<_loop_count);
return _loop_count;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::set_time
// Access: public
// Description: Sets the play position within the sound
////////////////////////////////////////////////////////////////////
void FmodAudioSound::set_time(float start_time) {
if (start_time < 0.0f) {
fmod_audio_debug("set_time(): param "<<start_time<<" out of range.");
@ -136,6 +267,11 @@ void FmodAudioSound::set_time(float start_time) {
FSOUND_Stream_SetTime(_audio, (int)(start_time * 1000.0f));
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_time
// Access: public
// Description: Gets the play position within the sound
////////////////////////////////////////////////////////////////////
float FmodAudioSound::get_time() const {
// A bug in stream WAV files causes FSOUND_Stream_GetTime() to
// divide-by-zero somewhere if the stream isn't currently playing.
@ -150,6 +286,12 @@ float FmodAudioSound::get_time() const {
return current_time;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::set_volume
// Access: public
// Description: 0.0 to 1.0 scale of volume converted to Fmod's
// internal 0.0 to 255.0 scale.
////////////////////////////////////////////////////////////////////
void FmodAudioSound::set_volume(float vol) {
if (vol < 0.0f) {
fmod_audio_debug("set_volume(): param "<<vol<<" out of range.");
@ -165,11 +307,21 @@ void FmodAudioSound::set_volume(float vol) {
FSOUND_SetVolume(_channel, new_volume);
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_volume
// Access: public
// Description:
////////////////////////////////////////////////////////////////////
float FmodAudioSound::get_volume() const {
fmod_audio_debug("get_volume() returning "<<_volume);
return _volume;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::set_balance
// Access: public
// Description: -1.0 to 1.0 scale
////////////////////////////////////////////////////////////////////
void FmodAudioSound::set_balance(float bal) {
if (bal < -1.0f) {
fmod_audio_debug("set_balance(): param "<<bal<<" out of range.");
@ -185,11 +337,21 @@ void FmodAudioSound::set_balance(float bal) {
FSOUND_SetPan(_channel, new_balance);
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_balance
// Access: public
// Description:
////////////////////////////////////////////////////////////////////
float FmodAudioSound::get_balance() const {
fmod_audio_debug("get_balance() returning "<<_balance);
return _balance;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::set_active
// Access: public
// Description:
////////////////////////////////////////////////////////////////////
void FmodAudioSound::set_active(bool active) {
fmod_audio_debug("set_active(active="<<active<<")");
if (!active) {
@ -200,20 +362,99 @@ void FmodAudioSound::set_active(bool active) {
_active = active;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_active
// Access: public
// Description:
////////////////////////////////////////////////////////////////////
bool FmodAudioSound::get_active() const {
fmod_audio_debug("get_active() returning "<<_active);
return _active;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::set_finished_event
// Access: public
// Description: Assign a string for the finished event to be referenced
// by in python by an accept method
////////////////////////////////////////////////////////////////////
void FmodAudioSound::
set_finished_event(const string& event) {
fmod_audio_debug("set_finished_event(event="<<event<<")");
_finished_event = event;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_finished_event
// Access: public
// Description: Return the string the finished event is referenced by
////////////////////////////////////////////////////////////////////
const string& FmodAudioSound::
get_finished_event() const {
fmod_audio_debug("get_finished_event() returning "<<_finished_event);
return _finished_event;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_name
// Access: public
// Description: Get name of sound file
////////////////////////////////////////////////////////////////////
const string& FmodAudioSound::get_name() const {
//fmod_audio_debug("get_name() returning "<<_file_name);
fmod_audio_debug("get_name() returning "<<_file_name);
return _file_name;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::length
// Access: public
// Description: Get length
////////////////////////////////////////////////////////////////////
float FmodAudioSound::length() const {
return _length;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::set_3d_attributes
// Access: public
// Description: Set position and velocity of this sound
////////////////////////////////////////////////////////////////////
void FmodAudioSound::
set_3d_attributes(float px, float py, float pz, float vx, float vy, float vz) {
fmod_audio_debug("Set 3d position and velocity (px="<<px<<", py="<<py<<", pz="<<pz<<", vx="<<vx<<", vy="<<vy<<", vz="<<vz<<")");
_pos[0] = px; _pos[1] = py; _pos[2] = pz;
_vel[0] = vx; _vel[1] = vy; _vel[2] = vz;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::get_3d_attributes
// Access: public
// Description: Get position and velocity of this sound
////////////////////////////////////////////////////////////////////
void FmodAudioSound::
get_3d_attributes(float px, float py, float pz, float vx, float vy, float vz) {
audio_error("get3dAttributes: Currently unimplemented. Get the attributes of the attached object.");
// 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};
//FSOUND_3D_GetAttributes(_channel, pos, vel);
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioSound::status
// Access: public
// Description: Get status of the sound.
////////////////////////////////////////////////////////////////////
AudioSound::SoundStatus FmodAudioSound::status() const {
// If the stream's channel isn't playing anything, then the stream
// definitely isn't playing.

View File

@ -20,7 +20,7 @@
#ifndef __FMOD_AUDIO_SOUND_H__
#define __FMOD_AUDIO_SOUND_H__
#include "pandabase.h"
#include <pandabase.h>
#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,

View File

@ -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();

View File

@ -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];
}
////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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++) {