Browse Source

added audioVolumeAttrib

Darren Ranalli 19 years ago
parent
commit
2a6b1cb479

+ 3 - 0
panda/src/pgraph/Sources.pp

@@ -17,6 +17,7 @@
     ambientLight.I ambientLight.h \
     antialiasAttrib.I antialiasAttrib.h \
     attribSlots.h attribSlots.I \
+    audioVolumeAttrib.I audioVolumeAttrib.h \
     auxSceneData.I auxSceneData.h \
     bamFile.I bamFile.h \
     billboardEffect.I billboardEffect.h \
@@ -124,6 +125,7 @@
     ambientLight.cxx \
     antialiasAttrib.cxx \
     attribSlots.cxx \
+    audioVolumeAttrib.cxx \
     auxSceneData.cxx \
     bamFile.cxx \
     billboardEffect.cxx \
@@ -226,6 +228,7 @@
     ambientLight.I ambientLight.h \
     antialiasAttrib.I antialiasAttrib.h \
     attribSlots.h attribSlots.I \
+    audioVolumeAttrib.I audioVolumeAttrib.h \
     auxSceneData.I auxSceneData.h \
     bamFile.I bamFile.h \
     billboardEffect.I billboardEffect.h \

+ 2 - 0
panda/src/pgraph/attribSlots.h

@@ -48,6 +48,7 @@
 #include "texGenAttrib.h"
 #include "textureAttrib.h"
 #include "transparencyAttrib.h"
+#include "audioVolumeAttrib.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : AttribSlots
@@ -82,6 +83,7 @@ class EXPCL_PANDA AttribSlots
   CPT(TexMatrixAttrib)       _tex_matrix;
   CPT(TextureAttrib)         _texture;
   CPT(TransparencyAttrib)    _transparency;
+  CPT(AudioVolumeAttrib)     _audio_volume;
 
  public:
   AttribSlots();

+ 68 - 0
panda/src/pgraph/audioVolumeAttrib.I

