Переглянути джерело

robustify light interface further

David Rose 21 роки тому
батько
коміт
64aece121a

+ 3 - 3
panda/src/display/graphicsStateGuardian.I

@@ -484,11 +484,11 @@ get_coordinate_system() const {
 //     Function: GraphicsStateGuardian::get_light
 //       Access: Protected
 //  Description: Returns the Light object that is bound to the
-//               indicated id, or NULL if no Light is bound.
+//               indicated id, or empty NodePath if no Light is bound.
 ////////////////////////////////////////////////////////////////////
-INLINE Light *GraphicsStateGuardian::
+INLINE NodePath GraphicsStateGuardian::
 get_light(int light_id) const {
-  nassertr(light_id >= 0 && light_id < (int)_light_info.size(), (Light *)NULL);
+  nassertr(light_id >= 0 && light_id < (int)_light_info.size(), NodePath::fail());
   return _light_info[light_id]._light;
 }
 

+ 13 - 12
panda/src/display/graphicsStateGuardian.cxx

@@ -335,7 +335,7 @@ begin_frame() {
         enable_light(i, false);
         _light_info[i]._enabled = false;
       }
-      _light_info[i]._light = (Light *)NULL;
+      _light_info[i]._light = NodePath();
     }
 
     // Also force the lighting state to unlit, so that issue_light()
