better PandaNode::get_children(), introduce PandaNode::reset_all_prev_transform()

This commit is contained in:
David Rose 2006-04-25 13:55:46 +00:00
parent ab6492b17d
commit 160c848b68
12 changed files with 517 additions and 504 deletions

View File

@ -41,7 +41,6 @@
#include "indent.h"
PStatCollector CollisionTraverser::_collisions_pcollector("App:Collisions");
PStatCollector CollisionTraverser::_reset_prev_pcollector("App:Collisions:Reset");
PStatCollector CollisionTraverser::_cnode_volume_pcollector("Collision Volumes:CollisionNode");
PStatCollector CollisionTraverser::_gnode_volume_pcollector("Collision Volumes:GeomNode");
@ -313,16 +312,12 @@ traverse(const NodePath &root) {
////////////////////////////////////////////////////////////////////
// Function: CollisionTraverser::reset_prev_transform
// Access: Published
// Description: Once the collision traversal has finished, resets all
// of the velocity deltas in the scene graph by setting
// the "previous" transform to the current transform.
// This must be called at least once per frame for
// collisions to respect this velocity setting properly.
// Description: This method is deprecated. Just call
// PandaNode::reset_all_prev_transform() now.
////////////////////////////////////////////////////////////////////
void CollisionTraverser::
reset_prev_transform(const NodePath &root) {
PStatTimer timer(_reset_prev_pcollector);
r_reset_prev_transform(root.node());
reset_prev_transform(const NodePath &) {
PandaNode::reset_all_prev_transform();
}
#ifdef DO_COLLISION_RECORDING
@ -883,22 +878,6 @@ remove_handler(CollisionTraverser::Handlers::iterator hi) {
return hi;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionTraverser::r_reset_prev_transform
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void CollisionTraverser::
r_reset_prev_transform(PandaNode *node) {
node->reset_prev_transform();
PandaNode::Children children = node->get_children();
int num_children = children.get_num_children();
for (int i = 0; i < num_children; ++i) {
r_reset_prev_transform(children.get_child(i));
}
}
////////////////////////////////////////////////////////////////////
// Function: CollisionTraverser::get_pass_collector
// Access: Private

View File

@ -102,8 +102,6 @@ private:
const GeometricBoundingVolume *from_node_gbv,
const GeometricBoundingVolume *solid_gbv);
void r_reset_prev_transform(PandaNode *node);
PStatCollector &get_pass_collector(int pass);
private:
@ -134,7 +132,6 @@ private:
// Statistics
static PStatCollector _collisions_pcollector;
static PStatCollector _reset_prev_pcollector;
static PStatCollector _cnode_volume_pcollector;
static PStatCollector _gnode_volume_pcollector;

View File

@ -73,6 +73,7 @@
nodePathComponent.I nodePathComponent.h \
nodePathLerps.h \
pandaNode.I pandaNode.h \
pandaNodeChain.I pandaNodeChain.h \
planeNode.I planeNode.h \
pointLight.I pointLight.h \
polylightNode.I polylightNode.h \
@ -174,6 +175,7 @@
nodePathComponent.cxx \
nodePathLerps.cxx \
pandaNode.cxx \
pandaNodeChain.cxx \
planeNode.cxx \
pointLight.cxx \
polylightNode.cxx \
@ -272,6 +274,7 @@
nodePathComponent.I nodePathComponent.h \
nodePathLerps.h \
pandaNode.I pandaNode.h \
pandaNodeChain.I pandaNodeChain.h \
planeNode.I planeNode.h \
pointLight.I pointLight.h \
polylightNode.I polylightNode.h \

View File

@ -248,22 +248,20 @@ traverse_below(CullTraverserData &data) {
#endif
}
// Now visit all the node's children. We cannot use the
// node->get_children() interface, because that will keep a read
// pointer open, and we might end up changing this node during the
// traversal.
int num_children = node->get_num_children();
// Now visit all the node's children.
PandaNode::Children children = node->get_children();
int num_children = children.get_num_children();
if (node->has_selective_visibility()) {
int i = node->get_first_visible_child();
while (i < num_children) {
CullTraverserData next_data(data, node->get_child(i));
CullTraverserData next_data(data, children.get_child(i));
traverse(next_data);
i = node->get_next_visible_child(i);
}
} else {
for (int i = 0; i < num_children; i++) {
CullTraverserData next_data(data, node->get_child(i));
CullTraverserData next_data(data, children.get_child(i));
traverse(next_data);
}
}

View File

@ -191,8 +191,9 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
}
}
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler) {
CDStageWriter cdata(_cycler, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
Geoms::iterator gi;
for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
GeomEntry &entry = (*gi);
@ -409,8 +410,9 @@ add_geom(Geom *geom, const RenderState *state) {
nassertv(geom->check_valid());
nassertv(state != (RenderState *)NULL);
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler) {
CDStageWriter cdata(_cycler, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
cdata->_geoms.push_back(GeomEntry(geom, state));
}
@ -427,9 +429,10 @@ add_geom(Geom *geom, const RenderState *state) {
////////////////////////////////////////////////////////////////////
void GeomNode::
add_geoms_from(const GeomNode *other) {
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler) {
CDStageWriter cdata(_cycler, pipeline_stage);
CDStageReader cdata_other(other->_cycler, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
Geoms::const_iterator gi;
for (gi = cdata_other->_geoms.begin();
@ -511,8 +514,9 @@ check_valid() const {
////////////////////////////////////////////////////////////////////
void GeomNode::
unify() {
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler) {
CDStageWriter cdata(_cycler, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
Geoms new_geoms;

View File

@ -128,8 +128,9 @@ bool GeomTransformer::
transform_vertices(GeomNode *node, const LMatrix4f &mat) {
bool any_changed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler) {
GeomNode::CDStageWriter cdata(node->_cycler, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler, current_thread) {
GeomNode::CDStageWriter cdata(node->_cycler, pipeline_stage, current_thread);
GeomNode::Geoms::iterator gi;
for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
GeomNode::GeomEntry &entry = (*gi);

View File

@ -86,20 +86,23 @@ compare_draw_mask(DrawMask running_draw_mask, DrawMask camera_mask) const {
INLINE int PandaNode::
get_num_parents() const {
CDLinksReader cdata(_cycler_links);
return cdata->_up.size();
return cdata->get_up()->size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_parent
// Access: Published
// Description: Returns the nth parent node of this node. See
// get_num_parents().
// get_num_parents(). Also see get_parents(), if your
// intention is to iterate through the complete list of
// parents; get_parents() is preferable in this case.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::
get_parent(int n) const {
CDLinksReader cdata(_cycler_links);
nassertr(n >= 0 && n < (int)cdata->_up.size(), NULL);
return cdata->_up[n].get_parent();
const Up &up = *cdata->get_up();
nassertr(n >= 0 && n < (int)up.size(), NULL);
return up[n].get_parent();
}
////////////////////////////////////////////////////////////////////
@ -125,20 +128,23 @@ find_parent(PandaNode *node) const {
INLINE int PandaNode::
get_num_children() const {
CDLinksReader cdata(_cycler_links);
return cdata->_down.size();
return cdata->get_down()->size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_child
// Access: Published
// Description: Returns the nth child node of this node. See
// get_num_children().
// get_num_children(). Also see get_children(), if your
// intention is to iterate through the complete list of
// children; get_children() is preferable in this case.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::
get_child(int n) const {
CDLinksReader cdata(_cycler_links);
nassertr(n >= 0 && n < (int)cdata->_down.size(), NULL);
return cdata->_down[n].get_child();
const Down &down = *cdata->get_down();
nassertr(n >= 0 && n < (int)down.size(), NULL);
return down[n].get_child();
}
////////////////////////////////////////////////////////////////////
@ -151,8 +157,9 @@ get_child(int n) const {
INLINE int PandaNode::
get_child_sort(int n) const {
CDLinksReader cdata(_cycler_links);
nassertr(n >= 0 && n < (int)cdata->_down.size(), -1);
return cdata->_down[n].get_sort();
const Down &down = *cdata->get_down();
nassertr(n >= 0 && n < (int)down.size(), -1);
return down[n].get_sort();
}
////////////////////////////////////////////////////////////////////
@ -229,20 +236,24 @@ unstash_child(PandaNode *child_node) {
INLINE int PandaNode::
get_num_stashed() const {
CDLinksReader cdata(_cycler_links);
return cdata->_stashed.size();
return cdata->get_stashed()->size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_stashed
// Access: Published
// Description: Returns the nth stashed node of this node. See
// get_num_stashed().
// Description: Returns the nth stashed child of this node. See
// get_num_stashed(). Also see get_stashed(), if your
// intention is to iterate through the complete list of
// stashed children; get_stashed() is preferable in this
// case.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::
get_stashed(int n) const {
CDLinksReader cdata(_cycler_links);
nassertr(n >= 0 && n < (int)cdata->_stashed.size(), NULL);
return cdata->_stashed[n].get_child();
const Down &stashed = *cdata->get_stashed();
nassertr(n >= 0 && n < (int)stashed.size(), NULL);
return stashed[n].get_child();
}
////////////////////////////////////////////////////////////////////
@ -255,8 +266,9 @@ get_stashed(int n) const {
INLINE int PandaNode::
get_stashed_sort(int n) const {
CDLinksReader cdata(_cycler_links);
nassertr(n >= 0 && n < (int)cdata->_stashed.size(), -1);
return cdata->_stashed[n].get_sort();
const Down &stashed = *cdata->get_stashed();
nassertr(n >= 0 && n < (int)stashed.size(), -1);
return stashed[n].get_sort();
}
////////////////////////////////////////////////////////////////////
@ -422,6 +434,20 @@ get_prev_transform() const {
return cdata->_prev_transform;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::has_dirty_prev_transform
// Access: Published
// Description: Returns true if this node has the
// _dirty_prev_transform flag set, which indicates its
// _prev_transform is different from its _transform
// value (in pipeline stage 0). In this case, the node
// will be visited by reset_prev_transform().
////////////////////////////////////////////////////////////////////
INLINE bool PandaNode::
has_dirty_prev_transform() const {
return _dirty_prev_transform;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_tag
// Access: Published
@ -690,22 +716,6 @@ mark_internal_bounds_stale(int pipeline_stage) {
mark_bounds_stale(pipeline_stage);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_children_copy
// Access: Public
// Description: Returns an object that can be used to walk through
// the list of children of the node. Unlike
// get_children(), this function actually returns an
// object that protects you from self-modifying loops,
// because it makes and returns a copy of the complete
// children list.
////////////////////////////////////////////////////////////////////
INLINE PandaNode::ChildrenCopy PandaNode::
get_children_copy() const {
CDLinksReader cdata(_cycler_links);
return ChildrenCopy(cdata);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_children
// Access: Public
@ -713,74 +723,56 @@ get_children_copy() const {
// the list of children of the node. When you intend to
// visit multiple children, using this is slightly
// faster than calling get_child() directly on the
// PandaNode, since this object keeps the PipelineCycler
// open the whole time.
// PandaNode, since this object avoids reopening the
// PipelineCycler each time.
//
// However, this object does not protect you from
// self-modifying loops (e.g. adding or removing
// children during traversal). Furthermore, if Panda is
// compiled with pipelining enabled, this method is
// compiled to behave exactly as get_children_copy(): it
// returns a copy. This is intended to reduce the risk
// of deadlocks.
// This object also protects you from self-modifying
// loops (e.g. adding or removing children during
// traversal), since a virtual copy of the children is
// made ahead of time. The virtual copy is fast--it is
// a form of copy-on-write, so the list is not actually
// copied unless it is modified during the traversal.
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Children PandaNode::
get_children() const {
CDLinksReader cdata(_cycler_links);
get_children(Thread *current_thread) const {
CDLinksReader cdata(_cycler_links, current_thread);
return Children(cdata);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_stashed_copy
// Access: Public
// Description: Returns an object that can be used to walk through
// the list of stashed children of the node. Unlike
// get_stashed(), this function actually returns an
// object that protects you from self-modifying loops,
// because it makes and returns a copy of the complete
// stashed list.
////////////////////////////////////////////////////////////////////
INLINE PandaNode::StashedCopy PandaNode::
get_stashed_copy() const {
CDLinksReader cdata(_cycler_links);
return StashedCopy(cdata);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_stashed
// Access: Public
// Description: Returns an object that can be used to walk through
// the list of stashed children of the node. When you
// intend to visit multiple children, using this is
// slightly faster than calling get_stashed() directly
// on the PandaNode, since this object keeps the
// PipelineCycler open the whole time.
// the list of children of the node. When you intend to
// visit multiple children, using this is slightly
// faster than calling get_stashed() directly on the
// PandaNode, since this object avoids reopening the
// PipelineCycler each time.
//
// However, this object does not protect you from
// self-modifying loops (e.g. adding or removing
// stashed during traversal). Furthermore, if Panda is
// compiled with pipelining enabled, this method is
// compiled to behave exactly as get_stashed_copy(): it
// returns a copy. This is intended to reduce the risk
// of deadlocks.
// This object also protects you from self-modifying
// loops (e.g. adding or removing children during
// traversal), since a virtual copy of the children is
// made ahead of time. The virtual copy is fast--it is
// a form of copy-on-write, so the list is not actually
// copied unless it is modified during the traversal.
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Stashed PandaNode::
get_stashed() const {
CDLinksReader cdata(_cycler_links);
get_stashed(Thread *current_thread) const {
CDLinksReader cdata(_cycler_links, current_thread);
return Stashed(cdata);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_parents_copy
// Function: PandaNode::get_parents
// Access: Public
// Description: Returns an object that can be used to walk through
// the list of parents of the node, similar to
// get_children_copy()/
// get_children() and get_stashed().
////////////////////////////////////////////////////////////////////
INLINE PandaNode::ParentsCopy PandaNode::
get_parents_copy() const {
CDLinksReader cdata(_cycler_links);
return ParentsCopy(cdata);
INLINE PandaNode::Parents PandaNode::
get_parents(Thread *current_thread) const {
CDLinksReader cdata(_cycler_links, current_thread);
return Parents(cdata);
}
////////////////////////////////////////////////////////////////////
@ -790,11 +782,46 @@ get_parents_copy() const {
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
do_find_parent(PandaNode *node, const CDataLinks *cdata) const {
Up::const_iterator ui = cdata->_up.find(UpConnection(node));
if (ui == cdata->_up.end()) {
const Up &up = *cdata->get_up();
Up::const_iterator ui = up.find(UpConnection(node));
if (ui == up.end()) {
return -1;
}
return ui - cdata->_up.begin();
return ui - up.begin();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_dirty_prev_transform
// Access: Private
// Description: Sets the dirty_prev_transform flag, and adds the node
// to the _dirty_prev_transforms chain.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_dirty_prev_transform() {
if (!_dirty_prev_transform) {
MutexHolder holder(_dirty_prev_transforms._lock);
if (!_dirty_prev_transform) {
LinkedListNode::insert_before(&_dirty_prev_transforms);
_dirty_prev_transform = true;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::clear_dirty_prev_transform
// Access: Private
// Description: Clears the dirty_prev_transform flag, and removes the node
// from the _dirty_prev_transforms chain.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
clear_dirty_prev_transform() {
if (_dirty_prev_transform) {
MutexHolder holder(_dirty_prev_transforms._lock);
if (_dirty_prev_transform) {
LinkedListNode::remove_from_list();
_dirty_prev_transform = false;
}
}
}
////////////////////////////////////////////////////////////////////
@ -936,10 +963,85 @@ CDataBounds() {
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::CDataLinks::
CDataLinks() {
CDataLinks() :
_down(new PandaNode::Down),
_stashed(new PandaNode::Down),
_up(new PandaNode::Up)
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CDataLinks::get_down
// Access: Public
// Description: Returns a read-only pointer to the _down list.
////////////////////////////////////////////////////////////////////
INLINE const PandaNode::Down *PandaNode::CDataLinks::
get_down() const {
return _down;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CDataLinks::modify_down
// Access: Public
// Description: Returns a modifiable, unique pointer to the _down
// list.
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Down *PandaNode::CDataLinks::
modify_down() {
if (_down->get_ref_count() > 1) {
_down = new Down(*_down);
}
return _down;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CDataLinks::get_stashed
// Access: Public
// Description: Returns a read-only pointer to the _stashed list.
////////////////////////////////////////////////////////////////////
INLINE const PandaNode::Down *PandaNode::CDataLinks::
get_stashed() const {
return _stashed;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CDataLinks::modify_stashed
// Access: Public
// Description: Returns a modifiable, unique pointer to the _stashed
// list.
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Down *PandaNode::CDataLinks::
modify_stashed() {
if (_stashed->get_ref_count() > 1) {
_stashed = new Down(*_stashed);
}
return _stashed;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CDataLinks::get_up
// Access: Public
// Description: Returns a read-only pointer to the _up list.
////////////////////////////////////////////////////////////////////
INLINE const PandaNode::Up *PandaNode::CDataLinks::
get_up() const {
return _up;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CDataLinks::modify_up
// Access: Public
// Description: Returns a modifiable, unique pointer to the _up
// list.
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Up *PandaNode::CDataLinks::
modify_up() {
if (_up->get_ref_count() > 1) {
_up = new Up(*_up);
}
return _up;
}
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::Constructor
// Access: Public
@ -947,12 +1049,10 @@ CDataLinks() {
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Children::
Children(const PandaNode::CDLinksReader &cdata) :
_cdata(cdata)
_down(cdata->get_down())
{
}
#endif // DO_PIPELINING
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::Copy Constructor
// Access: Public
@ -960,12 +1060,10 @@ Children(const PandaNode::CDLinksReader &cdata) :
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Children::
Children(const PandaNode::Children &copy) :
_cdata(copy._cdata)
_down(copy._down)
{
}
#endif // DO_PIPELINING
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::Copy Assignment Operator
// Access: Public
@ -973,11 +1071,9 @@ Children(const PandaNode::Children &copy) :
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::Children::
operator = (const PandaNode::Children &copy) {
_cdata = copy._cdata;
_down = copy._down;
}
#endif // DO_PIPELINING
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::get_num_children
// Access: Public
@ -985,11 +1081,9 @@ operator = (const PandaNode::Children &copy) {
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::Children::
get_num_children() const {
return _cdata->_down.size();
return _down->size();
}
#endif // DO_PIPELINING
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::get_child
// Access: Public
@ -997,54 +1091,10 @@ get_num_children() const {
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::Children::
get_child(int n) const {
nassertr(n >= 0 && n < (int)_cdata->_down.size(), NULL);
return _cdata->_down[n].get_child();
}
#endif // DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ChildrenCopy::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::ChildrenCopy::
ChildrenCopy(const PandaNode::ChildrenCopy &copy) :
_list(copy._list)
{
nassertr(n >= 0 && n < (int)_down->size(), NULL);
return (*_down)[n].get_child();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ChildrenCopy::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::ChildrenCopy::
operator = (const PandaNode::ChildrenCopy &copy) {
_list = copy._list;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ChildrenCopy::get_num_children
// Access: Public
// Description: Returns the number of children of the node.
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::ChildrenCopy::
get_num_children() const {
return _list.size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ChildrenCopy::get_child
// Access: Public
// Description: Returns the nth child of the node.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::ChildrenCopy::
get_child(int n) const {
nassertr(n >= 0 && n < (int)_list.size(), NULL);
return _list[n];
}
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Stashed::Constructor
// Access: Public
@ -1052,12 +1102,10 @@ get_child(int n) const {
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Stashed::
Stashed(const PandaNode::CDLinksReader &cdata) :
_cdata(cdata)
_stashed(cdata->get_stashed())
{
}
#endif // DO_PIPELINING
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Stashed::Copy Constructor
// Access: Public
@ -1065,12 +1113,10 @@ Stashed(const PandaNode::CDLinksReader &cdata) :
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Stashed::
Stashed(const PandaNode::Stashed &copy) :
_cdata(copy._cdata)
_stashed(copy._stashed)
{
}
#endif // DO_PIPELINING
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Stashed::Copy Assignment Operator
// Access: Public
@ -1078,11 +1124,9 @@ Stashed(const PandaNode::Stashed &copy) :
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::Stashed::
operator = (const PandaNode::Stashed &copy) {
_cdata = copy._cdata;
_stashed = copy._stashed;
}
#endif // DO_PIPELINING
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Stashed::get_num_stashed
// Access: Public
@ -1090,11 +1134,9 @@ operator = (const PandaNode::Stashed &copy) {
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::Stashed::
get_num_stashed() const {
return _cdata->_stashed.size();
return _stashed->size();
}
#endif // DO_PIPELINING
#ifndef DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Stashed::get_stashed
// Access: Public
@ -1102,91 +1144,59 @@ get_num_stashed() const {
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::Stashed::
get_stashed(int n) const {
nassertr(n >= 0 && n < (int)_cdata->_stashed.size(), NULL);
return _cdata->_stashed[n].get_child();
nassertr(n >= 0 && n < (int)_stashed->size(), NULL);
return (*_stashed)[n].get_child();
}
#endif // DO_PIPELINING
////////////////////////////////////////////////////////////////////
// Function: PandaNode::StashedCopy::Copy Constructor
// Function: PandaNode::Parents::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::StashedCopy::
StashedCopy(const PandaNode::StashedCopy &copy) :
_list(copy._list)
INLINE PandaNode::Parents::
Parents(const PandaNode::CDLinksReader &cdata) :
_up(cdata->get_up())
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::StashedCopy::Copy Assignment Operator
// Function: PandaNode::Parents::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::StashedCopy::
operator = (const PandaNode::StashedCopy &copy) {
_list = copy._list;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::StashedCopy::get_num_stashed
// Access: Public
// Description: Returns the number of stashed children of the node.
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::StashedCopy::
get_num_stashed() const {
return _list.size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::StashedCopy::get_stashed
// Access: Public
// Description: Returns the nth stashed child of the node.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::StashedCopy::
get_stashed(int n) const {
nassertr(n >= 0 && n < (int)_list.size(), NULL);
return _list[n];
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ParentsCopy::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::ParentsCopy::
ParentsCopy(const PandaNode::ParentsCopy &copy) :
_list(copy._list)
INLINE PandaNode::Parents::
Parents(const PandaNode::Parents &copy) :
_up(copy._up)
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ParentsCopy::Copy Assignment Operator
// Function: PandaNode::Parents::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::ParentsCopy::
operator = (const PandaNode::ParentsCopy &copy) {
_list = copy._list;
INLINE void PandaNode::Parents::
operator = (const PandaNode::Parents &copy) {
_up = copy._up;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ParentsCopy::get_num_parents
// Function: PandaNode::Parents::get_num_parents
// Access: Public
// Description: Returns the number of parents of the node.
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::ParentsCopy::
INLINE int PandaNode::Parents::
get_num_parents() const {
return _list.size();
return _up->size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ParentsCopy::get_parent
// Function: PandaNode::Parents::get_parent
// Access: Public
// Description: Returns the nth parent of the node.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::ParentsCopy::
INLINE PandaNode *PandaNode::Parents::
get_parent(int n) const {
nassertr(n >= 0 && n < (int)_list.size(), NULL);
return _list[n];
nassertr(n >= 0 && n < (int)_up->size(), NULL);
return (*_up)[n].get_parent();
}

View File

@ -27,12 +27,17 @@
#include "accumulatedAttribs.h"
#include "clipPlaneAttrib.h"
#include "boundingSphere.h"
#include "pStatTimer.h"
// This category is just temporary for debugging convenience.
NotifyCategoryDecl(drawmask, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDef(drawmask, "");
PandaNodeChain PandaNode::_dirty_prev_transforms;
DrawMask PandaNode::_overall_bit = DrawMask::bit(31);
PStatCollector PandaNode::_reset_prev_pcollector("App:Collisions:Reset");
TypeHandle PandaNode::_type_handle;
//
@ -68,7 +73,8 @@ TypeHandle PandaNode::_type_handle;
PandaNode::
PandaNode(const string &name) :
Namable(name),
_paths_lock("PandaNode::_paths_lock")
_paths_lock("PandaNode::_paths_lock"),
_dirty_prev_transform(false)
{
if (pgraph_cat.is_debug()) {
pgraph_cat.debug()
@ -90,13 +96,14 @@ PandaNode::
pgraph_cat.debug()
<< "Destructing " << (void *)this << ", " << get_name() << "\n";
}
clear_dirty_prev_transform();
// We shouldn't have any parents left by the time we destruct, or
// there's a refcount fault somewhere.
#ifndef NDEBUG
{
CDLinksReader cdata(_cycler_links);
nassertv(cdata->_up.empty());
nassertv(cdata->get_up()->empty());
}
#endif // NDEBUG
@ -115,7 +122,8 @@ PandaNode(const PandaNode &copy) :
ReferenceCount(copy),
TypedWritable(copy),
Namable(copy),
_paths_lock("PandaNode::_paths_lock")
_paths_lock("PandaNode::_paths_lock"),
_dirty_prev_transform(false)
{
if (pgraph_cat.is_debug()) {
pgraph_cat.debug()
@ -129,14 +137,17 @@ PandaNode(const PandaNode &copy) :
// Copy the other node's state.
{
CDLightReader copy_cdata(copy._cycler_light);
CDLightWriter cdata(_cycler_light);
CDLightWriter cdata(_cycler_light, true);
cdata->_state = copy_cdata->_state;
cdata->_transform = copy_cdata->_transform;
cdata->_prev_transform = copy_cdata->_prev_transform;
if (cdata->_transform != cdata->_prev_transform) {
set_dirty_prev_transform();
}
}
{
CDHeavyReader copy_cdata(copy._cycler_heavy);
CDHeavyWriter cdata(_cycler_heavy);
CDHeavyWriter cdata(_cycler_heavy, true);
cdata->_effects = copy_cdata->_effects;
cdata->_tag_data = copy_cdata->_tag_data;
cdata->_draw_control_mask = copy_cdata->_draw_control_mask;
@ -565,16 +576,17 @@ add_child(PandaNode *child_node, int sort) {
// Apply this operation to the current stage as well as to all
// upstream stages.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_links) {
CDLinksStageWriter cdata(_cycler_links, pipeline_stage);
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_links, current_thread) {
CDLinksStageWriter cdata(_cycler_links, pipeline_stage, current_thread);
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage, current_thread);
cdata->_down.insert(DownConnection(child_node, sort));
cdata_child->_up.insert(UpConnection(this));
cdata->modify_down()->insert(DownConnection(child_node, sort));
cdata_child->modify_up()->insert(UpConnection(this));
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_links);
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links) {
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links, current_thread) {
new_connection(this, child_node, pipeline_stage);
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links);
@ -595,13 +607,15 @@ remove_child(int child_index) {
nassertv(pipeline_stage == 0);
CDLinksStageWriter cdata(_cycler_links, pipeline_stage);
nassertv(child_index >= 0 && child_index < (int)cdata->_down.size());
Down &down = *cdata->modify_down();
nassertv(child_index >= 0 && child_index < (int)down.size());
PT(PandaNode) child_node = cdata->_down[child_index].get_child();
PT(PandaNode) child_node = down[child_index].get_child();
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage);
Up &up = *cdata_child->modify_up();
cdata->_down.erase(cdata->_down.begin() + child_index);
int num_erased = cdata_child->_up.erase(UpConnection(this));
down.erase(down.begin() + child_index);
int num_erased = up.erase(UpConnection(this));
nassertv(num_erased == 1);
sever_connection(this, child_node, pipeline_stage);
@ -630,7 +644,8 @@ remove_child(PandaNode *child_node) {
// We have to do this for each upstream pipeline stage.
bool any_removed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links) {
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links, current_thread) {
if (stage_remove_child(child_node, pipeline_stage)) {
any_removed = true;
@ -674,7 +689,8 @@ replace_child(PandaNode *orig_child, PandaNode *new_child) {
// We have to do this for each upstream pipeline stage.
bool any_replaced = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_links) {
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_links, current_thread) {
if (stage_replace_child(orig_child, new_child, pipeline_stage)) {
any_replaced = true;
}
@ -723,8 +739,8 @@ stash_child(int child_index) {
CDLinksStageWriter cdata(_cycler_links, pipeline_stage);
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage);
cdata->_stashed.insert(DownConnection(child_node, sort));
cdata_child->_up.insert(UpConnection(this));
cdata->modify_stashed()->insert(DownConnection(child_node, sort));
cdata_child->modify_up()->insert(UpConnection(this));
}
new_connection(this, child_node, pipeline_stage);
@ -767,9 +783,9 @@ unstash_child(int stashed_index) {
{
CDLinksWriter cdata(_cycler_links);
CDLinksWriter cdata_child(child_node->_cycler_links);
cdata->_down.insert(DownConnection(child_node, sort));
cdata_child->_up.insert(UpConnection(this));
cdata->modify_down()->insert(DownConnection(child_node, sort));
cdata_child->modify_up()->insert(UpConnection(this));
}
int pipeline_stage = Thread::get_current_pipeline_stage();
@ -806,8 +822,8 @@ add_stashed(PandaNode *child_node, int sort) {
CDLinksWriter cdata(_cycler_links);
CDLinksWriter cdata_child(child_node->_cycler_links);
cdata->_stashed.insert(DownConnection(child_node, sort));
cdata_child->_up.insert(UpConnection(this));
cdata->modify_stashed()->insert(DownConnection(child_node, sort));
cdata_child->modify_up()->insert(UpConnection(this));
}
int pipeline_stage = Thread::get_current_pipeline_stage();
@ -829,13 +845,14 @@ remove_stashed(int child_index) {
nassertv(pipeline_stage == 0);
CDLinksStageWriter cdata(_cycler_links, pipeline_stage);
nassertv(child_index >= 0 && child_index < (int)cdata->_stashed.size());
Down &stashed = *cdata->modify_stashed();
nassertv(child_index >= 0 && child_index < (int)stashed.size());
PT(PandaNode) child_node = cdata->_stashed[child_index].get_child();
PT(PandaNode) child_node = stashed[child_index].get_child();
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage);
cdata->_stashed.erase(cdata->_stashed.begin() + child_index);
int num_erased = cdata_child->_up.erase(UpConnection(this));
stashed.erase(stashed.begin() + child_index);
int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
nassertv(num_erased == 1);
sever_connection(this, child_node, pipeline_stage);
@ -857,29 +874,33 @@ remove_stashed(int child_index) {
void PandaNode::
remove_all_children() {
// We have to do this for each upstream pipeline stage.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_links) {
CDLinksStageWriter cdata(_cycler_links, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_links, current_thread) {
CDLinksStageWriter cdata(_cycler_links, pipeline_stage, current_thread);
Down &down = *cdata->modify_down();
Down::iterator di;
for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) {
for (di = down.begin(); di != down.end(); ++di) {
PT(PandaNode) child_node = (*di).get_child();
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage);
cdata_child->_up.erase(UpConnection(this));
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage,
current_thread);
cdata_child->modify_up()->erase(UpConnection(this));
sever_connection(this, child_node, pipeline_stage);
child_node->parents_changed();
}
cdata->_down.clear();
down.clear();
for (di = cdata->_stashed.begin(); di != cdata->_stashed.end(); ++di) {
Down &stashed = *cdata->modify_stashed();
for (di = stashed.begin(); di != stashed.end(); ++di) {
PT(PandaNode) child_node = (*di).get_child();
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage);
cdata_child->_up.erase(UpConnection(this));
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage,
current_thread);
cdata_child->modify_up()->erase(UpConnection(this));
sever_connection(this, child_node, pipeline_stage);
child_node->parents_changed();
}
cdata->_stashed.clear();
stashed.clear();
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_links);
@ -965,8 +986,9 @@ set_attrib(const RenderAttrib *attrib, int override) {
// Apply this operation to the current stage as well as to all
// upstream stages.
bool any_changed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light, current_thread) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage, current_thread);
CPT(RenderState) new_state = cdata->_state->add_attrib(attrib, override);
if (cdata->_state != new_state) {
@ -995,8 +1017,9 @@ void PandaNode::
clear_attrib(TypeHandle type) {
bool any_changed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light, current_thread) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage, current_thread);
CPT(RenderState) new_state = cdata->_state->remove_attrib(type);
if (cdata->_state != new_state) {
@ -1025,8 +1048,9 @@ void PandaNode::
set_effect(const RenderEffect *effect) {
// Apply this operation to the current stage as well as to all
// upstream stages.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage, current_thread);
cdata->_effects = cdata->_effects->add_effect(effect);
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy);
@ -1040,8 +1064,9 @@ set_effect(const RenderEffect *effect) {
////////////////////////////////////////////////////////////////////
void PandaNode::
clear_effect(TypeHandle type) {
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage, current_thread);
cdata->_effects = cdata->_effects->remove_effect(type);
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy);
@ -1062,8 +1087,9 @@ set_state(const RenderState *state) {
// Apply this operation to the current stage as well as to all
// upstream stages.
bool any_changed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light, current_thread) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage, current_thread);
if (cdata->_state != state) {
cdata->_state = state;
any_changed = true;
@ -1090,8 +1116,9 @@ void PandaNode::
set_effects(const RenderEffects *effects) {
// Apply this operation to the current stage as well as to all
// upstream stages.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage, current_thread);
cdata->_effects = effects;
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy);
@ -1109,8 +1136,9 @@ set_transform(const TransformState *transform) {
// Apply this operation to the current stage as well as to all
// upstream stages.
bool any_changed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light, current_thread) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage, current_thread);
if (cdata->_transform != transform) {
cdata->_transform = transform;
any_changed = true;
@ -1136,9 +1164,17 @@ void PandaNode::
set_prev_transform(const TransformState *transform) {
// Apply this operation to the current stage as well as to all
// upstream stages.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light, current_thread) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage, current_thread);
cdata->_prev_transform = transform;
if (pipeline_stage == 0) {
if (cdata->_transform != cdata->_prev_transform) {
set_dirty_prev_transform();
} else {
clear_dirty_prev_transform();
}
}
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light);
}
@ -1146,24 +1182,63 @@ set_prev_transform(const TransformState *transform) {
////////////////////////////////////////////////////////////////////
// Function: PandaNode::reset_prev_transform
// Access: Published
// Description: Resets the "previous" transform on this node to be
// the same as the current transform. This is not the
// same as clearing it to identity.
// Description: Resets the transform that represents this node's
// "previous" position to the same as the current
// transform. This is not the same thing as clearing it
// to identity.
////////////////////////////////////////////////////////////////////
void PandaNode::
reset_prev_transform() {
// Apply this operation to the current stage as well as to all
// upstream stages.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light) {
CDLightStageReader cdata(_cycler_light, pipeline_stage);
if (cdata->_prev_transform != cdata->_transform) {
CDLightStageWriter cdataw(_cycler_light, pipeline_stage, cdata);
cdataw->_prev_transform = cdataw->_transform;
}
Thread *current_thread = Thread::get_current_thread();
clear_dirty_prev_transform();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light, current_thread) {
CDLightStageWriter cdata(_cycler_light, pipeline_stage, current_thread);
cdata->_prev_transform = cdata->_transform;
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_light);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::reset_all_prev_transform
// Access: Published, Static
// Description: Visits all nodes in the world with the
// _dirty_prev_transform flag--that is, all nodes whose
// _prev_transform is different from the _transform in
// pipeline stage 0--and resets the _prev_transform to
// be the same as _transform.
////////////////////////////////////////////////////////////////////
void PandaNode::
reset_all_prev_transform() {
Thread *current_thread = Thread::get_current_thread();
nassertv(current_thread->get_pipeline_stage() == 0);
PStatTimer timer(_reset_prev_pcollector);
MutexHolder holder(_dirty_prev_transforms._lock);
LinkedListNode *list_node = _dirty_prev_transforms._next;
while (list_node != &_dirty_prev_transforms) {
PandaNode *panda_node = (PandaNode *)list_node;
nassertv(panda_node->_dirty_prev_transform);
panda_node->_dirty_prev_transform = false;
CDLightStageWriter cdata(panda_node->_cycler_light, 0, current_thread);
cdata->_prev_transform = cdata->_transform;
list_node = panda_node->_next;
#ifndef NDEBUG
panda_node->_prev = NULL;
panda_node->_next = NULL;
#endif // NDEBUG
}
_dirty_prev_transforms._prev = &_dirty_prev_transforms;
_dirty_prev_transforms._next = &_dirty_prev_transforms;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_tag
// Access: Published
@ -1181,8 +1256,9 @@ void PandaNode::
set_tag(const string &key, const string &value) {
// Apply this operation to the current stage as well as to all
// upstream stages.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage, current_thread);
cdata->_tag_data[key] = value;
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy);
@ -1197,8 +1273,9 @@ set_tag(const string &key, const string &value) {
////////////////////////////////////////////////////////////////////
void PandaNode::
clear_tag(const string &key) {
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage, current_thread);
cdata->_tag_data.erase(key);
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy);
@ -1322,9 +1399,11 @@ copy_tags(PandaNode *other) {
// Apply this operation to the current stage as well as to all
// upstream stages.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdataw(_cycler_heavy, pipeline_stage);
CDHeavyStageReader cdatar(other->_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdataw(_cycler_heavy, pipeline_stage, current_thread);
CDHeavyStageReader cdatar(other->_cycler_heavy, pipeline_stage,
current_thread);
TagData::const_iterator ti;
for (ti = cdatar->_tag_data.begin();
@ -1444,8 +1523,9 @@ void PandaNode::
adjust_draw_mask(DrawMask show_mask, DrawMask hide_mask, DrawMask clear_mask) {
bool any_changed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage, current_thread);
DrawMask draw_control_mask = (cdata->_draw_control_mask | show_mask | hide_mask) & ~clear_mask;
DrawMask draw_show_mask = (cdata->_draw_show_mask | show_mask) & ~hide_mask;
@ -1543,8 +1623,9 @@ set_into_collide_mask(CollideMask mask) {
mask &= get_legal_collide_mask();
bool any_changed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage, current_thread);
if (cdata->_into_collide_mask != mask) {
cdata->_into_collide_mask = mask;
any_changed = true;
@ -1686,8 +1767,9 @@ write(ostream &out, int indent_level) const {
////////////////////////////////////////////////////////////////////
void PandaNode::
set_bounds(const BoundingVolume *volume) {
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage, current_thread);
if (volume == NULL) {
cdata->_user_bounds = NULL;
} else {
@ -1756,7 +1838,8 @@ get_bounds() const {
////////////////////////////////////////////////////////////////////
void PandaNode::
mark_bounds_stale() const {
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links) {
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links, current_thread) {
mark_bounds_stale(pipeline_stage);
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links);
@ -1839,8 +1922,9 @@ get_internal_bounds(int pipeline_stage) const {
////////////////////////////////////////////////////////////////////
void PandaNode::
set_internal_bounds(const BoundingVolume *volume) {
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdataw(_cycler_heavy, pipeline_stage);
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy, current_thread) {
CDHeavyStageWriter cdataw(_cycler_heavy, pipeline_stage, current_thread);
cdataw->_internal_bounds = volume;
cdataw->_internal_bounds_stale = false;
}
@ -1861,7 +1945,8 @@ set_internal_bounds(const BoundingVolume *volume) {
////////////////////////////////////////////////////////////////////
void PandaNode::
force_bounds_stale() {
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links) {
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links, current_thread) {
force_bounds_stale(pipeline_stage);
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links);
@ -1888,7 +1973,7 @@ force_bounds_stale(int pipeline_stage) {
// It is similarly important that we use get_parents() here to copy
// the parents list, instead of keeping the lock open while we walk
// through the parents list directly on the node.
ParentsCopy parents = get_parents_copy();
Parents parents = get_parents();
int num_parents = parents.get_num_parents();
for (int i = 0; i < num_parents; ++i) {
PandaNode *parent = parents.get_parent(i);
@ -1910,7 +1995,8 @@ force_bounds_stale(int pipeline_stage) {
////////////////////////////////////////////////////////////////////
void PandaNode::
mark_internal_bounds_stale() {
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links) {
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links, current_thread) {
mark_internal_bounds_stale(pipeline_stage);
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler_links);
@ -2032,8 +2118,9 @@ r_copy_subgraph(PandaNode::InstanceMap &inst_map) const {
void PandaNode::
r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map) {
CDLinksReader from_cdata(from->_cycler_links);
const Down &from_down = *from_cdata->get_down();
Down::const_iterator di;
for (di = from_cdata->_down.begin(); di != from_cdata->_down.end(); ++di) {
for (di = from_down.begin(); di != from_down.end(); ++di) {
int sort = (*di).get_sort();
PandaNode *source_child = (*di).get_child();
PT(PandaNode) dest_child;
@ -2066,10 +2153,11 @@ do_find_child(PandaNode *node, const CDataLinks *cdata) const {
// We have to search for the child by brute force, since we don't
// know what sort index it was added as.
const Down &down = *cdata->get_down();
Down::const_iterator di;
for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) {
for (di = down.begin(); di != down.end(); ++di) {
if ((*di).get_child() == node) {
return di - cdata->_down.begin();
return di - down.begin();
}
}
@ -2087,10 +2175,11 @@ do_find_stashed(PandaNode *node, const CDataLinks *cdata) const {
// We have to search for the child by brute force, since we don't
// know what sort index it was added as.
const Down &stashed = *cdata->get_stashed();
Down::const_iterator di;
for (di = cdata->_stashed.begin(); di != cdata->_stashed.end(); ++di) {
for (di = stashed.begin(); di != stashed.end(); ++di) {
if ((*di).get_child() == node) {
return di - cdata->_stashed.begin();
return di - stashed.begin();
}
}
@ -2120,8 +2209,9 @@ stage_remove_child(PandaNode *child_node, int pipeline_stage) {
int child_index = do_find_child(child_node, cdata);
if (child_index >= 0) {
// The child exists; remove it.
cdata->_down.erase(cdata->_down.begin() + child_index);
int num_erased = cdata_child->_up.erase(UpConnection(this));
Down &down = *cdata->modify_down();
down.erase(down.begin() + child_index);
int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
nassertr(num_erased == 1, false);
return true;
}
@ -2129,8 +2219,9 @@ stage_remove_child(PandaNode *child_node, int pipeline_stage) {
int stashed_index = do_find_stashed(child_node, cdata);
if (stashed_index >= 0) {
// The child has been stashed; remove it.
cdata->_stashed.erase(cdata->_stashed.begin() + stashed_index);
int num_erased = cdata_child->_up.erase(UpConnection(this));
Down &stashed = *cdata->modify_down();
stashed.erase(stashed.begin() + stashed_index);
int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
nassertr(num_erased == 1, false);
return true;
}
@ -2175,7 +2266,7 @@ stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
int child_index = do_find_child(orig_child, cdata);
if (child_index >= 0) {
// The child exists; replace it.
DownConnection &down = cdata->_down[child_index];
DownConnection &down = (*cdata->modify_down())[child_index];
nassertr(down.get_child() == orig_child, false);
down.set_child(new_child);
@ -2183,7 +2274,7 @@ stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
int stashed_index = do_find_stashed(orig_child, cdata);
if (stashed_index >= 0) {
// The child has been stashed; remove it.
DownConnection &down = cdata->_stashed[stashed_index];
DownConnection &down = (*cdata->modify_stashed())[stashed_index];
nassertr(down.get_child() == orig_child, false);
down.set_child(new_child);
@ -2197,8 +2288,8 @@ stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
}
// Now adjust the bookkeeping on both children.
cdata_new_child->_up.insert(UpConnection(this));
int num_erased = cdata_orig_child->_up.erase(UpConnection(this));
cdata_new_child->modify_up()->insert(UpConnection(this));
int num_erased = cdata_orig_child->modify_up()->erase(UpConnection(this));
nassertr(num_erased == 1, false);
}
@ -2300,7 +2391,7 @@ detach_one_stage(NodePathComponent *child, int pipeline_stage) {
// First, look for and remove the parent node from the child's up
// list.
int num_erased = cdata_child->_up.erase(UpConnection(parent_node));
int num_erased = cdata_child->modify_up()->erase(UpConnection(parent_node));
nassertv(num_erased == 1);
// Now, look for and remove the child node from the parent's down
@ -2308,19 +2399,17 @@ detach_one_stage(NodePathComponent *child, int pipeline_stage) {
// has been stashed.
Down::iterator di;
bool found = false;
for (di = cdata_parent->_down.begin();
di != cdata_parent->_down.end() && !found;
++di) {
Down &down = *cdata_parent->modify_down();
for (di = down.begin(); di != down.end() && !found; ++di) {
if ((*di).get_child() == child_node) {
cdata_parent->_down.erase(di);
down.erase(di);
found = true;
}
}
for (di = cdata_parent->_stashed.begin();
di != cdata_parent->_stashed.end() && !found;
++di) {
Down &stashed = *cdata_parent->modify_stashed();
for (di = stashed.begin(); di != stashed.end() && !found; ++di) {
if ((*di).get_child() == child_node) {
cdata_parent->_stashed.erase(di);
stashed.erase(di);
found = true;
}
}
@ -2417,11 +2506,11 @@ reparent_one_stage(NodePathComponent *new_parent, NodePathComponent *child,
CDLinksStageWriter cdata_child(child_node->_cycler_links, pipeline_stage);
if (as_stashed) {
cdata_parent->_stashed.insert(DownConnection(child_node, sort));
cdata_parent->modify_stashed()->insert(DownConnection(child_node, sort));
} else {
cdata_parent->_down.insert(DownConnection(child_node, sort));
cdata_parent->modify_down()->insert(DownConnection(child_node, sort));
}
cdata_child->_up.insert(UpConnection(parent_node));
cdata_child->modify_up()->insert(UpConnection(parent_node));
#ifndef NDEBUG
// The NodePathComponent should already be in the set.
@ -2569,7 +2658,7 @@ r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected,
{
CDLinksStageReader cdata(_cycler_links, pipeline_stage);
int num_parents = cdata->_up.size();
int num_parents = cdata->get_up()->size();
if (num_parents == 0) {
// No parents; no ambiguity. This is the root.
return get_top_component(this, true, pipeline_stage);
@ -2590,7 +2679,8 @@ r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected,
<< " parents; choosing arbitrary path to root.\n";
}
ambiguity_detected = true;
parent_node = cdata->_up[0].get_parent();
const Up &up = *cdata->get_up();
parent_node = up[0].get_parent();
}
// Now that the lock is released, it's safe to recurse.
@ -3453,9 +3543,9 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
void PandaNode::CDataLinks::
write_datagram(BamWriter *manager, Datagram &dg) const {
write_up_list(_up, manager, dg);
write_down_list(_down, manager, dg);
write_down_list(_stashed, manager, dg);
write_up_list(*get_up(), manager, dg);
write_down_list(*get_down(), manager, dg);
write_down_list(*get_stashed(), manager, dg);
}
////////////////////////////////////////////////////////////////////
@ -3470,9 +3560,9 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
// Get the parent and child pointers.
pi += complete_up_list(_up, p_list + pi, manager);
pi += complete_down_list(_down, p_list + pi, manager);
pi += complete_down_list(_stashed, p_list + pi, manager);
pi += complete_up_list(*modify_up(), p_list + pi, manager);
pi += complete_down_list(*modify_down(), p_list + pi, manager);
pi += complete_down_list(*modify_stashed(), p_list + pi, manager);
return pi;
}
@ -3486,9 +3576,9 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
////////////////////////////////////////////////////////////////////
void PandaNode::CDataLinks::
fillin(DatagramIterator &scan, BamReader *manager) {
fillin_up_list(_up, scan, manager);
fillin_down_list(_down, scan, manager);
fillin_down_list(_stashed, scan, manager);
fillin_up_list(*modify_up(), scan, manager);
fillin_down_list(*modify_down(), scan, manager);
fillin_down_list(*modify_stashed(), scan, manager);
}
////////////////////////////////////////////////////////////////////
@ -3620,10 +3710,10 @@ fillin_up_list(PandaNode::Up &up_list,
DatagramIterator &scan, BamReader *manager) {
int num_parents = scan.get_uint16();
// Read the list of parent nodes. Push back a NULL for each one.
_up.reserve(num_parents);
up_list.reserve(num_parents);
for (int i = 0; i < num_parents; i++) {
manager->read_pointer(scan);
_up.push_back(UpConnection(NULL));
up_list.push_back(UpConnection(NULL));
}
}
@ -3646,51 +3736,3 @@ fillin_down_list(PandaNode::Down &down_list,
down_list.push_back(DownConnection(NULL, sort));
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ChildrenCopy::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PandaNode::ChildrenCopy::
ChildrenCopy(const PandaNode::CDLinksReader &cdata) {
_list.reserve(cdata->_down.size());
Down::const_iterator di;
for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) {
PandaNode *child = (*di).get_child();
_list.push_back(child);
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::StashedCopy::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PandaNode::StashedCopy::
StashedCopy(const PandaNode::CDLinksReader &cdata) {
_list.reserve(cdata->_down.size());
Down::const_iterator di;
for (di = cdata->_stashed.begin(); di != cdata->_stashed.end(); ++di) {
PandaNode *child = (*di).get_child();
_list.push_back(child);
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ParentsCopy::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PandaNode::ParentsCopy::
ParentsCopy(const PandaNode::CDLinksReader &cdata) {
_list.reserve(cdata->_up.size());
Up::const_iterator ui;
for (ui = cdata->_up.begin(); ui != cdata->_up.end(); ++ui) {
PandaNode *parent = (*ui).get_parent();
_list.push_back(parent);
}
}

View File

@ -43,6 +43,8 @@
#include "pnotify.h"
#include "updateSeq.h"
#include "deletedChain.h"
#include "pandaNodeChain.h"
#include "pStatCollector.h"
#ifdef HAVE_PYTHON
@ -66,7 +68,8 @@ class GeomTransformer;
// is the base class of all specialized nodes, and also
// serves as a generic node with no special properties.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PandaNode : public TypedWritable, public Namable,
class EXPCL_PANDA PandaNode : public TypedWritable, public Namable,
public LinkedListNode,
virtual public ReferenceCount {
PUBLISHED:
PandaNode(const string &name);
@ -169,6 +172,8 @@ PUBLISHED:
void set_prev_transform(const TransformState *transform);
INLINE const TransformState *get_prev_transform() const;
void reset_prev_transform();
INLINE bool has_dirty_prev_transform() const;
static void reset_all_prev_transform();
void set_tag(const string &key, const string &value);
INLINE string get_tag(const string &key) const;
@ -303,6 +308,9 @@ private:
void fix_path_lengths(int pipeline_stage);
void r_list_descendants(ostream &out, int indent_level) const;
INLINE void set_dirty_prev_transform();
INLINE void clear_dirty_prev_transform();
public:
// This must be declared public so that VC6 will allow the nested
// CData class to access it.
@ -323,7 +331,7 @@ public:
};
private:
typedef ov_multiset<DownConnection> Down;
typedef RefCountObj< ov_multiset<DownConnection> > Down;
class EXPCL_PANDA UpConnection {
public:
@ -336,7 +344,7 @@ private:
// children do not circularly reference each other.
PandaNode *_parent;
};
typedef ov_set<UpConnection> Up;
typedef RefCountObj< ov_set<UpConnection> > Up;
// We also maintain a set of NodePathComponents in the node. This
// represents the set of instances of this node that we have
@ -352,6 +360,9 @@ private:
Paths _paths;
Mutex _paths_lock;
bool _dirty_prev_transform;
static PandaNodeChain _dirty_prev_transforms;
// This is used to maintain a table of keyed data on each node, for
// the user's purposes.
typedef phash_map<string, string, string_hash> TagData;
@ -368,7 +379,7 @@ private:
// are grouped into a different one.
// The CDataLight object stores the lightweight parts of the node
// that are likely to change fairly often: transform and stage.
// that are likely to change fairly often: transform and state.
class EXPCL_PANDA CDataLight : public CycleData {
public:
INLINE CDataLight();
@ -529,9 +540,19 @@ private:
void fillin_down_list(Down &down_list,
DatagramIterator &scan, BamReader *manager);
Down _down;
Down _stashed;
Up _up;
INLINE const Down *get_down() const;
INLINE Down *modify_down();
INLINE const Down *get_stashed() const;
INLINE Down *modify_stashed();
INLINE const Up *get_up() const;
INLINE Up *modify_up();
private:
// We store the child lists by reference, so we can copy them
// quickly. We perform copy-on-write when necessary.
PT(Down) _down;
PT(Down) _stashed;
PT(Up) _up;
};
PipelineCycler<CDataLinks> _cycler_links;
@ -545,37 +566,16 @@ private:
static DrawMask _overall_bit;
static PStatCollector _reset_prev_pcollector;
public:
// This class is returned from get_children_copy(). Use it to walk
// through the list of children, particularly with a self-modifying
// loop, since the list of children is copied first and is thus safe
// from self modification.
class EXPCL_PANDA ChildrenCopy {
public:
ChildrenCopy(const CDLinksReader &cdata);
INLINE ChildrenCopy(const ChildrenCopy &copy);
INLINE void operator = (const ChildrenCopy &copy);
INLINE int get_num_children() const;
INLINE PandaNode *get_child(int n) const;
private:
typedef PTA(PT(PandaNode)) List;
List _list;
};
// This class is returned from get_children(). Use this interface
// when you want to walk through the list of children with less
// overhead than get_children_copy(); in single-threaded Panda, a
// copy is not made first, so this interface is fast. However, this
// does not protect you from self-modifying loops. Also, since the
// lock is kept open the whole time, this is generally unsafe to use
// in threaded code (which would then hold the lock on the root node
// during an entire traversal), so when pipelining is enabled,
// get_children() returns the same thing as get_children_copy().
#ifdef DO_PIPELINING
typedef ChildrenCopy Children;
#else
// This class is returned from get_children(). Use it to walk
// through the list of children. This is faster, and safer, than
// walking through the children one at a time via
// get_num_children()/get_child(), since the list of children is
// saved out ahead of time, rather than having to reacquire the lock
// with each iteration, or to keep the lock held for the entire
// pass.
class EXPCL_PANDA Children {
public:
INLINE Children(const CDLinksReader &cdata);
@ -586,28 +586,10 @@ public:
INLINE PandaNode *get_child(int n) const;
private:
CDLinksReader _cdata;
CPT(Down) _down;
};
#endif // DO_PIPELINING
// Similarly for stashed children.
class EXPCL_PANDA StashedCopy {
public:
StashedCopy(const CDLinksReader &cdata);
INLINE StashedCopy(const StashedCopy &copy);
INLINE void operator = (const StashedCopy &copy);
INLINE int get_num_stashed() const;
INLINE PandaNode *get_stashed(int n) const;
private:
typedef PTA(PT(PandaNode)) List;
List _list;
};
#ifdef DO_PIPELINING
typedef StashedCopy Stashed;
#else
class EXPCL_PANDA Stashed {
public:
INLINE Stashed(const CDLinksReader &cdata);
@ -618,30 +600,26 @@ public:
INLINE PandaNode *get_stashed(int n) const;
private:
CDLinksReader _cdata;
CPT(Down) _stashed;
};
#endif // DO_PIPELINING
// This class is returned from get_parents_copy().
class EXPCL_PANDA ParentsCopy {
// This class is returned from get_parents().
class EXPCL_PANDA Parents {
public:
ParentsCopy(const CDLinksReader &cdata);
INLINE ParentsCopy(const ParentsCopy &copy);
INLINE void operator = (const ParentsCopy &copy);
INLINE Parents(const CDLinksReader &cdata);
INLINE Parents(const Parents &copy);
INLINE void operator = (const Parents &copy);
INLINE int get_num_parents() const;
INLINE PandaNode *get_parent(int n) const;
private:
typedef PTA(PT(PandaNode)) List;
List _list;
CPT(Up) _up;
};
INLINE ChildrenCopy get_children_copy() const;
INLINE Children get_children() const;
INLINE StashedCopy get_stashed_copy() const;
INLINE Stashed get_stashed() const;
INLINE ParentsCopy get_parents_copy() const;
INLINE Children get_children(Thread *current_thread = Thread::get_current_thread()) const;
INLINE Stashed get_stashed(Thread *current_thread = Thread::get_current_thread()) const;
INLINE Parents get_parents(Thread *current_thread = Thread::get_current_thread()) const;
public:
static void register_with_read_factory();

View File

@ -19,6 +19,7 @@
#include "nodePathComponent.cxx"
#include "nodePathLerps.cxx"
#include "pandaNode.cxx"
#include "pandaNodeChain.cxx"
#include "planeNode.cxx"
#include "pointLight.cxx"
#include "polylightNode.cxx"

View File

@ -62,7 +62,7 @@ flatten(PandaNode *root, int combine_siblings_bits) {
// Get a copy of the children list, so we don't have to worry
// about self-modifications.
PandaNode::ChildrenCopy cr = root->get_children_copy();
PandaNode::Children cr = root->get_children();
// Now visit each of the children in turn.
int num_children = cr.get_num_children();
@ -257,7 +257,7 @@ r_flatten(PandaNode *grandparent_node, PandaNode *parent_node,
// First, recurse on each of the children.
{
PandaNode::ChildrenCopy cr = parent_node->get_children_copy();
PandaNode::Children cr = parent_node->get_children();
int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) {
PandaNode *child_node = cr.get_child(i);

View File

@ -95,10 +95,10 @@ private:
// Iterates through all of the pipeline stages upstream of the current
// stage, but not including the current stage.
#define OPEN_ITERATE_UPSTREAM_ONLY(cycler) { \
#define OPEN_ITERATE_UPSTREAM_ONLY(cycler, current_thread) { \
CyclerHolder cholder(cycler); \
int pipeline_stage; \
for (pipeline_stage = Thread::get_current_pipeline_stage() - 1; \
for (pipeline_stage = current_thread->get_pipeline_stage() - 1; \
pipeline_stage >= 0; \
--pipeline_stage)
@ -107,10 +107,10 @@ private:
// Iterates through all of the pipeline stages upstream of the current
// stage, and including the current stage.
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler) { \
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler, current_thread) { \
CyclerHolder cholder(cycler); \
int pipeline_stage; \
for (pipeline_stage = Thread::get_current_pipeline_stage(); \
for (pipeline_stage = current_thread->get_pipeline_stage(); \
pipeline_stage >= 0; \
--pipeline_stage)
@ -118,9 +118,9 @@ private:
}
// As above, but without holding the cycler lock during the loop.
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) { \
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler, current_thread) { \
int pipeline_stage; \
for (pipeline_stage = Thread::get_current_pipeline_stage(); \
for (pipeline_stage = current_thread->get_pipeline_stage(); \
pipeline_stage >= 0; \
--pipeline_stage)
@ -142,20 +142,20 @@ private:
// These are trivial implementations of the above macros, defined when
// pipelining is not enabled, that simply operate on stage 0 without
// bothering to create a for loop.
#define OPEN_ITERATE_UPSTREAM_ONLY(cycler) \
#define OPEN_ITERATE_UPSTREAM_ONLY(cycler, current_thread) \
if (false) { \
const int pipeline_stage = -1;
#define CLOSE_ITERATE_UPSTREAM_ONLY(cycler) \
}
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler) { \
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler, current_thread) { \
const int pipeline_stage = 0; \
#define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler) \
}
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) { \
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler, current_thread) { \
const int pipeline_stage = 0; \
#define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) \