diff --git a/panda/src/chan/animBundleNode.cxx b/panda/src/chan/animBundleNode.cxx index 302f3e8a0f..176e30a5a4 100644 --- a/panda/src/chan/animBundleNode.cxx +++ b/panda/src/chan/animBundleNode.cxx @@ -64,7 +64,7 @@ void AnimBundleNode:: fillin(DatagramIterator& scan, BamReader* manager) { NamedNode::fillin(scan, manager); - manager->read_pointer(scan, this); + manager->read_pointer(scan); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/chan/animGroup.cxx b/panda/src/chan/animGroup.cxx index 8558e81a64..01dddc045e 100644 --- a/panda/src/chan/animGroup.cxx +++ b/panda/src/chan/animGroup.cxx @@ -205,11 +205,11 @@ void AnimGroup:: fillin(DatagramIterator& scan, BamReader* manager) { set_name(scan.get_string()); - manager->read_pointer(scan, this); + manager->read_pointer(scan); _num_children = scan.get_uint16(); for(int i = 0; i < _num_children; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); } } diff --git a/panda/src/chan/partBundleNode.cxx b/panda/src/chan/partBundleNode.cxx index 86401c5cb5..e5992bb275 100644 --- a/panda/src/chan/partBundleNode.cxx +++ b/panda/src/chan/partBundleNode.cxx @@ -65,7 +65,7 @@ void PartBundleNode:: fillin(DatagramIterator& scan, BamReader* manager) { NamedNode::fillin(scan, manager); - manager->read_pointer(scan, this); + manager->read_pointer(scan); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/chan/partGroup.cxx b/panda/src/chan/partGroup.cxx index 74679504de..2ae8c89398 100644 --- a/panda/src/chan/partGroup.cxx +++ b/panda/src/chan/partGroup.cxx @@ -497,7 +497,7 @@ fillin(DatagramIterator& scan, BamReader* manager) _num_children = scan.get_uint16(); for(i = 0; i < _num_children; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); } } diff --git a/panda/src/chan/qpanimBundleNode.cxx b/panda/src/chan/qpanimBundleNode.cxx index 47d183db17..3e6b8e3c72 100644 --- a/panda/src/chan/qpanimBundleNode.cxx +++ b/panda/src/chan/qpanimBundleNode.cxx @@ -106,5 +106,5 @@ make_from_bam(const FactoryParams ¶ms) { void qpAnimBundleNode:: fillin(DatagramIterator &scan, BamReader* manager) { PandaNode::fillin(scan, manager); - manager->read_pointer(scan, this); + manager->read_pointer(scan); } diff --git a/panda/src/chan/qppartBundleNode.cxx b/panda/src/chan/qppartBundleNode.cxx index 9b93119878..b3465c9e8e 100644 --- a/panda/src/chan/qppartBundleNode.cxx +++ b/panda/src/chan/qppartBundleNode.cxx @@ -76,5 +76,5 @@ complete_pointers(TypedWritable **p_list, BamReader* manager) { void qpPartBundleNode:: fillin(DatagramIterator &scan, BamReader* manager) { PandaNode::fillin(scan, manager); - manager->read_pointer(scan, this); + manager->read_pointer(scan); } diff --git a/panda/src/char/character.cxx b/panda/src/char/character.cxx index 37b1aaad79..91309b29e5 100644 --- a/panda/src/char/character.cxx +++ b/panda/src/char/character.cxx @@ -426,7 +426,7 @@ fillin(DatagramIterator& scan, BamReader* manager) { PartBundleNode::fillin(scan, manager); _cv.fillin(scan, manager); - manager->read_pointer(scan, this); + manager->read_pointer(scan); // Read the number of parts to expect in the _parts list, and then // fill the array up with NULLs. We'll fill in the actual values in @@ -435,7 +435,7 @@ fillin(DatagramIterator& scan, BamReader* manager) _parts.clear(); _parts.reserve(num_parts); for (int i = 0; i < num_parts; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); _parts.push_back((PartGroup *)NULL); } diff --git a/panda/src/char/characterJoint.cxx b/panda/src/char/characterJoint.cxx index d85ea8c026..aec495ac24 100644 --- a/panda/src/char/characterJoint.cxx +++ b/panda/src/char/characterJoint.cxx @@ -339,13 +339,13 @@ fillin(DatagramIterator& scan, BamReader* manager) _num_net_arcs = scan.get_uint16(); for(i = 0; i < _num_net_arcs; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); } _num_local_arcs = scan.get_uint16(); for(i = 0; i < _num_local_arcs; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); } _initial_net_transform_inverse.read_datagram(scan); diff --git a/panda/src/char/qpcharacter.cxx b/panda/src/char/qpcharacter.cxx index 5fc9076f1b..8d6af643da 100644 --- a/panda/src/char/qpcharacter.cxx +++ b/panda/src/char/qpcharacter.cxx @@ -515,7 +515,7 @@ void qpCharacter:: fillin(DatagramIterator &scan, BamReader *manager) { qpPartBundleNode::fillin(scan, manager); _cv.fillin(scan, manager); - manager->read_pointer(scan, this); + manager->read_pointer(scan); // Read the number of parts to expect in the _parts list, and then // fill the array up with NULLs. We'll fill in the actual values in @@ -524,7 +524,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { _parts.clear(); _parts.reserve(num_parts); for (int i = 0; i < num_parts; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); _parts.push_back((PartGroup *)NULL); } diff --git a/panda/src/collide/collisionNode.cxx b/panda/src/collide/collisionNode.cxx index 847351df32..c7bdf2fc20 100644 --- a/panda/src/collide/collisionNode.cxx +++ b/panda/src/collide/collisionNode.cxx @@ -286,7 +286,7 @@ fillin(DatagramIterator& scan, BamReader* manager) _solids.reserve(num_solids); for(i = 0; i < num_solids; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); _solids.push_back((CollisionSolid *)NULL); } diff --git a/panda/src/display/graphicsWindow.cxx b/panda/src/display/graphicsWindow.cxx index 52e60ca33e..5cb237622e 100644 --- a/panda/src/display/graphicsWindow.cxx +++ b/panda/src/display/graphicsWindow.cxx @@ -34,7 +34,12 @@ TypeHandle GraphicsWindow::WindowPipe::_type_handle; GraphicsWindow::WindowFactory *GraphicsWindow::_factory = NULL; -#if defined(DO_PSTATS) && !defined(CPPPARSER) +#ifndef CPPPARSER +// We must compile these lines, even if DO_PSTATS is not defined, +// because the symbols for them are declared in the header file. +// Otherwise they will be undefined symbols at link time. However, +// there's no runtime overhead to speak of for declaring these, so +// there's no harm in compiling them all the time. PStatCollector GraphicsWindow::_app_pcollector("App"); PStatCollector GraphicsWindow::_show_code_pcollector("App:Show code"); PStatCollector GraphicsWindow::_swap_pcollector("Swap buffers"); diff --git a/panda/src/effects/lensFlareNode.cxx b/panda/src/effects/lensFlareNode.cxx index 87d5d07207..abf3fb824c 100644 --- a/panda/src/effects/lensFlareNode.cxx +++ b/panda/src/effects/lensFlareNode.cxx @@ -449,14 +449,14 @@ fillin(DatagramIterator &scan, BamReader *manager) _num_flares = scan.get_uint16(); for(i = 0; i < _num_flares; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); } - manager->read_pointer(scan, this); + manager->read_pointer(scan); _num_arcs = scan.get_uint16(); for(i = 0; i < _num_arcs; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); } size = scan.get_uint16(); @@ -496,7 +496,7 @@ fillin(DatagramIterator &scan, BamReader *manager) _blind_fall_off = scan.get_float32(); _flare_fall_off = scan.get_float32(); - manager->read_pointer(scan, this); + manager->read_pointer(scan); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomSprite.cxx b/panda/src/gobj/geomSprite.cxx index 950bf097c5..62d85cf715 100644 --- a/panda/src/gobj/geomSprite.cxx +++ b/panda/src/gobj/geomSprite.cxx @@ -133,7 +133,7 @@ fillin(DatagramIterator& scan, BamReader* manager) { _x_bind_type = (GeomBindType) scan.get_uint8(); _y_bind_type = (GeomBindType) scan.get_uint8(); _alpha_disable = (scan.get_uint8() !=0); - manager->read_pointer(scan, this); + manager->read_pointer(scan); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/graph/boundedObject.I b/panda/src/graph/boundedObject.I index 170f8828cf..14a46584a6 100644 --- a/panda/src/graph/boundedObject.I +++ b/panda/src/graph/boundedObject.I @@ -29,6 +29,31 @@ CData() { _flags = F_bound_stale; } +//////////////////////////////////////////////////////////////////// +// Function: BoundedObject::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_GRAPH BoundedObject::CData:: +CData(const BoundedObject::CData ©) : + _flags(copy._flags), + _bound_type(copy._bound_type), + _bound(copy._bound) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundedObject::CData::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_GRAPH void BoundedObject::CData:: +operator = (const BoundedObject::CData ©) { + _flags = copy._flags; + _bound_type = copy._bound_type; + _bound = copy._bound; +} + //////////////////////////////////////////////////////////////////// // Function: BoundedObject::Constructor @@ -45,12 +70,9 @@ BoundedObject() { // Description: //////////////////////////////////////////////////////////////////// INLINE_GRAPH BoundedObject:: -BoundedObject(const BoundedObject ©) { - CDWriter cdata(_cycler); - CDReader copy_cdata(copy._cycler); - cdata->_flags = copy_cdata->_flags; - cdata->_bound_type = copy_cdata->_bound_type; - cdata->_bound = copy_cdata->_bound; +BoundedObject(const BoundedObject ©) : + _cycler(copy._cycler) +{ } //////////////////////////////////////////////////////////////////// @@ -60,11 +82,7 @@ BoundedObject(const BoundedObject ©) { //////////////////////////////////////////////////////////////////// INLINE_GRAPH void BoundedObject:: operator = (const BoundedObject ©) { - CDWriter cdata(_cycler); - CDReader copy_cdata(copy._cycler); - cdata->_flags = copy_cdata->_flags; - cdata->_bound_type = copy_cdata->_bound_type; - cdata->_bound = copy_cdata->_bound; + _cycler = copy._cycler; } //////////////////////////////////////////////////////////////////// @@ -77,8 +95,8 @@ operator = (const BoundedObject ©) { INLINE_GRAPH void BoundedObject:: set_bound(BoundedObject::BoundingVolumeType type) { nassertv(type != BVT_static); - CDWriter cdata(_cycler); mark_bound_stale(); + CDWriter cdata(_cycler); cdata->_bound_type = type; } @@ -91,35 +109,13 @@ set_bound(BoundedObject::BoundingVolumeType type) { //////////////////////////////////////////////////////////////////// INLINE_GRAPH void BoundedObject:: set_bound(const BoundingVolume &bound) { - CDWriter cdata(_cycler); mark_bound_stale(); + CDWriter cdata(_cycler); cdata->_bound_type = BVT_static; cdata->_flags &= ~F_bound_stale; cdata->_bound = bound.make_copy(); } -//////////////////////////////////////////////////////////////////// -// Function: BoundedObject::get_bound -// Access: Published -// Description: Returns the current bounding volume on this node, -// possibly forcing a recompute. A node's bounding -// volume encloses only the node itself, irrespective of -// the nodes above or below it in the graph. This is -// different from the bounding volumes on the arcs, -// which enclose all geometry below them. -//////////////////////////////////////////////////////////////////// -INLINE_GRAPH const BoundingVolume &BoundedObject:: -get_bound() const { - CDReader cdata(_cycler); - if (cdata->_bound_type == BVT_static) { - CDWriter cdata_w(((BoundedObject *)this)->_cycler); - cdata_w->_flags &= ~F_bound_stale; - } else if (is_bound_stale() || cdata->_bound == (BoundingVolume *)NULL) { - ((BoundedObject *)this)->recompute_bound(); - } - return *cdata->_bound; -} - //////////////////////////////////////////////////////////////////// // Function: BoundedObject::mark_bound_stale // Access: Published @@ -135,8 +131,10 @@ mark_bound_stale() { if (is_bound_stale()) { return false; } - CDWriter cdata(_cycler); - cdata->_flags |= F_bound_stale; + { + CDWriter cdata(_cycler); + cdata->_flags |= F_bound_stale; + } propagate_stale_bound(); return true; @@ -151,8 +149,10 @@ mark_bound_stale() { //////////////////////////////////////////////////////////////////// INLINE_GRAPH void BoundedObject:: force_bound_stale() { - CDWriter cdata(_cycler); - cdata->_flags |= F_bound_stale; + { + CDWriter cdata(_cycler); + cdata->_flags |= F_bound_stale; + } propagate_stale_bound(); } diff --git a/panda/src/graph/boundedObject.cxx b/panda/src/graph/boundedObject.cxx index 523d60db2f..bf174a2779 100644 --- a/panda/src/graph/boundedObject.cxx +++ b/panda/src/graph/boundedObject.cxx @@ -23,19 +23,6 @@ TypeHandle BoundedObject::_type_handle; -//////////////////////////////////////////////////////////////////// -// Function: BoundedObject::CData::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -BoundedObject::CData:: -CData(const BoundedObject::CData ©) : - _flags(copy._flags), - _bound_type(copy._bound_type), - _bound(copy._bound) -{ -} - //////////////////////////////////////////////////////////////////// // Function: BoundedObject::Destructor // Access: Public, Virtual @@ -45,6 +32,41 @@ BoundedObject:: ~BoundedObject() { } +//////////////////////////////////////////////////////////////////// +// Function: BoundedObject::get_bound +// Access: Published +// Description: Returns the current bounding volume on this node, +// possibly forcing a recompute. A node's bounding +// volume encloses only the node itself, irrespective of +// the nodes above or below it in the graph. This is +// different from the bounding volumes on the arcs, +// which enclose all geometry below them. +//////////////////////////////////////////////////////////////////// +INLINE_GRAPH const BoundingVolume &BoundedObject:: +get_bound() const { + { + CDReader cdata(_cycler); + if (cdata->_bound_type == BVT_static) { + CDWriter cdata_w(((BoundedObject *)this)->_cycler, cdata); + cdata_w->_flags &= ~F_bound_stale; + return *cdata_w->_bound; + } + + if (!is_bound_stale() && cdata->_bound != (BoundingVolume *)NULL) { + return *cdata->_bound; + } + + // We need to recompute the bounding volume. First, we need to + // release the old CDReader, so we can get a CDReader in + // recompute_bound(). + } + + // Now it's safe to recompute the bounds. + ((BoundedObject *)this)->recompute_bound(); + CDReader cdata(_cycler); + return *cdata->_bound; +} + //////////////////////////////////////////////////////////////////// // Function: BoundedObject::CData::make_copy // Access: Public, Virtual diff --git a/panda/src/graph/boundedObject.h b/panda/src/graph/boundedObject.h index c71107facf..473a92bbb7 100644 --- a/panda/src/graph/boundedObject.h +++ b/panda/src/graph/boundedObject.h @@ -52,7 +52,7 @@ PUBLISHED: INLINE_GRAPH void set_bound(BoundingVolumeType type); INLINE_GRAPH void set_bound(const BoundingVolume &volume); - INLINE_GRAPH const BoundingVolume &get_bound() const; + const BoundingVolume &get_bound() const; INLINE_GRAPH bool mark_bound_stale(); INLINE_GRAPH void force_bound_stale(); @@ -78,7 +78,9 @@ private: class EXPCL_PANDA CData : public CycleData { public: INLINE_GRAPH CData(); - CData(const CData ©); + INLINE_GRAPH CData(const CData ©); + INLINE_GRAPH void operator = (const CData ©); + virtual CycleData *make_copy() const; int _flags; diff --git a/panda/src/graph/node.cxx b/panda/src/graph/node.cxx index 011c26c605..0d80961783 100644 --- a/panda/src/graph/node.cxx +++ b/panda/src/graph/node.cxx @@ -636,7 +636,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { while (num_types > 0) { int num_arcs = scan.get_uint16(); while (num_arcs > 0) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); num_arcs--; } num_types--; @@ -666,7 +666,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { DownRelationPointers &drp = _connections[i].get_down(); int num_arcs = scan.get_uint16(); while (num_arcs > 0) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); drp.push_back((NodeRelation *)NULL); num_arcs--; } diff --git a/panda/src/graph/nodeRelation.cxx b/panda/src/graph/nodeRelation.cxx index c32a533a28..2037a27c17 100644 --- a/panda/src/graph/nodeRelation.cxx +++ b/panda/src/graph/nodeRelation.cxx @@ -984,9 +984,9 @@ fillin(DatagramIterator& scan, BamReader* manager) { _graph_type = manager->read_handle(scan); //Read in my parent - manager->read_pointer(scan, this); + manager->read_pointer(scan); //Read in my child - manager->read_pointer(scan, this); + manager->read_pointer(scan); //Get my sort relation _sort = scan.get_uint16(); @@ -994,7 +994,7 @@ fillin(DatagramIterator& scan, BamReader* manager) _num_transitions = scan.get_uint16(); for(int i = 0; i < _num_transitions; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); } } diff --git a/panda/src/parametrics/piecewiseCurve.cxx b/panda/src/parametrics/piecewiseCurve.cxx index 56e5cf5d28..99cb464c6f 100644 --- a/panda/src/parametrics/piecewiseCurve.cxx +++ b/panda/src/parametrics/piecewiseCurve.cxx @@ -610,7 +610,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { size_t i; for (i = 0; i < num_segs; i++) { Curveseg seg; - manager->read_pointer(scan, this); + manager->read_pointer(scan); seg._curve = (ParametricCurve *)NULL; seg._tend = scan.get_float64(); _segs.push_back(seg); diff --git a/panda/src/pgraph/materialAttrib.cxx b/panda/src/pgraph/materialAttrib.cxx index 510c992eed..583135606d 100644 --- a/panda/src/pgraph/materialAttrib.cxx +++ b/panda/src/pgraph/materialAttrib.cxx @@ -192,5 +192,5 @@ fillin(DatagramIterator &scan, BamReader *manager) { RenderAttrib::fillin(scan, manager); // Read the _material pointer. - manager->read_pointer(scan, this); + manager->read_pointer(scan); } diff --git a/panda/src/pgraph/pandaNode.I b/panda/src/pgraph/pandaNode.I index 002e69021b..4d69be0999 100644 --- a/panda/src/pgraph/pandaNode.I +++ b/panda/src/pgraph/pandaNode.I @@ -353,8 +353,10 @@ clear_state() { //////////////////////////////////////////////////////////////////// INLINE void PandaNode:: set_transform(const TransformState *transform) { - CDWriter cdata(_cycler); - cdata->_transform = transform; + { + CDWriter cdata(_cycler); + cdata->_transform = transform; + } mark_bound_stale(); } diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index ad9be7b126..3081e09633 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -53,6 +53,122 @@ make_copy() const { return new CData(*this); } +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void PandaNode::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { + manager->write_pointer(dg, _state); + manager->write_pointer(dg, _transform); + + // When we write a PandaNode, we write out its complete list of + // child node pointers, but we only write out the parent node + // pointers that have already been added to the bam file by a + // previous write operation. This is a bit of trickery that allows + // us to write out just a subgraph (instead of the complete graph) + // when we write out an arbitrary node in the graph, yet also allows + // us to keep nodes completely in sync when we use the bam format + // for streaming scene graph operations over the network. + + int num_parents = 0; + Up::const_iterator ui; + for (ui = _up.begin(); ui != _up.end(); ++ui) { + PandaNode *parent_node = (*ui).get_parent(); + if (manager->has_object(parent_node)) { + num_parents++; + } + } + nassertv(num_parents == (int)(PN_uint16)num_parents); + dg.add_uint16(num_parents); + for (ui = _up.begin(); ui != _up.end(); ++ui) { + PandaNode *parent_node = (*ui).get_parent(); + if (manager->has_object(parent_node)) { + manager->write_pointer(dg, parent_node); + } + } + + int num_children = _down.size(); + nassertv(num_children == (int)(PN_uint16)num_children); + dg.add_uint16(num_children); + + // **** We should smarten up the writing of the sort number--most of + // the time these will all be zero. + Down::const_iterator ci; + for (ci = _down.begin(); ci != _down.end(); ++ci) { + PandaNode *child_node = (*ci).get_child(); + int sort = (*ci).get_sort(); + manager->write_pointer(dg, child_node); + dg.add_int32(sort); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::CData::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int PandaNode::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + // Get the state and transform pointers. + _state = DCAST(RenderState, p_list[pi++]); + _transform = DCAST(TransformState, p_list[pi++]); + + // Get the parent pointers. + Up::iterator ui; + for (ui = _up.begin(); ui != _up.end(); ++ui) { + PT(PandaNode) parent_node = DCAST(PandaNode, p_list[pi++]); + (*ui) = UpConnection(parent_node); + } + + // Get the child pointers. + Down::iterator di; + for (di = _down.begin(); di != _down.end(); ++di) { + int sort = (*di).get_sort(); + PT(PandaNode) child_node = DCAST(PandaNode, p_list[pi++]); + (*di) = DownConnection(child_node, sort); + } + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new PandaNode. +//////////////////////////////////////////////////////////////////// +void PandaNode::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { + // Read the state and transform pointers. + manager->read_pointer(scan); + manager->read_pointer(scan); + + int num_parents = scan.get_uint16(); + // Read the list of parent nodes. Push back a NULL for each one. + _up.reserve(num_parents); + for (int i = 0; i < num_parents; i++) { + manager->read_pointer(scan); + _up.push_back(UpConnection(NULL)); + } + + int num_children = scan.get_uint16(); + // Read the list of child nodes. Push back a NULL for each one. + _down.reserve(num_children); + for (int i = 0; i < num_children; i++) { + manager->read_pointer(scan); + int sort = scan.get_int32(); + _down.push_back(DownConnection(NULL, sort)); + } +} + //////////////////////////////////////////////////////////////////// // Function: PandaNode::Constructor // Access: Published @@ -73,16 +189,22 @@ PandaNode:: ~PandaNode() { // We shouldn't have any parents left by the time we destruct, or // there's a refcount fault somewhere. - CDReader cdata(_cycler); - nassertv(cdata->_up.empty()); +#ifndef NDEBUG + { + CDReader cdata(_cycler); + nassertv(cdata->_up.empty()); + } +#endif // NDEBUG remove_all_children(); } //////////////////////////////////////////////////////////////////// // Function: PandaNode::Copy Constructor -// Access: Public -// Description: +// Access: Protected +// Description: Do not call the copy constructor directly; instead, +// use make_copy() or copy_subgraph() to make a copy of +// a node. //////////////////////////////////////////////////////////////////// PandaNode:: PandaNode(const PandaNode ©) : @@ -101,29 +223,24 @@ PandaNode(const PandaNode ©) : //////////////////////////////////////////////////////////////////// // Function: PandaNode::Copy Assignment Operator -// Access: Public -// Description: +// Access: Private +// Description: Do not call the copy assignment operator at all. Use +// make_copy() or copy_subgraph() to make a copy of a +// node. //////////////////////////////////////////////////////////////////// void PandaNode:: operator = (const PandaNode ©) { - TypedWritable::operator = (copy); - Namable::operator = (copy); - ReferenceCount::operator = (copy); - - // Copy the other node's state. - CDReader copy_cdata(copy._cycler); - CDWriter cdata(_cycler); - cdata->_state = copy_cdata->_state; - cdata->_transform = copy_cdata->_transform; + nassertv(false); } //////////////////////////////////////////////////////////////////// // Function: PandaNode::make_copy // Access: Public, Virtual -// Description: Returns a newly-allocated PandaNode that is a shallow copy -// of this one. It will be a different pointer, but its -// internal data may or may not be shared with that of -// the original PandaNode. No children will be copied. +// Description: Returns a newly-allocated PandaNode that is a shallow +// copy of this one. It will be a different pointer, +// but its internal data may or may not be shared with +// that of the original PandaNode. No children will be +// copied. //////////////////////////////////////////////////////////////////// PandaNode *PandaNode:: make_copy() const { @@ -361,29 +478,30 @@ find_child(PandaNode *node) const { void PandaNode:: add_child(PandaNode *child_node, int sort) { // Ensure the child_node is not deleted while we do this. - PT(PandaNode) keep_child = child_node; - remove_child(child_node); - CDWriter cdata(_cycler); - CDWriter cdata_child(child_node->_cycler); - - cdata->_down.insert(DownConnection(child_node, sort)); - cdata_child->_up.insert(UpConnection(this)); - - // We also have to adjust any qpNodePathComponents the child might - // have that reference the child as a top node. Any other - // components we can leave alone, because we are making a new - // instance of the child. - Chains::iterator ci; - for (ci = cdata_child->_chains.begin(); - ci != cdata_child->_chains.end(); - ++ci) { - if ((*ci)->is_top_node()) { - (*ci)->set_next(get_generic_component()); + { + PT(PandaNode) keep_child = child_node; + remove_child(child_node); + CDWriter cdata(_cycler); + CDWriter cdata_child(child_node->_cycler); + + cdata->_down.insert(DownConnection(child_node, sort)); + cdata_child->_up.insert(UpConnection(this)); + + // We also have to adjust any qpNodePathComponents the child might + // have that reference the child as a top node. Any other + // components we can leave alone, because we are making a new + // instance of the child. + Chains::iterator ci; + for (ci = cdata_child->_chains.begin(); + ci != cdata_child->_chains.end(); + ++ci) { + if ((*ci)->is_top_node()) { + (*ci)->set_next(get_generic_component()); + } } + child_node->fix_chain_lengths(cdata_child); } - child_node->fix_chain_lengths(); - // Mark the bounding volumes stale. force_bound_stale(); } @@ -395,45 +513,47 @@ add_child(PandaNode *child_node, int sort) { //////////////////////////////////////////////////////////////////// void PandaNode:: remove_child(int n) { - CDWriter cdata(_cycler); - nassertv(n >= 0 && n < (int)cdata->_down.size()); - - PT(PandaNode) child_node = cdata->_down[n].get_child(); - CDWriter cdata_child(child_node->_cycler); - - cdata->_down.erase(cdata->_down.begin() + n); - int num_erased = cdata_child->_up.erase(UpConnection(this)); - nassertv(num_erased == 1); - - // Now sever any qpNodePathComponents on the child that reference - // this node. If we have multiple of these, we have to collapse - // them together. - qpNodePathComponent *collapsed = (qpNodePathComponent *)NULL; - Chains::iterator ci; - ci = cdata_child->_chains.begin(); - while (ci != cdata_child->_chains.end()) { - Chains::iterator cnext = ci; - ++cnext; - if (!(*ci)->is_top_node() && (*ci)->get_next()->get_node() == this) { - if (collapsed == (qpNodePathComponent *)NULL) { - (*ci)->set_top_node(); - collapsed = (*ci); - } else { - // This is a different component that used to reference a - // different instance, but now it's all just the same topnode. - // We have to collapse this and the previous one together. - // However, there might be some qpNodePaths out there that - // still keep a pointer to this one, so we can't remove it - // altogether. - (*ci)->collapse_with(collapsed); - cdata_child->_chains.erase(ci); + { + CDWriter cdata(_cycler); + nassertv(n >= 0 && n < (int)cdata->_down.size()); + + PT(PandaNode) child_node = cdata->_down[n].get_child(); + CDWriter cdata_child(child_node->_cycler); + + cdata->_down.erase(cdata->_down.begin() + n); + int num_erased = cdata_child->_up.erase(UpConnection(this)); + nassertv(num_erased == 1); + + // Now sever any qpNodePathComponents on the child that reference + // this node. If we have multiple of these, we have to collapse + // them together. + qpNodePathComponent *collapsed = (qpNodePathComponent *)NULL; + Chains::iterator ci; + ci = cdata_child->_chains.begin(); + while (ci != cdata_child->_chains.end()) { + Chains::iterator cnext = ci; + ++cnext; + if (!(*ci)->is_top_node() && (*ci)->get_next()->get_node() == this) { + if (collapsed == (qpNodePathComponent *)NULL) { + (*ci)->set_top_node(); + collapsed = (*ci); + } else { + // This is a different component that used to reference a + // different instance, but now it's all just the same topnode. + // We have to collapse this and the previous one together. + // However, there might be some qpNodePaths out there that + // still keep a pointer to this one, so we can't remove it + // altogether. + (*ci)->collapse_with(collapsed); + cdata_child->_chains.erase(ci); + } } + ci = cnext; } - ci = cnext; + + child_node->fix_chain_lengths(cdata_child); } - child_node->fix_chain_lengths(); - // Mark the bounding volumes stale. force_bound_stale(); } @@ -448,73 +568,20 @@ remove_child(int n) { bool PandaNode:: remove_child(PandaNode *child_node) { // Ensure the child_node is not deleted while we do this. - PT(PandaNode) keep_child = child_node; - CDWriter cdata_child(child_node->_cycler); - - // First, look for and remove this node from the child's parent - // list. - int num_erased = cdata_child->_up.erase(UpConnection(this)); - if (num_erased == 0) { - // No such node; it wasn't our child to begin with. - return false; - } - - // Now sever any qpNodePathComponents on the child that reference - // this node. If we have multiple of these, we have to collapse - // them together (see above). - qpNodePathComponent *collapsed = (qpNodePathComponent *)NULL; - Chains::iterator ci; - ci = cdata_child->_chains.begin(); - while (ci != cdata_child->_chains.end()) { - Chains::iterator cnext = ci; - ++cnext; - if (!(*ci)->is_top_node() && (*ci)->get_next()->get_node() == this) { - if (collapsed == (qpNodePathComponent *)NULL) { - (*ci)->set_top_node(); - collapsed = (*ci); - } else { - (*ci)->collapse_with(collapsed); - cdata_child->_chains.erase(ci); - } - } - ci = cnext; - } - - child_node->fix_chain_lengths(); - - // Mark the bounding volumes stale. - force_bound_stale(); - - CDWriter cdata(_cycler); - - // Now, look for and remove the child node from our down list. - Down::iterator di; - for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) { - if ((*di).get_child() == child_node) { - cdata->_down.erase(di); - return true; - } - } - - // We shouldn't get here unless there was a parent-child mismatch. - nassertr(false, false); - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::remove_all_children -// Access: Published -// Description: Removes all the children from the node at once. -//////////////////////////////////////////////////////////////////// -void PandaNode:: -remove_all_children() { - CDWriter cdata(_cycler); - Down::iterator ci; - for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) { - PT(PandaNode) child_node = (*ci).get_child(); + { + PT(PandaNode) keep_child = child_node; + + CDWriter cdata(_cycler); CDWriter cdata_child(child_node->_cycler); - cdata_child->_up.erase(UpConnection(this)); - + + // First, look for and remove this node from the child's parent + // list. + int num_erased = cdata_child->_up.erase(UpConnection(this)); + if (num_erased == 0) { + // No such node; it wasn't our child to begin with. + return false; + } + // Now sever any qpNodePathComponents on the child that reference // this node. If we have multiple of these, we have to collapse // them together (see above). @@ -525,18 +592,75 @@ remove_all_children() { Chains::iterator cnext = ci; ++cnext; if (!(*ci)->is_top_node() && (*ci)->get_next()->get_node() == this) { - if (collapsed == (qpNodePathComponent *)NULL) { - (*ci)->set_top_node(); - collapsed = (*ci); - } else { - (*ci)->collapse_with(collapsed); - cdata_child->_chains.erase(ci); - } + if (collapsed == (qpNodePathComponent *)NULL) { + (*ci)->set_top_node(); + collapsed = (*ci); + } else { + (*ci)->collapse_with(collapsed); + cdata_child->_chains.erase(ci); + } } ci = cnext; } + + child_node->fix_chain_lengths(cdata_child); + + // Now, look for and remove the child node from our down list. + Down::iterator di; + bool found = false; + for (di = cdata->_down.begin(); di != cdata->_down.end() && !found; ++di) { + if ((*di).get_child() == child_node) { + cdata->_down.erase(di); + found = true; + } + } - child_node->fix_chain_lengths(); + nassertr(found, false); + } + + // Mark the bounding volumes stale. + force_bound_stale(); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::remove_all_children +// Access: Published +// Description: Removes all the children from the node at once. +//////////////////////////////////////////////////////////////////// +void PandaNode:: +remove_all_children() { + { + CDWriter cdata(_cycler); + Down::iterator ci; + for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) { + PT(PandaNode) child_node = (*ci).get_child(); + CDWriter cdata_child(child_node->_cycler); + cdata_child->_up.erase(UpConnection(this)); + + // Now sever any qpNodePathComponents on the child that reference + // this node. If we have multiple of these, we have to collapse + // them together (see above). + qpNodePathComponent *collapsed = (qpNodePathComponent *)NULL; + Chains::iterator ci; + ci = cdata_child->_chains.begin(); + while (ci != cdata_child->_chains.end()) { + Chains::iterator cnext = ci; + ++cnext; + if (!(*ci)->is_top_node() && (*ci)->get_next()->get_node() == this) { + if (collapsed == (qpNodePathComponent *)NULL) { + (*ci)->set_top_node(); + collapsed = (*ci); + } else { + (*ci)->collapse_with(collapsed); + cdata_child->_chains.erase(ci); + } + } + ci = cnext; + } + + child_node->fix_chain_lengths(cdata_child); + } } // Mark the bounding volumes stale. @@ -600,8 +724,8 @@ propagate_stale_bound() { CDWriter cdata(_cycler); Up::const_iterator ui; for (ui = cdata->_up.begin(); ui != cdata->_up.end(); ++ui) { - PandaNode *parent = (*ui).get_parent(); - parent->mark_bound_stale(); + PandaNode *parent_node = (*ui).get_parent(); + parent_node->mark_bound_stale(); } } @@ -718,57 +842,58 @@ void PandaNode:: detach(qpNodePathComponent *child) { nassertv(child != (qpNodePathComponent *)NULL); nassertv(!child->is_top_node()); + PandaNode *child_node = child->get_node(); PandaNode *parent_node = child->get_next()->get_node(); - - // Break the qpNodePathComponent connection. - child->set_top_node(); - - CDWriter cdata_child(child_node->_cycler); - - // Any other components in the same child_node that previously - // referenced the same parent has now become invalid and must be - // collapsed into this one and removed from the chains set. - Chains::iterator ci; - ci = cdata_child->_chains.begin(); - while (ci != cdata_child->_chains.end()) { - Chains::iterator cnext = ci; - ++cnext; - if ((*ci) != child && !(*ci)->is_top_node() && - (*ci)->get_next()->get_node() == parent_node) { - (*ci)->collapse_with(child); - cdata_child->_chains.erase(ci); + + { + // Break the qpNodePathComponent connection. + child->set_top_node(); + + CDWriter cdata_child(child_node->_cycler); + CDWriter cdata_parent(parent_node->_cycler); + + // Any other components in the same child_node that previously + // referenced the same parent has now become invalid and must be + // collapsed into this one and removed from the chains set. + Chains::iterator ci; + ci = cdata_child->_chains.begin(); + while (ci != cdata_child->_chains.end()) { + Chains::iterator cnext = ci; + ++cnext; + if ((*ci) != child && !(*ci)->is_top_node() && + (*ci)->get_next()->get_node() == parent_node) { + (*ci)->collapse_with(child); + cdata_child->_chains.erase(ci); + } + ci = cnext; } - ci = cnext; + + // Now look for the child and break the actual connection. + + // First, look for and remove the parent node from the child's up + // list. + int num_erased = cdata_child->_up.erase(UpConnection(parent_node)); + nassertv(num_erased == 1); + + child_node->fix_chain_lengths(cdata_child); + + // Now, look for and remove the child node from the parent's down list. + Down::iterator di; + bool found = false; + for (di = cdata_parent->_down.begin(); + di != cdata_parent->_down.end() && !found; + ++di) { + if ((*di).get_child() == child_node) { + cdata_parent->_down.erase(di); + found = true; + } + } + nassertv(found); } - child_node->fix_chain_lengths(); - // Mark the bounding volumes stale. parent_node->force_bound_stale(); - - // Now look for the child and break the actual connection. - - // First, look for and remove the parent node from the child's up - // list. - int num_erased = cdata_child->_up.erase(UpConnection(parent_node)); - nassertv(num_erased == 1); - - CDWriter cdata_parent(parent_node->_cycler); - - // Now, look for and remove the child node from the parent's down list. - Down::iterator di; - for (di = cdata_parent->_down.begin(); - di != cdata_parent->_down.end(); - ++di) { - if ((*di).get_child() == child_node) { - cdata_parent->_down.erase(di); - return; - } - } - - // We shouldn't get here unless there was a parent-child mismatch. - nassertv(false); } //////////////////////////////////////////////////////////////////// @@ -791,15 +916,17 @@ reparent(qpNodePathComponent *new_parent, qpNodePathComponent *child, int sort) PandaNode *child_node = child->get_node(); PandaNode *parent_node = new_parent->get_node(); - // Now reattach at the indicated sort position. - CDWriter cdata_parent(parent_node->_cycler); - CDWriter cdata_child(child_node->_cycler); - - cdata_parent->_down.insert(DownConnection(child_node, sort)); - cdata_child->_up.insert(UpConnection(parent_node)); - - cdata_child->_chains.insert(child); - child_node->fix_chain_lengths(); + { + // Now reattach at the indicated sort position. + CDWriter cdata_parent(parent_node->_cycler); + CDWriter cdata_child(child_node->_cycler); + + cdata_parent->_down.insert(DownConnection(child_node, sort)); + cdata_child->_up.insert(UpConnection(parent_node)); + + cdata_child->_chains.insert(child); + child_node->fix_chain_lengths(cdata_child); + } // Mark the bounding volumes stale. parent_node->force_bound_stale(); @@ -947,8 +1074,7 @@ delete_component(qpNodePathComponent *component) { // these up. //////////////////////////////////////////////////////////////////// void PandaNode:: -fix_chain_lengths() { - CDReader cdata(_cycler); +fix_chain_lengths(const CData *cdata) { bool any_wrong = false; Chains::const_iterator ci; @@ -964,7 +1090,9 @@ fix_chain_lengths() { if (any_wrong) { Down::const_iterator di; for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) { - (*di).get_child()->fix_chain_lengths(); + PandaNode *child_node = (*di).get_child(); + CDReader cdata_child(child_node->_cycler); + child_node->fix_chain_lengths(cdata_child); } } } @@ -1012,57 +1140,9 @@ register_with_read_factory() { //////////////////////////////////////////////////////////////////// void PandaNode:: write_datagram(BamWriter *manager, Datagram &dg) { - CDReader cdata(_cycler); - dg.add_string(get_name()); - manager->write_pointer(dg, cdata->_state); - manager->write_pointer(dg, cdata->_transform); - // When we write a PandaNode, we write out its list of child nodes, - // but not its parent nodes--so that writing out a node implicitly - // writes out all of the nodes in the subgraph below, but not the - // nodes above as well. - - int num_children = cdata->_down.size(); - nassertv(num_children == (int)(PN_uint16)num_children); - dg.add_uint16(num_children); - - // **** We should smarten up the writing of the sort number--most of - // the time these will all be zero. - Down::const_iterator ci; - for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) { - PandaNode *child = (*ci).get_child(); - int sort = (*ci).get_sort(); - manager->write_pointer(dg, child); - dg.add_int32(sort); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::complete_pointers -// Access: Public, Virtual -// Description: Receives an array of pointers, one for each time -// manager->read_pointer() was called in fillin(). -// Returns the number of pointers processed. -//////////////////////////////////////////////////////////////////// -int PandaNode:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - CDWriter cdata(_cycler); - int pi = TypedWritable::complete_pointers(p_list, manager); - - // Get the state and transform pointers. - cdata->_state = DCAST(RenderState, p_list[pi++]); - cdata->_transform = DCAST(TransformState, p_list[pi++]); - - // Get the child pointers. - Down::iterator ci; - for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) { - int sort = (*ci).get_sort(); - PT(PandaNode) node = DCAST(PandaNode, p_list[pi++]); - (*ci) = DownConnection(node, sort); - } - - return pi; + manager->write_cdata(dg, _cycler); } //////////////////////////////////////////////////////////////////// @@ -1094,23 +1174,10 @@ make_from_bam(const FactoryParams ¶ms) { //////////////////////////////////////////////////////////////////// void PandaNode:: fillin(DatagramIterator &scan, BamReader *manager) { - CDWriter cdata(_cycler); - TypedWritable::fillin(scan, manager); string name = scan.get_string(); set_name(name); - // Read the state and transform pointers. - manager->read_pointer(scan, this); - manager->read_pointer(scan, this); - - int num_children = scan.get_uint16(); - // Read the list of child nodes. Push back a NULL for each one. - cdata->_down.reserve(num_children); - for (int i = 0; i < num_children; i++) { - manager->read_pointer(scan, this); - int sort = scan.get_int32(); - cdata->_down.push_back(DownConnection(NULL, sort)); - } + manager->read_cdata(scan, _cycler); } diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index e92028b05d..e3bc6d1f08 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -53,10 +53,12 @@ PUBLISHED: PandaNode(const string &name); virtual ~PandaNode(); -public: +protected: PandaNode(const PandaNode ©); +private: void operator = (const PandaNode ©); +public: virtual PandaNode *make_copy() const; PandaNode *copy_subgraph() const; @@ -161,7 +163,8 @@ private: static PT(qpNodePathComponent) get_top_component(PandaNode *child); PT(qpNodePathComponent) get_generic_component(); void delete_component(qpNodePathComponent *component); - void fix_chain_lengths(); + class CData; + void fix_chain_lengths(const CData *cdata); void r_list_descendants(ostream &out, int indent_level) const; private: @@ -207,6 +210,9 @@ private: INLINE CData(); CData(const CData ©); virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + virtual void fillin(DatagramIterator &scan, BamReader *manager); Down _down; Up _up; @@ -242,8 +248,6 @@ public: public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); - virtual int complete_pointers(TypedWritable **plist, - BamReader *manager); protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); diff --git a/panda/src/pgraph/qpcamera.cxx b/panda/src/pgraph/qpcamera.cxx index 1f34828588..e97e835a6c 100644 --- a/panda/src/pgraph/qpcamera.cxx +++ b/panda/src/pgraph/qpcamera.cxx @@ -37,7 +37,7 @@ qpCamera(const string &name) : //////////////////////////////////////////////////////////////////// // Function: qpCamera::Copy Constructor -// Access: Public +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// qpCamera:: @@ -48,18 +48,6 @@ qpCamera(const qpCamera ©) : { } -//////////////////////////////////////////////////////////////////// -// Function: qpCamera::Copy Assignment Operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void qpCamera:: -operator = (const qpCamera ©) { - qpLensNode::operator = (copy); - _active = copy._active; - _scene = copy._scene; -} - //////////////////////////////////////////////////////////////////// // Function: qpCamera::Destructor // Access: Public, Virtual diff --git a/panda/src/pgraph/qpcamera.h b/panda/src/pgraph/qpcamera.h index 1a24455404..68c01faad6 100644 --- a/panda/src/pgraph/qpcamera.h +++ b/panda/src/pgraph/qpcamera.h @@ -36,9 +36,9 @@ class EXPCL_PANDA qpCamera : public qpLensNode { PUBLISHED: qpCamera(const string &name); -public: +protected: qpCamera(const qpCamera ©); - void operator = (const qpCamera ©); +public: virtual ~qpCamera(); virtual PandaNode *make_copy() const; diff --git a/panda/src/pgraph/qpgeomNode.cxx b/panda/src/pgraph/qpgeomNode.cxx index 11557084d3..252675b887 100644 --- a/panda/src/pgraph/qpgeomNode.cxx +++ b/panda/src/pgraph/qpgeomNode.cxx @@ -46,6 +46,67 @@ make_copy() const { return new CData(*this); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeomNode::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { + int num_geoms = _geoms.size(); + nassertv(num_geoms == (int)(PN_uint16)num_geoms); + dg.add_uint16(num_geoms); + + Geoms::const_iterator gi; + for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) { + const GeomEntry &entry = (*gi); + manager->write_pointer(dg, entry._geom); + manager->write_pointer(dg, entry._state); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::CData::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int qpGeomNode::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + // Get the geom and state pointers. + Geoms::iterator gi; + for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) { + GeomEntry &entry = (*gi); + entry._geom = DCAST(Geom, p_list[pi++]); + entry._state = DCAST(RenderState, p_list[pi++]); + } + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new qpGeomNode. +//////////////////////////////////////////////////////////////////// +void qpGeomNode::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { + int num_geoms = scan.get_uint16(); + // Read the list of geoms and states. Push back a NULL for each one. + _geoms.reserve(num_geoms); + for (int i = 0; i < num_geoms; i++) { + manager->read_pointer(scan); + manager->read_pointer(scan); + _geoms.push_back(GeomEntry(NULL, NULL)); + } +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomNode::Constructor // Access: Published @@ -59,37 +120,19 @@ qpGeomNode(const string &name) : //////////////////////////////////////////////////////////////////// // Function: qpGeomNode::Copy Constructor -// Access: Published +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// qpGeomNode:: qpGeomNode(const qpGeomNode ©) : - PandaNode(copy) + PandaNode(copy), + _cycler(copy._cycler) { - // Copy the other node's _geoms. - CDReader copy_cdata(copy._cycler); - CDWriter cdata(_cycler); - cdata->_geoms = copy_cdata->_geoms; -} - -//////////////////////////////////////////////////////////////////// -// Function: qpGeomNode::Copy Assignment Operator -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -void qpGeomNode:: -operator = (const qpGeomNode ©) { - PandaNode::operator = (copy); - - // Copy the other node's _geoms. - CDReader copy_cdata(copy._cycler); - CDWriter cdata(_cycler); - cdata->_geoms = copy_cdata->_geoms; } //////////////////////////////////////////////////////////////////// // Function: qpGeomNode::Destructor -// Access: Published, Virtual +// Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// qpGeomNode:: @@ -212,42 +255,7 @@ register_with_read_factory() { void qpGeomNode:: write_datagram(BamWriter *manager, Datagram &dg) { PandaNode::write_datagram(manager, dg); - - CDReader cdata(_cycler); - - int num_geoms = cdata->_geoms.size(); - nassertv(num_geoms == (int)(PN_uint16)num_geoms); - dg.add_uint16(num_geoms); - - Geoms::const_iterator gi; - for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) { - const GeomEntry &entry = (*gi); - manager->write_pointer(dg, entry._geom); - manager->write_pointer(dg, entry._state); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: qpGeomNode::complete_pointers -// Access: Public, Virtual -// Description: Receives an array of pointers, one for each time -// manager->read_pointer() was called in fillin(). -// Returns the number of pointers processed. -//////////////////////////////////////////////////////////////////// -int qpGeomNode:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - CDWriter cdata(_cycler); - int pi = PandaNode::complete_pointers(p_list, manager); - - // Get the geom and state pointers. - Geoms::iterator gi; - for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) { - GeomEntry &entry = (*gi); - entry._geom = DCAST(Geom, p_list[pi++]); - entry._state = DCAST(RenderState, p_list[pi++]); - } - - return pi; + manager->write_cdata(dg, _cycler); } //////////////////////////////////////////////////////////////////// @@ -279,16 +287,6 @@ make_from_bam(const FactoryParams ¶ms) { //////////////////////////////////////////////////////////////////// void qpGeomNode:: fillin(DatagramIterator &scan, BamReader *manager) { - CDWriter cdata(_cycler); - PandaNode::fillin(scan, manager); - - int num_geoms = scan.get_uint16(); - // Read the list of geoms and states. Push back a NULL for each one. - cdata->_geoms.reserve(num_geoms); - for (int i = 0; i < num_geoms; i++) { - manager->read_pointer(scan, this); - manager->read_pointer(scan, this); - cdata->_geoms.push_back(GeomEntry(NULL, NULL)); - } + manager->read_cdata(scan, _cycler); } diff --git a/panda/src/pgraph/qpgeomNode.h b/panda/src/pgraph/qpgeomNode.h index b5efbf77a8..d8c43802d3 100644 --- a/panda/src/pgraph/qpgeomNode.h +++ b/panda/src/pgraph/qpgeomNode.h @@ -39,9 +39,9 @@ class EXPCL_PANDA qpGeomNode : public PandaNode { PUBLISHED: qpGeomNode(const string &name); -public: +protected: qpGeomNode(const qpGeomNode ©); - void operator = (const qpGeomNode ©); +public: virtual ~qpGeomNode(); PUBLISHED: @@ -80,6 +80,9 @@ private: INLINE CData(); CData(const CData ©); virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + virtual void fillin(DatagramIterator &scan, BamReader *manager); Geoms _geoms; }; @@ -91,8 +94,6 @@ private: public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); - virtual int complete_pointers(TypedWritable **plist, - BamReader *manager); protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); diff --git a/panda/src/pgraph/qplensNode.I b/panda/src/pgraph/qplensNode.I index c1de65de68..8a38886336 100644 --- a/panda/src/pgraph/qplensNode.I +++ b/panda/src/pgraph/qplensNode.I @@ -30,7 +30,7 @@ qpLensNode(const string &name) : //////////////////////////////////////////////////////////////////// // Function: qpLensNode::Copy Constructor -// Access: Public +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// INLINE qpLensNode:: @@ -40,17 +40,6 @@ qpLensNode(const qpLensNode ©) : { } -//////////////////////////////////////////////////////////////////// -// Function: qpLensNode::Copy Assignment Operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void qpLensNode:: -operator = (const qpLensNode ©) { - PandaNode::operator = (copy); - _lens = copy._lens; -} - //////////////////////////////////////////////////////////////////// // Function: copy_lens // Access: Public diff --git a/panda/src/pgraph/qplensNode.h b/panda/src/pgraph/qplensNode.h index 3b366f895a..ad84b958a1 100644 --- a/panda/src/pgraph/qplensNode.h +++ b/panda/src/pgraph/qplensNode.h @@ -36,10 +36,9 @@ class EXPCL_PANDA qpLensNode : public PandaNode { PUBLISHED: INLINE qpLensNode(const string &name); -public: +protected: INLINE qpLensNode(const qpLensNode ©); - INLINE void operator = (const qpLensNode ©); - +public: virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/pgraph/qplodNode.I b/panda/src/pgraph/qplodNode.I index f767486239..37ccefae84 100644 --- a/panda/src/pgraph/qplodNode.I +++ b/panda/src/pgraph/qplodNode.I @@ -47,6 +47,18 @@ qpLODNode(const string &name) : { } +//////////////////////////////////////////////////////////////////// +// Function: qpLODNode::Copy Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpLODNode:: +qpLODNode(const qpLODNode ©) : + SelectiveChildNode(copy), + _cycler(copy._cycler) +{ +} + //////////////////////////////////////////////////////////////////// // Function: qpLODNode::add_switch // Access: Published diff --git a/panda/src/pgraph/qplodNode.cxx b/panda/src/pgraph/qplodNode.cxx index bbaa2f79fd..833ec4d28d 100644 --- a/panda/src/pgraph/qplodNode.cxx +++ b/panda/src/pgraph/qplodNode.cxx @@ -32,33 +32,26 @@ make_copy() const { } //////////////////////////////////////////////////////////////////// -// Function: qpLODNode::Copy Constructor -// Access: Public -// Description: +// Function: qpLODNode::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. //////////////////////////////////////////////////////////////////// -qpLODNode:: -qpLODNode(const qpLODNode ©) : - SelectiveChildNode(copy) -{ - CDWriter cdata(_cycler); - CDReader cdata_copy(copy._cycler); - - cdata->_lod = cdata_copy->_lod; +void qpLODNode::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { + _lod.write_datagram(dg); } //////////////////////////////////////////////////////////////////// -// Function: qpLODNode::Copy Assignment Operator -// Access: Public -// Description: +// Function: qpLODNode::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new qpLODNode. //////////////////////////////////////////////////////////////////// -void qpLODNode:: -operator = (const qpLODNode ©) { - SelectiveChildNode::operator = (copy); - - CDWriter cdata(_cycler); - CDReader cdata_copy(copy._cycler); - - cdata->_lod = cdata_copy->_lod; +void qpLODNode::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { + _lod.read_datagram(scan); } //////////////////////////////////////////////////////////////////// @@ -177,9 +170,7 @@ register_with_read_factory() { void qpLODNode:: write_datagram(BamWriter *manager, Datagram &dg) { SelectiveChildNode::write_datagram(manager, dg); - - CDReader cdata(_cycler); - cdata->_lod.write_datagram(dg); + manager->write_cdata(dg, _cycler); } //////////////////////////////////////////////////////////////////// @@ -212,7 +203,5 @@ make_from_bam(const FactoryParams ¶ms) { void qpLODNode:: fillin(DatagramIterator &scan, BamReader *manager) { SelectiveChildNode::fillin(scan, manager); - - CDWriter cdata(_cycler); - cdata->_lod.read_datagram(scan); + manager->read_cdata(scan, _cycler); } diff --git a/panda/src/pgraph/qplodNode.h b/panda/src/pgraph/qplodNode.h index 1ecda9fed8..20b3180f7c 100644 --- a/panda/src/pgraph/qplodNode.h +++ b/panda/src/pgraph/qplodNode.h @@ -36,10 +36,9 @@ class EXPCL_PANDA qpLODNode : public SelectiveChildNode { PUBLISHED: INLINE qpLODNode(const string &name); -public: +protected: INLINE qpLODNode(const qpLODNode ©); - INLINE void operator = (const qpLODNode ©); - +public: virtual PandaNode *make_copy() const; virtual void xform(const LMatrix4f &mat); virtual bool has_cull_callback() const; @@ -78,6 +77,8 @@ private: INLINE CData(); INLINE CData(const CData ©); virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); LOD _lod; }; diff --git a/panda/src/pgraph/qpnodePathComponent.I b/panda/src/pgraph/qpnodePathComponent.I index 09eb73f6ac..857bbdbc4f 100644 --- a/panda/src/pgraph/qpnodePathComponent.I +++ b/panda/src/pgraph/qpnodePathComponent.I @@ -136,8 +136,8 @@ is_collapsed() const { //////////////////////////////////////////////////////////////////// INLINE int qpNodePathComponent:: get_length() const { - CDReader cdata(_cycler); nassertr(!is_collapsed(), 0); + CDReader cdata(_cycler); return cdata->_length; } @@ -150,8 +150,8 @@ get_length() const { //////////////////////////////////////////////////////////////////// INLINE qpNodePathComponent *qpNodePathComponent:: get_collapsed() const { - CDReader cdata(_cycler); nassertr(is_collapsed(), (qpNodePathComponent *)NULL); + CDReader cdata(_cycler); return cdata->_next; } @@ -162,9 +162,9 @@ get_collapsed() const { //////////////////////////////////////////////////////////////////// INLINE void qpNodePathComponent:: set_next(qpNodePathComponent *next) { - CDWriter cdata(_cycler); nassertv(!is_collapsed()); nassertv(next != (qpNodePathComponent *)NULL); + CDWriter cdata(_cycler); cdata->_next = next; } @@ -176,8 +176,8 @@ set_next(qpNodePathComponent *next) { //////////////////////////////////////////////////////////////////// INLINE void qpNodePathComponent:: set_top_node() { - CDWriter cdata(_cycler); nassertv(!is_collapsed()); + CDWriter cdata(_cycler); cdata->_next = (qpNodePathComponent *)NULL; } @@ -192,9 +192,9 @@ set_top_node() { //////////////////////////////////////////////////////////////////// INLINE void qpNodePathComponent:: collapse_with(qpNodePathComponent *next) { - CDWriter cdata(_cycler); nassertv(!is_collapsed()); nassertv(next != (qpNodePathComponent *)NULL); + CDWriter cdata(_cycler); cdata->_next = next; cdata->_length = 0; diff --git a/panda/src/pgraph/qpsequenceNode.cxx b/panda/src/pgraph/qpsequenceNode.cxx index 1b0bfae04e..90063da93c 100644 --- a/panda/src/pgraph/qpsequenceNode.cxx +++ b/panda/src/pgraph/qpsequenceNode.cxx @@ -31,38 +31,47 @@ make_copy() const { return new CData(*this); } +//////////////////////////////////////////////////////////////////// +// Function: qpSequenceNode::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpSequenceNode::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { + dg.add_float32(_cycle_rate); + + float now = ClockObject::get_global_clock()->get_frame_time(); + float frame = (now - _start_time) * _cycle_rate + _frame_offset; + dg.add_float32(frame); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpSequenceNode::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new qpSequenceNode. +//////////////////////////////////////////////////////////////////// +void qpSequenceNode::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { + _cycle_rate = scan.get_float32(); + _frame_offset = scan.get_float32(); + + float now = ClockObject::get_global_clock()->get_frame_time(); + _start_time = now; +} + //////////////////////////////////////////////////////////////////// // Function: qpSequenceNode::Copy Constructor -// Access: Public +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// qpSequenceNode:: qpSequenceNode(const qpSequenceNode ©) : - SelectiveChildNode(copy) + SelectiveChildNode(copy), + _cycler(copy._cycler) { - CDWriter cdata(_cycler); - CDReader cdata_copy(copy._cycler); - - cdata->_cycle_rate = cdata_copy->_cycle_rate; - cdata->_start_time = cdata_copy->_start_time; - cdata->_frame_offset = cdata_copy->_frame_offset; -} - -//////////////////////////////////////////////////////////////////// -// Function: qpSequenceNode::Copy Assignment Operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void qpSequenceNode:: -operator = (const qpSequenceNode ©) { - SelectiveChildNode::operator = (copy); - - CDWriter cdata(_cycler); - CDReader cdata_copy(copy._cycler); - - cdata->_cycle_rate = cdata_copy->_cycle_rate; - cdata->_start_time = cdata_copy->_start_time; - cdata->_frame_offset = cdata_copy->_frame_offset; } //////////////////////////////////////////////////////////////////// @@ -137,10 +146,7 @@ register_with_read_factory() { void qpSequenceNode:: write_datagram(BamWriter *manager, Datagram &dg) { SelectiveChildNode::write_datagram(manager, dg); - - CDReader cdata(_cycler); - dg.add_float32(cdata->_cycle_rate); - dg.add_float32(calc_frame()); + manager->write_cdata(dg, _cycler); } //////////////////////////////////////////////////////////////////// @@ -173,11 +179,5 @@ make_from_bam(const FactoryParams ¶ms) { void qpSequenceNode:: fillin(DatagramIterator &scan, BamReader *manager) { SelectiveChildNode::fillin(scan, manager); - - CDWriter cdata(_cycler); - cdata->_cycle_rate = scan.get_float32(); - cdata->_frame_offset = scan.get_float32(); - - float now = ClockObject::get_global_clock()->get_frame_time(); - cdata->_start_time = now; + manager->read_cdata(scan, _cycler); } diff --git a/panda/src/pgraph/qpsequenceNode.h b/panda/src/pgraph/qpsequenceNode.h index 165a23791a..63ce60523c 100644 --- a/panda/src/pgraph/qpsequenceNode.h +++ b/panda/src/pgraph/qpsequenceNode.h @@ -35,7 +35,6 @@ PUBLISHED: public: qpSequenceNode(const qpSequenceNode ©); - void operator = (const qpSequenceNode ©); virtual PandaNode *make_copy() const; @@ -57,6 +56,8 @@ private: INLINE CData(); INLINE CData(const CData ©); virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); float _cycle_rate; float _frame_offset; diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index ab8e096fb3..41a799c3da 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -1080,7 +1080,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { // the actual list of pointers later in complete_pointers(). _attributes.reserve(num_attribs); for (int i = 0; i < num_attribs; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); int override = scan.get_int32(); _attributes.push_back(Attribute(override)); } diff --git a/panda/src/pgraph/selectiveChildNode.I b/panda/src/pgraph/selectiveChildNode.I index 41b566c10d..09828404df 100644 --- a/panda/src/pgraph/selectiveChildNode.I +++ b/panda/src/pgraph/selectiveChildNode.I @@ -31,7 +31,7 @@ SelectiveChildNode(const string &name) : //////////////////////////////////////////////////////////////////// // Function: SelectiveChildNode::Copy Constructor -// Access: Public +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// INLINE SelectiveChildNode:: @@ -41,17 +41,6 @@ SelectiveChildNode(const SelectiveChildNode ©) : { } -//////////////////////////////////////////////////////////////////// -// Function: SelectiveChildNode::Copy Assignment Operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void SelectiveChildNode:: -operator = (const SelectiveChildNode ©) { - PandaNode::operator = (copy); - _selected_child = copy._selected_child; -} - //////////////////////////////////////////////////////////////////// // Function: SelectiveChildNode::select_child // Access: Protected diff --git a/panda/src/pgraph/selectiveChildNode.h b/panda/src/pgraph/selectiveChildNode.h index c99fc86539..4bbcc582b3 100644 --- a/panda/src/pgraph/selectiveChildNode.h +++ b/panda/src/pgraph/selectiveChildNode.h @@ -32,10 +32,10 @@ class EXPCL_PANDA SelectiveChildNode : public PandaNode { PUBLISHED: INLINE SelectiveChildNode(const string &name); -public: +protected: INLINE SelectiveChildNode(const SelectiveChildNode ©); - INLINE void operator = (const SelectiveChildNode ©); +public: virtual bool has_selective_visibility() const; virtual int get_first_visible_child() const; virtual int get_next_visible_child(int n) const; @@ -44,6 +44,10 @@ protected: INLINE void select_child(int n); private: + // Not sure if this should be cycled or not. It's not exactly + // thread-safe not to cycle it, but it doesn't really need the full + // pipeline control. It's probably a problem in the non-thread-safe + // design; need to rethink the design a bit. int _selected_child; public: diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index c44dfe8670..f41cc0f25e 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -192,5 +192,5 @@ fillin(DatagramIterator &scan, BamReader *manager) { RenderAttrib::fillin(scan, manager); // Read the _texture pointer. - manager->read_pointer(scan, this); + manager->read_pointer(scan); } diff --git a/panda/src/putil/bamReader.cxx b/panda/src/putil/bamReader.cxx index 529be3dd0a..8edb31f401 100644 --- a/panda/src/putil/bamReader.cxx +++ b/panda/src/putil/bamReader.cxx @@ -16,13 +16,14 @@ // //////////////////////////////////////////////////////////////////// -#include -#include +#include "pandabase.h" +#include "notify.h" #include "bam.h" #include "bamReader.h" -#include +#include "datagramIterator.h" #include "config_util.h" +#include "pipelineCyclerBase.h" WritableFactory *BamReader::_factory = (WritableFactory*)0L; BamReader *const BamReader::Null = (BamReader*)0L; @@ -43,6 +44,7 @@ BamReader(DatagramGenerator *generator) { _num_extra_objects = 0; _now_creating = _created_objs.end(); + _reading_cycler = (PipelineCyclerBase *)NULL; _pta_id = -1; } @@ -225,71 +227,25 @@ resolve() { any_completed_this_pass = false; // Walk through all the objects that still have outstanding pointers. - Requests::iterator ri; - ri = _deferred_pointers.begin(); - while (ri != _deferred_pointers.end()) { - int object_id = (*ri).first; - const vector_int &children = (*ri).second; - + ObjectPointers::iterator oi; + oi = _object_pointers.begin(); + while (oi != _object_pointers.end()) { + int object_id = (*oi).first; + const vector_int &pointer_ids = (*oi).second; + CreatedObjs::iterator ci = _created_objs.find(object_id); nassertr(ci != _created_objs.end(), false); CreatedObj &created_obj = (*ci).second; TypedWritable *object_ptr = created_obj._ptr; - - // Now make sure we have all of the pointers this object is - // waiting for. If any of the pointers has not yet been read - // in, we can't resolve this object--we can't do anything for a - // given object until we have *all* outstanding pointers for - // that object. - bool is_complete = true; - vector_typedWritable references; - - vector_int::const_iterator pi; - for (pi = children.begin(); pi != children.end() && is_complete; ++pi) { - int child_id = (*pi); - - if (child_id == 0) { - // A NULL pointer is a NULL pointer. - references.push_back((TypedWritable *)NULL); - - } else { - // See if we have the pointer available now. - CreatedObjs::const_iterator oi = _created_objs.find(child_id); - if (oi == _created_objs.end()) { - // No, too bad. - is_complete = false; - - } else { - const CreatedObj &child_obj = (*oi).second; - if (child_obj._change_this != NULL) { - // It's been created, but the pointer might still change. - is_complete = false; - - } else { - // Yes, it's ready. - references.push_back(child_obj._ptr); - } - } - } - } - - if (is_complete) { - // Okay, here's the complete list of pointers for you! - int num_completed = object_ptr->complete_pointers(&references[0], this); - if (num_completed != (int)references.size()) { - bam_cat.warning() - << object_ptr->get_type() << " completed " << num_completed - << " of " << references.size() << " pointers.\n"; - } - + if (resolve_object_pointers(object_ptr, pointer_ids)) { // Now remove this object from the list of things that need // completion. We have to be a bit careful when deleting things // from the STL container while we are traversing it. - Requests::iterator old = ri; - ++ri; - _deferred_pointers.erase(old); + ObjectPointers::iterator old = oi; + ++oi; + _object_pointers.erase(old); // Does the pointer need to change? if (created_obj._change_this != NULL) { @@ -300,12 +256,36 @@ resolve() { } else { // Couldn't complete this object yet; it'll wait for next time. - ++ri; + ++oi; all_completed = false; } } } while (!all_completed && any_completed_this_pass); + // Also do the PipelineCycler objects. We only need to try these + // once, since they don't depend on each other. + + CyclerPointers::iterator ci; + ci = _cycler_pointers.begin(); + while (ci != _cycler_pointers.end()) { + PipelineCyclerBase *cycler = (*ci).first; + const vector_int &pointer_ids = (*ci).second; + + if (resolve_cycler_pointers(cycler, pointer_ids)) { + // Now remove this cycler from the list of things that need + // completion. We have to be a bit careful when deleting things + // from the STL container while we are traversing it. + CyclerPointers::iterator old = ci; + ++ci; + _cycler_pointers.erase(old); + + } else { + // Couldn't complete this cycler yet; it'll wait for next time. + ++ci; + all_completed = false; + } + } + if (all_completed) { finalize(); } else { @@ -314,11 +294,11 @@ resolve() { // which some objects might legitimately be uncompleted after // calling resolve(), but for now we expect resolve() to always // succeed. - Requests::const_iterator ri; - for (ri = _deferred_pointers.begin(); - ri != _deferred_pointers.end(); - ++ri) { - int object_id = (*ri).first; + ObjectPointers::const_iterator oi; + for (oi = _object_pointers.begin(); + oi != _object_pointers.end(); + ++oi) { + int object_id = (*oi).first; CreatedObjs::iterator ci = _created_objs.find(object_id); nassertr(ci != _created_objs.end(), false); CreatedObj &created_obj = (*ci).second; @@ -435,32 +415,20 @@ read_handle(DatagramIterator &scan) { // object properly. //////////////////////////////////////////////////////////////////// void BamReader:: -read_pointer(DatagramIterator &scan, TypedWritable *for_whom) { +read_pointer(DatagramIterator &scan) { nassertv(_now_creating != _created_objs.end()); int requestor_id = (*_now_creating).first; - /* - On reflection, we'll let this go undetected for now. Maybe we - should remove the this pointer from read_pointer() altogether. - -#ifndef NDEBUG - // A bit of sanity checking here: we look up the object ID, and - // assign the "this" pointer into the record if it's not there - // already. Then we can verify the "this" pointer later. - CreatedObj &created_obj = (*_now_creating).second; - if (created_obj._ptr == (TypedWritable *)NULL) { - created_obj._ptr = for_whom; - } else { - // We've previously assigned this pointer, and we should have - // assigned it to the same this pointer we have now. - nassertv(created_obj._ptr == for_whom); - } -#endif // NDEBUG - */ - // Read the object ID, and associate it with the requesting object. int object_id = scan.get_uint16(); - _deferred_pointers[requestor_id].push_back(object_id); + + if (_reading_cycler == (PipelineCyclerBase *)NULL) { + // This is not being read within a read_cdata() call. + _object_pointers[requestor_id].push_back(object_id); + } else { + // This *is* being read within a read_cdata() call. + _cycler_pointers[_reading_cycler].push_back(object_id); + } // If the object ID is zero (which indicates a NULL pointer), we // don't have to do anything else. @@ -482,9 +450,9 @@ read_pointer(DatagramIterator &scan, TypedWritable *for_whom) { // read_pointer() count times. //////////////////////////////////////////////////////////////////// void BamReader:: -read_pointers(DatagramIterator &scan, TypedWritable *for_whom, int count) { +read_pointers(DatagramIterator &scan, int count) { for (int i = 0; i < count; i++) { - read_pointer(scan, for_whom); + read_pointer(scan); } } @@ -501,6 +469,25 @@ skip_pointer(DatagramIterator &scan) { scan.get_uint16(); } +//////////////////////////////////////////////////////////////////// +// Function: BamReader::read_cdata +// Access: Public +// Description: Reads in the indicated CycleData object. This should +// be used by classes that store some or all of their +// data within a CycleData subclass, in support of +// pipelining. This will call the virtual +// CycleData::fillin() method to do the actual reading. +//////////////////////////////////////////////////////////////////// +void BamReader:: +read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler) { + PipelineCyclerBase *old_cycler = _reading_cycler; + _reading_cycler = &cycler; + CycleData *cdata = cycler.write(); + cdata->fillin(scan, this); + cycler.release_write(cdata); + _reading_cycler = old_cycler; +} + //////////////////////////////////////////////////////////////////// // Function: BamReader::register_finalize // Access: Public @@ -739,11 +726,11 @@ p_read_object() { if (created_obj._change_this != NULL) { // If the pointer is scheduled to change after // complete_pointers(), but we have no entry in - // _deferred_pointers for this object (and hence no plan to call + // _object_pointers for this object (and hence no plan to call // complete_pointers()), then just change the pointer // immediately. - Requests::const_iterator ri = _deferred_pointers.find(object_id); - if (ri == _deferred_pointers.end()) { + ObjectPointers::const_iterator ri = _object_pointers.find(object_id); + if (ri == _object_pointers.end()) { object = created_obj._change_this(object, this); created_obj._ptr = object; created_obj._change_this = NULL; @@ -772,6 +759,133 @@ p_read_object() { return object_id; } +//////////////////////////////////////////////////////////////////// +// Function: BamReader::resolve_object_pointers +// Access: Private +// Description: Checks whether all of the pointers a particular +// object is waiting for have been filled in yet. If +// they have, calls complete_pointers() on the object +// and returns true; otherwise, returns false. +//////////////////////////////////////////////////////////////////// +bool BamReader:: +resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) { + // Now make sure we have all of the pointers this object is + // waiting for. If any of the pointers has not yet been read + // in, we can't resolve this object--we can't do anything for a + // given object until we have *all* outstanding pointers for + // that object. + + bool is_complete = true; + vector_typedWritable references; + + vector_int::const_iterator pi; + for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) { + int child_id = (*pi); + + if (child_id == 0) { + // A NULL pointer is a NULL pointer. + references.push_back((TypedWritable *)NULL); + + } else { + // See if we have the pointer available now. + CreatedObjs::const_iterator oi = _created_objs.find(child_id); + if (oi == _created_objs.end()) { + // No, too bad. + is_complete = false; + + } else { + const CreatedObj &child_obj = (*oi).second; + if (child_obj._change_this != NULL) { + // It's been created, but the pointer might still change. + is_complete = false; + + } else { + // Yes, it's ready. + references.push_back(child_obj._ptr); + } + } + } + } + + if (is_complete) { + // Okay, here's the complete list of pointers for you! + int num_completed = object->complete_pointers(&references[0], this); + if (num_completed != (int)references.size()) { + bam_cat.warning() + << object->get_type() << " completed " << num_completed + << " of " << references.size() << " pointers.\n"; + } + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: BamReader::resolve_cycler_pointers +// Access: Private +// Description: Checks whether all of the pointers a particular +// PipelineCycler is waiting for have been filled in +// yet. If they have, calls complete_pointers() on the +// cycler and returns true; otherwise, returns false. +//////////////////////////////////////////////////////////////////// +bool BamReader:: +resolve_cycler_pointers(PipelineCyclerBase *cycler, + const vector_int &pointer_ids) { + // Now make sure we have all of the pointers this cycler is + // waiting for. If any of the pointers has not yet been read + // in, we can't resolve this cycler--we can't do anything for a + // given cycler until we have *all* outstanding pointers for + // that cycler. + + bool is_complete = true; + vector_typedWritable references; + + vector_int::const_iterator pi; + for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) { + int child_id = (*pi); + + if (child_id == 0) { + // A NULL pointer is a NULL pointer. + references.push_back((TypedWritable *)NULL); + + } else { + // See if we have the pointer available now. + CreatedObjs::const_iterator oi = _created_objs.find(child_id); + if (oi == _created_objs.end()) { + // No, too bad. + is_complete = false; + + } else { + const CreatedObj &child_obj = (*oi).second; + if (child_obj._change_this != NULL) { + // It's been created, but the pointer might still change. + is_complete = false; + + } else { + // Yes, it's ready. + references.push_back(child_obj._ptr); + } + } + } + } + + if (is_complete) { + // Okay, here's the complete list of pointers for you! + CycleData *cdata = cycler->write(); + int num_completed = cdata->complete_pointers(&references[0], this); + cycler->release_write(cdata); + if (num_completed != (int)references.size()) { + bam_cat.warning() + << "CycleData object completed " << num_completed + << " of " << references.size() << " pointers.\n"; + } + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: BamReader::finalize // Access: Private diff --git a/panda/src/putil/bamReader.h b/panda/src/putil/bamReader.h index 2db1bf292d..331c85f661 100644 --- a/panda/src/putil/bamReader.h +++ b/panda/src/putil/bamReader.h @@ -19,8 +19,8 @@ #ifndef __BAM_READER_ #define __BAM_READER_ -#include -#include +#include "pandabase.h" +#include "notify.h" #include "typedWritable.h" #include "datagramGenerator.h" @@ -33,6 +33,8 @@ #include +class PipelineCyclerBase; + // A handy macro for reading PointerToArrays. #define READ_PTA(Manager, source, Read_func, array) \ @@ -108,10 +110,12 @@ public: public: // Functions to support classes that read themselves from the Bam. - void read_pointer(DatagramIterator &scan, TypedWritable *for_whom); - void read_pointers(DatagramIterator &scan, TypedWritable *for_whom, int count); + void read_pointer(DatagramIterator &scan); + void read_pointers(DatagramIterator &scan, int count); void skip_pointer(DatagramIterator &scan); + void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler); + void register_finalize(TypedWritable *whom); typedef TypedWritable *(*ChangeThisFunc)(TypedWritable *object, BamReader *manager); @@ -132,6 +136,8 @@ private: private: int p_read_object(); + bool resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids); + bool resolve_cycler_pointers(PipelineCyclerBase *cycler, const vector_int &pointer_ids); void finalize(); private: @@ -158,12 +164,20 @@ private: // during recursion. We need this so we can associate // read_pointer() calls with the proper objects. CreatedObjs::iterator _now_creating; + // This is the pointer to the current PipelineCycler we are reading, + // if we are within a read_cdata() call. + PipelineCyclerBase *_reading_cycler; // This records all the objects that still need their pointers // completed, along with the object ID's of the pointers they need, - // in the order in which read_pointer() was called. - typedef pmap Requests; - Requests _deferred_pointers; + // in the order in which read_pointer() was called, so that we may + // call the appropriate complete_pointers() later. + typedef pmap ObjectPointers; + ObjectPointers _object_pointers; + + // Ditto, for the PiplineCycler objects. + typedef pmap CyclerPointers; + CyclerPointers _cycler_pointers; // This is the number of extra objects that must still be read (and // saved in the _created_objs map) before returning from diff --git a/panda/src/putil/bamWriter.cxx b/panda/src/putil/bamWriter.cxx index 29235ee69f..24ad9a6418 100644 --- a/panda/src/putil/bamWriter.cxx +++ b/panda/src/putil/bamWriter.cxx @@ -162,6 +162,19 @@ write_object(const TypedWritable *object) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: BamWriter::has_object +// Access: Public +// Description: Returns true if the object has previously been +// written (or at least requested to be written) to the +// bam file, or false if we've never heard of it before. +//////////////////////////////////////////////////////////////////// +bool BamWriter:: +has_object(const TypedWritable *object) const { + StateMap::const_iterator si = _state_map.find(object); + return (si != _state_map.end()); +} + //////////////////////////////////////////////////////////////////// // Function: BamWriter::write_pointer // Access: Public @@ -199,6 +212,23 @@ write_pointer(Datagram &packet, const TypedWritable *object) { } } +//////////////////////////////////////////////////////////////////// +// Function: BamWriter::write_cdata +// Access: Public +// Description: Writes out the indicated CycleData object. This +// should be used by classes that store some or all of +// their data within a CycleData subclass, in support of +// pipelining. This will call the virtual +// CycleData::write_datagram() method to do the actual +// writing. +//////////////////////////////////////////////////////////////////// +void BamWriter:: +write_cdata(Datagram &packet, const PipelineCyclerBase &cycler) { + const CycleData *cdata = cycler.read(); + cdata->write_datagram(this, packet); + cycler.release_read(cdata); +} + //////////////////////////////////////////////////////////////////// // Function: BamWriter::register_pta // Access: Public diff --git a/panda/src/putil/bamWriter.h b/panda/src/putil/bamWriter.h index b5e0bcbb32..20c78c92e3 100644 --- a/panda/src/putil/bamWriter.h +++ b/panda/src/putil/bamWriter.h @@ -19,13 +19,15 @@ #ifndef __BAM_WRITER_ #define __BAM_WRITER_ -#include -#include +#include "pandabase.h" +#include "notify.h" #include "typedWritable.h" #include "datagramSink.h" #include "pdeque.h" +class PipelineCyclerBase; + // A handy macro for writing PointerToArrays. #define WRITE_PTA(Manager, dest, Write_func, array) \ if (!Manager->register_pta(dest, array.p())) \ @@ -78,14 +80,18 @@ public: bool init(); bool write_object(const TypedWritable *obj); + bool has_object(const TypedWritable *obj) const; public: // Functions to support classes that write themselves to the Bam. void write_pointer(Datagram &packet, const TypedWritable *dest); + void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler); bool register_pta(Datagram &packet, const void *ptr); void write_handle(Datagram &packet, TypeHandle type); + + private: int enqueue_object(const TypedWritable *object); diff --git a/panda/src/putil/cycleData.cxx b/panda/src/putil/cycleData.cxx index ae7b69fd8f..e4d94866da 100644 --- a/panda/src/putil/cycleData.cxx +++ b/panda/src/putil/cycleData.cxx @@ -27,3 +27,38 @@ CycleData:: ~CycleData() { } + +//////////////////////////////////////////////////////////////////// +// Function: CycleData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void CycleData:: +write_datagram(BamWriter *, Datagram &) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: CycleData::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int CycleData:: +complete_pointers(TypedWritable **, BamReader *) { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: CycleData::fillin +// Access: Public, Virtual +// Description: This internal function is intended to be called by +// each class's make_from_bam() method to read in all of +// the relevant data from the BamFile for the new +// object. +//////////////////////////////////////////////////////////////////// +void CycleData:: +fillin(DatagramIterator &, BamReader *) { +} + diff --git a/panda/src/putil/cycleData.h b/panda/src/putil/cycleData.h index 10edd34b33..04d3af654a 100644 --- a/panda/src/putil/cycleData.h +++ b/panda/src/putil/cycleData.h @@ -23,6 +23,12 @@ #include "referenceCount.h" +class BamWriter; +class BamReader; +class TypedWritable; +class Datagram; +class DatagramIterator; + //////////////////////////////////////////////////////////////////// // Class : CycleData // Description : A single page of data maintained by a PipelineCycler. @@ -51,6 +57,10 @@ public: virtual ~CycleData(); virtual CycleData *make_copy() const=0; + + virtual void write_datagram(BamWriter *, Datagram &) const; + virtual int complete_pointers(TypedWritable **p_list, BamReader *manager); + virtual void fillin(DatagramIterator &scan, BamReader *manager); }; #include "cycleData.I" diff --git a/panda/src/putil/cycleDataReader.I b/panda/src/putil/cycleDataReader.I index 77d82360bb..cd9b80433d 100644 --- a/panda/src/putil/cycleDataReader.I +++ b/panda/src/putil/cycleDataReader.I @@ -28,6 +28,7 @@ CycleDataReader(const PipelineCycler &cycler) : _cycler(cycler) { _pointer = _cycler.read(); + _write_pointer = (CycleDataType *)NULL; } //////////////////////////////////////////////////////////////////// @@ -39,8 +40,13 @@ template INLINE CycleDataReader:: CycleDataReader(const CycleDataReader ©) : _cycler(copy._cycler), - _pointer(copy._pointer) + _pointer(copy._pointer), + _write_pointer(copy._write_pointer) { + nassertv(_pointer != (const CycleDataType *)NULL); + // We cannot copy-construct a CycleDataReader that has elevated + // itself to a write pointer. + nassertv(_write_pointer == (const CycleDataType *)NULL); _cycler.increment_read(_pointer); } @@ -52,7 +58,14 @@ CycleDataReader(const CycleDataReader ©) : template INLINE CycleDataReader:: ~CycleDataReader() { - _cycler.release_read(_pointer); + if (_write_pointer != (CycleDataType *)NULL) { + // If the _write_pointer is non-NULL, then someone called + // elevate_to_write() at some point, and we now actually hold a + // write pointer, not a read pointer. + ((PipelineCycler &)_cycler).release_write(_write_pointer); + } else if (_pointer != (CycleDataType *)NULL) { + _cycler.release_read(_pointer); + } } //////////////////////////////////////////////////////////////////// @@ -64,5 +77,58 @@ INLINE CycleDataReader:: template INLINE const CycleDataType *CycleDataReader:: operator -> () const { + nassertr(_pointer != (const CycleDataType *)NULL, _cycler.cheat()); return _pointer; } + +//////////////////////////////////////////////////////////////////// +// Function: CycleDataReader::Typecast pointer +// Access: Public +// Description: This allows the CycleDataReader to be passed to any +// function that expects a const CycleDataType pointer. +//////////////////////////////////////////////////////////////////// +template +INLINE CycleDataReader:: +operator const CycleDataType * () const { + nassertr(_pointer != (const CycleDataType *)NULL, _cycler.cheat()); + return _pointer; +} + +//////////////////////////////////////////////////////////////////// +// Function: CycleDataReader::take_pointer +// Access: Public +// Description: This is intended to be called only from +// CycleDataWriter when it elevates the pointer from +// read to write status. This function returns the +// reader's pointer and relinquishes ownership of the +// pointer, rendering the reader invalid for future +// reads. +//////////////////////////////////////////////////////////////////// +template +INLINE const CycleDataType *CycleDataReader:: +take_pointer() { + const CycleDataType *pointer = _pointer; + _pointer = (CycleDataType *)NULL; + _write_pointer = (CycleDataType *)NULL; + nassertr(_pointer != (const CycleDataType *)NULL, _cycler.cheat()); + return pointer; +} + +//////////////////////////////////////////////////////////////////// +// Function: CycleDataReader::elevate_to_write +// Access: Public +// Description: Call this to permanently elevate the readable pointer +// to a writable pointer. This returns a writable +// pointer; subsequent calls to the same function will +// trivially return the same writable pointer. +//////////////////////////////////////////////////////////////////// +template +INLINE CycleDataType *CycleDataReader:: +elevate_to_write(PipelineCycler &cycler) { + nassertr(&cycler = &_cycler, cycler.cheat()); + if (_write_pointer == (CycleDataType *)NULL) { + _write_pointer = cycler.elevate_read(_pointer); + _pointer = _write_pointer; + } + return _write_pointer; +} diff --git a/panda/src/putil/cycleDataReader.h b/panda/src/putil/cycleDataReader.h index 0eefff7c32..62dcf51cc6 100644 --- a/panda/src/putil/cycleDataReader.h +++ b/panda/src/putil/cycleDataReader.h @@ -45,10 +45,15 @@ public: INLINE ~CycleDataReader(); INLINE const CycleDataType *operator -> () const; + INLINE operator const CycleDataType * () const; + + INLINE const CycleDataType *take_pointer(); + INLINE CycleDataType *elevate_to_write(PipelineCycler &cycler); private: const PipelineCycler &_cycler; const CycleDataType *_pointer; + CycleDataType *_write_pointer; }; #include "cycleDataReader.I" diff --git a/panda/src/putil/cycleDataWriter.I b/panda/src/putil/cycleDataWriter.I index c10d211dba..a11429cdfe 100644 --- a/panda/src/putil/cycleDataWriter.I +++ b/panda/src/putil/cycleDataWriter.I @@ -31,17 +31,39 @@ CycleDataWriter(PipelineCycler &cycler) : } //////////////////////////////////////////////////////////////////// -// Function: CycleDataWriter::Copy Constructor +// Function: CycleDataWriter::Constructor // Access: Public -// Description: +// Description: This is a lot like a copy constructor, in that the +// new CycleDataWriter object gets a handle to the same +// pointer held by the old CycleDataWriter object. +// However, since only one write pointer may be active +// at a time, this invalidates the old object. //////////////////////////////////////////////////////////////////// template INLINE CycleDataWriter:: -CycleDataWriter(const CycleDataWriter ©) : - _cycler(copy._cycler), - _pointer(copy._pointer) +CycleDataWriter(PipelineCycler &cycler, + CycleDataWriter &take_from) : + _cycler(cycler), + _pointer(take_from._pointer) { - _cycler.increment_write(_pointer); + take_from._pointer = (CycleDataType *)NULL; + nassertv(_pointer != (CycleDataType *)NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: CycleDataWriter::Constructor +// Access: Public +// Description: This flavor of the constructor elevates the pointer +// from the CycleDataReader from a read to a write +// pointer (and invalidates the reader). +//////////////////////////////////////////////////////////////////// +template +INLINE CycleDataWriter:: +CycleDataWriter(PipelineCycler &cycler, + CycleDataReader &take_from) : + _cycler(cycler) +{ + _pointer = _cycler.elevate_read(take_from.take_pointer()); } //////////////////////////////////////////////////////////////////// @@ -52,7 +74,9 @@ CycleDataWriter(const CycleDataWriter ©) : template INLINE CycleDataWriter:: ~CycleDataWriter() { - _cycler.release_write(_pointer); + if (_pointer != (CycleDataType *)NULL) { + _cycler.release_write(_pointer); + } } //////////////////////////////////////////////////////////////////// @@ -64,6 +88,7 @@ INLINE CycleDataWriter:: template INLINE CycleDataType *CycleDataWriter:: operator -> () { + nassertr(_pointer != (CycleDataType *)NULL, _cycler.cheat()); return _pointer; } @@ -76,5 +101,19 @@ operator -> () { template INLINE const CycleDataType *CycleDataWriter:: operator -> () const { + nassertr(_pointer != (CycleDataType *)NULL, _cycler.cheat()); + return _pointer; +} + +//////////////////////////////////////////////////////////////////// +// Function: CycleDataWriter::Typecast pointer +// Access: Public +// Description: This allows the CycleDataWriter to be passed to any +// function that expects a CycleDataType pointer. +//////////////////////////////////////////////////////////////////// +template +INLINE CycleDataWriter:: +operator CycleDataType * () { + nassertr(_pointer != (CycleDataType *)NULL, _cycler.cheat()); return _pointer; } diff --git a/panda/src/putil/cycleDataWriter.h b/panda/src/putil/cycleDataWriter.h index 9b213c0acb..5c82a77024 100644 --- a/panda/src/putil/cycleDataWriter.h +++ b/panda/src/putil/cycleDataWriter.h @@ -40,13 +40,16 @@ template class CycleDataWriter { public: INLINE CycleDataWriter(PipelineCycler &cycler); - INLINE CycleDataWriter(const CycleDataWriter ©); + INLINE CycleDataWriter(PipelineCycler &cycler, CycleDataWriter &take_from); + INLINE CycleDataWriter(PipelineCycler &cycler, CycleDataReader &take_from); INLINE ~CycleDataWriter(); INLINE CycleDataType *operator -> (); INLINE const CycleDataType *operator -> () const; + INLINE operator CycleDataType * (); + private: PipelineCycler &_cycler; CycleDataType *_pointer; diff --git a/panda/src/putil/pipelineCycler.I b/panda/src/putil/pipelineCycler.I index ba174c490b..d98b7bafa0 100644 --- a/panda/src/putil/pipelineCycler.I +++ b/panda/src/putil/pipelineCycler.I @@ -33,6 +33,29 @@ PipelineCycler(Pipeline *pipeline) : { } +//////////////////////////////////////////////////////////////////// +// Function: PipelineCycler::Copy Constructor (sanity-check) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE PipelineCycler:: +PipelineCycler(const PipelineCycler ©) : + PipelineCyclerBase(copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCycler::Copy Assignment (sanity-check) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE void PipelineCycler:: +operator = (const PipelineCycler ©) { + PipelineCyclerBase::operator = (copy); +} + //////////////////////////////////////////////////////////////////// // Function: PipelineCycler::read (sanity-check) // Access: Public @@ -55,6 +78,17 @@ write() { return (CycleDataType *)PipelineCyclerBase::write(); } +//////////////////////////////////////////////////////////////////// +// Function: PipelineCycler::elevate_read (sanity-check) +// Access: Public +// Description: See PipelineCyclerBase::elevate_read(). +//////////////////////////////////////////////////////////////////// +template +INLINE CycleDataType *PipelineCycler:: +elevate_read(const CycleDataType *pointer) { + return (CycleDataType *)PipelineCyclerBase::elevate_read(pointer); +} + //////////////////////////////////////////////////////////////////// // Function: PipelineCycler::write_stage (sanity-check) // Access: Public @@ -66,6 +100,22 @@ write_stage(int n) { return (CycleDataType *)PipelineCyclerBase::write_stage(n); } +//////////////////////////////////////////////////////////////////// +// Function: PipelineCycler::cheat (sanity-check) +// Access: Public +// Description: Returns a pointer without counting it. This is only +// intended for use as the return value for certain +// nassertr() functions, so the application can recover +// after a failure to manage the read and write pointers +// correctly. You should never call this function +// directly. +//////////////////////////////////////////////////////////////////// +template +INLINE CycleDataType *PipelineCycler:: +cheat() const { + return (CycleDataType *)PipelineCyclerBase::cheat(); +} + #else // !DO_PIPELINING // The following implementations are provided for when pipelining is // not compiled in. They are trivial functions that do as little as @@ -83,6 +133,31 @@ PipelineCycler(Pipeline *pipeline) : { } +//////////////////////////////////////////////////////////////////// +// Function: PipelineCycler::Copy Constructor (trivial) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE PipelineCycler:: +PipelineCycler(const PipelineCycler ©) : + PipelineCyclerBase(copy), + _data(copy._data) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCycler::Copy Assignment (trivial) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE void PipelineCycler:: +operator = (const PipelineCycler ©) { + PipelineCyclerBase::operator = (copy); + _data = copy._data; +} + //////////////////////////////////////////////////////////////////// // Function: PipelineCycler::read (trivial) // Access: Public @@ -105,6 +180,17 @@ write() { return &_data; } +//////////////////////////////////////////////////////////////////// +// Function: PipelineCycler::elevate_read (trivial) +// Access: Public +// Description: See PipelineCyclerBase::elevate_read(). +//////////////////////////////////////////////////////////////////// +template +INLINE CycleDataType *PipelineCycler:: +elevate_read(const CycleDataType *) { + return &_data; +} + //////////////////////////////////////////////////////////////////// // Function: PipelineCycler::write_stage (trivial) // Access: Public @@ -116,5 +202,21 @@ write_stage(int) { return &_data; } +//////////////////////////////////////////////////////////////////// +// Function: PipelineCycler::cheat (trivial) +// Access: Public +// Description: Returns a pointer without counting it. This is only +// intended for use as the return value for certain +// nassertr() functions, so the application can recover +// after a failure to manage the read and write pointers +// correctly. You should never call this function +// directly. +//////////////////////////////////////////////////////////////////// +template +INLINE CycleDataType *PipelineCycler:: +cheat() const { + return &_data; +} + #endif // DO_PIPELINING diff --git a/panda/src/putil/pipelineCycler.h b/panda/src/putil/pipelineCycler.h index 53a1c9329e..75e7bb3cb1 100644 --- a/panda/src/putil/pipelineCycler.h +++ b/panda/src/putil/pipelineCycler.h @@ -53,11 +53,16 @@ template class PipelineCycler : public PipelineCyclerBase { public: INLINE PipelineCycler(Pipeline *pipeline = NULL); + INLINE PipelineCycler(const PipelineCycler ©); + INLINE void operator = (const PipelineCycler ©); INLINE const CycleDataType *read() const; INLINE CycleDataType *write(); + INLINE CycleDataType *elevate_read(const CycleDataType *pointer); INLINE CycleDataType *write_stage(int n); + INLINE CycleDataType *cheat() const; + #ifndef DO_PIPELINING private: // If we are *not* compiling in support for pipelining, we just diff --git a/panda/src/putil/pipelineCyclerBase.I b/panda/src/putil/pipelineCyclerBase.I index bdc2c07d7a..b7d84650c4 100644 --- a/panda/src/putil/pipelineCyclerBase.I +++ b/panda/src/putil/pipelineCyclerBase.I @@ -21,6 +21,61 @@ // The following implementations are to support compiled-in pipeline // sanity checks. +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::Constructor (sanity-check) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PipelineCyclerBase:: +PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline) : + _data(initial_data), + _pipeline(pipeline), + _read_count(0), + _write_count(0), + _stage_count(0) +{ + if (_pipeline == (Pipeline *)NULL) { + _pipeline = Pipeline::get_render_pipeline(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::Copy Constructor (sanity-check) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PipelineCyclerBase:: +PipelineCyclerBase(const PipelineCyclerBase ©) : + _data(copy._data->make_copy()), + _pipeline(copy._pipeline), + _read_count(0), + _write_count(0), + _stage_count(0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::Copy Assignment (sanity-check) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void PipelineCyclerBase:: +operator = (const PipelineCyclerBase ©) { + nassertv(_read_count == 0 && _write_count == 0 && _stage_count == 0); + _data = copy._data->make_copy(); + _pipeline = copy._pipeline; +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::Destructor (sanity-check) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PipelineCyclerBase:: +~PipelineCyclerBase() { + nassertv(_read_count == 0 && _write_count == 0 && _stage_count == 0); +} + //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerBase::read (sanity-check) // Access: Public @@ -28,12 +83,16 @@ // data for the current stage of the pipeline as seen by // this thread. This pointer should eventually be // released by calling release_read(). +// +// There should be no outstanding write pointers on the +// data when this function is called. //////////////////////////////////////////////////////////////////// INLINE const CycleData *PipelineCyclerBase:: read() const { // This function isn't truly const, but it doesn't change the data // in any meaningful way, so we pretend it is. ((PipelineCyclerBase *)this)->_read_count++; + nassertr(_write_count == 0, _data); return _data; } @@ -78,25 +137,33 @@ release_read(const CycleData *pointer) const { // the data will be propagate to all later stages of the // pipeline. This pointer should eventually be released // by calling release_write(). +// +// There may only be one outstanding write pointer on a +// given stage at a time, and if there is a write +// pointer there may be no read pointers on the same +// stage (but see elevate_read). //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerBase:: write() { _write_count++; + nassertr(_read_count == 0, _data); + nassertr(_write_count == 1, _data); return _data; } //////////////////////////////////////////////////////////////////// -// Function: PipelineCyclerBase::increment_write (sanity-check) +// Function: PipelineCyclerBase::elevate_read (sanity-check) // Access: Public -// Description: Increments the count on a pointer previously -// retrieved by write(); now the pointer will need to be -// released twice. +// Description: Elevates a currently-held read pointer into a write +// pointer. This may or may not change the value of the +// pointer. It is only valid to do this if this is the +// only currently-outstanding read pointer on the +// current stage. //////////////////////////////////////////////////////////////////// -INLINE void PipelineCyclerBase:: -increment_write(CycleData *pointer) { - nassertv(pointer == _data); - nassertv(_write_count > 0); - _write_count++; +INLINE CycleData *PipelineCyclerBase:: +elevate_read(const CycleData *pointer) { + release_read(pointer); + return write(); } //////////////////////////////////////////////////////////////////// @@ -166,13 +233,43 @@ release_write_stage(int n, CycleData *pointer) { } //////////////////////////////////////////////////////////////////// -// Function: PipelineCyclerBase::Destructor (sanity-check) +// Function: PipelineCyclerBase::cheat (sanity-check) // Access: Public -// Description: +// Description: Returns a pointer without counting it. This is only +// intended for use as the return value for certain +// nassertr() functions, so the application can recover +// after a failure to manage the read and write pointers +// correctly. You should never call this function +// directly. //////////////////////////////////////////////////////////////////// -INLINE PipelineCyclerBase:: -~PipelineCyclerBase() { - nassertv(_read_count == 0 && _write_count == 0 && _stage_count == 0); +INLINE CycleData *PipelineCyclerBase:: +cheat() const { + return _data; +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::get_read_count (sanity-check) +// Access: Public +// Description: Returns the number of handles currently outstanding +// to read the current stage of the data. This should +// only be used for debugging purposes. +//////////////////////////////////////////////////////////////////// +INLINE int PipelineCyclerBase:: +get_read_count() const { + return _read_count; +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::get_write_count (sanity-check) +// Access: Public +// Description: Returns the number of handles currently outstanding +// to read the current stage of the data. This will +// normally only be either 0 or 1. This should only be +// used for debugging purposes. +//////////////////////////////////////////////////////////////////// +INLINE int PipelineCyclerBase:: +get_write_count() const { + return _write_count; } #else // !DO_PIPELINING @@ -180,6 +277,43 @@ INLINE PipelineCyclerBase:: // not compiled in. They are trivial functions that do as little as // possible. +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::Constructor (trivial) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PipelineCyclerBase:: +PipelineCyclerBase(CycleData *initial_data, Pipeline *) { + // In the trivial implementation, a derived class (the + // PipelineCycler template class) stores the CycleData object + // directly within itself, and since we have no data members or + // virtual functions, we get away with assuming the pointer is the + // same as the 'this' pointer. + + // If this turns out not to be true on a particular platform, we + // will have to store the pointer in this class, for a little bit of + // extra overhead. + nassertv(initial_data == (CycleData *)this); +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::Copy Constructor (trivial) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PipelineCyclerBase:: +PipelineCyclerBase(const PipelineCyclerBase &) { +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::Copy Assignment (trivial) +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void PipelineCyclerBase:: +operator = (const PipelineCyclerBase &) { +} + //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerBase::Destructor (trivial) // Access: Public @@ -233,6 +367,11 @@ release_read(const CycleData *) const { // the data will be propagate to all later stages of the // pipeline. This pointer should eventually be released // by calling release_write(). +// +// There may only be one outstanding write pointer on a +// given stage at a time, and if there is a write +// pointer there may be no read pointers on the same +// stage (but see elevate_read). //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerBase:: write() { @@ -240,14 +379,17 @@ write() { } //////////////////////////////////////////////////////////////////// -// Function: PipelineCyclerBase::increment_write (trivial) +// Function: PipelineCyclerBase::elevate_read (trivial) // Access: Public -// Description: Increments the count on a pointer previously -// retrieved by write(); now the pointer will need to be -// released twice. +// Description: Elevates a currently-held read pointer into a write +// pointer. This may or may not change the value of the +// pointer. It is only valid to do this if this is the +// only currently-outstanding read pointer on the +// current stage. //////////////////////////////////////////////////////////////////// -INLINE void PipelineCyclerBase:: -increment_write(CycleData *) { +INLINE CycleData *PipelineCyclerBase:: +elevate_read(const CycleData *) { + return (CycleData *)this; } //////////////////////////////////////////////////////////////////// @@ -307,5 +449,45 @@ INLINE void PipelineCyclerBase:: release_write_stage(int, CycleData *) { } +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::cheat (trivial) +// Access: Public +// Description: Returns a pointer without counting it. This is only +// intended for use as the return value for certain +// nassertr() functions, so the application can recover +// after a failure to manage the read and write pointers +// correctly. You should never call this function +// directly. +//////////////////////////////////////////////////////////////////// +INLINE CycleData *PipelineCyclerBase:: +cheat() const { + return (CycleData *)this; +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::get_read_count (trivial) +// Access: Public +// Description: Returns the number of handles currently outstanding +// to read the current stage of the data. This should +// only be used for debugging purposes. +//////////////////////////////////////////////////////////////////// +INLINE int PipelineCyclerBase:: +get_read_count() const { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: PipelineCyclerBase::get_write_count (trivial) +// Access: Public +// Description: Returns the number of handles currently outstanding +// to read the current stage of the data. This will +// normally only be either 0 or 1. This should only be +// used for debugging purposes. +//////////////////////////////////////////////////////////////////// +INLINE int PipelineCyclerBase:: +get_write_count() const { + return 0; +} + #endif // DO_PIPELINING diff --git a/panda/src/putil/pipelineCyclerBase.cxx b/panda/src/putil/pipelineCyclerBase.cxx index 895ce8cb75..80ad789901 100644 --- a/panda/src/putil/pipelineCyclerBase.cxx +++ b/panda/src/putil/pipelineCyclerBase.cxx @@ -23,47 +23,10 @@ // The following implementations are to support compiled-in pipeline // sanity checks. -//////////////////////////////////////////////////////////////////// -// Function: PipelineCyclerBase::Constructor (sanity-check) -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PipelineCyclerBase:: -PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline) : - _data(initial_data), - _pipeline(pipeline), - _read_count(0), - _write_count(0), - _stage_count(0) -{ - if (_pipeline == (Pipeline *)NULL) { - _pipeline = Pipeline::get_render_pipeline(); - } -} - #else // !DO_PIPELINING // The following implementations are provided for when pipelining is // not compiled in. They are trivial functions that do as little as // possible. -//////////////////////////////////////////////////////////////////// -// Function: PipelineCyclerBase::Constructor (trivial) -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PipelineCyclerBase:: -PipelineCyclerBase(CycleData *initial_data, Pipeline *) { - // In the trivial implementation, a derived class (the - // PipelineCycler template class) stores the CycleData object - // directly within itself, and since we have no data members or - // virtual functions, we get away with assuming the pointer is the - // same as the 'this' pointer. - - // If this turns out not to be true on a particular platform, we - // will have to store the pointer in this class, for a little bit of - // extra overhead. - nassertv(initial_data == (CycleData *)this); -} - #endif diff --git a/panda/src/putil/pipelineCyclerBase.h b/panda/src/putil/pipelineCyclerBase.h index 9ee758acdb..15195f53ad 100644 --- a/panda/src/putil/pipelineCyclerBase.h +++ b/panda/src/putil/pipelineCyclerBase.h @@ -32,7 +32,9 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA PipelineCyclerBase { public: - PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline = NULL); + INLINE PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline = NULL); + INLINE PipelineCyclerBase(const PipelineCyclerBase ©); + INLINE void operator = (const PipelineCyclerBase ©); INLINE ~PipelineCyclerBase(); INLINE const CycleData *read() const; @@ -40,7 +42,7 @@ public: INLINE void release_read(const CycleData *pointer) const; INLINE CycleData *write(); - INLINE void increment_write(CycleData *pointer); + INLINE CycleData *elevate_read(const CycleData *pointer); INLINE void release_write(CycleData *pointer); INLINE int get_num_stages(); @@ -48,6 +50,10 @@ public: INLINE CycleData *write_stage(int n); INLINE void release_write_stage(int n, CycleData *pointer); + INLINE CycleData *cheat() const; + INLINE int get_read_count() const; + INLINE int get_write_count() const; + #ifdef DO_PIPELINING // This private data is only stored here if we have pipelining // compiled in. Actually, this particular data is only used for diff --git a/panda/src/putil/test_bam.cxx b/panda/src/putil/test_bam.cxx index c76cc4cc79..f5c0806fec 100644 --- a/panda/src/putil/test_bam.cxx +++ b/panda/src/putil/test_bam.cxx @@ -77,8 +77,8 @@ fillin(Person* me, DatagramIterator& scan, BamReader* manager) { _name = scan.get_string(); myGender = scan.get_uint8(); - manager->read_pointer(scan, this); - manager->read_pointer(scan, this); + manager->read_pointer(scan); + manager->read_pointer(scan); } int Person:: @@ -122,8 +122,8 @@ void Parent:: fillin(Parent* me, DatagramIterator& scan, BamReader* manager) { Person::fillin(me, scan, manager); - manager->read_pointer(scan, this); - manager->read_pointer(scan, this); + manager->read_pointer(scan); + manager->read_pointer(scan); } int Parent:: @@ -182,8 +182,8 @@ void Child:: fillin(Child* me, DatagramIterator& scan, BamReader* manager) { Person::fillin(me, scan, manager); - manager->read_pointer(scan, this); - manager->read_pointer(scan, this); + manager->read_pointer(scan); + manager->read_pointer(scan); } int Child:: diff --git a/panda/src/sgattrib/materialTransition.cxx b/panda/src/sgattrib/materialTransition.cxx index 8a098c65be..36ed539617 100644 --- a/panda/src/sgattrib/materialTransition.cxx +++ b/panda/src/sgattrib/materialTransition.cxx @@ -189,5 +189,5 @@ make_MaterialTransition(const FactoryParams ¶ms) { void MaterialTransition:: fillin(DatagramIterator& scan, BamReader* manager) { OnOffTransition::fillin(scan, manager); - manager->read_pointer(scan, this); + manager->read_pointer(scan); } diff --git a/panda/src/sgattrib/textureTransition.cxx b/panda/src/sgattrib/textureTransition.cxx index 7f92f3b5bc..7d7bca50f2 100644 --- a/panda/src/sgattrib/textureTransition.cxx +++ b/panda/src/sgattrib/textureTransition.cxx @@ -190,5 +190,5 @@ make_TextureTransition(const FactoryParams ¶ms) { void TextureTransition:: fillin(DatagramIterator& scan, BamReader* manager) { OnOffTransition::fillin(scan, manager); - manager->read_pointer(scan, this); + manager->read_pointer(scan); } diff --git a/panda/src/sgraph/geomNode.cxx b/panda/src/sgraph/geomNode.cxx index 2519f81a85..e124145db3 100644 --- a/panda/src/sgraph/geomNode.cxx +++ b/panda/src/sgraph/geomNode.cxx @@ -507,7 +507,7 @@ fillin(DatagramIterator& scan, BamReader* manager) _num_geoms = scan.get_uint16(); for(int i = 0; i < _num_geoms; i++) { - manager->read_pointer(scan, this); + manager->read_pointer(scan); } } diff --git a/pandatool/src/egg-palettize/eggFile.cxx b/pandatool/src/egg-palettize/eggFile.cxx index 48636db7e0..aa17c3b587 100644 --- a/pandatool/src/egg-palettize/eggFile.cxx +++ b/pandatool/src/egg-palettize/eggFile.cxx @@ -628,10 +628,10 @@ fillin(DatagramIterator &scan, BamReader *manager) { _dest_filename = FilenameUnifier::get_bam_filename(scan.get_string()); _num_textures = scan.get_uint32(); - manager->read_pointers(scan, this, _num_textures); + manager->read_pointers(scan, _num_textures); _explicitly_assigned_groups.fillin(scan, manager); - manager->read_pointer(scan, this); // _default_group + manager->read_pointer(scan); // _default_group _is_surprise = scan.get_bool(); _is_stale = scan.get_bool(); diff --git a/pandatool/src/egg-palettize/paletteGroup.cxx b/pandatool/src/egg-palettize/paletteGroup.cxx index 45ef01574d..637efc59ef 100644 --- a/pandatool/src/egg-palettize/paletteGroup.cxx +++ b/pandatool/src/egg-palettize/paletteGroup.cxx @@ -725,8 +725,8 @@ fillin(DatagramIterator &scan, BamReader *manager) { } _num_placements = scan.get_uint32(); - manager->read_pointers(scan, this, _num_placements); + manager->read_pointers(scan, _num_placements); _num_pages = scan.get_uint32(); - manager->read_pointers(scan, this, _num_pages); + manager->read_pointers(scan, _num_pages); } diff --git a/pandatool/src/egg-palettize/paletteGroups.cxx b/pandatool/src/egg-palettize/paletteGroups.cxx index 57ffd81e20..bd419d1bdb 100644 --- a/pandatool/src/egg-palettize/paletteGroups.cxx +++ b/pandatool/src/egg-palettize/paletteGroups.cxx @@ -338,5 +338,5 @@ void PaletteGroups:: fillin(DatagramIterator &scan, BamReader *manager) { TypedWritable::fillin(scan, manager); _num_groups = scan.get_int32(); - manager->read_pointers(scan, this, _num_groups); + manager->read_pointers(scan, _num_groups); } diff --git a/pandatool/src/egg-palettize/paletteImage.cxx b/pandatool/src/egg-palettize/paletteImage.cxx index b008e4ed30..f83f2378f2 100644 --- a/pandatool/src/egg-palettize/paletteImage.cxx +++ b/pandatool/src/egg-palettize/paletteImage.cxx @@ -849,9 +849,9 @@ fillin(DatagramIterator &scan, BamReader *manager) { } _num_placements = scan.get_uint32(); - manager->read_pointers(scan, this, _num_placements); + manager->read_pointers(scan, _num_placements); - manager->read_pointer(scan, this); // _page + manager->read_pointer(scan); // _page _index = scan.get_uint32(); _basename = scan.get_string(); diff --git a/pandatool/src/egg-palettize/palettePage.cxx b/pandatool/src/egg-palettize/palettePage.cxx index e59faaad7d..8ff406de72 100644 --- a/pandatool/src/egg-palettize/palettePage.cxx +++ b/pandatool/src/egg-palettize/palettePage.cxx @@ -347,9 +347,9 @@ fillin(DatagramIterator &scan, BamReader *manager) { TypedWritable::fillin(scan, manager); set_name(scan.get_string()); - manager->read_pointer(scan, this); // _group + manager->read_pointer(scan); // _group _properties.fillin(scan, manager); _num_images = scan.get_uint32(); - manager->read_pointers(scan, this, _num_images); + manager->read_pointers(scan, _num_images); } diff --git a/pandatool/src/egg-palettize/palettizer.cxx b/pandatool/src/egg-palettize/palettizer.cxx index 75276809d9..91ffd51a33 100644 --- a/pandatool/src/egg-palettize/palettizer.cxx +++ b/pandatool/src/egg-palettize/palettizer.cxx @@ -1018,18 +1018,18 @@ fillin(DatagramIterator &scan, BamReader *manager) { _remap_char_uv = (RemapUV)scan.get_int32(); } - manager->read_pointer(scan, this); // _color_type - manager->read_pointer(scan, this); // _alpha_type - manager->read_pointer(scan, this); // _shadow_color_type - manager->read_pointer(scan, this); // _shadow_alpha_type + manager->read_pointer(scan); // _color_type + manager->read_pointer(scan); // _alpha_type + manager->read_pointer(scan); // _shadow_color_type + manager->read_pointer(scan); // _shadow_alpha_type _num_egg_files = scan.get_int32(); - manager->read_pointers(scan, this, _num_egg_files); + manager->read_pointers(scan, _num_egg_files); _num_groups = scan.get_int32(); - manager->read_pointers(scan, this, _num_groups); + manager->read_pointers(scan, _num_groups); _num_textures = scan.get_int32(); - manager->read_pointers(scan, this, _num_textures); + manager->read_pointers(scan, _num_textures); } diff --git a/pandatool/src/egg-palettize/sourceTextureImage.cxx b/pandatool/src/egg-palettize/sourceTextureImage.cxx index 214e0d9fef..28be9e901f 100644 --- a/pandatool/src/egg-palettize/sourceTextureImage.cxx +++ b/pandatool/src/egg-palettize/sourceTextureImage.cxx @@ -237,5 +237,5 @@ make_SourceTextureImage(const FactoryParams ¶ms) { void SourceTextureImage:: fillin(DatagramIterator &scan, BamReader *manager) { ImageFile::fillin(scan, manager); - manager->read_pointer(scan, this); // _texture + manager->read_pointer(scan); // _texture } diff --git a/pandatool/src/egg-palettize/textureImage.cxx b/pandatool/src/egg-palettize/textureImage.cxx index 9c8cc9980c..410cfab5ff 100644 --- a/pandatool/src/egg-palettize/textureImage.cxx +++ b/pandatool/src/egg-palettize/textureImage.cxx @@ -1245,10 +1245,10 @@ fillin(DatagramIterator &scan, BamReader *manager) { _actual_assigned_groups.fillin(scan, manager); _num_placement = scan.get_uint32(); - manager->read_pointers(scan, this, _num_placement * 2); + manager->read_pointers(scan, _num_placement * 2); _num_sources = scan.get_uint32(); - manager->read_pointers(scan, this, _num_sources); + manager->read_pointers(scan, _num_sources); _num_dests = scan.get_uint32(); - manager->read_pointers(scan, this, _num_dests); + manager->read_pointers(scan, _num_dests); } diff --git a/pandatool/src/egg-palettize/texturePlacement.cxx b/pandatool/src/egg-palettize/texturePlacement.cxx index 3ece37ac40..eaf840fc06 100644 --- a/pandatool/src/egg-palettize/texturePlacement.cxx +++ b/pandatool/src/egg-palettize/texturePlacement.cxx @@ -1029,12 +1029,12 @@ void TexturePlacement:: fillin(DatagramIterator &scan, BamReader *manager) { TypedWritable::fillin(scan, manager); - manager->read_pointer(scan, this); // _texture - manager->read_pointer(scan, this); // _group - manager->read_pointer(scan, this); // _image + manager->read_pointer(scan); // _texture + manager->read_pointer(scan); // _group + manager->read_pointer(scan); // _image if (Palettizer::_read_pi_version >= 2) { - manager->read_pointer(scan, this); // _dest + manager->read_pointer(scan); // _dest } _has_uvs = scan.get_bool(); @@ -1046,7 +1046,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { _omit_reason = (OmitReason)scan.get_int32(); _num_references = scan.get_int32(); - manager->read_pointers(scan, this, _num_references); + manager->read_pointers(scan, _num_references); } diff --git a/pandatool/src/egg-palettize/textureProperties.cxx b/pandatool/src/egg-palettize/textureProperties.cxx index dedc9e7338..178554a831 100644 --- a/pandatool/src/egg-palettize/textureProperties.cxx +++ b/pandatool/src/egg-palettize/textureProperties.cxx @@ -681,6 +681,6 @@ fillin(DatagramIterator &scan, BamReader *manager) { } _minfilter = (EggTexture::FilterType)scan.get_int32(); _magfilter = (EggTexture::FilterType)scan.get_int32(); - manager->read_pointer(scan, this); // _color_type - manager->read_pointer(scan, this); // _alpha_type + manager->read_pointer(scan); // _color_type + manager->read_pointer(scan); // _alpha_type } diff --git a/pandatool/src/egg-palettize/textureReference.cxx b/pandatool/src/egg-palettize/textureReference.cxx index 6404fc7b3a..36fe0af909 100644 --- a/pandatool/src/egg-palettize/textureReference.cxx +++ b/pandatool/src/egg-palettize/textureReference.cxx @@ -773,13 +773,13 @@ make_TextureReference(const FactoryParams ¶ms) { void TextureReference:: fillin(DatagramIterator &scan, BamReader *manager) { TypedWritable::fillin(scan, manager); - manager->read_pointer(scan, this); // _egg_file + manager->read_pointer(scan); // _egg_file _tex_mat.read_datagram(scan); _inv_tex_mat.read_datagram(scan); - manager->read_pointer(scan, this); // _source_texture - manager->read_pointer(scan, this); // _placement + manager->read_pointer(scan); // _source_texture + manager->read_pointer(scan); // _placement _uses_alpha = scan.get_bool(); _any_uvs = scan.get_bool();