@@ -683,8 +683,9 @@ issue_light(const LightAttrib *attrib) {
   int num_enabled = 0;
   int num_on_lights = attrib->get_num_on_lights();
   for (int li = 0; li < num_on_lights; li++) {
-    Light *light = attrib->get_on_light(li);
-    nassertv(light != (Light *)NULL);
+    NodePath light = attrib->get_on_light(li);
+    nassertv(!light.is_empty() && light.node()->as_light() != (Light *)NULL);
+    Light *light_obj = light.node()->as_light();
 
     num_enabled++;
 
@@ -693,10 +694,10 @@ issue_light(const LightAttrib *attrib) {
     _lighting_enabled = true;
     _lighting_enabled_this_frame = true;
 
-    if (light->get_type() == AmbientLight::get_class_type()) {
+    if (light_obj->get_type() == AmbientLight::get_class_type()) {
       // Ambient lights don't require specific light ids; simply add
       // in the ambient contribution to the current total
-      cur_ambient_light += light->get_color();
+      cur_ambient_light += light_obj->get_color();
         
     } else {
       // Check to see if this light has already been bound to an id
@@ -716,7 +717,7 @@ issue_light(const LightAttrib *attrib) {
       // See if there are any unbound light ids
       if (cur_light_id == -1) {
         for (i = 0; i < max_lights; i++) {
-          if (_light_info[i]._light == (Light *)NULL) {
+          if (_light_info[i]._light.is_empty()) {
             _light_info[i]._light = light;
             cur_light_id = i;
             break;
@@ -728,7 +729,7 @@ issue_light(const LightAttrib *attrib) {
       // a currently unused but previously bound id
       if (cur_light_id == -1) {
         for (i = 0; i < max_lights; i++) {
-          if (!attrib->has_light(_light_info[i]._light)) {
+          if (!attrib->has_on_light(_light_info[i]._light)) {
             _light_info[i]._light = light;
             cur_light_id = i;
             break;
@@ -758,11 +759,11 @@ issue_light(const LightAttrib *attrib) {
 
         // This is the first time this frame that this light has been
         // bound to this particular id.
-        light->bind(this, cur_light_id);
+        light_obj->bind(this, light, cur_light_id);
 
       } else if (cur_light_id == -1) {
         gsg_cat.warning()
-          << "Failed to bind " << *light << " to id.\n";
+          << "Failed to bind " << light << " to id.\n";
       }
     }
   }
@@ -949,7 +950,7 @@ issue_clip_plane(const ClipPlaneAttrib *attrib) {
 //               properties.
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
-bind_light(PointLight *light, int light_id) {
+bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -961,7 +962,7 @@ bind_light(PointLight *light, int light_id) {
 //               properties.
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
-bind_light(DirectionalLight *light, int light_id) {
+bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -973,7 +974,7 @@ bind_light(DirectionalLight *light, int light_id) {
 //               properties.
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
-bind_light(Spotlight *light, int light_id) {
+bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
 }
 
 ////////////////////////////////////////////////////////////////////

+ 8 - 5
panda/src/display/graphicsStateGuardian.h

@@ -165,12 +165,15 @@ public:
   virtual void issue_color_blend(const ColorBlendAttrib *attrib);
   virtual void issue_clip_plane(const ClipPlaneAttrib *attrib);
 
-  virtual void bind_light(PointLight *light, int light_id);
-  virtual void bind_light(DirectionalLight *light, int light_id);
-  virtual void bind_light(Spotlight *light, int light_id);
+  virtual void bind_light(PointLight *light_obj, const NodePath &light, 
+                          int light_id);
+  virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
+                          int light_id);
+  virtual void bind_light(Spotlight *light_obj, const NodePath &light,
+                          int light_id);
 
 protected:
-  INLINE Light *get_light(int light_id) const;
+  INLINE NodePath get_light(int light_id) const;
   virtual bool slot_new_light(int light_id);
   virtual void enable_lighting(bool enable);
   virtual void set_ambient_light(const Colorf &color);
@@ -301,7 +304,7 @@ private:
   class LightInfo {
   public:
     INLINE LightInfo();
-    PT(Light) _light;
+    NodePath _light;
     bool _enabled;
     bool _next_enabled;
   };

+ 18 - 21
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -2728,18 +2728,17 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) {
 //               properties.
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
-bind_light(PointLight *light, int light_id) {
+bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
   GLenum id = get_light_id(light_id);
   static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
   GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
-  GLP(Lightfv)(id, GL_DIFFUSE, light->get_color().get_data());
-  GLP(Lightfv)(id, GL_SPECULAR, light->get_specular_color().get_data());
+  GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
+  GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
 
   // Position needs to specify x, y, z, and w
   // w == 1 implies non-infinite position
-  NodePath light_np(light);
-  const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
-  LPoint3f pos = light->get_point() * light_mat;
+  const LMatrix4f &light_mat = light.get_mat(_scene_setup->get_scene_root());
+  LPoint3f pos = light_obj->get_point() * light_mat;
 
   LPoint4f fpos(pos[0], pos[1], pos[2], 1.0f);
   GLP(Lightfv)(id, GL_POSITION, fpos.get_data());
@@ -2752,7 +2751,7 @@ bind_light(PointLight *light, int light_id) {
   // Cutoff == 180 means uniform point light source
   GLP(Lightf)(id, GL_SPOT_CUTOFF, 180.0f);
 
-  const LVecBase3f &att = light->get_attenuation();
+  const LVecBase3f &att = light_obj->get_attenuation();
   GLP(Lightf)(id, GL_CONSTANT_ATTENUATION, att[0]);
   GLP(Lightf)(id, GL_LINEAR_ATTENUATION, att[1]);
   GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, att[2]);
@@ -2769,18 +2768,17 @@ bind_light(PointLight *light, int light_id) {
 //               properties.
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
-bind_light(DirectionalLight *light, int light_id) {
+bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
   GLenum id = get_light_id( light_id );
   static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
   GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
-  GLP(Lightfv)(id, GL_DIFFUSE, light->get_color().get_data());
-  GLP(Lightfv)(id, GL_SPECULAR, light->get_specular_color().get_data());
+  GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
+  GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
 
   // Position needs to specify x, y, z, and w.
   // w == 0 implies light is at infinity
-  NodePath light_np(light);
-  const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
-  LVector3f dir = light->get_direction() * light_mat;
+  const LMatrix4f &light_mat = light.get_mat(_scene_setup->get_scene_root());
+  LVector3f dir = light_obj->get_direction() * light_mat;
   LPoint4f fdir(-dir[0], -dir[1], -dir[2], 0);
   GLP(Lightfv)(id, GL_POSITION, fdir.get_data());
 
@@ -2811,20 +2809,19 @@ bind_light(DirectionalLight *light, int light_id) {
 //               properties.
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
-bind_light(Spotlight *light, int light_id) {
-  Lens *lens = light->get_lens();
+bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
+  Lens *lens = light_obj->get_lens();
   nassertv(lens != (Lens *)NULL);
 
   GLenum id = get_light_id(light_id);
   static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
   GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
-  GLP(Lightfv)(id, GL_DIFFUSE, light->get_color().get_data());
-  GLP(Lightfv)(id, GL_SPECULAR, light->get_specular_color().get_data());
+  GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
+  GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
 
   // Position needs to specify x, y, z, and w
   // w == 1 implies non-infinite position
-  NodePath light_np(light);
-  const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
+  const LMatrix4f &light_mat = light.get_mat(_scene_setup->get_scene_root());
   LPoint3f pos = lens->get_nodal_point() * light_mat;
   LVector3f dir = lens->get_view_vector() * light_mat;
 
@@ -2832,10 +2829,10 @@ bind_light(Spotlight *light, int light_id) {
   GLP(Lightfv)(id, GL_POSITION, fpos.get_data());
   GLP(Lightfv)(id, GL_SPOT_DIRECTION, dir.get_data());
 
-  GLP(Lightf)(id, GL_SPOT_EXPONENT, light->get_exponent());
+  GLP(Lightf)(id, GL_SPOT_EXPONENT, light_obj->get_exponent());
   GLP(Lightf)(id, GL_SPOT_CUTOFF, lens->get_hfov());
 
-  const LVecBase3f &att = light->get_attenuation();
+  const LVecBase3f &att = light_obj->get_attenuation();
   GLP(Lightf)(id, GL_CONSTANT_ATTENUATION, att[0]);
   GLP(Lightf)(id, GL_LINEAR_ATTENUATION, att[1]);
   GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, att[2]);

+ 6 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -112,9 +112,12 @@ public:
   virtual void issue_cg_shader_bind(const CgShaderAttrib *attrib);
   //  virtual void issue_stencil(const StencilAttrib *attrib);
 
-  virtual void bind_light(PointLight *light, int light_id);
-  virtual void bind_light(DirectionalLight *light, int light_id);
-  virtual void bind_light(Spotlight *light, int light_id);
+  virtual void bind_light(PointLight *light_obj, const NodePath &light, 
+                          int light_id);
+  virtual void bind_light(DirectionalLight *light_obj, const NodePath &light, 
+                          int light_id);
+  virtual void bind_light(Spotlight *light_obj, const NodePath &light, 
+                          int light_id);
 
   virtual bool wants_texcoords(void) const;
 

+ 0 - 1
panda/src/gobj/geom.cxx

@@ -1200,7 +1200,6 @@ fillin(DatagramIterator& scan, BamReader* manager) {
     // read the multitexture data
     int num_texcoords_by_names = scan.get_uint8();
     // read the TexCoordsByName pointers of num_texcoords_by_names
-    TexCoordsByName::const_iterator tci;
     _temp_texcoord_set.reserve(num_texcoords_by_names);
     for (int i=0; i<num_texcoords_by_names; ++i) {
       manager->read_pointer(scan);

+ 7 - 3
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -28,6 +28,7 @@
 
 class RenderBuffer;
 class GraphicsWindow;
+class NodePath;
 
 class GeomContext;
 class GeomNode;
@@ -197,9 +198,12 @@ public:
   virtual void issue_stencil(const StencilAttrib *) { }
   virtual void issue_clip_plane(const ClipPlaneAttrib *) { }
 
-  virtual void bind_light(PointLight *light, int light_id) { }
-  virtual void bind_light(DirectionalLight *light, int light_id) { }
-  virtual void bind_light(Spotlight *light, int light_id) { }
+  virtual void bind_light(PointLight *light_obj, const NodePath &light, 
+                          int light_id) { }
+  virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
+                          int light_id) { }
+  virtual void bind_light(Spotlight *light_obj, const NodePath &light,
+                          int light_id) { }
 
 PUBLISHED:
   static TypeHandle get_class_type() {

+ 1 - 1
panda/src/pgraph/ambientLight.cxx

@@ -80,7 +80,7 @@ write(ostream &out, int indent_level) const {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void AmbientLight::
-bind(GraphicsStateGuardianBase *, int) {
+bind(GraphicsStateGuardianBase *, const NodePath &, int) {
   // AmbientLights aren't bound to light id's; this function should
   // never be called.
   nassertv(false);

+ 2 - 1
panda/src/pgraph/ambientLight.h

@@ -42,7 +42,8 @@ public:
   virtual void write(ostream &out, int indent_level) const;
   
 public:
-  virtual void bind(GraphicsStateGuardianBase *gsg, int light_id);
+  virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
+                    int light_id);
 
 public:
   static void register_with_read_factory();

+ 2 - 2
panda/src/pgraph/directionalLight.cxx

@@ -139,8 +139,8 @@ write(ostream &out, int indent_level) const {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void DirectionalLight::
-bind(GraphicsStateGuardianBase *gsg, int light_id) {
-  gsg->bind_light(this, light_id);
+bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) {
+  gsg->bind_light(this, light, light_id);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 1
panda/src/pgraph/directionalLight.h

@@ -51,7 +51,8 @@ PUBLISHED:
   INLINE void set_direction(const LVector3f &direction);
   
 public:
-  virtual void bind(GraphicsStateGuardianBase *gsg, int light_id);
+  virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
+                    int light_id);
 
 private:
   // This is the data that must be cycled between pipeline stages.

+ 3 - 1
panda/src/pgraph/light.h

@@ -29,6 +29,7 @@
 #include "pipelineCycler.h"
 #include "geomNode.h"
 
+class NodePath;
 class PandaNode;
 class GraphicsStateGuardianBase;
 
@@ -58,7 +59,8 @@ PUBLISHED:
 public:
   virtual void output(ostream &out) const=0;
   virtual void write(ostream &out, int indent_level) const=0;
-  virtual void bind(GraphicsStateGuardianBase *gsg, int light_id)=0;
+  virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
+                    int light_id)=0;
 
   GeomNode *get_viz();
 

+ 8 - 7
panda/src/pgraph/lightAttrib.I

@@ -60,9 +60,9 @@ get_num_on_lights() const {
 //  Description: Returns the nth light turned on by the attribute,
 //               sorted in render order.
 ////////////////////////////////////////////////////////////////////
-INLINE Light *LightAttrib::
+INLINE NodePath LightAttrib::
 get_on_light(int n) const {
-  nassertr(n >= 0 && n < (int)_on_lights.size(), (Light *)NULL);
+  nassertr(n >= 0 && n < (int)_on_lights.size(), NodePath::fail());
   return _on_lights[n];
 }
 
@@ -73,7 +73,7 @@ get_on_light(int n) const {
 //               the attrib, false otherwise.
 ////////////////////////////////////////////////////////////////////
 INLINE bool LightAttrib::
-has_on_light(Light *light) const {
+has_on_light(const NodePath &light) const {
   return _on_lights.find(light) != _on_lights.end();
 }
 
@@ -94,9 +94,9 @@ get_num_off_lights() const {
 //  Description: Returns the nth light turned off by the attribute,
 //               sorted in arbitrary (pointer) order.
 ////////////////////////////////////////////////////////////////////
-INLINE Light *LightAttrib::
+INLINE NodePath LightAttrib::
 get_off_light(int n) const {
-  nassertr(n >= 0 && n < (int)_off_lights.size(), (Light *)NULL);
+  nassertr(n >= 0 && n < (int)_off_lights.size(), NodePath::fail());
   return _off_lights[n];
 }
 
@@ -107,8 +107,9 @@ get_off_light(int n) const {
 //               the attrib, false otherwise.
 ////////////////////////////////////////////////////////////////////
 INLINE bool LightAttrib::
-has_off_light(Light *light) const {
-  return _off_all_lights || _off_lights.find(light) != _off_lights.end();
+has_off_light(const NodePath &light) const {
+  return _off_lights.find(light) != _off_lights.end() ||
+    (_off_all_lights && !has_on_light(light));
 }
 
 ////////////////////////////////////////////////////////////////////

+ 71 - 63
panda/src/pgraph/lightAttrib.cxx

@@ -44,17 +44,17 @@ make(LightAttrib::Operation op, Light *light) {
   switch (op) {
   case O_set:
     attrib = make_all_off();
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light);
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light->as_node()));
     return attrib;
    
   case O_add:
     attrib = make();
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light);
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light->as_node()));
     return attrib;
 
   case O_remove:
     attrib = make();
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light);
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light->as_node()));
     return attrib;
   }
 
@@ -78,20 +78,20 @@ make(LightAttrib::Operation op, Light *light1, Light *light2) {
   switch (op) {
   case O_set:
     attrib = make_all_off();
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
     return attrib;
    
   case O_add:
     attrib = make();
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
     return attrib;
 
   case O_remove:
     attrib = make();
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light2);
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
     return attrib;
   }
 
@@ -116,23 +116,23 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
   switch (op) {
   case O_set:
     attrib = make_all_off();
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light3);
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
     return attrib;
    
   case O_add:
     attrib = make();
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light3);
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
     return attrib;
 
   case O_remove:
     attrib = make();
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light2);
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light3);
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light3->as_node()));
     return attrib;
   }
 
@@ -157,26 +157,26 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
   switch (op) {
   case O_set:
     attrib = make_all_off();
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light3);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light4);
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light4->as_node()));
     return attrib;
    
   case O_add:
     attrib = make();
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light3);
-    attrib = DCAST(LightAttrib, attrib)->add_on_light(light4);
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light4->as_node()));
     return attrib;
 
   case O_remove:
     attrib = make();
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light1);
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light2);
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light3);
-    attrib = DCAST(LightAttrib, attrib)->add_off_light(light4);
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light3->as_node()));
+    attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light4->as_node()));
     return attrib;
   }
 
@@ -235,7 +235,7 @@ get_num_lights() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: LightAttrib::get_light
 //       Access: Published
-//  Description: Returns the nth lights listed in the attribute.
+//  Description: Returns the nth light listed in the attribute.
 //
 //               This method is now deprecated.  LightAttribs nowadays
 //               have a separate list of on_lights and off_lights, so
@@ -245,9 +245,9 @@ get_num_lights() const {
 Light *LightAttrib::
 get_light(int n) const {
   if (get_num_off_lights() == 0) {
-    return get_on_light(n);
+    return get_on_light(n).node()->as_light();
   } else {
-    return get_off_light(n);
+    return get_off_light(n).node()->as_light();
   }
 }
 
@@ -265,9 +265,9 @@ get_light(int n) const {
 bool LightAttrib::
 has_light(Light *light) const {
   if (get_num_off_lights() == 0) {
-    return has_on_light(light);
+    return has_on_light(NodePath(light->as_node()));
   } else {
-    return has_off_light(light);
+    return has_off_light(NodePath(light->as_node()));
   }
 }
 
@@ -283,9 +283,9 @@ has_light(Light *light) const {
 CPT(RenderAttrib) LightAttrib::
 add_light(Light *light) const {
   if (get_num_off_lights() == 0) {
-    return add_on_light(light);
+    return add_on_light(NodePath(light->as_node()));
   } else {
-    return add_off_light(light);
+    return add_off_light(NodePath(light->as_node()));
   }
 }
 
@@ -302,9 +302,9 @@ add_light(Light *light) const {
 CPT(RenderAttrib) LightAttrib::
 remove_light(Light *light) const {
   if (get_num_off_lights() == 0) {
-    return remove_on_light(light);
+    return remove_on_light(NodePath(light->as_node()));
   } else {
-    return remove_off_light(light);
+    return remove_off_light(NodePath(light->as_node()));
   }
 }
 
@@ -352,7 +352,8 @@ make_all_off() {
 //               turned on by this attrib.
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) LightAttrib::
-add_on_light(Light *light) const {
+add_on_light(const NodePath &light) const {
+  nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
   LightAttrib *attrib = new LightAttrib(*this);
   attrib->_on_lights.insert(light);
   attrib->_off_lights.erase(light);
@@ -375,7 +376,8 @@ add_on_light(Light *light) const {
 //               lights turned on by this attrib.
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) LightAttrib::
-remove_on_light(Light *light) const {
+remove_on_light(const NodePath &light) const {
+  nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
   LightAttrib *attrib = new LightAttrib(*this);
   attrib->_on_lights.erase(light);
   return return_new(attrib);
@@ -389,7 +391,8 @@ remove_on_light(Light *light) const {
 //               turned off by this attrib.
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) LightAttrib::
-add_off_light(Light *light) const {
+add_off_light(const NodePath &light) const {
+  nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
   LightAttrib *attrib = new LightAttrib(*this);
   if (!_off_all_lights) {
     attrib->_off_lights.insert(light);
@@ -406,7 +409,8 @@ add_off_light(Light *light) const {
 //               lights turned off by this attrib.
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) LightAttrib::
-remove_off_light(Light *light) const {
+remove_off_light(const NodePath &light) const {
+  nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
   LightAttrib *attrib = new LightAttrib(*this);
   attrib->_off_lights.erase(light);
   return return_new(attrib);
@@ -453,8 +457,8 @@ output(ostream &out) const {
     out << "off";
     Lights::const_iterator fi;
     for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
-      Light *light = (*fi);
-      out << " " << *light;
+      NodePath light = (*fi);
+      out << " " << light;
     }
 
     if (!_on_lights.empty()) {
@@ -464,8 +468,8 @@ output(ostream &out) const {
     
   Lights::const_iterator li;
   for (li = _on_lights.begin(); li != _on_lights.end(); ++li) {
-    Light *light = (*li);
-    out << " " << *light;
+    NodePath light = (*li);
+    out << " " << light;
   }
 }
 
@@ -497,11 +501,12 @@ compare_to_impl(const RenderAttrib *other) const {
   Lights::const_iterator oli = ta->_on_lights.begin();
 
   while (li != _on_lights.end() && oli != ta->_on_lights.end()) {
-    Light *light = (*li);
-    Light *other_light = (*oli);
+    NodePath light = (*li);
+    NodePath other_light = (*oli);
 
-    if (light != other_light) {
-      return light < other_light ? -1 : 1;
+    int compare = light.compare_to(other_light);
+    if (compare != 0) {
+      return compare;
     }
 
     ++li;
@@ -519,11 +524,12 @@ compare_to_impl(const RenderAttrib *other) const {
   Lights::const_iterator ofi = ta->_off_lights.begin();
 
   while (fi != _off_lights.end() && ofi != ta->_off_lights.end()) {
-    Light *light = (*fi);
-    Light *other_light = (*ofi);
+    NodePath light = (*fi);
+    NodePath other_light = (*ofi);
 
-    if (light != other_light) {
-      return light < other_light ? -1 : 1;
+    int compare = light.compare_to(other_light);
+    if (compare != 0) {
+      return compare;
     }
 
     ++fi;
@@ -612,7 +618,7 @@ compose_impl(const RenderAttrib *other) const {
 
     } else {  // (*bi) == (*ai)
       // Here is a light we have in both.
-      *result = *ai;
+      *result = *bi;
       ++ai;
       ++bi;
       ++result;
@@ -636,7 +642,7 @@ compose_impl(const RenderAttrib *other) const {
 
     } else {
       // Here is a light we have in both.
-      *result = *ai;
+      *result = *bi;
       ++ai;
       ++bi;
       ++result;
@@ -740,8 +746,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   // write the off lights pointers if any
   Lights::const_iterator fi;
   for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
-    Light *light = (*fi);
-    manager->write_pointer(dg, light->as_node());
+    NodePath light = (*fi);
+
+    // Whoops, we don't have a way to write out a NodePath right now.
+    manager->write_pointer(dg, light.node());
   }
 
   // write the number of on lights
@@ -749,8 +757,8 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   // write the on lights pointers if any
   Lights::const_iterator nti;
   for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
-    Light *light = (*nti);
-    manager->write_pointer(dg, light->as_node());
+    NodePath light = (*nti);
+    manager->write_pointer(dg, light.node());
   }
 }
 
@@ -769,7 +777,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
   while (ci != _off_lights.end()) {
     PandaNode *node;
     DCAST_INTO_R(node, p_list[pi++], pi);
-    (*ci) = node->as_light();
+    (*ci) = NodePath(node);
     ++ci;
   }
 
@@ -777,7 +785,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
   while (ci != _on_lights.end()) {
     PandaNode *node;
     DCAST_INTO_R(node, p_list[pi++], pi);
-    (*ci) = node->as_light();
+    (*ci) = NodePath(node);
     ++ci;
   }
 

+ 10 - 9
panda/src/pgraph/lightAttrib.h

@@ -24,6 +24,7 @@
 #include "light.h"
 #include "renderAttrib.h"
 #include "ordered_vector.h"
+#include "nodePath.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : LightAttrib
@@ -74,20 +75,20 @@ PUBLISHED:
   static CPT(RenderAttrib) make_all_off();
 
   INLINE int get_num_on_lights() const;
-  INLINE Light *get_on_light(int n) const;
-  INLINE bool has_on_light(Light *light) const;
+  INLINE NodePath get_on_light(int n) const;
+  INLINE bool has_on_light(const NodePath &light) const;
 
   INLINE int get_num_off_lights() const;
-  INLINE Light *get_off_light(int n) const;
-  INLINE bool has_off_light(Light *light) const;
+  INLINE NodePath get_off_light(int n) const;
+  INLINE bool has_off_light(const NodePath &light) const;
   INLINE bool has_all_off() const;
 
   INLINE bool is_identity() const;
 
-  CPT(RenderAttrib) add_on_light(Light *light) const;
-  CPT(RenderAttrib) remove_on_light(Light *light) const;
-  CPT(RenderAttrib) add_off_light(Light *light) const;
-  CPT(RenderAttrib) remove_off_light(Light *light) const;
+  CPT(RenderAttrib) add_on_light(const NodePath &light) const;
+  CPT(RenderAttrib) remove_on_light(const NodePath &light) const;
+  CPT(RenderAttrib) add_off_light(const NodePath &light) const;
+  CPT(RenderAttrib) remove_off_light(const NodePath &light) const;
 
 public:
   virtual void issue(GraphicsStateGuardianBase *gsg) const;
@@ -100,7 +101,7 @@ protected:
   virtual RenderAttrib *make_default_impl() const;
 
 private:
-  typedef ov_set< PT(Light) > Lights;
+  typedef ov_set<NodePath> Lights;
   Lights _on_lights, _off_lights;
   bool _off_all_lights;
 

+ 75 - 195
panda/src/pgraph/nodePath.cxx

@@ -2024,54 +2024,6 @@ get_color_scale() const {
   return ident_scale;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_light
-//       Access: Published
-//  Description: Adds the indicated Light to the list of lights that
-//               illuminate geometry at this node and below.  The
-//               light itself should be parented into the scene graph
-//               elsewhere, to represent the light's position in
-//               space; but until set_light() is called it will
-//               illuminate no geometry.
-////////////////////////////////////////////////////////////////////
-void NodePath::
-set_light(Light *light, int priority) {
-  nassertv_always(!is_empty());
-
-  const RenderAttrib *attrib =
-    node()->get_attrib(LightAttrib::get_class_type());
-  if (attrib != (const RenderAttrib *)NULL) {
-    priority = max(priority,
-                   node()->get_state()->get_override(LightAttrib::get_class_type()));
-    const LightAttrib *la = DCAST(LightAttrib, attrib);
-
-    // Modify the existing LightAttrib to add the indicated
-    // light.
-    node()->set_attrib(la->add_on_light(light), priority);
-
-  } else {
-    // Create a new LightAttrib for this node.
-    CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
-    node()->set_attrib(la->add_on_light(light), priority);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_light
-//       Access: Published
-//  Description: Adds a PolylightEffect to the geometry at this node
-//               and below.  This makes the geometry at this point in
-//               the scene graph grow brighter or dimmer according to
-//               its proximity to the indicated PolylightNode; this is
-//               an effect similar to lighting, but is not related to
-//               traditional hardware T&L.
-////////////////////////////////////////////////////////////////////
-void NodePath::
-set_light(PolylightNode *) {
-  // Not yet implemented.
-  nassertv(false);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::set_light
 //       Access: Published
@@ -2084,11 +2036,26 @@ set_light(PolylightNode *) {
 ////////////////////////////////////////////////////////////////////
 void NodePath::
 set_light(const NodePath &light, int priority) {
+  nassertv_always(!is_empty());
   if (!light.is_empty()) {
-    PandaNode *node = light.node();
-    Light *light_obj = node->as_light();
+    Light *light_obj = light.node()->as_light();
     if (light_obj != (Light *)NULL) {
-      set_light(light_obj, priority);
+      const RenderAttrib *attrib =
+        node()->get_attrib(LightAttrib::get_class_type());
+      if (attrib != (const RenderAttrib *)NULL) {
+        priority = max(priority,
+                       node()->get_state()->get_override(LightAttrib::get_class_type()));
+        const LightAttrib *la = DCAST(LightAttrib, attrib);
+        
+        // Modify the existing LightAttrib to add the indicated
+        // light.
+        node()->set_attrib(la->add_on_light(light), priority);
+        
+      } else {
+        // Create a new LightAttrib for this node.
+        CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
+        node()->set_attrib(la->add_on_light(light), priority);
+      }
       return;
     }
   }
@@ -2115,40 +2082,6 @@ set_light_off(int priority) {
   node()->set_attrib(LightAttrib::make_all_off(), priority);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_light_off
-//       Access: Published
-//  Description: Sets the geometry at this level and below to render
-//               using without the indicated Light.  This is different
-//               from not specifying the Light; rather, this
-//               specifically contradicts set_light() at a higher node
-//               level (or, with a priority, overrides a set_light()
-//               at a lower level).
-////////////////////////////////////////////////////////////////////
-void NodePath::
-set_light_off(Light *light, int priority) {
-  nassertv_always(!is_empty());
-
-  const RenderAttrib *attrib =
-    node()->get_attrib(LightAttrib::get_class_type());
-  if (attrib != (const RenderAttrib *)NULL) {
-    priority = max(priority,
-                   node()->get_state()->get_override(LightAttrib::get_class_type()));
-    const LightAttrib *la = DCAST(LightAttrib, attrib);
-
-    // Modify the existing LightAttrib to add the indicated light
-    // to the "off" list.  This also, incidentally, removes it from
-    // the "on" list if it is there.
-    node()->set_attrib(la->add_off_light(light), priority);
-
-  } else {
-    // Create a new LightAttrib for this node that turns off the
-    // indicated light.
-    CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
-    node()->set_attrib(la->add_off_light(light), priority);
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::set_light_off
 //       Access: Published
@@ -2164,11 +2097,29 @@ set_light_off(Light *light, int priority) {
 ////////////////////////////////////////////////////////////////////
 void NodePath::
 set_light_off(const NodePath &light, int priority) {
+  nassertv_always(!is_empty());
+
   if (!light.is_empty()) {
-    PandaNode *node = light.node();
-    Light *light_obj = node->as_light();
+    Light *light_obj = light.node()->as_light();
     if (light_obj != (Light *)NULL) {
-      set_light_off(light_obj, priority);
+      const RenderAttrib *attrib =
+        node()->get_attrib(LightAttrib::get_class_type());
+      if (attrib != (const RenderAttrib *)NULL) {
+        priority = max(priority,
+                       node()->get_state()->get_override(LightAttrib::get_class_type()));
+        const LightAttrib *la = DCAST(LightAttrib, attrib);
+        
+        // Modify the existing LightAttrib to add the indicated light
+        // to the "off" list.  This also, incidentally, removes it from
+        // the "on" list if it is there.
+        node()->set_attrib(la->add_off_light(light), priority);
+        
+      } else {
+        // Create a new LightAttrib for this node that turns off the
+        // indicated light.
+        CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
+        node()->set_attrib(la->add_off_light(light), priority);
+      }
       return;
     }
   }
@@ -2189,45 +2140,6 @@ clear_light() {
   node()->clear_effect(PolylightEffect::get_class_type());
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::clear_light
-//       Access: Published
-//  Description: Removes any reference to the indicated Light 
-//               from the NodePath.
-////////////////////////////////////////////////////////////////////
-void NodePath::
-clear_light(Light *light) {
-  nassertv_always(!is_empty());
-
-  const RenderAttrib *attrib =
-    node()->get_attrib(LightAttrib::get_class_type());
-  if (attrib != (const RenderAttrib *)NULL) {
-    CPT(LightAttrib) la = DCAST(LightAttrib, attrib);
-    la = DCAST(LightAttrib, la->remove_on_light(light));
-    la = DCAST(LightAttrib, la->remove_off_light(light));
-
-    if (la->is_identity()) {
-      node()->clear_attrib(LightAttrib::get_class_type());
-
-    } else {
-      int priority = node()->get_state()->get_override(LightAttrib::get_class_type());
-      node()->set_attrib(la, priority);
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::clear_light
-//       Access: Published
-//  Description: Removes the indicated PolylightEffect from the
-//               geometry.  This undoes a previous set_light() call.
-////////////////////////////////////////////////////////////////////
-void NodePath::
-clear_light(PolylightNode *) {
-  // Not yet implemented.
-  nassertv(false);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::clear_light
 //       Access: Published
@@ -2236,54 +2148,32 @@ clear_light(PolylightNode *) {
 ////////////////////////////////////////////////////////////////////
 void NodePath::
 clear_light(const NodePath &light) {
+  nassertv_always(!is_empty());
+
   if (!light.is_empty()) {
-    PandaNode *node = light.node();
-    Light *light_obj = node->as_light();
+    Light *light_obj = light.node()->as_light();
     if (light_obj != (Light *)NULL) {
-      clear_light(light_obj);
+      const RenderAttrib *attrib =
+        node()->get_attrib(LightAttrib::get_class_type());
+      if (attrib != (const RenderAttrib *)NULL) {
+        CPT(LightAttrib) la = DCAST(LightAttrib, attrib);
+        la = DCAST(LightAttrib, la->remove_on_light(light));
+        la = DCAST(LightAttrib, la->remove_off_light(light));
+        
+        if (la->is_identity()) {
+          node()->clear_attrib(LightAttrib::get_class_type());
+          
+        } else {
+          int priority = node()->get_state()->get_override(LightAttrib::get_class_type());
+          node()->set_attrib(la, priority);
+        }
+      }
       return;
     }
   }
   nassert_raise("Not a Light object.");
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::has_light
-//       Access: Published
-//  Description: Returns true if the indicated Light has been
-//               specifically enabled on this particular node.  This
-//               means that someone called set_light() on this node
-//               with the indicated light.
-////////////////////////////////////////////////////////////////////
-bool NodePath::
-has_light(Light *light) const {
-  nassertr_always(!is_empty(), false);
-
-  const RenderAttrib *attrib =
-    node()->get_attrib(LightAttrib::get_class_type());
-  if (attrib != (const RenderAttrib *)NULL) {
-    const LightAttrib *la = DCAST(LightAttrib, attrib);
-    return la->has_on_light(light);
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::has_light
-//       Access: Published
-//  Description: Returns true if the indicated PolylightNode has been
-//               specifically enabled on this particular node.  This
-//               means that someone called set_light() on this node
-//               with the indicated light.
-////////////////////////////////////////////////////////////////////
-bool NodePath::
-has_light(PolylightNode *) const {
-  // Not yet implemented.
-  nassertr(false, false);
-  return false;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::has_light
 //       Access: Published
@@ -2294,11 +2184,17 @@ has_light(PolylightNode *) const {
 ////////////////////////////////////////////////////////////////////
 bool NodePath::
 has_light(const NodePath &light) const {
+  nassertr_always(!is_empty(), false);
+
   if (!light.is_empty()) {
-    PandaNode *node = light.node();
-    Light *light_obj = node->as_light();
+    Light *light_obj = light.node()->as_light();
     if (light_obj != (Light *)NULL) {
-      return has_light(light_obj);
+      const RenderAttrib *attrib =
+        node()->get_attrib(LightAttrib::get_class_type());
+      if (attrib != (const RenderAttrib *)NULL) {
+        const LightAttrib *la = DCAST(LightAttrib, attrib);
+        return la->has_on_light(light);
+      }
     }
   }
   nassert_raise("Not a Light object.");
@@ -2316,33 +2212,12 @@ has_light(const NodePath &light) const {
 bool NodePath::
 has_light_off() const {
   nassertr_always(!is_empty(), false);
-  const RenderAttrib *attrib =
-    node()->get_attrib(LightAttrib::get_class_type());
-  if (attrib != (const RenderAttrib *)NULL) {
-    const LightAttrib *la = DCAST(LightAttrib, attrib);
-    return la->has_all_off();
-  }
-
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::has_light_off
-//       Access: Published
-//  Description: Returns true if the indicated Light has been
-//               specifically disabled on this particular node.  This
-//               means that someone called set_light_off() on this
-//               node with the indicated light.
-////////////////////////////////////////////////////////////////////
-bool NodePath::
-has_light_off(Light *light) const {
-  nassertr_always(!is_empty(), false);
 
   const RenderAttrib *attrib =
     node()->get_attrib(LightAttrib::get_class_type());
   if (attrib != (const RenderAttrib *)NULL) {
     const LightAttrib *la = DCAST(LightAttrib, attrib);
-    return la->has_off_light(light);
+    return la->has_all_off();
   }
 
   return false;
@@ -2361,11 +2236,16 @@ has_light_off(Light *light) const {
 ////////////////////////////////////////////////////////////////////
 bool NodePath::
 has_light_off(const NodePath &light) const {
+  nassertr_always(!is_empty(), false);
   if (!light.is_empty()) {
-    PandaNode *node = light.node();
-    Light *light_obj = node->as_light();
+    Light *light_obj = light.node()->as_light();
     if (light_obj != (Light *)NULL) {
-      return has_light(light_obj);
+      const RenderAttrib *attrib =
+        node()->get_attrib(LightAttrib::get_class_type());
+      if (attrib != (const RenderAttrib *)NULL) {
+        const LightAttrib *la = DCAST(LightAttrib, attrib);
+        return la->has_off_light(light);
+      }
     }
   }
   nassert_raise("Not a Light object.");

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

@@ -487,25 +487,13 @@ PUBLISHED:
   INLINE float get_sb() const;
   INLINE float get_sa() const;
 
-  void set_light(Light *light, int priority = 0);
-  void set_light(PolylightNode *light);
   void set_light(const NodePath &light, int priority = 0);
-
   void set_light_off(int priority = 0);
-  void set_light_off(Light *light, int priority = 0);
   void set_light_off(const NodePath &light, int priority = 0);
-
   void clear_light();
-  void clear_light(Light *light);
-  void clear_light(PolylightNode *light);
   void clear_light(const NodePath &light);
-
-  bool has_light(Light *light) const;
-  bool has_light(PolylightNode *light) const;
   bool has_light(const NodePath &light) const;
-
   bool has_light_off() const;
-  bool has_light_off(Light *light) const;
   bool has_light_off(const NodePath &light) const;
 
   void set_bin(const string &bin_name, int draw_order, int priority = 0);

+ 2 - 2
panda/src/pgraph/pointLight.cxx

@@ -138,8 +138,8 @@ write(ostream &out, int indent_level) const {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void PointLight::
-bind(GraphicsStateGuardianBase *gsg, int light_id) {
-  gsg->bind_light(this, light_id);
+bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) {
+  gsg->bind_light(this, light, light_id);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 1
panda/src/pgraph/pointLight.h

@@ -51,7 +51,8 @@ PUBLISHED:
   INLINE void set_point(const LPoint3f &point);
   
 public:
-  virtual void bind(GraphicsStateGuardianBase *gsg, int light_id);
+  virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
+                    int light_id);
 
 private:
   // This is the data that must be cycled between pipeline stages.

+ 2 - 2
panda/src/pgraph/spotlight.cxx

@@ -146,8 +146,8 @@ write(ostream &out, int indent_level) const {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void Spotlight::
-bind(GraphicsStateGuardianBase *gsg, int light_id) {
-  gsg->bind_light(this, light_id);
+bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) {
+  gsg->bind_light(this, light, light_id);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 1
panda/src/pgraph/spotlight.h

@@ -62,7 +62,8 @@ PUBLISHED:
   INLINE void set_attenuation(const LVecBase3f &attenuation);
   
 public:
-  virtual void bind(GraphicsStateGuardianBase *gsg, int light_id);
+  virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
+                    int light_id);
 
   bool make_image(Texture *texture, float radius);
 

+ 2 - 1
panda/src/pgraph/textureAttrib.I

@@ -160,7 +160,8 @@ get_off_stage(int n) const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool TextureAttrib::
 has_off_stage(TextureStage *stage) const {
-  return _off_all_stages || _off_stages.find(stage) != _off_stages.end();
+  return _off_stages.find(stage) != _off_stages.end() ||
+    (_off_all_stages && !has_on_stage(stage));
 }
 
 ////////////////////////////////////////////////////////////////////