|
|
@@ -24,33 +24,42 @@
|
|
|
#include "datagram.h"
|
|
|
#include "datagramIterator.h"
|
|
|
|
|
|
+CPT(RenderAttrib) LightAttrib::_empty_attrib;
|
|
|
+CPT(RenderAttrib) LightAttrib::_all_off_attrib;
|
|
|
TypeHandle LightAttrib::_type_handle;
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: LightAttrib::make_all_off
|
|
|
-// Access: Published, Static
|
|
|
-// Description: Constructs a new LightAttrib object that turns off
|
|
|
-// all lights (and hence disables lighting).
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-CPT(RenderAttrib) LightAttrib::
|
|
|
-make_all_off() {
|
|
|
- LightAttrib *attrib = new LightAttrib;
|
|
|
- attrib->_operation = O_set;
|
|
|
- return return_new(attrib);
|
|
|
-}
|
|
|
-
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: LightAttrib::make
|
|
|
// Access: Published, Static
|
|
|
// Description: Constructs a new LightAttrib object that turns on (or
|
|
|
-// off, according to op) the indicate light(s).
|
|
|
+// off, according to op) the indicated light(s).
|
|
|
+//
|
|
|
+// This method is now deprecated. Use add_on_light() or
|
|
|
+// add_off_light() instead.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
CPT(RenderAttrib) LightAttrib::
|
|
|
make(LightAttrib::Operation op, Light *light) {
|
|
|
- LightAttrib *attrib = new LightAttrib;
|
|
|
- attrib->_operation = op;
|
|
|
- attrib->_lights.push_back(light);
|
|
|
- return return_new(attrib);
|
|
|
+ CPT(RenderAttrib) attrib;
|
|
|
+
|
|
|
+ switch (op) {
|
|
|
+ case O_set:
|
|
|
+ attrib = make_all_off();
|
|
|
+ attrib = DCAST(LightAttrib, attrib)->add_on_light(light);
|
|
|
+ return attrib;
|
|
|
+
|
|
|
+ case O_add:
|
|
|
+ attrib = make();
|
|
|
+ attrib = DCAST(LightAttrib, attrib)->add_on_light(light);
|
|
|
+ return attrib;
|
|
|
+
|
|
|
+ case O_remove:
|
|
|
+ attrib = make();
|
|
|
+ attrib = DCAST(LightAttrib, attrib)->add_off_light(light);
|
|
|
+ return attrib;
|
|
|
+ }
|
|
|
+
|
|
|
+ nassertr(false, make());
|
|
|
+ return make();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -58,16 +67,36 @@ make(LightAttrib::Operation op, Light *light) {
|
|
|
// Access: Published, Static
|
|
|
// Description: Constructs a new LightAttrib object that turns on (or
|
|
|
// off, according to op) the indicate light(s).
|
|
|
+//
|
|
|
+// This method is now deprecated. Use add_on_light() or
|
|
|
+// add_off_light() instead.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
CPT(RenderAttrib) LightAttrib::
|
|
|
make(LightAttrib::Operation op, Light *light1, Light *light2) {
|
|
|
- LightAttrib *attrib = new LightAttrib;
|
|
|
- attrib->_operation = op;
|
|
|
- attrib->_lights.push_back(light1);
|
|
|
- attrib->_lights.push_back(light2);
|
|
|
+ CPT(RenderAttrib) attrib;
|
|
|
+
|
|
|
+ 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);
|
|
|
+ return attrib;
|
|
|
+
|
|
|
+ case O_add:
|
|
|
+ attrib = make();
|
|
|
+ attrib = DCAST(LightAttrib, attrib)->add_on_light(light1);
|
|
|
+ attrib = DCAST(LightAttrib, attrib)->add_on_light(light2);
|
|
|
+ return attrib;
|
|
|
+
|
|
|
+ case O_remove:
|
|
|
+ attrib = make();
|
|
|
+ attrib = DCAST(LightAttrib, attrib)->add_off_light(light1);
|
|
|
+ attrib = DCAST(LightAttrib, attrib)->add_off_light(light2);
|
|
|
+ return attrib;
|
|
|
+ }
|
|
|
|
|
|
- attrib->_lights.sort();
|
|
|
- return return_new(attrib);
|
|
|
+ nassertr(false, make());
|
|
|
+ return make();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -75,18 +104,40 @@ make(LightAttrib::Operation op, Light *light1, Light *light2) {
|
|
|
// Access: Published, Static
|
|
|
// Description: Constructs a new LightAttrib object that turns on (or
|
|
|
// off, according to op) the indicate light(s).
|
|
|
+//
|
|
|
+// This method is now deprecated. Use add_on_light() or
|
|
|
+// add_off_light() instead.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
CPT(RenderAttrib) LightAttrib::
|
|
|
make(LightAttrib::Operation op, Light *light1, Light *light2,
|
|
|
Light *light3) {
|
|
|
- LightAttrib *attrib = new LightAttrib;
|
|
|
- attrib->_operation = op;
|
|
|
- attrib->_lights.push_back(light1);
|
|
|
- attrib->_lights.push_back(light2);
|
|
|
- attrib->_lights.push_back(light3);
|
|
|
+ CPT(RenderAttrib) attrib;
|
|
|
+
|
|
|
+ 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);
|
|
|
+ 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);
|
|
|
+ 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);
|
|
|
+ return attrib;
|
|
|
+ }
|
|
|
|
|
|
- attrib->_lights.sort();
|
|
|
- return return_new(attrib);
|
|
|
+ nassertr(false, make());
|
|
|
+ return make();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -94,19 +145,110 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
|
|
|
// Access: Published, Static
|
|
|
// Description: Constructs a new LightAttrib object that turns on (or
|
|
|
// off, according to op) the indicate light(s).
|
|
|
+//
|
|
|
+// This method is now deprecated. Use add_on_light() or
|
|
|
+// add_off_light() instead.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
CPT(RenderAttrib) LightAttrib::
|
|
|
make(LightAttrib::Operation op, Light *light1, Light *light2,
|
|
|
Light *light3, Light *light4) {
|
|
|
- LightAttrib *attrib = new LightAttrib;
|
|
|
- attrib->_operation = op;
|
|
|
- attrib->_lights.push_back(light1);
|
|
|
- attrib->_lights.push_back(light2);
|
|
|
- attrib->_lights.push_back(light3);
|
|
|
- attrib->_lights.push_back(light4);
|
|
|
+ CPT(RenderAttrib) attrib;
|
|
|
+
|
|
|
+ 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);
|
|
|
+ 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);
|
|
|
+ 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);
|
|
|
+ return attrib;
|
|
|
+ }
|
|
|
|
|
|
- attrib->_lights.sort();
|
|
|
- return return_new(attrib);
|
|
|
+ nassertr(false, make());
|
|
|
+ return make();
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::get_operation
|
|
|
+// Access: Published
|
|
|
+// Description: Returns the basic operation type of the LightAttrib.
|
|
|
+// If this is O_set, the lights listed here completely
|
|
|
+// replace any lights that were already on. If this is
|
|
|
+// O_add, the lights here are added to the set of of
|
|
|
+// lights that were already on, and if O_remove, the
|
|
|
+// lights here are removed from the set of lights that
|
|
|
+// were on.
|
|
|
+//
|
|
|
+// This method is now deprecated. LightAttribs nowadays
|
|
|
+// have a separate list of on_lights and off_lights, so
|
|
|
+// this method doesn't make sense. Query the lists
|
|
|
+// independently.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+LightAttrib::Operation LightAttrib::
|
|
|
+get_operation() const {
|
|
|
+ if (has_all_off()) {
|
|
|
+ return O_set;
|
|
|
+
|
|
|
+ } else if (get_num_on_lights() != 0) {
|
|
|
+ return O_add;
|
|
|
+
|
|
|
+ } else {
|
|
|
+ return O_remove;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::get_num_lights
|
|
|
+// Access: Published
|
|
|
+// Description: Returns the number of lights listed in the attribute.
|
|
|
+//
|
|
|
+// This method is now deprecated. LightAttribs nowadays
|
|
|
+// have a separate list of on_lights and off_lights, so
|
|
|
+// this method doesn't make sense. Query the lists
|
|
|
+// independently.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int LightAttrib::
|
|
|
+get_num_lights() const {
|
|
|
+ if (get_num_on_lights() != 0) {
|
|
|
+ return get_num_on_lights();
|
|
|
+ } else {
|
|
|
+ return get_num_off_lights();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::get_light
|
|
|
+// Access: Published
|
|
|
+// Description: Returns the nth lights listed in the attribute.
|
|
|
+//
|
|
|
+// This method is now deprecated. LightAttribs nowadays
|
|
|
+// have a separate list of on_lights and off_lights, so
|
|
|
+// this method doesn't make sense. Query the lists
|
|
|
+// independently.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+Light *LightAttrib::
|
|
|
+get_light(int n) const {
|
|
|
+ if (get_num_on_lights() != 0) {
|
|
|
+ return get_on_light(n);
|
|
|
+ } else {
|
|
|
+ return get_off_light(n);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -114,10 +256,160 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
|
|
|
// Access: Published
|
|
|
// Description: Returns true if the indicated light is listed in the
|
|
|
// attrib, false otherwise.
|
|
|
+//
|
|
|
+// This method is now deprecated. LightAttribs nowadays
|
|
|
+// have a separate list of on_lights and off_lights, so
|
|
|
+// this method doesn't make sense. Query the lists
|
|
|
+// independently.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool LightAttrib::
|
|
|
has_light(Light *light) const {
|
|
|
- return _lights.find(light) != _lights.end();
|
|
|
+ if (get_num_on_lights() != 0) {
|
|
|
+ return has_on_light(light);
|
|
|
+ } else {
|
|
|
+ return has_off_light(light);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::add_light
|
|
|
+// Access: Published
|
|
|
+// Description: Returns a new LightAttrib, just like this one, but
|
|
|
+// with the indicated light added to the list of lights.
|
|
|
+//
|
|
|
+// This method is now deprecated. Use add_on_light() or
|
|
|
+// add_off_light() instead.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+CPT(RenderAttrib) LightAttrib::
|
|
|
+add_light(Light *light) const {
|
|
|
+ if (get_num_on_lights() != 0) {
|
|
|
+ return add_on_light(light);
|
|
|
+ } else {
|
|
|
+ return add_off_light(light);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::remove_light
|
|
|
+// Access: Published
|
|
|
+// Description: Returns a new LightAttrib, just like this one, but
|
|
|
+// with the indicated light removed from the list of
|
|
|
+// lights.
|
|
|
+//
|
|
|
+// This method is now deprecated. Use remove_on_light()
|
|
|
+// or remove_off_light() instead.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+CPT(RenderAttrib) LightAttrib::
|
|
|
+remove_light(Light *light) const {
|
|
|
+ if (get_num_on_lights() != 0) {
|
|
|
+ return remove_on_light(light);
|
|
|
+ } else {
|
|
|
+ return remove_off_light(light);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::make
|
|
|
+// Access: Published, Static
|
|
|
+// Description: Constructs a new LightAttrib object that does
|
|
|
+// nothing.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+CPT(RenderAttrib) LightAttrib::
|
|
|
+make() {
|
|
|
+ // We make it a special case and store a pointer to the empty attrib
|
|
|
+ // forever once we find it the first time, as an optimization.
|
|
|
+ if (_empty_attrib == (RenderAttrib *)NULL) {
|
|
|
+ _empty_attrib = return_new(new LightAttrib);
|
|
|
+ }
|
|
|
+
|
|
|
+ return _empty_attrib;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::make_all_off
|
|
|
+// Access: Published, Static
|
|
|
+// Description: Constructs a new LightAttrib object that turns off
|
|
|
+// all lights (and hence disables lighting).
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+CPT(RenderAttrib) LightAttrib::
|
|
|
+make_all_off() {
|
|
|
+ // We make it a special case and store a pointer to the off attrib
|
|
|
+ // forever once we find it the first time, as an optimization.
|
|
|
+ if (_all_off_attrib == (RenderAttrib *)NULL) {
|
|
|
+ LightAttrib *attrib = new LightAttrib;
|
|
|
+ attrib->_off_all_lights = true;
|
|
|
+ _all_off_attrib = return_new(attrib);
|
|
|
+ }
|
|
|
+
|
|
|
+ return _all_off_attrib;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::add_on_light
|
|
|
+// Access: Published
|
|
|
+// Description: Returns a new LightAttrib, just like this one, but
|
|
|
+// with the indicated light added to the list of lights
|
|
|
+// turned on by this attrib.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+CPT(RenderAttrib) LightAttrib::
|
|
|
+add_on_light(Light *light) const {
|
|
|
+ LightAttrib *attrib = new LightAttrib(*this);
|
|
|
+ attrib->_on_lights.insert(light);
|
|
|
+ attrib->_off_lights.erase(light);
|
|
|
+
|
|
|
+ pair<Lights::iterator, bool> insert_result =
|
|
|
+ attrib->_on_lights.insert(Lights::value_type(light));
|
|
|
+ if (insert_result.second) {
|
|
|
+ // Also ensure it is removed from the off_lights list.
|
|
|
+ attrib->_off_lights.erase(light);
|
|
|
+ }
|
|
|
+
|
|
|
+ return return_new(attrib);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::remove_on_light
|
|
|
+// Access: Published
|
|
|
+// Description: Returns a new LightAttrib, just like this one, but
|
|
|
+// with the indicated light removed from the list of
|
|
|
+// lights turned on by this attrib.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+CPT(RenderAttrib) LightAttrib::
|
|
|
+remove_on_light(Light *light) const {
|
|
|
+ LightAttrib *attrib = new LightAttrib(*this);
|
|
|
+ attrib->_on_lights.erase(light);
|
|
|
+ return return_new(attrib);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::add_off_light
|
|
|
+// Access: Published
|
|
|
+// Description: Returns a new LightAttrib, just like this one, but
|
|
|
+// with the indicated light added to the list of lights
|
|
|
+// turned off by this attrib.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+CPT(RenderAttrib) LightAttrib::
|
|
|
+add_off_light(Light *light) const {
|
|
|
+ LightAttrib *attrib = new LightAttrib(*this);
|
|
|
+ if (!_off_all_lights) {
|
|
|
+ attrib->_off_lights.insert(light);
|
|
|
+ }
|
|
|
+ attrib->_on_lights.erase(light);
|
|
|
+ return return_new(attrib);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::remove_off_light
|
|
|
+// Access: Published
|
|
|
+// Description: Returns a new LightAttrib, just like this one, but
|
|
|
+// with the indicated light removed from the list of
|
|
|
+// lights turned off by this attrib.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+CPT(RenderAttrib) LightAttrib::
|
|
|
+remove_off_light(Light *light) const {
|
|
|
+ LightAttrib *attrib = new LightAttrib(*this);
|
|
|
+ attrib->_off_lights.erase(light);
|
|
|
+ return return_new(attrib);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -142,27 +434,39 @@ issue(GraphicsStateGuardianBase *gsg) const {
|
|
|
void LightAttrib::
|
|
|
output(ostream &out) const {
|
|
|
out << get_type() << ":";
|
|
|
- if (_operation == O_set && _lights.empty()) {
|
|
|
- out << "all off";
|
|
|
+ if (_off_lights.empty()) {
|
|
|
+ if (_on_lights.empty()) {
|
|
|
+ if (_off_all_lights) {
|
|
|
+ out << "all off";
|
|
|
+ } else {
|
|
|
+ out << "identity";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (_off_all_lights) {
|
|
|
+ out << "set";
|
|
|
+ } else {
|
|
|
+ out << "on";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
} else {
|
|
|
- switch (_operation) {
|
|
|
- case O_set:
|
|
|
- out << "set";
|
|
|
- break;
|
|
|
- case O_add:
|
|
|
- out << "add";
|
|
|
- break;
|
|
|
- case O_remove:
|
|
|
- out << "remove";
|
|
|
- break;
|
|
|
+ out << "off";
|
|
|
+ Lights::const_iterator fi;
|
|
|
+ for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
|
|
|
+ Light *light = (*fi);
|
|
|
+ out << " " << *light;
|
|
|
}
|
|
|
|
|
|
- Lights::const_iterator li;
|
|
|
- for (li = _lights.begin(); li != _lights.end(); ++li) {
|
|
|
- Light *light = (*li);
|
|
|
- out << " " << light->get_type();
|
|
|
+ if (!_on_lights.empty()) {
|
|
|
+ out << " on";
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ Lights::const_iterator li;
|
|
|
+ for (li = _on_lights.begin(); li != _on_lights.end(); ++li) {
|
|
|
+ Light *light = (*li);
|
|
|
+ out << " " << *light;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -185,14 +489,14 @@ compare_to_impl(const RenderAttrib *other) const {
|
|
|
const LightAttrib *ta;
|
|
|
DCAST_INTO_R(ta, other, 0);
|
|
|
|
|
|
- if (_operation != ta->_operation) {
|
|
|
- return (int)_operation - (int)ta->_operation;
|
|
|
+ if (_off_all_lights != ta->_off_all_lights) {
|
|
|
+ return (int)_off_all_lights - (int)ta->_off_all_lights;
|
|
|
}
|
|
|
|
|
|
- Lights::const_iterator li = _lights.begin();
|
|
|
- Lights::const_iterator oli = ta->_lights.begin();
|
|
|
+ Lights::const_iterator li = _on_lights.begin();
|
|
|
+ Lights::const_iterator oli = ta->_on_lights.begin();
|
|
|
|
|
|
- while (li != _lights.end() && oli != ta->_lights.end()) {
|
|
|
+ while (li != _on_lights.end() && oli != ta->_on_lights.end()) {
|
|
|
Light *light = (*li);
|
|
|
Light *other_light = (*oli);
|
|
|
|
|
|
@@ -204,10 +508,32 @@ compare_to_impl(const RenderAttrib *other) const {
|
|
|
++oli;
|
|
|
}
|
|
|
|
|
|
- if (li != _lights.end()) {
|
|
|
+ if (li != _on_lights.end()) {
|
|
|
return 1;
|
|
|
}
|
|
|
- if (oli != ta->_lights.end()) {
|
|
|
+ if (oli != ta->_on_lights.end()) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ Lights::const_iterator fi = _off_lights.begin();
|
|
|
+ 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);
|
|
|
+
|
|
|
+ if (light != other_light) {
|
|
|
+ return light < other_light ? -1 : 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ ++fi;
|
|
|
+ ++ofi;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (fi != _off_lights.end()) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ if (ofi != ta->_off_lights.end()) {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
@@ -236,95 +562,78 @@ compose_impl(const RenderAttrib *other) const {
|
|
|
const LightAttrib *ta;
|
|
|
DCAST_INTO_R(ta, other, 0);
|
|
|
|
|
|
- if (ta->_operation == O_set) {
|
|
|
- // If the other type is O_set, it doesn't matter what we are.
|
|
|
- return ta;
|
|
|
- }
|
|
|
-
|
|
|
- if (_operation == ta->_operation) {
|
|
|
- // If the operation types match, the composition is simply the
|
|
|
- // union.
|
|
|
- return do_add(ta, _operation);
|
|
|
-
|
|
|
- } else if (ta->_operation == O_remove) {
|
|
|
- // If the other operation type is remove, and our type is add or
|
|
|
- // set, then remove.
|
|
|
- return do_remove(ta, _operation);
|
|
|
-
|
|
|
- } else if (_operation == O_remove) {
|
|
|
- // If our type is remove, then the other one wins.
|
|
|
+ if (ta->_off_all_lights) {
|
|
|
+ // If the other type turns off all lights, it doesn't matter what
|
|
|
+ // we are.
|
|
|
return ta;
|
|
|
-
|
|
|
- } else {
|
|
|
- // Otherwise, the result is the union.
|
|
|
- return do_add(ta, _operation);
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: LightAttrib::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) LightAttrib::
|
|
|
-invert_compose_impl(const RenderAttrib *other) const {
|
|
|
- // I think in this case the other attrib always wins. Maybe this
|
|
|
- // needs a bit more thought. It's hard to imagine that it's even
|
|
|
- // important to compute this properly.
|
|
|
- return other;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: LightAttrib::make_default_impl
|
|
|
-// Access: Protected, Virtual
|
|
|
-// Description: Intended to be overridden by derived LightAttrib
|
|
|
-// types to specify what the default property for a
|
|
|
-// LightAttrib of this type should be.
|
|
|
-//
|
|
|
-// This should return a newly-allocated LightAttrib of
|
|
|
-// the same type that corresponds to whatever the
|
|
|
-// standard default for this kind of LightAttrib is.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-RenderAttrib *LightAttrib::
|
|
|
-make_default_impl() const {
|
|
|
- return new LightAttrib;
|
|
|
-}
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: LightAttrib::do_add
|
|
|
-// Access: Private
|
|
|
-// Description: Returns a new LightAttrib that represents all the
|
|
|
-// lights of this attrib, with those of the other one
|
|
|
-// added in.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-CPT(RenderAttrib) LightAttrib::
|
|
|
-do_add(const LightAttrib *other, LightAttrib::Operation op) const {
|
|
|
- Lights::const_iterator ai = _lights.begin();
|
|
|
- Lights::const_iterator bi = other->_lights.begin();
|
|
|
+ // This is a three-way merge between ai, bi, and ci, except that bi
|
|
|
+ // and ci should have no intersection and therefore needn't be
|
|
|
+ // compared to each other.
|
|
|
+ Lights::const_iterator ai = _on_lights.begin();
|
|
|
+ Lights::const_iterator bi = ta->_on_lights.begin();
|
|
|
+ Lights::const_iterator ci = ta->_off_lights.begin();
|
|
|
|
|
|
// Create a new LightAttrib that will hold the result.
|
|
|
LightAttrib *new_attrib = new LightAttrib;
|
|
|
- new_attrib->_operation = op;
|
|
|
back_insert_iterator<Lights> result =
|
|
|
- back_inserter(new_attrib->_lights);
|
|
|
+ back_inserter(new_attrib->_on_lights);
|
|
|
|
|
|
- while (ai != _lights.end() && bi != other->_lights.end()) {
|
|
|
+ while (ai != _on_lights.end() &&
|
|
|
+ bi != ta->_on_lights.end() &&
|
|
|
+ ci != ta->_off_lights.end()) {
|
|
|
+ if ((*ai) < (*bi)) {
|
|
|
+ if ((*ai) < (*ci)) {
|
|
|
+ // Here is a light that we have in the original, which is not
|
|
|
+ // present in the secondary.
|
|
|
+ *result = *ai;
|
|
|
+ ++ai;
|
|
|
+ ++result;
|
|
|
+
|
|
|
+ } else if ((*ci) < (*ai)) {
|
|
|
+ // Here is a light that is turned off in the secondary, but
|
|
|
+ // was not present in the original.
|
|
|
+ ++ci;
|
|
|
+
|
|
|
+ } else { // (*ci) == (*ai)
|
|
|
+ // Here is a light that is turned off in the secondary, and
|
|
|
+ // was present in the original.
|
|
|
+ ++ai;
|
|
|
+ ++ci;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if ((*bi) < (*ai)) {
|
|
|
+ // Here is a new light we have in the secondary, that was not
|
|
|
+ // present in the original.
|
|
|
+ *result = *bi;
|
|
|
+ ++bi;
|
|
|
+ ++result;
|
|
|
+
|
|
|
+ } else { // (*bi) == (*ai)
|
|
|
+ // Here is a light we have in both.
|
|
|
+ *result = *ai;
|
|
|
+ ++ai;
|
|
|
+ ++bi;
|
|
|
+ ++result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ while (ai != _on_lights.end() && bi != ta->_on_lights.end()) {
|
|
|
if ((*ai) < (*bi)) {
|
|
|
// Here is a light that we have in the original, which is not
|
|
|
// present in the secondary.
|
|
|
*result = *ai;
|
|
|
++ai;
|
|
|
++result;
|
|
|
+
|
|
|
} else if ((*bi) < (*ai)) {
|
|
|
// Here is a new light we have in the secondary, that was not
|
|
|
// present in the original.
|
|
|
*result = *bi;
|
|
|
++bi;
|
|
|
++result;
|
|
|
+
|
|
|
} else {
|
|
|
// Here is a light we have in both.
|
|
|
*result = *ai;
|
|
|
@@ -334,13 +643,34 @@ do_add(const LightAttrib *other, LightAttrib::Operation op) const {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- while (ai != _lights.end()) {
|
|
|
+ while (ai != _on_lights.end() && ci != ta->_off_lights.end()) {
|
|
|
+ if ((*ai) < (*ci)) {
|
|
|
+ // Here is a light that we have in the original, which is not
|
|
|
+ // present in the secondary.
|
|
|
+ *result = *ai;
|
|
|
+ ++ai;
|
|
|
+ ++result;
|
|
|
+
|
|
|
+ } else if ((*ci) < (*ai)) {
|
|
|
+ // Here is a light that is turned off in the secondary, but
|
|
|
+ // was not present in the original.
|
|
|
+ ++ci;
|
|
|
+
|
|
|
+ } else { // (*ci) == (*ai)
|
|
|
+ // Here is a light that is turned off in the secondary, and
|
|
|
+ // was present in the original.
|
|
|
+ ++ai;
|
|
|
+ ++ci;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ while (ai != _on_lights.end()) {
|
|
|
*result = *ai;
|
|
|
++ai;
|
|
|
++result;
|
|
|
}
|
|
|
|
|
|
- while (bi != other->_lights.end()) {
|
|
|
+ while (bi != ta->_on_lights.end()) {
|
|
|
*result = *bi;
|
|
|
++bi;
|
|
|
++result;
|
|
|
@@ -350,48 +680,36 @@ do_add(const LightAttrib *other, LightAttrib::Operation op) const {
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: LightAttrib::do_remove
|
|
|
-// Access: Private
|
|
|
-// Description: Returns a new LightAttrib that represents all the
|
|
|
-// lights of this attrib, with those of the other one
|
|
|
-// removed.
|
|
|
+// Function: LightAttrib::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) LightAttrib::
|
|
|
-do_remove(const LightAttrib *other, LightAttrib::Operation op) const {
|
|
|
- Lights::const_iterator ai = _lights.begin();
|
|
|
- Lights::const_iterator bi = other->_lights.begin();
|
|
|
-
|
|
|
- // Create a new LightAttrib that will hold the result.
|
|
|
- LightAttrib *new_attrib = new LightAttrib;
|
|
|
- new_attrib->_operation = op;
|
|
|
- back_insert_iterator<Lights> result =
|
|
|
- back_inserter(new_attrib->_lights);
|
|
|
-
|
|
|
- while (ai != _lights.end() && bi != other->_lights.end()) {
|
|
|
- if ((*ai) < (*bi)) {
|
|
|
- // Here is a light that we have in the original, which is
|
|
|
- // not present in the secondary. Keep it.
|
|
|
- *result = *ai;
|
|
|
- ++ai;
|
|
|
- ++result;
|
|
|
- } else if ((*bi) < (*ai)) {
|
|
|
- // Here is a new light we have in the secondary, that was
|
|
|
- // not present in the original. Ignore it.
|
|
|
- ++bi;
|
|
|
- } else {
|
|
|
- // Here is a light we have in both. Drop it.
|
|
|
- ++ai;
|
|
|
- ++bi;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- while (ai != _lights.end()) {
|
|
|
- *result = *ai;
|
|
|
- ++ai;
|
|
|
- ++result;
|
|
|
- }
|
|
|
+invert_compose_impl(const RenderAttrib *other) const {
|
|
|
+ // I think in this case the other attrib always wins. Maybe this
|
|
|
+ // needs a bit more thought. It's hard to imagine that it's even
|
|
|
+ // important to compute this properly.
|
|
|
+ return other;
|
|
|
+}
|
|
|
|
|
|
- return return_new(new_attrib);
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LightAttrib::make_default_impl
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Intended to be overridden by derived LightAttrib
|
|
|
+// types to specify what the default property for a
|
|
|
+// LightAttrib of this type should be.
|
|
|
+//
|
|
|
+// This should return a newly-allocated LightAttrib of
|
|
|
+// the same type that corresponds to whatever the
|
|
|
+// standard default for this kind of LightAttrib is.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+RenderAttrib *LightAttrib::
|
|
|
+make_default_impl() const {
|
|
|
+ return new LightAttrib;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -415,14 +733,23 @@ void LightAttrib::
|
|
|
write_datagram(BamWriter *manager, Datagram &dg) {
|
|
|
RenderAttrib::write_datagram(manager, dg);
|
|
|
|
|
|
- dg.add_int8((int)_operation);
|
|
|
- PN_uint16 num_lights = _lights.size();
|
|
|
- nassertv(num_lights == _lights.size());
|
|
|
- dg.add_uint16(num_lights);
|
|
|
+ dg.add_bool(_off_all_lights);
|
|
|
|
|
|
- Lights::const_iterator li;
|
|
|
- for (li = _lights.begin(); li != _lights.end(); ++li) {
|
|
|
- Light *light = (*li);
|
|
|
+ // write the number of off_lights
|
|
|
+ dg.add_uint16(get_num_off_lights());
|
|
|
+ // 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());
|
|
|
+ }
|
|
|
+
|
|
|
+ // write the number of on lights
|
|
|
+ dg.add_uint16(get_num_on_lights());
|
|
|
+ // 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());
|
|
|
}
|
|
|
}
|
|
|
@@ -438,11 +765,20 @@ int LightAttrib::
|
|
|
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
|
|
int pi = RenderAttrib::complete_pointers(p_list, manager);
|
|
|
|
|
|
- Lights::iterator li;
|
|
|
- for (li = _lights.begin(); li != _lights.end(); ++li) {
|
|
|
+ Lights::iterator ci = _off_lights.begin();
|
|
|
+ while (ci != _off_lights.end()) {
|
|
|
+ PandaNode *node;
|
|
|
+ DCAST_INTO_R(node, p_list[pi++], pi);
|
|
|
+ (*ci) = node->as_light();
|
|
|
+ ++ci;
|
|
|
+ }
|
|
|
+
|
|
|
+ ci = _on_lights.begin();
|
|
|
+ while (ci != _on_lights.end()) {
|
|
|
PandaNode *node;
|
|
|
DCAST_INTO_R(node, p_list[pi++], pi);
|
|
|
- (*li) = node->as_light();
|
|
|
+ (*ci) = node->as_light();
|
|
|
+ ++ci;
|
|
|
}
|
|
|
|
|
|
return pi;
|
|
|
@@ -479,11 +815,31 @@ void LightAttrib::
|
|
|
fillin(DatagramIterator &scan, BamReader *manager) {
|
|
|
RenderAttrib::fillin(scan, manager);
|
|
|
|
|
|
- _operation = (Operation)scan.get_int8();
|
|
|
- int num_lights = scan.get_uint16();
|
|
|
-
|
|
|
- for (int i = 0; i < num_lights; i++) {
|
|
|
+ // We cheat a little bit here. In the middle of bam version 4.10,
|
|
|
+ // we completely redefined the bam storage definition for
|
|
|
+ // LightAttribs, without bothering to up the bam version or even to
|
|
|
+ // attempt to read the old definition. We get away with this,
|
|
|
+ // knowing that the egg loader doesn't create LightAttribs, and
|
|
|
+ // hence no old bam files have the old definition for LightAttrib
|
|
|
+ // within them.
|
|
|
+
|
|
|
+ _off_all_lights = scan.get_bool();
|
|
|
+
|
|
|
+ int num_off_lights = scan.get_uint16();
|
|
|
+
|
|
|
+ // Push back a NULL pointer for each off Light for now, until
|
|
|
+ // we get the actual list of pointers later in complete_pointers().
|
|
|
+ _off_lights.reserve(num_off_lights);
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < num_off_lights; i++) {
|
|
|
+ manager->read_pointer(scan);
|
|
|
+ _off_lights.push_back(NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ int num_on_lights = scan.get_uint16();
|
|
|
+ _on_lights.reserve(num_on_lights);
|
|
|
+ for (i = 0; i < num_on_lights; i++) {
|
|
|
manager->read_pointer(scan);
|
|
|
- _lights.push_back(NULL);
|
|
|
+ _on_lights.push_back(NULL);
|
|
|
}
|
|
|
}
|