@@ -0,0 +1,68 @@
+// Filename: audioVolumeAttrib.I
+// Created by:  darren (15Dec06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::Copy Constructor
+//       Access: Protected
+//  Description: Use AudioVolumeAttrib::make() to construct a new
+//               AudioVolumeAttrib object.
+////////////////////////////////////////////////////////////////////
+INLINE AudioVolumeAttrib::
+AudioVolumeAttrib(const AudioVolumeAttrib &copy) :
+  _off(copy._off),
+  _has_volume(copy._has_volume),
+  _volume(copy._volume)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::is_off
+//       Access: Published
+//  Description: Returns true if the AudioVolumeAttrib will ignore any
+//               color scales inherited from above, false otherwise.
+//               This is not the same thing as !has_scale(); a
+//               AudioVolumeAttrib may have the "off" flag set and also
+//               have another scale specified.
+////////////////////////////////////////////////////////////////////
+INLINE bool AudioVolumeAttrib::
+is_off() const {
+  return _off;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::has_volume
+//       Access: Published
+//  Description: Returns true if the AudioVolumeAttrib has a
+//               non-identity volume, false otherwise (in which case it
+//               might be an off attrib or an identity attrib).
+////////////////////////////////////////////////////////////////////
+INLINE bool AudioVolumeAttrib::
+has_volume() const {
+  return _has_volume;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::get_volume
+//       Access: Published
+//  Description: Returns the volume to be applied to sounds.
+////////////////////////////////////////////////////////////////////
+INLINE float AudioVolumeAttrib::
+get_volume() const {
+  return _volume;
+}

+ 307 - 0
panda/src/pgraph/audioVolumeAttrib.cxx

@@ -0,0 +1,307 @@
+// Filename: audioVolumeAttrib.cxx
+// Created by:  darren (15Dec06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "audioVolumeAttrib.h"
+#include "attribSlots.h"
+#include "graphicsStateGuardianBase.h"
+#include "dcast.h"
+#include "bamReader.h"
+#include "bamWriter.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+#include "config_pgraph.h"
+
+TypeHandle AudioVolumeAttrib::_type_handle;
+CPT(RenderAttrib) AudioVolumeAttrib::_identity_attrib;
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::Constructor
+//       Access: Protected
+//  Description: Use AudioVolumeAttrib::make() to construct a new
+//               AudioVolumeAttrib object.
+////////////////////////////////////////////////////////////////////
+AudioVolumeAttrib::
+AudioVolumeAttrib(bool off, float volume) :
+  _off(off),
+  _volume(volume)
+{
+  nassertv(_volume >= 0.f);
+  _has_volume = !IS_NEARLY_EQUAL(_volume, 1.0f);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::make_identity
+//       Access: Published, Static
+//  Description: Constructs an identity audio volume attrib.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AudioVolumeAttrib::
+make_identity() {
+  // We make identity a special case and store a pointer forever once
+  // we find it the first time.
+  if (_identity_attrib == (AudioVolumeAttrib *)NULL) {
+    AudioVolumeAttrib *attrib = new AudioVolumeAttrib(false, 1.0f);;
+    _identity_attrib = return_new(attrib);
+  }
+
+  return _identity_attrib;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::make
+//       Access: Published, Static
+//  Description: Constructs a new AudioVolumeAttrib object that indicates
+//               audio volume should be scaled by the indicated factor.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AudioVolumeAttrib::
+make(float volume) {
+  AudioVolumeAttrib *attrib = new AudioVolumeAttrib(false, volume);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::make_off
+//       Access: Published, Static
+//  Description: Constructs a new AudioVolumeAttrib object that ignores
+//               any AudioVolumeAttrib inherited from above.  You may
+//               also specify an additional volume scale to apply to
+//               geometry below (using set_volume()).
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AudioVolumeAttrib::
+make_off() {
+  AudioVolumeAttrib *attrib = 
+    new AudioVolumeAttrib(true, 1.0f);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::set_volume
+//       Access: Published
+//  Description: Returns a new AudioVolumeAttrib, just like this one, but
+//               with the volume changed to the indicated value.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AudioVolumeAttrib::
+set_volume(float volume) const {
+  AudioVolumeAttrib *attrib = new AudioVolumeAttrib(*this);
+  assert(volume >= 0.f);
+  attrib->_volume = volume;
+  attrib->_has_volume = !IS_NEARLY_EQUAL(volume, 1.0f);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void AudioVolumeAttrib::
+output(ostream &out) const {
+  out << get_type() << ":";
+  if (is_off()) {
+    out << "off";
+  }
+  if (has_volume()) {
+    out << "(" << get_volume() << ")";
+
+  } else if (!is_off()) {
+    out << "identity";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::compare_to_impl
+//       Access: Protected, Virtual
+//  Description: Intended to be overridden by derived AudioVolumeAttrib
+//               types to return a unique number indicating whether
+//               this AudioVolumeAttrib is equivalent to the other one.
+//
+//               This should return 0 if the two AudioVolumeAttrib objects
+//               are equivalent, a number less than zero if this one
+//               should be sorted before the other one, and a number
+//               greater than zero otherwise.
+//
+//               This will only be called with two AudioVolumeAttrib
+//               objects whose get_type() functions return the same.
+////////////////////////////////////////////////////////////////////
+int AudioVolumeAttrib::
+compare_to_impl(const RenderAttrib *other) const {
+  const AudioVolumeAttrib *ta;
+  DCAST_INTO_R(ta, other, 0);
+
+  if (is_off() != ta->is_off()) {
+    if (pgraph_cat.is_spam()) {
+      pgraph_cat.spam()
+        << "Comparing " << (int)is_off() << " to " << (int)ta->is_off() << " result = "
+        << (int)is_off() - (int)ta->is_off() << "\n";
+    }
+    
+    return (int)is_off() - (int)ta->is_off();
+  }
+
+  int result = int(_volume * 1000.0f) - int(ta->_volume * 1000.0f);
+  if (pgraph_cat.is_spam()) {
+    pgraph_cat.spam()
+      << "Comparing " << _volume << " to " << ta->_volume << " result = "
+      << result << "\n";
+  }
+
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::compose_impl
+//       Access: Protected, Virtual
+//  Description: Intended to be overridden by derived RenderAttrib
+//               types to specify how two consecutive RenderAttrib
+//               objects of the same type interact.
+//
+//               This should return the result of applying the other
+//               RenderAttrib to a node in the scene graph below this
+//               RenderAttrib, which was already applied.  In most
+//               cases, the result is the same as the other
+//               RenderAttrib (that is, a subsequent RenderAttrib
+//               completely replaces the preceding one).  On the other
+//               hand, some kinds of RenderAttrib (for instance,
+//               ColorTransformAttrib) might combine in meaningful
+//               ways.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AudioVolumeAttrib::
+compose_impl(const RenderAttrib *other) const {
+  const AudioVolumeAttrib *ta;
+  DCAST_INTO_R(ta, other, 0);
+
+  if (ta->is_off()) {
+    return ta;
+  }
+
+  AudioVolumeAttrib *attrib = new AudioVolumeAttrib(is_off(), ta->_volume * _volume);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::invert_compose_impl
+//       Access: Protected, Virtual
+//  Description: Intended to be overridden by derived RenderAttrib
+//               types to specify how two consecutive RenderAttrib
+//               objects of the same type interact.
+//
+//               See invert_compose() and compose_impl().
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AudioVolumeAttrib::
+invert_compose_impl(const RenderAttrib *other) const {
+  if (is_off()) {
+    return other;
+  }
+  const AudioVolumeAttrib *ta;
+  DCAST_INTO_R(ta, other, 0);
+  float new_volume = _volume == 0.0f ? 1.0f : ta->_volume / _volume;
+
+  AudioVolumeAttrib *attrib = new AudioVolumeAttrib(false, new_volume);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::make_default_impl
+//       Access: Protected, Virtual
+//  Description: Intended to be overridden by derived AudioVolumeAttrib
+//               types to specify what the default property for a
+//               AudioVolumeAttrib of this type should be.
+//
+//               This should return a newly-allocated AudioVolumeAttrib of
+//               the same type that corresponds to whatever the
+//               standard default for this kind of AudioVolumeAttrib is.
+////////////////////////////////////////////////////////////////////
+RenderAttrib *AudioVolumeAttrib::
+make_default_impl() const {
+  return new AudioVolumeAttrib(false, 1.0f);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::store_into_slot
+//       Access: Public, Virtual
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
+////////////////////////////////////////////////////////////////////
+void AudioVolumeAttrib::
+store_into_slot(AttribSlots *slots) const {
+  slots->_audio_volume = this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               AudioVolumeAttrib.
+////////////////////////////////////////////////////////////////////
+void AudioVolumeAttrib::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void AudioVolumeAttrib::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  RenderAttrib::write_datagram(manager, dg);
+
+  // We cheat, and modify the bam stream without upping the bam
+  // version.  We can do this since we know that no existing bam files
+  // have an AudioVolumeAttrib in them.
+  dg.add_bool(_off);
+  dg.add_float32(_volume);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type AudioVolumeAttrib is encountered
+//               in the Bam file.  It should create the AudioVolumeAttrib
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *AudioVolumeAttrib::
+make_from_bam(const FactoryParams &params) {
+  AudioVolumeAttrib *attrib = new AudioVolumeAttrib(false, 1.0f);
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  attrib->fillin(scan, manager);
+
+  return attrib;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new AudioVolumeAttrib.
+////////////////////////////////////////////////////////////////////
+void AudioVolumeAttrib::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  RenderAttrib::fillin(scan, manager);
+
+  _off = scan.get_bool();
+  _volume = scan.get_float32();
+  nassertv(_volume >= 0.f);
+  _has_volume = !IS_NEARLY_EQUAL(_volume, 1.0f);
+}

+ 94 - 0
panda/src/pgraph/audioVolumeAttrib.h

@@ -0,0 +1,94 @@
+// Filename: audioVolumeAttrib.h
+// Created by:  darren (15Dec06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef AUDIOVOLUMEATTRIB_H
+#define AUDIOVOLUMEATTRIB_H
+
+#include "pandabase.h"
+
+#include "renderAttrib.h"
+#include "luse.h"
+
+class FactoryParams;
+
+////////////////////////////////////////////////////////////////////
+//       Class : AudioVolumeAttrib
+// Description : Applies a scale to audio volume for positional sounds
+//               in the scene graph.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA AudioVolumeAttrib : public RenderAttrib {
+protected:
+  AudioVolumeAttrib(bool off, float volume);
+  INLINE AudioVolumeAttrib(const AudioVolumeAttrib &copy);
+
+PUBLISHED:
+  static CPT(RenderAttrib) make_identity();
+  static CPT(RenderAttrib) make(float volume);
+  static CPT(RenderAttrib) make_off();
+
+  INLINE bool is_off() const;
+  INLINE bool has_volume() const;
+  INLINE float get_volume() const;
+  CPT(RenderAttrib) set_volume(float volume) const;
+
+public:
+  virtual void output(ostream &out) const;
+  virtual void store_into_slot(AttribSlots *slots) const;
+
+protected:
+  virtual int compare_to_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
+  virtual RenderAttrib *make_default_impl() const;
+
+private:
+  bool _off;
+  bool _has_volume;
+  float _volume;
+  static CPT(RenderAttrib) _identity_attrib;
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    RenderAttrib::init_type();
+    register_type(_type_handle, "AudioVolumeAttrib",
+                  RenderAttrib::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "audioVolumeAttrib.I"
+
+#endif
+

+ 3 - 0
panda/src/pgraph/config_pgraph.cxx

@@ -19,6 +19,7 @@
 #include "config_pgraph.h"
 
 #include "alphaTestAttrib.h"
+#include "audioVolumeAttrib.h"
 #include "ambientLight.h"
 #include "antialiasAttrib.h"
 #include "auxSceneData.h"
@@ -296,6 +297,7 @@ init_libpgraph() {
   AlphaTestAttrib::init_type();
   AmbientLight::init_type();
   AntialiasAttrib::init_type();
+  AudioVolumeAttrib::init_type();
   AuxSceneData::init_type();
   BillboardEffect::init_type();
   Camera::init_type();
@@ -381,6 +383,7 @@ init_libpgraph() {
   AlphaTestAttrib::register_with_read_factory();
   AmbientLight::register_with_read_factory();
   AntialiasAttrib::register_with_read_factory();
+  AudioVolumeAttrib::register_with_read_factory();
   BillboardEffect::register_with_read_factory();
   Camera::register_with_read_factory();
   ClipPlaneAttrib::register_with_read_factory();

+ 115 - 0
panda/src/pgraph/nodePath.cxx

@@ -45,6 +45,7 @@
 #include "showBoundsEffect.h"
 #include "transparencyAttrib.h"
 #include "antialiasAttrib.h"
+#include "audioVolumeAttrib.h"
 #include "texProjectorEffect.h"
 #include "texturePool.h"
 #include "planeNode.h"
@@ -5241,6 +5242,120 @@ get_antialias() const {
   return AntialiasAttrib::M_none;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::has_audio_volume
+//       Access: Published
+//  Description: Returns true if an audio volume has been applied
+//               to the referenced node, false otherwise.  It is still
+//               possible that volume at this node might have been
+//               scaled by an ancestor node.
+////////////////////////////////////////////////////////////////////
+bool NodePath::
+has_audio_volume() const {
+  nassertr_always(!is_empty(), false);
+  return node()->has_attrib(AudioVolumeAttrib::get_class_type());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::clear_audio_volume
+//       Access: Published
+//  Description: Completely removes any audio volume from the
+//               referenced node.  This is preferable to simply
+//               setting the audio volume to identity, as it also
+//               removes the overhead associated with having an audio
+//               volume at all.
+////////////////////////////////////////////////////////////////////
+void NodePath::
+clear_audio_volume() {
+  nassertv_always(!is_empty());
+  node()->clear_attrib(AudioVolumeAttrib::get_class_type());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_audio_volume
+//       Access: Published
+//  Description: Sets the audio volume component of the transform
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_audio_volume(float volume, int priority) {
+  nassertv_always(!is_empty());
+
+  const RenderAttrib *attrib =
+    node()->get_attrib(AudioVolumeAttrib::get_class_type());
+  if (attrib != (const RenderAttrib *)NULL) {
+    priority = max(priority,
+                   node()->get_state()->get_override(AudioVolumeAttrib::get_class_type()));
+    CPT(AudioVolumeAttrib) ava = DCAST(AudioVolumeAttrib, attrib);
+
+    // Modify the existing AudioVolumeAttrib to add the indicated
+    // volume.
+    node()->set_attrib(ava->set_volume(volume), priority);
+
+  } else {
+    // Create a new AudioVolumeAttrib for this node.
+    node()->set_attrib(AudioVolumeAttrib::make(volume), priority);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_audio_volume_off
+//       Access: Published
+//  Description: Disables any audio volume attribute inherited from
+//               above.  This is not the same thing as
+//               clear_audio_volume(), which undoes any previous
+//               set_audio_volume() operation on this node; rather,
+//               this actively disables any set_audio_volume() that
+//               might be inherited from a parent node.
+//
+//               It is legal to specify a new volume on the same
+//               node with a subsequent call to set_audio_volume();
+//               this new scale will apply to lower nodes.
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_audio_volume_off(int priority) {
+  nassertv_always(!is_empty());
+  node()->set_attrib(AudioVolumeAttrib::make_off(), priority);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::get_audio_volume
+//       Access: Published
+//  Description: Returns the complete audio volume that has been
+//               applied to this node via a previous call to
+//               set_audio_volume(), or 1. (identity) if no volume has
+//               been applied to this particular node.
+////////////////////////////////////////////////////////////////////
+float NodePath::
+get_audio_volume() const {
+  const RenderAttrib *attrib =
+    node()->get_attrib(AudioVolumeAttrib::get_class_type());
+  if (attrib != (const RenderAttrib *)NULL) {
+    const AudioVolumeAttrib *ava = DCAST(AudioVolumeAttrib, attrib);
+    return ava->get_volume();
+  }
+
+  return 1.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::get_net_audio_volume
+//       Access: Published
+//  Description: Returns the complete audio volume for this node
+//               taking highers nodes in the graph into account.
+////////////////////////////////////////////////////////////////////
+float NodePath::
+get_net_audio_volume() const {
+  CPT(RenderState) net_state = get_net_state();
+  const RenderAttrib *attrib = net_state->get_audio_volume();
+  if (attrib != (const RenderAttrib *)NULL) {
+    const AudioVolumeAttrib *ava = DCAST(AudioVolumeAttrib, attrib);
+    if (ava != (const AudioVolumeAttrib *)NULL) {
+      return ava->get_volume();
+    }
+  }
+
+  return 1.0f;
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::get_hidden_ancestor

+ 8 - 0
panda/src/pgraph/nodePath.h

@@ -747,6 +747,14 @@ PUBLISHED:
   bool has_antialias() const;
   unsigned short get_antialias() const;
 
+  bool has_audio_volume() const;
+  void clear_audio_volume();
+  void set_audio_volume(float volume,
+                        int priority = 0);
+  void set_audio_volume_off(int priority = 0);
+  float get_audio_volume() const;
+  float get_net_audio_volume() const;
+
   INLINE void adjust_all_priorities(int adjustment);
 
   // Variants on show and hide

+ 1 - 0
panda/src/pgraph/pgraph_composite1.cxx

@@ -1,6 +1,7 @@
 #include "accumulatedAttribs.cxx"
 #include "ambientLight.cxx"
 #include "antialiasAttrib.cxx"
+#include "audioVolumeAttrib.cxx"
 #include "auxSceneData.cxx"
 #include "attribSlots.cxx"
 #include "bamFile.cxx"

+ 19 - 0
panda/src/pgraph/renderState.I

@@ -389,6 +389,25 @@ get_shader() const {
   return _shader;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::get_audio_volume
+//       Access: Published
+//  Description: This function is provided as an optimization, to
+//               speed up the render-time checking for the existance
+//               of an AudioVolumeAttrib on this state.  It returns a
+//               pointer to the AudioVolumeAttrib, if there is one, or
+//               NULL if there is not.
+////////////////////////////////////////////////////////////////////
+INLINE const AudioVolumeAttrib *RenderState::
+get_audio_volume() const {
+  if ((_flags & F_checked_audio_volume) == 0) {
+    // We pretend this function is const, even though it transparently
+    // modifies the internal audio_volume cache.
+    ((RenderState *)this)->determine_audio_volume();
+  }
+  return _audio_volume;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::determine_bin
 //       Access: Private

+ 21 - 0
panda/src/pgraph/renderState.cxx

@@ -1775,6 +1775,27 @@ determine_cull_callback() {
   _flags |= F_checked_cull_callback;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::determine_audio_volume
+//       Access: Private
+//  Description: This is the private implementation of has_audio_volume().
+////////////////////////////////////////////////////////////////////
+void RenderState::
+determine_audio_volume() {
+  MutexHolder holder(_lock);
+  if ((_flags & F_checked_audio_volume) != 0) {
+    // Someone else checked it first.
+    return;
+  }
+
+  const RenderAttrib *attrib = get_attrib(AudioVolumeAttrib::get_class_type());
+  _audio_volume = (const AudioVolumeAttrib *)NULL;
+  if (attrib != (const RenderAttrib *)NULL) {
+    _audio_volume = DCAST(AudioVolumeAttrib, attrib);
+  }
+  _flags |= F_checked_audio_volume;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::update_pstats
 //       Access: Private

+ 6 - 1
panda/src/pgraph/renderState.h

@@ -47,6 +47,7 @@ class TexGenAttrib;
 class ClipPlaneAttrib;
 class ShaderAttrib;
 class FactoryParams;
+class AudioVolumeAttrib;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : RenderState
@@ -147,6 +148,7 @@ PUBLISHED:
   INLINE const RenderModeAttrib *get_render_mode() const;
   INLINE const ClipPlaneAttrib *get_clip_plane() const;
   INLINE const ShaderAttrib *get_shader() const;
+  INLINE const AudioVolumeAttrib *get_audio_volume() const;
   
   int get_geom_rendering(int geom_rendering) const;
 
@@ -197,6 +199,7 @@ private:
   void determine_clip_plane();
   void determine_shader();
   void determine_cull_callback();
+  void determine_audio_volume();
 
   INLINE void set_destructing();
   INLINE bool is_destructing() const;
@@ -308,6 +311,7 @@ private:
   const RenderModeAttrib *_render_mode;
   const ClipPlaneAttrib *_clip_plane;
   const ShaderAttrib *_shader;
+  const AudioVolumeAttrib *_audio_volume;
   
   enum Flags {
     F_checked_bin_index     = 0x0001,
@@ -323,7 +327,8 @@ private:
     F_checked_clip_plane    = 0x0400,
     F_checked_shader        = 0x0800,
     F_checked_cull_callback = 0x1000,
-    F_has_cull_callback     = 0x2000,
+    F_checked_audio_volume  = 0x2000,
+    F_has_cull_callback     = 0x4000,
     F_is_destructing        = 0x8000,
   };
   unsigned short _flags;