pgraph NodePath

This commit is contained in:
David Rose 2002-03-07 02:45:21 +00:00
parent 533f6043ca
commit c7d0e2d117
36 changed files with 4646 additions and 1267 deletions

View File

@ -108,7 +108,7 @@ get_camera() const {
// Description: Returns the camera associated with this
// DisplayRegion, or NULL if no camera is associated.
////////////////////////////////////////////////////////////////////
INLINE const NodeChain &DisplayRegion::
INLINE const qpNodePath &DisplayRegion::
get_qpcamera() const {
return _qpcamera;
}

View File

@ -98,7 +98,7 @@ operator = (const DisplayRegion&) {
////////////////////////////////////////////////////////////////////
DisplayRegion::
~DisplayRegion() {
set_qpcamera(NodeChain());
set_qpcamera(qpNodePath());
}
////////////////////////////////////////////////////////////////////
@ -193,12 +193,12 @@ set_camera(Camera *camera) {
// was already associated with a different
// DisplayRegion, that association is removed.
//
// The camera is actually set via a NodeChain, which
// The camera is actually set via a qpNodePath, which
// clarifies which instance of the camera (if there
// happen to be multiple instances) we should use.
////////////////////////////////////////////////////////////////////
void DisplayRegion::
set_qpcamera(const NodeChain &camera) {
set_qpcamera(const qpNodePath &camera) {
qpCamera *camera_node = (qpCamera *)NULL;
if (!camera.is_empty()) {
DCAST_INTO_V(camera_node, camera.node());

View File

@ -22,7 +22,7 @@
#include "referenceCount.h"
#include "camera.h"
#include "nodeChain.h"
#include "qpnodePath.h"
#include "cullResult.h"
#include "pointerTo.h"
@ -69,8 +69,8 @@ PUBLISHED:
void set_camera(Camera *camera);
INLINE Camera *get_camera() const;
void set_qpcamera(const NodeChain &camera);
INLINE const NodeChain &get_qpcamera() const;
void set_qpcamera(const qpNodePath &camera);
INLINE const qpNodePath &get_qpcamera() const;
INLINE void set_cull_frustum(LensNode *cull_frustum);
INLINE LensNode *get_cull_frustum() const;
@ -104,7 +104,7 @@ protected:
GraphicsLayer *_layer;
PT(Camera) _camera;
NodeChain _qpcamera;
qpNodePath _qpcamera;
qpCamera *_camera_node;
PT(LensNode) _cull_frustum;

View File

@ -197,7 +197,7 @@ cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr) {
// Description: Fires off a cull traversal using the indicated camera.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::
do_cull(CullHandler *cull_handler, const NodeChain &camera,
do_cull(CullHandler *cull_handler, const qpNodePath &camera,
GraphicsStateGuardian *gsg) {
if (camera.is_empty()) {
// No camera, no draw.
@ -218,7 +218,7 @@ do_cull(CullHandler *cull_handler, const NodeChain &camera,
return;
}
NodeChain scene = camera_node->get_scene();
qpNodePath scene = camera_node->get_scene();
if (scene.is_empty()) {
// No scene, no draw.
return;
@ -298,7 +298,7 @@ do_draw(CullResult *cull_result, GraphicsStateGuardian *gsg,
////////////////////////////////////////////////////////////////////
bool GraphicsEngine::
set_gsg_lens(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
const NodeChain &camera = dr->get_qpcamera();
const qpNodePath &camera = dr->get_qpcamera();
if (camera.is_empty()) {
// No camera, no draw.
return false;

View File

@ -57,7 +57,7 @@ private:
void cull_bin_draw();
void cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr);
void do_cull(CullHandler *cull_handler, const NodeChain &camera,
void do_cull(CullHandler *cull_handler, const qpNodePath &camera,
GraphicsStateGuardian *gsg);
void do_draw(CullResult *cull_result, GraphicsStateGuardian *gsg,
DisplayRegion *dr);

View File

@ -20,7 +20,7 @@
#include "qpeggLoader.h"
#include "config_egg2pg.h"
#include "nodeChain.h"
#include "qpnodePath.h"
#include "renderState.h"
#include "transformState.h"
#include "textureAttrib.h"
@ -154,14 +154,14 @@ reparent_decals() {
PandaNode *node = (*di);
nassertv(node != (PandaNode *)NULL);
// The NodeChain interface is best for this.
NodeChain parent(node);
// The qpNodePath interface is best for this.
qpNodePath parent(node);
// First, search for the GeomNode.
NodeChain geom_parent;
qpNodePath geom_parent;
int num_children = parent.get_num_children();
for (int i = 0; i < num_children; i++) {
NodeChain child = parent.get_child(i);
qpNodePath child = parent.get_child(i);
if (child.node()->is_of_type(qpGeomNode::get_class_type())) {
if (!geom_parent.is_empty()) {
@ -187,7 +187,7 @@ reparent_decals() {
// list.
int i = 0;
while (i < num_children) {
NodeChain child = parent.get_child(i);
qpNodePath child = parent.get_child(i);
if (child.node()->is_of_type(qpGeomNode::get_class_type())) {
i++;

View File

@ -31,8 +31,9 @@
qplensNode.h qplensNode.I \
qplodNode.h qplodNode.I \
materialAttrib.h materialAttrib.I \
nodeChain.h nodeChain.I \
nodeChainComponent.h nodeChainComponent.I \
qpnodePath.h qpnodePath.I \
qpnodePathCollection.h qpnodePathCollection.I \
qpnodePathComponent.h qpnodePathComponent.I \
pandaNode.h pandaNode.I \
renderAttrib.h renderAttrib.I \
renderState.h renderState.I \
@ -70,8 +71,9 @@
qplensNode.cxx \
qplodNode.cxx \
materialAttrib.cxx \
nodeChain.cxx \
nodeChainComponent.cxx \
qpnodePath.cxx \
qpnodePathCollection.cxx \
qpnodePathComponent.cxx \
pandaNode.cxx \
renderAttrib.cxx \
renderState.cxx \
@ -114,8 +116,9 @@
qplensNode.h qplensNode.I \
qplodNode.h qplodNode.I \
materialAttrib.h materialAttrib.I \
nodeChain.h nodeChain.I \
nodeChainComponent.h nodeChainComponent.I \
qpnodePath.h qpnodePath.I \
qpnodePathCollection.h qpnodePathCollection.I \
qpnodePathComponent.h qpnodePathComponent.I \
pandaNode.h pandaNode.I \
renderAttrib.h renderAttrib.I \
renderState.h renderState.I \

View File

@ -37,7 +37,7 @@ BillboardAttrib() {
INLINE CPT(RenderAttrib) BillboardAttrib::
make_axis() {
return make(LVector3f::up(), false, true,
0.0f, NodeChain(), LPoint3f(0.0f, 0.0f, 0.0f));
0.0f, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
@ -49,7 +49,7 @@ make_axis() {
INLINE CPT(RenderAttrib) BillboardAttrib::
make_point_eye() {
return make(LVector3f::up(), true, false,
0.0f, NodeChain(), LPoint3f(0.0f, 0.0f, 0.0f));
0.0f, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
@ -61,7 +61,7 @@ make_point_eye() {
INLINE CPT(RenderAttrib) BillboardAttrib::
make_point_world() {
return make(LVector3f::up(), false, false,
0.0f, NodeChain(), LPoint3f(0.0f, 0.0f, 0.0f));
0.0f, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
@ -73,7 +73,7 @@ make_point_world() {
// particularly useful and isn't normally created or
// stored in the graph; it might be implicitly
// discovered as the result of a
// NodeChain::get_rel_state().
// qpNodePath::get_rel_state().
////////////////////////////////////////////////////////////////////
INLINE bool BillboardAttrib::
is_off() const {
@ -135,7 +135,7 @@ get_offset() const {
// will rotate towards the current camera node, wherever
// that might be.
////////////////////////////////////////////////////////////////////
INLINE const NodeChain &BillboardAttrib::
INLINE const qpNodePath &BillboardAttrib::
get_look_at() const {
return _look_at;
}

View File

@ -33,7 +33,7 @@ TypeHandle BillboardAttrib::_type_handle;
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) BillboardAttrib::
make(const LVector3f &up_vector, bool eye_relative,
bool axial_rotate, float offset, const NodeChain &look_at,
bool axial_rotate, float offset, const qpNodePath &look_at,
const LPoint3f &look_at_point) {
BillboardAttrib *attrib = new BillboardAttrib;
attrib->_up_vector = up_vector;
@ -228,7 +228,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
dg.add_float32(_offset);
_look_at_point.write_datagram(dg);
// *** We don't write out the _look_at NodeChain right now. Maybe
// *** We don't write out the _look_at qpNodePath right now. Maybe
// we should.
}

View File

@ -23,7 +23,7 @@
#include "renderAttrib.h"
#include "luse.h"
#include "nodeChain.h"
#include "qpnodePath.h"
////////////////////////////////////////////////////////////////////
// Class : BillboardAttrib
@ -40,7 +40,7 @@ PUBLISHED:
bool eye_relative,
bool axial_rotate,
float offset,
const NodeChain &look_at,
const qpNodePath &look_at,
const LPoint3f &look_at_point);
INLINE static CPT(RenderAttrib) make_axis();
INLINE static CPT(RenderAttrib) make_point_eye();
@ -51,7 +51,7 @@ PUBLISHED:
INLINE bool get_eye_relative() const;
INLINE bool get_axial_rotate() const;
INLINE float get_offset() const;
INLINE const NodeChain &get_look_at() const;
INLINE const qpNodePath &get_look_at() const;
INLINE const LPoint3f &get_look_at_point() const;
public:
@ -70,7 +70,7 @@ private:
bool _eye_relative;
bool _axial_rotate;
float _offset;
NodeChain _look_at;
qpNodePath _look_at;
LPoint3f _look_at_point;
public:

View File

@ -35,8 +35,8 @@
#include "qplensNode.h"
#include "qplodNode.h"
#include "materialAttrib.h"
#include "nodeChain.h"
#include "nodeChainComponent.h"
#include "qpnodePath.h"
#include "qpnodePathComponent.h"
#include "pandaNode.h"
#include "renderAttrib.h"
#include "renderState.h"
@ -95,8 +95,8 @@ init_libpgraph() {
qpLensNode::init_type();
qpLODNode::init_type();
MaterialAttrib::init_type();
NodeChain::init_type();
NodeChainComponent::init_type();
qpNodePath::init_type();
qpNodePathComponent::init_type();
PandaNode::init_type();
RenderAttrib::init_type();
RenderState::init_type();

View File

@ -36,7 +36,7 @@ private:
INLINE MaterialAttrib();
PUBLISHED:
static CPT(RenderAttrib) make(const Material *tex);
static CPT(RenderAttrib) make(const Material *material);
static CPT(RenderAttrib) make_off();
INLINE bool is_off() const;

View File

@ -1,348 +0,0 @@
// Filename: nodeChain.I
// Created by: drose (25Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: NodeChain::Default Constructor
// Access: Published
// Description: This constructs an empty NodeChain with no nodes. It
// cannot be extended, since you cannot add nodes without
// first specifying the top node. Use the constructor
// that receives a node if you ever want to do anything
// with this chain.
////////////////////////////////////////////////////////////////////
INLINE NodeChain::
NodeChain() :
_error_type(ET_ok)
{
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::Constructor
// Access: Published
// Description: This constructs an empty NodeChain with a single node.
// This chain may now be extended by repeatedly calling
// push_back() with each node below that node in
// sequence.
//
// If the Node pointer is NULL, this quietly creates an
// empty NodeChain.
////////////////////////////////////////////////////////////////////
INLINE NodeChain::
NodeChain(PandaNode *top_node) :
_error_type(ET_ok)
{
if (top_node != (PandaNode *)NULL) {
_head = top_node->get_generic_component();
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE NodeChain::
NodeChain(const NodeChain &copy) :
_head(copy._head),
_error_type(copy._error_type)
{
uncollapse_head();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void NodeChain::
operator = (const NodeChain &copy) {
_head = copy._head;
_error_type = copy._error_type;
uncollapse_head();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::not_found named constructor
// Access: Published, Static
// Description: Creates a NodeChain with the ET_not_found error type
// set.
////////////////////////////////////////////////////////////////////
INLINE NodeChain NodeChain::
not_found() {
NodeChain result;
result._error_type = ET_not_found;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::removed named constructor
// Access: Published, Static
// Description: Creates a NodeChain with the ET_removed error type
// set.
////////////////////////////////////////////////////////////////////
INLINE NodeChain NodeChain::
removed() {
NodeChain result;
result._error_type = ET_removed;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::fail named constructor
// Access: Published, Static
// Description: Creates a NodeChain with the ET_fail error type
// set.
////////////////////////////////////////////////////////////////////
INLINE NodeChain NodeChain::
fail() {
NodeChain result;
result._error_type = ET_fail;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::is_empty
// Access: Published
// Description: Returns true if the NodeChain contains no nodes.
////////////////////////////////////////////////////////////////////
INLINE bool NodeChain::
is_empty() const {
return (_head == (NodeChainComponent *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::is_singleton
// Access: Published
// Description: Returns true if the NodeChain contains exactly one
// node.
////////////////////////////////////////////////////////////////////
INLINE bool NodeChain::
is_singleton() const {
uncollapse_head();
return (_head != (NodeChainComponent *)NULL && _head->is_top_node());
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_error_type
// Access: Published
// Description: If is_empty() is true, this returns a code that
// represents the reason why the NodeChain is empty.
////////////////////////////////////////////////////////////////////
INLINE NodeChain::ErrorType NodeChain::
get_error_type() const {
return _error_type;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::node
// Access: Published
// Description: Returns the bottom node of the path, or NULL if the
// path is empty.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *NodeChain::
node() const {
if (is_empty()) {
return (PandaNode *)NULL;
}
return _head->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_num_children
// Access: Published
// Description: Returns the number of children of the bottom node.
////////////////////////////////////////////////////////////////////
INLINE int NodeChain::
get_num_children() const {
nassertr(!is_empty(), 0);
return _head->get_node()->get_num_children();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_child
// Access: Published
// Description: Returns a NodeChain representing the nth child of the
// bottom node.
////////////////////////////////////////////////////////////////////
INLINE NodeChain NodeChain::
get_child(int n) const {
nassertr(n >= 0 && n < get_num_children(), NodeChain());
NodeChain child;
child._head = PandaNode::get_component(_head, _head->get_node()->get_child(n));
return child;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::has_parent
// Access: Published
// Description: Returns true if the node at the bottom of the
// NodeChain has a parent; i.e. the NodeChain contains at
// least two nodes.
////////////////////////////////////////////////////////////////////
INLINE bool NodeChain::
has_parent() const {
return !is_empty() && !is_singleton();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_parent
// Access: Published
// Description: Returns the NodeChain to the parent of the bottom
// node: that is, this NodeChain, shortened by one node.
////////////////////////////////////////////////////////////////////
INLINE NodeChain NodeChain::
get_parent() const {
nassertr(has_parent(), NodeChain::fail());
NodeChain parent;
parent._head = _head->get_next();
return parent;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::attach_new_node
// Access: Published
// Description: Creates an ordinary PandaNode and attaches it below
// the current NodeChain, returning a new NodeChain that
// references it.
////////////////////////////////////////////////////////////////////
INLINE NodeChain NodeChain::
attach_new_node(const string &name, int sort) const {
nassertr(verify_complete(), NodeChain::fail());
nassertr(!is_empty(), *this);
return attach_new_node(new PandaNode(name), sort);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_net_state
// Access: Published
// Description: Returns the net state on this node from the root.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderState) NodeChain::
get_net_state() const {
uncollapse_head();
return r_get_net_state(_head);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_net_transform
// Access: Published
// Description: Returns the net transform on this node from the root.
////////////////////////////////////////////////////////////////////
INLINE CPT(TransformState) NodeChain::
get_net_transform() const {
uncollapse_head();
return r_get_net_transform(_head);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_mat
// Access: Published
// Description: Returns the matrix that describes the coordinate
// space of this node, relative to the other
// node's coordinate space. If either NodeChain is
// empty, it is taken to indicate the top of the graph.
////////////////////////////////////////////////////////////////////
INLINE const LMatrix4f &NodeChain::
get_mat(const NodeChain &other) const {
CPT(TransformState) transform = get_rel_transform(other);
// We can safely assume the transform won't go away when the
// function returns, since its reference count is also held in the
// cache. This assumption allows us to return a reference to the
// matrix, instead of having to return a matrix on the stack.
nassertr(transform->get_ref_count() > 1, LMatrix4f::ident_mat());
return transform->get_mat();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::operator ==
// Access: Published
// Description: Returns true if the two chains are equivalent; that
// is, if they contain the same list of nodes in the same
// order.
////////////////////////////////////////////////////////////////////
INLINE bool NodeChain::
operator == (const NodeChain &other) const {
return (compare_to(other) == 0);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::operator !=
// Access: Published
// Description: Returns true if the two chains are not equivalent.
////////////////////////////////////////////////////////////////////
INLINE bool NodeChain::
operator != (const NodeChain &other) const {
return (compare_to(other) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::operator <
// Access: Published
// Description: Returns true if this NodeChain sorts before the other
// one, false otherwise. The sorting order of two
// nonequivalent NodeChains is consistent but undefined,
// and is useful only for storing NodeChains in a sorted
// container like an STL set.
////////////////////////////////////////////////////////////////////
INLINE bool NodeChain::
operator < (const NodeChain &other) const {
return (compare_to(other) < 0);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::compare_to
// Access: Published
// Description: Returns a number less than zero if this NodeChain
// sorts before the other one, greater than zero if it
// sorts after, or zero if they are equivalent.
//
// Two NodeChains are considered equivalent if they
// consist of exactly the same list of nodes in the same
// order. Otherwise, they are different; different
// NodeChains will be ranked in a consistent but
// undefined ordering; the ordering is useful only for
// placing the NodeChains in a sorted container like an
// STL set.
////////////////////////////////////////////////////////////////////
INLINE int NodeChain::
compare_to(const NodeChain &other) const {
return r_compare_to(_head, other._head);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::output
// Access: Published
// Description: Writes a sensible description of the NodeChain to the
// indicated output stream.
////////////////////////////////////////////////////////////////////
INLINE void NodeChain::
output(ostream &out) const {
if (_head == (NodeChainComponent *)NULL) {
out << "(empty)";
} else {
r_output(out, _head);
}
}
INLINE ostream &operator << (ostream &out, const NodeChain &node_chain) {
node_chain.output(out);
return out;
}

View File

@ -1,514 +0,0 @@
// Filename: nodeChain.cxx
// Created by: drose (25Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "nodeChain.h"
#include "node.h"
#include "namedNode.h"
#include "config_pgraph.h"
#include "plist.h"
TypeHandle NodeChain::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_num_nodes
// Access: Published
// Description: Returns the number of nodes in the path.
////////////////////////////////////////////////////////////////////
int NodeChain::
get_num_nodes() const {
if (is_empty()) {
return 0;
}
uncollapse_head();
return _head->get_length();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_node
// Access: Published
// Description: Returns the nth node of the path, where 0 is the
// bottom node and get_num_nodes() - 1 is the top node.
// This requires iterating through the path.
////////////////////////////////////////////////////////////////////
PandaNode *NodeChain::
get_node(int index) const {
nassertr(index >= 0 && index < get_num_nodes(), NULL);
uncollapse_head();
NodeChainComponent *comp = _head;
while (index > 0) {
// If this assertion fails, the index was out of range; the
// component's length must have been invalid.
nassertr(comp != (NodeChainComponent *)NULL, NULL);
comp = comp->get_next();
index--;
}
// If this assertion fails, the index was out of range; the
// component's length must have been invalid.
nassertr(comp != (NodeChainComponent *)NULL, NULL);
return comp->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_top_node
// Access: Published
// Description: Returns the top node of the path, or NULL if the path
// is empty. This requires iterating through the path.
////////////////////////////////////////////////////////////////////
PandaNode *NodeChain::
get_top_node() const {
if (is_empty()) {
return (PandaNode *)NULL;
}
uncollapse_head();
NodeChainComponent *comp = _head;
while (!comp->is_top_node()) {
comp = comp->get_next();
nassertr(comp != (NodeChainComponent *)NULL, NULL);
}
return comp->get_node();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::reparent_to
// Access: Published
// Description: Removes the bottom node of the NodeChain from its
// current parent and attaches it to the bottom node of
// the indicated NodeChain.
////////////////////////////////////////////////////////////////////
void NodeChain::
reparent_to(const NodeChain &other, int sort) {
nassertv(other.verify_complete());
nassertv_always(!is_empty());
nassertv_always(!other.is_empty());
uncollapse_head();
other.uncollapse_head();
PandaNode::reparent(other._head, _head, sort);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::wrt_reparent_to
// Access: Published
// Description: This functions identically to reparent_to(), except
// the transform on this node is also adjusted so that
// the node remains in the same place in world
// coordinates, even if it is reparented into a
// different coordinate system.
////////////////////////////////////////////////////////////////////
void NodeChain::
wrt_reparent_to(const NodeChain &other, int sort) {
nassertv(other.verify_complete());
nassertv_always(!is_empty());
nassertv_always(!other.is_empty());
//****
/*
LMatrix4f mat = get_mat(other);
set_mat(mat);
*/
reparent_to(other, sort);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::instance_to
// Access: Published
// Description: Adds the bottom node of the NodeChain as a child of
// the bottom node of the indicated other NodeChain. Any
// other parent-child relations of the node are
// unchanged; in particular, the node is not removed
// from its existing parent, if any.
//
// If the node already had an existing parent, this
// method will create a new instance of the node within
// the scene graph.
//
// This does not change the NodeChain itself, but does
// return a new NodeChain that reflects the new instance
// node.
////////////////////////////////////////////////////////////////////
NodeChain NodeChain::
instance_to(const NodeChain &other, int sort) const {
nassertr(verify_complete(), NodeChain::fail());
nassertr(!is_empty(), NodeChain::fail());
nassertr(!other.is_empty(), NodeChain::fail());
uncollapse_head();
other.uncollapse_head();
NodeChain new_instance;
new_instance._head = PandaNode::attach(other._head, node(), sort);
return new_instance;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::copy_to
// Access: Published
// Description: Functions exactly like instance_to(), except a deep
// copy is made of the bottom node and all of its
// descendents, which is then parented to the indicated
// node. A NodeChain to the newly created copy is
// returned.
//
// Certain kinds of nodes may not be copied; if one of
// these is encountered, the node will be "copied" as
// the nearest copyable base class. For instance, a
// Camera node in the graph will become a simple
// NamedNode.
////////////////////////////////////////////////////////////////////
NodeChain NodeChain::
copy_to(const NodeChain &other, int sort) const {
//*****
return instance_to(other, sort);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::attach_new_node
// Access: Published
// Description: Attaches a new node, with or without existing
// parents, to the scene graph below the bottom node of
// this NodeChain. This is the preferred way to add
// nodes to the graph.
//
// This does *not* automatically extend the current
// NodeChain to reflect the attachment; however, a
// NodeChain that does reflect this extension is
// returned.
////////////////////////////////////////////////////////////////////
NodeChain NodeChain::
attach_new_node(PandaNode *node, int sort) const {
nassertr(verify_complete(), NodeChain::fail());
nassertr(!is_empty(), NodeChain());
nassertr(node != (PandaNode *)NULL, NodeChain());
uncollapse_head();
NodeChain new_path(*this);
new_path._head = PandaNode::attach(_head, node, sort);
return new_path;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::remove_node
// Access: Published
// Description: Disconnects the bottom node from the scene graph.
// This will also delete the node if there are no other
// pointers to it.
//
// Normally, this should be called only when you are
// really done with the node. If you want to remove a
// node from the scene graph but keep it around for
// later, you should probably use reparent_to() and put
// it under a holding node instead.
//
// After the node is removed, the NodeChain will have
// been cleared.
////////////////////////////////////////////////////////////////////
void NodeChain::
remove_node() {
nassertv(_error_type != ET_not_found);
if (is_empty()) {
// If we have no arcs (maybe we were already removed), quietly do
// nothing except to ensure the NodeChain is clear.
(*this) = NodeChain::removed();
return;
}
uncollapse_head();
PandaNode::detach(_head);
(*this) = NodeChain::removed();
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_rel_state
// Access: Published
// Description: Returns the state changes that must be made to
// transition from the render state of this node to the
// render state of the other node.
////////////////////////////////////////////////////////////////////
CPT(RenderState) NodeChain::
get_rel_state(const NodeChain &other) const {
if (is_empty()) {
return other.get_net_state();
}
if (other.is_empty()) {
return get_net_state()->invert_compose(RenderState::make_empty());
}
nassertr(verify_complete(), RenderState::make_empty());
nassertr(other.verify_complete(), RenderState::make_empty());
int a_count, b_count;
find_common_ancestor(*this, other, a_count, b_count);
CPT(RenderState) a_state = r_get_partial_state(_head, a_count);
CPT(RenderState) b_state = r_get_partial_state(other._head, b_count);
return a_state->invert_compose(b_state);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::get_rel_transform
// Access: Published
// Description: Returns the relative transform from this node to the
// other node; i.e. the transformation of the other node
// as seen from this node.
////////////////////////////////////////////////////////////////////
CPT(TransformState) NodeChain::
get_rel_transform(const NodeChain &other) const {
if (is_empty()) {
return other.get_net_transform();
}
if (other.is_empty()) {
return get_net_transform()->invert_compose(TransformState::make_identity());
}
nassertr(verify_complete(), TransformState::make_identity());
nassertr(other.verify_complete(), TransformState::make_identity());
int a_count, b_count;
find_common_ancestor(*this, other, a_count, b_count);
CPT(TransformState) a_transform = r_get_partial_transform(_head, a_count);
CPT(TransformState) b_transform = r_get_partial_transform(other._head, b_count);
return a_transform->invert_compose(b_transform);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::verify_complete
// Access: Published
// Description: Returns true if all of the nodes described in the
// NodeChain are connected *and* the top node is the top
// of the graph, or false otherwise.
////////////////////////////////////////////////////////////////////
bool NodeChain::
verify_complete() const {
if (is_empty()) {
return true;
}
uncollapse_head();
const NodeChainComponent *comp = _head;
nassertr(comp != (const NodeChainComponent *)NULL, false);
PandaNode *node = comp->get_node();
nassertr(node != (const PandaNode *)NULL, false);
int length = comp->get_length();
comp = comp->get_next();
length--;
while (comp != (const NodeChainComponent *)NULL) {
PandaNode *next_node = comp->get_node();
nassertr(next_node != (const PandaNode *)NULL, false);
if (next_node->find_child(node) < 0) {
return false;
}
if (comp->get_length() != length) {
return false;
}
node = next_node;
comp = comp->get_next();
length--;
}
// Now that we've reached the top, we should have no parents.
return length == 0 && node->get_num_parents() == 0;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::uncollapse_head
// Access: Private
// Description: Quietly and transparently uncollapses the _head
// pointer if it needs it.
////////////////////////////////////////////////////////////////////
void NodeChain::
uncollapse_head() const {
if (_head != (NodeChainComponent *)NULL && _head->is_collapsed()) {
((NodeChain *)this)->_head = _head->uncollapse();
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::find_common_ancestor
// Access: Private, Static
// Description: Walks up from both NodeChains to find the first node
// that both have in common, if any. Fills a_count and
// b_count with the number of nodes below the common
// node in each chain.
////////////////////////////////////////////////////////////////////
void NodeChain::
find_common_ancestor(const NodeChain &a, const NodeChain &b,
int &a_count, int &b_count) {
nassertv(!a.is_empty() && !b.is_empty());
a.uncollapse_head();
b.uncollapse_head();
NodeChainComponent *ac = a._head;
NodeChainComponent *bc = b._head;
a_count = 0;
b_count = 0;
// Shorten up the longer one until they are the same length.
while (ac->get_length() > bc->get_length()) {
nassertv(ac != (NodeChainComponent *)NULL);
ac = ac->get_next();
a_count++;
}
while (bc->get_length() > ac->get_length()) {
nassertv(bc != (NodeChainComponent *)NULL);
bc = bc->get_next();
b_count++;
}
// Now shorten them both up until we reach the same component.
while (ac != bc) {
// These shouldn't go to NULL unless they both go there together.
nassertv(ac != (NodeChainComponent *)NULL);
nassertv(bc != (NodeChainComponent *)NULL);
ac = ac->get_next();
a_count++;
bc = bc->get_next();
b_count++;
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::r_get_net_state
// Access: Private
// Description: Recursively determines the net state chnages to the
// indicated component node from the root of the graph.
////////////////////////////////////////////////////////////////////
CPT(RenderState) NodeChain::
r_get_net_state(NodeChainComponent *comp) const {
if (comp == (NodeChainComponent *)NULL) {
return RenderState::make_empty();
} else {
CPT(RenderState) state = comp->get_node()->get_state();
return r_get_net_state(comp->get_next())->compose(state);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::r_get_partial_state
// Access: Private
// Description: Recursively determines the net state changes to the
// indicated component node from the nth node above it.
////////////////////////////////////////////////////////////////////
CPT(RenderState) NodeChain::
r_get_partial_state(NodeChainComponent *comp, int n) const {
nassertr(comp != (NodeChainComponent *)NULL, RenderState::make_empty());
if (n == 0) {
return RenderState::make_empty();
} else {
CPT(RenderState) state = comp->get_node()->get_state();
return r_get_partial_state(comp->get_next(), n - 1)->compose(state);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::r_get_net_transform
// Access: Private
// Description: Recursively determines the net transform to the
// indicated component node from the root of the graph.
////////////////////////////////////////////////////////////////////
CPT(TransformState) NodeChain::
r_get_net_transform(NodeChainComponent *comp) const {
if (comp == (NodeChainComponent *)NULL) {
return TransformState::make_identity();
} else {
CPT(TransformState) transform = comp->get_node()->get_transform();
return r_get_net_transform(comp->get_next())->compose(transform);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::r_get_partial_transform
// Access: Private
// Description: Recursively determines the net transform to the
// indicated component node from the nth node above it.
////////////////////////////////////////////////////////////////////
CPT(TransformState) NodeChain::
r_get_partial_transform(NodeChainComponent *comp, int n) const {
nassertr(comp != (NodeChainComponent *)NULL, TransformState::make_identity());
if (n == 0) {
return TransformState::make_identity();
} else {
CPT(TransformState) transform = comp->get_node()->get_transform();
return r_get_partial_transform(comp->get_next(), n - 1)->compose(transform);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::r_output
// Access: Private
// Description: The recursive implementation of output(), this writes
// the names of each node component in order from
// beginning to end, by first walking to the end of the
// linked list and then outputting from there.
////////////////////////////////////////////////////////////////////
void NodeChain::
r_output(ostream &out, NodeChainComponent *comp) const {
NodeChainComponent *next = comp->get_next();
if (next != (NodeChainComponent *)NULL) {
// This is not the head of the list; keep going up.
r_output(out, next);
out << "/";
}
// Now output this component.
PandaNode *node = comp->get_node();
if (node->has_name()) {
out << node->get_name();
} else {
out << "+" << node->get_type();
}
out << "[" << comp->get_length() << "]";
}
////////////////////////////////////////////////////////////////////
// Function: NodeChain::r_compare_to
// Access: Private, Static
// Description: The recursive implementation of compare_to(). Returns
// < 0 if a sorts before b, > 0 if b sorts before a, or
// == 0 if they are equivalent.
////////////////////////////////////////////////////////////////////
int NodeChain::
r_compare_to(const NodeChainComponent *a, const NodeChainComponent *b) {
if (a == b) {
return 0;
} else if (a == (const NodeChainComponent *)NULL) {
return -1;
} else if (b == (const NodeChainComponent *)NULL) {
return 1;
} else if (a->get_node() != b->get_node()) {
return a->get_node() - b->get_node();
} else {
return r_compare_to(a->get_next(), b->get_next());
}
}

View File

@ -1,176 +0,0 @@
// Filename: nodeChain.h
// Created by: drose (25Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef NODECHAIN_H
#define NODECHAIN_H
#include "pandabase.h"
#include "pandaNode.h"
#include "renderState.h"
#include "transformState.h"
#include "nodeChainComponent.h"
#include "pointerTo.h"
#include "referenceCount.h"
#include "notify.h"
#include "typedObject.h"
////////////////////////////////////////////////////////////////////
// Class : NodeChain
// Description : A NodeChain is the fundamental system for
// disambiguating instances and manipulating the scene
// graph. NodeChain is the base class of NodePath,
// which adds a bit more high-level functionality, but
// the fundamental scene graph manipulations are defined
// at the NodeChain level.
//
// A NodeChain is a list of connected nodes from the
// root of the graph to any sub-node. Each NodeChain
// therefore unqiuely describes one instance of a node.
//
// NodeChains themselves are lightweight objects that
// may easily be copied and passed by value. Their data
// is stored as a series of NodeChainComponents that are
// stored on the nodes. Holding a NodeChain will keep a
// reference count to all the nodes in the chain.
// However, if any node in the chain is removed or
// reparented (perhaps through a different NodeChain),
// the NodeChain will automatically be updated to
// reflect the changes.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA NodeChain {
PUBLISHED:
// This enumeration is returned by get_error_type() for an empty
// NodeChain to report the reason it's empty.
enum ErrorType {
ET_ok = 0, // i.e. not empty, or never assigned to anything.
ET_not_found, // returned from a failed find() or similar function.
ET_removed, // remove_node() was previously called on this NodeChain.
ET_fail, // general failure return from some function.
};
INLINE NodeChain();
INLINE NodeChain(PandaNode *top_node);
INLINE NodeChain(const NodeChain &copy);
INLINE void operator = (const NodeChain &copy);
INLINE static NodeChain not_found();
INLINE static NodeChain removed();
INLINE static NodeChain fail();
// Methods to query a NodeChain's contents.
INLINE bool is_empty() const;
INLINE bool is_singleton() const;
int get_num_nodes() const;
PandaNode *get_node(int index) const;
INLINE ErrorType get_error_type() const;
PandaNode *get_top_node() const;
INLINE PandaNode *node() const;
// Methods that return collections of NodePaths derived from or
// related to this one.
/*
NodeChainCollection get_siblings() const;
NodeChainCollection get_children() const;
*/
INLINE int get_num_children() const;
INLINE NodeChain get_child(int n) const;
INLINE bool has_parent() const;
INLINE NodeChain get_parent() const;
/*
INLINE NodeChain find_path_down_to(Node *dnode) const;
INLINE NodeChain find(const string &chain) const;
NodeChainCollection
find_all_paths_down_to(Node *dnode) const;
NodeChainCollection
find_all_matches(const string &chain) const;
*/
// Methods that actually move nodes around in the scene graph. The
// optional "sort" parameter can be used to force a particular
// ordering between sibling nodes, useful when dealing with LOD's
// and similar switch nodes. If the sort value is the same, nodes
// will be arranged in the order they were added.
void reparent_to(const NodeChain &other, int sort = 0);
void wrt_reparent_to(const NodeChain &other, int sort = 0);
NodeChain instance_to(const NodeChain &other, int sort = 0) const;
NodeChain copy_to(const NodeChain &other, int sort = 0) const;
NodeChain attach_new_node(PandaNode *node, int sort = 0) const;
INLINE NodeChain attach_new_node(const string &name, int sort = 0) const;
void remove_node();
// Relative transform and state changes between nodes.
CPT(RenderState) get_rel_state(const NodeChain &other) const;
INLINE CPT(RenderState) get_net_state() const;
CPT(TransformState) get_rel_transform(const NodeChain &other) const;
INLINE CPT(TransformState) get_net_transform() const;
INLINE const LMatrix4f &get_mat(const NodeChain &other) const;
bool verify_complete() const;
public:
INLINE bool operator == (const NodeChain &other) const;
INLINE bool operator != (const NodeChain &other) const;
INLINE bool operator < (const NodeChain &other) const;
INLINE int compare_to(const NodeChain &other) const;
INLINE void output(ostream &out) const;
private:
void uncollapse_head() const;
static void find_common_ancestor(const NodeChain &a, const NodeChain &b,
int &a_count, int &b_count);
CPT(RenderState) r_get_net_state(NodeChainComponent *comp) const;
CPT(RenderState) r_get_partial_state(NodeChainComponent *comp, int n) const;
CPT(TransformState) r_get_net_transform(NodeChainComponent *comp) const;
CPT(TransformState) r_get_partial_transform(NodeChainComponent *comp, int n) const;
void r_output(ostream &out, NodeChainComponent *comp) const;
static int r_compare_to(const NodeChainComponent *a, const NodeChainComponent *v);
PT(NodeChainComponent) _head;
ErrorType _error_type;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
register_type(_type_handle, "NodeChain");
}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const NodeChain &node_chain);
#include "nodeChain.I"
#endif

View File

@ -271,6 +271,20 @@ get_attrib(TypeHandle type) const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::has_attrib
// Access: Published
// Description: Returns true if there is a render attribute of the
// indicated type defined on this node, or false if
// there is not.
////////////////////////////////////////////////////////////////////
INLINE bool PandaNode::
has_attrib(TypeHandle type) const {
CDReader cdata(_cycler);
int index = cdata->_state->find_attrib(type);
return (index >= 0);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::clear_attrib
// Access: Published
@ -370,17 +384,6 @@ clear_transform() {
cdata->_transform = TransformState::make_identity();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ls
// Access: Published
// Description: Lists all the nodes at and below the current path
// hierarchically.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
ls() const {
ls(nout);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::ls
// Access: Published

View File

@ -18,7 +18,7 @@
#include "pandaNode.h"
#include "config_pgraph.h"
#include "nodeChainComponent.h"
#include "qpnodePathComponent.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "indent.h"
@ -369,7 +369,7 @@ add_child(PandaNode *child_node, int sort) {
cdata->_down.insert(DownConnection(child_node, sort));
cdata_child->_up.insert(UpConnection(this));
// We also have to adjust any NodeChainComponents the child might
// 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.
@ -402,24 +402,24 @@ remove_child(int n) {
int num_erased = cdata_child->_up.erase(UpConnection(this));
nassertv(num_erased == 1);
// Now sever any NodeChainComponents on the child that reference
// Now sever any qpNodePathComponents on the child that reference
// this node. If we have multiple of these, we have to collapse
// them together.
NodeChainComponent *collapsed = (NodeChainComponent *)NULL;
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 == (NodeChainComponent *)NULL) {
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 NodeChains out there that
// 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);
@ -453,17 +453,17 @@ remove_child(PandaNode *child_node) {
return false;
}
// Now sever any NodeChainComponents on the child that reference
// 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).
NodeChainComponent *collapsed = (NodeChainComponent *)NULL;
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 == (NodeChainComponent *)NULL) {
if (collapsed == (qpNodePathComponent *)NULL) {
(*ci)->set_top_node();
collapsed = (*ci);
} else {
@ -506,17 +506,17 @@ remove_all_children() {
CDWriter cdata_child(child_node->_cycler);
cdata_child->_up.erase(UpConnection(this));
// Now sever any NodeChainComponents on the child that reference
// 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).
NodeChainComponent *collapsed = (NodeChainComponent *)NULL;
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 == (NodeChainComponent *)NULL) {
if (collapsed == (qpNodePathComponent *)NULL) {
(*ci)->set_top_node();
collapsed = (*ci);
} else {
@ -675,19 +675,19 @@ recompute_internal_bound() {
// Function: PandaNode::attach
// Access: Private, Static
// Description: Creates a new parent-child relationship, and returns
// the new NodeChainComponent. If the child was already
// the new qpNodePathComponent. If the child was already
// attached to the indicated parent, repositions it and
// returns the original NodeChainComponent.
// returns the original qpNodePathComponent.
////////////////////////////////////////////////////////////////////
PT(NodeChainComponent) PandaNode::
attach(NodeChainComponent *parent, PandaNode *child_node, int sort) {
nassertr(parent != (NodeChainComponent *)NULL, (NodeChainComponent *)NULL);
PT(qpNodePathComponent) PandaNode::
attach(qpNodePathComponent *parent, PandaNode *child_node, int sort) {
nassertr(parent != (qpNodePathComponent *)NULL, (qpNodePathComponent *)NULL);
// See if the child was already attached to the parent. If it was,
// we'll use that same NodeChainComponent.
PT(NodeChainComponent) child = get_component(parent, child_node);
// we'll use that same qpNodePathComponent.
PT(qpNodePathComponent) child = get_component(parent, child_node);
if (child == (NodeChainComponent *)NULL) {
if (child == (qpNodePathComponent *)NULL) {
// The child was not already attached to the parent, so get a new
// component.
child = get_top_component(child_node);
@ -703,13 +703,13 @@ attach(NodeChainComponent *parent, PandaNode *child_node, int sort) {
// Description: Breaks a parent-child relationship.
////////////////////////////////////////////////////////////////////
void PandaNode::
detach(NodeChainComponent *child) {
nassertv(child != (NodeChainComponent *)NULL);
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 NodeChainComponent connection.
// Break the qpNodePathComponent connection.
child->set_top_node();
CDWriter cdata_child(child_node->_cycler);
@ -762,15 +762,15 @@ detach(NodeChainComponent *child) {
// Description: Switches a node from one parent to another.
////////////////////////////////////////////////////////////////////
void PandaNode::
reparent(NodeChainComponent *new_parent, NodeChainComponent *child, int sort) {
nassertv(new_parent != (NodeChainComponent *)NULL);
nassertv(child != (NodeChainComponent *)NULL);
reparent(qpNodePathComponent *new_parent, qpNodePathComponent *child, int sort) {
nassertv(new_parent != (qpNodePathComponent *)NULL);
nassertv(child != (qpNodePathComponent *)NULL);
if (!child->is_top_node()) {
detach(child);
}
// Adjust the NodeChainComponents.
// Adjust the qpNodePathComponents.
child->set_next(new_parent);
PandaNode *child_node = child->get_node();
@ -790,19 +790,19 @@ reparent(NodeChainComponent *new_parent, NodeChainComponent *child, int sort) {
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_component
// Access: Private, Static
// Description: Returns the NodeChainComponent based on the indicated
// Description: Returns the qpNodePathComponent based on the indicated
// child of the given parent, or NULL if there is no
// such parent-child relationship.
////////////////////////////////////////////////////////////////////
PT(NodeChainComponent) PandaNode::
get_component(NodeChainComponent *parent, PandaNode *child_node) {
nassertr(parent != (NodeChainComponent *)NULL, (NodeChainComponent *)NULL);
PT(qpNodePathComponent) PandaNode::
get_component(qpNodePathComponent *parent, PandaNode *child_node) {
nassertr(parent != (qpNodePathComponent *)NULL, (qpNodePathComponent *)NULL);
PandaNode *parent_node = parent->get_node();
{
CDReader cdata_child(child_node->_cycler);
// First, walk through the list of NodeChainComponents we already
// First, walk through the list of qpNodePathComponents we already
// have on the child, looking for one that already exists,
// referencing the indicated parent component.
Chains::const_iterator ci;
@ -816,13 +816,13 @@ get_component(NodeChainComponent *parent, PandaNode *child_node) {
}
}
// We don't already have a NodeChainComponent referring to this
// We don't already have a qpNodePathComponent referring to this
// parent-child relationship. Are they actually related?
int child_index = child_node->find_parent(parent_node);
if (child_index >= 0) {
// They are. Create and return a new one.
PT(NodeChainComponent) child =
new NodeChainComponent(child_node, parent);
PT(qpNodePathComponent) child =
new qpNodePathComponent(child_node, parent);
CDWriter cdata_child(child_node->_cycler);
cdata_child->_chains.insert(child);
return child;
@ -835,18 +835,18 @@ get_component(NodeChainComponent *parent, PandaNode *child_node) {
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_top_component
// Access: Private, Static
// Description: Returns a NodeChainComponent referencing the
// Description: Returns a qpNodePathComponent referencing the
// indicated node as a singleton. It is invalid to call
// this for a node that has parents, unless you are
// about to create a new instance (and immediately
// reconnect the NodeChainComponent elsewhere).
// reconnect the qpNodePathComponent elsewhere).
////////////////////////////////////////////////////////////////////
PT(NodeChainComponent) PandaNode::
PT(qpNodePathComponent) PandaNode::
get_top_component(PandaNode *child_node) {
{
CDReader cdata_child(child_node->_cycler);
// Walk through the list of NodeChainComponents we already have on
// Walk through the list of qpNodePathComponents we already have on
// the child, looking for one that already exists as a top node.
Chains::const_iterator ci;
for (ci = cdata_child->_chains.begin();
@ -859,10 +859,10 @@ get_top_component(PandaNode *child_node) {
}
}
// We don't already have such a NodeChainComponent; create and
// We don't already have such a qpNodePathComponent; create and
// return a new one.
PT(NodeChainComponent) child =
new NodeChainComponent(child_node, (NodeChainComponent *)NULL);
PT(qpNodePathComponent) child =
new qpNodePathComponent(child_node, (qpNodePathComponent *)NULL);
CDWriter cdata_child(child_node->_cycler);
cdata_child->_chains.insert(child);
@ -872,13 +872,13 @@ get_top_component(PandaNode *child_node) {
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_generic_component
// Access: Private
// Description: Returns a NodeChainComponent referencing this node as
// Description: Returns a qpNodePathComponent referencing this node as
// a chain from the root. It is only valid to call this
// if there is an unambiguous path from the root;
// otherwise, a warning will be issued and one path will
// be chosen arbitrarily.
////////////////////////////////////////////////////////////////////
PT(NodeChainComponent) PandaNode::
PT(qpNodePathComponent) PandaNode::
get_generic_component() {
int num_parents = get_num_parents();
if (num_parents == 0) {
@ -890,7 +890,7 @@ get_generic_component() {
<< *this << " has " << num_parents
<< " parents; choosing arbitrary path to root.\n";
}
PT(NodeChainComponent) parent = get_parent(0)->get_generic_component();
PT(qpNodePathComponent) parent = get_parent(0)->get_generic_component();
return get_component(parent, this);
}
}
@ -898,12 +898,12 @@ get_generic_component() {
////////////////////////////////////////////////////////////////////
// Function: PandaNode::delete_component
// Access: Private
// Description: Removes a NodeChainComponent from the set prior to
// Description: Removes a qpNodePathComponent from the set prior to
// its deletion. This should only be called by the
// NodeChainComponent destructor.
// qpNodePathComponent destructor.
////////////////////////////////////////////////////////////////////
void PandaNode::
delete_component(NodeChainComponent *component) {
delete_component(qpNodePathComponent *component) {
// We have to remove the component from all of the pipeline stages,
// not just the current one.
int max_num_erased = 0;
@ -924,7 +924,7 @@ delete_component(NodeChainComponent *component) {
// Function: PandaNode::fix_chain_lengths
// Access: Private
// Description: Recursively fixes the _length member of each
// NodeChainComponent at this level and below, after an
// qpNodePathComponent at this level and below, after an
// add or delete child operation that might have messed
// these up.
////////////////////////////////////////////////////////////////////

View File

@ -37,7 +37,7 @@
#include "pointerTo.h"
#include "notify.h"
class NodeChainComponent;
class qpNodePathComponent;
class CullTraverserData;
////////////////////////////////////////////////////////////////////
@ -98,6 +98,7 @@ PUBLISHED:
INLINE void set_attrib(const RenderAttrib *attrib, int override = 0);
INLINE const RenderAttrib *get_attrib(TypeHandle type) const;
INLINE bool has_attrib(TypeHandle type) const;
INLINE void clear_attrib(TypeHandle type);
INLINE void set_state(const RenderState *state);
@ -111,8 +112,7 @@ PUBLISHED:
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
INLINE void ls() const;
INLINE void ls(ostream &out, int indent_level = 0) const;
INLINE void ls(ostream &out, int indent_level) const;
// A node has two bounding volumes: the BoundedObject it inherits
// from is the "external" bound and represnts the node and all of
@ -149,18 +149,18 @@ protected:
BoundedObject _internal_bound;
private:
// parent-child manipulation for NodeChain support. Don't try to
// parent-child manipulation for qpNodePath support. Don't try to
// call these directly.
static PT(NodeChainComponent) attach(NodeChainComponent *parent,
static PT(qpNodePathComponent) attach(qpNodePathComponent *parent,
PandaNode *child, int sort);
static void detach(NodeChainComponent *child);
static void reparent(NodeChainComponent *new_parent,
NodeChainComponent *child, int sort);
static PT(NodeChainComponent) get_component(NodeChainComponent *parent,
static void detach(qpNodePathComponent *child);
static void reparent(qpNodePathComponent *new_parent,
qpNodePathComponent *child, int sort);
static PT(qpNodePathComponent) get_component(qpNodePathComponent *parent,
PandaNode *child);
static PT(NodeChainComponent) get_top_component(PandaNode *child);
PT(NodeChainComponent) get_generic_component();
void delete_component(NodeChainComponent *component);
static PT(qpNodePathComponent) get_top_component(PandaNode *child);
PT(qpNodePathComponent) get_generic_component();
void delete_component(qpNodePathComponent *component);
void fix_chain_lengths();
void r_list_descendants(ostream &out, int indent_level) const;
@ -194,12 +194,12 @@ private:
};
typedef ov_set<UpConnection> Up;
// We also maintain a set of NodeChainComponents in the node. This
// We also maintain a set of qpNodePathComponents in the node. This
// represents the set of instances of this node that we have
// requested a NodeChain for. We don't keep reference counts; when
// each NodeChainComponent destructs, it removes itself from this
// requested a qpNodePath for. We don't keep reference counts; when
// each qpNodePathComponent destructs, it removes itself from this
// set.
typedef pset<NodeChainComponent *> Chains;
typedef pset<qpNodePathComponent *> Chains;
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
@ -271,8 +271,8 @@ private:
static TypeHandle _type_handle;
friend class PandaNode::Children;
friend class NodeChain;
friend class NodeChainComponent;
friend class qpNodePath;
friend class qpNodePathComponent;
};
INLINE ostream &operator << (ostream &out, const PandaNode &node) {

View File

@ -6,8 +6,9 @@
#include "qplensNode.cxx"
#include "qplodNode.cxx"
#include "materialAttrib.cxx"
#include "nodeChain.cxx"
#include "nodeChainComponent.cxx"
#include "qpnodePath.cxx"
#include "qpnodePathCollection.cxx"
#include "qpnodePathComponent.cxx"
#include "pandaNode.cxx"
#include "renderAttrib.cxx"
#include "renderState.cxx"

View File

@ -48,7 +48,7 @@ is_active() const {
// represent the root of any subgraph.
////////////////////////////////////////////////////////////////////
INLINE void qpCamera::
set_scene(const NodeChain &scene) {
set_scene(const qpNodePath &scene) {
_scene = scene;
}
@ -58,7 +58,7 @@ set_scene(const NodeChain &scene) {
// Description: Returns the scene that will be rendered by the
// camera. See set_scene().
////////////////////////////////////////////////////////////////////
INLINE const NodeChain &qpCamera::
INLINE const qpNodePath &qpCamera::
get_scene() const {
return _scene;
}

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
#include "qplensNode.h"
#include "nodeChain.h"
#include "qpnodePath.h"
class DisplayRegion;
@ -49,8 +49,8 @@ PUBLISHED:
INLINE void set_active(bool active);
INLINE bool is_active() const;
INLINE void set_scene(const NodeChain &scene);
INLINE const NodeChain &get_scene() const;
INLINE void set_scene(const qpNodePath &scene);
INLINE const qpNodePath &get_scene() const;
INLINE int get_num_display_regions() const;
INLINE DisplayRegion *get_display_region(int n) const;
@ -60,7 +60,7 @@ private:
void remove_display_region(DisplayRegion *display_region);
bool _active;
NodeChain _scene;
qpNodePath _scene;
typedef pvector<DisplayRegion *> DisplayRegions;
DisplayRegions _display_regions;

View File

@ -29,6 +29,7 @@
class PandaNode;
class CullHandler;
class CullTraverserData;
class CullableObject;
////////////////////////////////////////////////////////////////////
// Class : CullTraverser

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,427 @@
// Filename: qpnodePath.h
// Created by: drose (25Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef qpNODEPATH_H
#define qpNODEPATH_H
#include "pandabase.h"
#include "pandaNode.h"
#include "renderState.h"
#include "transformState.h"
#include "qpnodePathComponent.h"
#include "pointerTo.h"
#include "referenceCount.h"
#include "notify.h"
#include "typedObject.h"
class qpNodePathCollection;
class Texture;
class Material;
class Fog;
////////////////////////////////////////////////////////////////////
// Class : NodePath
// Description : NodePath is the fundamental system for disambiguating
// instances, and also provides a higher-level interface
// for manipulating the scene graph.
//
// A NodePath is a list of connected nodes from the root
// of the graph to any sub-node. Each NodePath
// therefore unqiuely describes one instance of a node.
//
// NodePaths themselves are lightweight objects that may
// easily be copied and passed by value. Their data is
// stored as a series of NodePathComponents that are
// stored on the nodes. Holding a NodePath will keep a
// reference count to all the nodes in the chain.
// However, if any node in the chain is removed or
// reparented (perhaps through a different NodePath),
// the NodePath will automatically be updated to reflect
// the changes.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpNodePath {
PUBLISHED:
// This enumeration is returned by get_error_type() for an empty
// qpNodePath to report the reason it's empty.
enum ErrorType {
ET_ok = 0, // i.e. not empty, or never assigned to anything.
ET_not_found, // returned from a failed find() or similar function.
ET_removed, // remove_node() was previously called on this qpNodePath.
ET_fail, // general failure return from some function.
};
INLINE qpNodePath();
INLINE qpNodePath(PandaNode *top_node);
INLINE qpNodePath(const qpNodePath &copy);
INLINE void operator = (const qpNodePath &copy);
INLINE static qpNodePath not_found();
INLINE static qpNodePath removed();
INLINE static qpNodePath fail();
// Methods to query a qpNodePath's contents.
INLINE bool is_empty() const;
INLINE bool is_singleton() const;
int get_num_nodes() const;
PandaNode *get_node(int index) const;
INLINE ErrorType get_error_type() const;
PandaNode *get_top_node() const;
INLINE PandaNode *node() const;
// Methods that return collections of NodePaths derived from or
// related to this one.
qpNodePathCollection get_children() const;
INLINE int get_num_children() const;
INLINE qpNodePath get_child(int n) const;
INLINE bool has_parent() const;
INLINE qpNodePath get_parent() const;
/*
INLINE qpNodePath find(const string &path) const;
qpNodePathCollection
find_all_matches(const string &path) const;
*/
// Methods that actually move nodes around in the scene graph. The
// optional "sort" parameter can be used to force a particular
// ordering between sibling nodes, useful when dealing with LOD's
// and similar switch nodes. If the sort value is the same, nodes
// will be arranged in the order they were added.
void reparent_to(const qpNodePath &other, int sort = 0);
void wrt_reparent_to(const qpNodePath &other, int sort = 0);
qpNodePath instance_to(const qpNodePath &other, int sort = 0) const;
qpNodePath copy_to(const qpNodePath &other, int sort = 0) const;
qpNodePath attach_new_node(PandaNode *node, int sort = 0) const;
INLINE qpNodePath attach_new_node(const string &name, int sort = 0) const;
void remove_node();
// Handy ways to look at what's there, and other miscellaneous
// operations.
INLINE void output(ostream &out) const;
INLINE void ls() const;
INLINE void ls(ostream &out, int indent_level = 0) const;
INLINE void ls_transitions() const;
INLINE void ls_transforms() const;
// Aggregate transform and state information.
INLINE CPT(RenderState) get_state() const;
INLINE void set_state(const RenderState *state) const;
CPT(RenderState) get_state(const qpNodePath &other) const;
void set_state(const qpNodePath &other, const RenderState *state) const;
INLINE CPT(RenderState) get_net_state() const;
INLINE CPT(TransformState) get_transform() const;
INLINE void set_transform(const TransformState *transform) const;
CPT(TransformState) get_transform(const qpNodePath &other) const;
void set_transform(const qpNodePath &other, const TransformState *transform) const;
INLINE CPT(TransformState) get_net_transform() const;
// Methods that get and set the matrix transform: pos, hpr, scale,
// in the local coordinate system.
INLINE void set_pos(float x, float y, float z);
void set_pos(const LVecBase3f &pos);
void set_x(float x);
void set_y(float y);
void set_z(float z);
LPoint3f get_pos() const;
INLINE float get_x() const;
INLINE float get_y() const;
INLINE float get_z() const;
INLINE void set_hpr(float h, float p, float r);
void set_hpr(const LVecBase3f &hpr);
void set_h(float h);
void set_p(float p);
void set_r(float r);
LVecBase3f get_hpr() const;
LVecBase3f get_hpr(float roll) const;
INLINE float get_h() const;
INLINE float get_p() const;
INLINE float get_r() const;
INLINE void set_scale(float scale);
INLINE void set_scale(float sx, float sy, float sz);
void set_scale(const LVecBase3f &sv3);
void set_sx(float sx);
void set_sy(float sy);
void set_sz(float sz);
LVecBase3f get_scale() const;
INLINE float get_sx() const;
INLINE float get_sy() const;
INLINE float get_sz() const;
INLINE void set_pos_hpr(float x, float y, float z,
float h, float p, float r);
void set_pos_hpr(const LVecBase3f &pos,
const LVecBase3f &hpr);
INLINE void set_hpr_scale(float h, float p, float r,
float sx, float sy, float sz);
void set_hpr_scale(const LVecBase3f &hpr,
const LVecBase3f &scale);
INLINE void set_pos_hpr_scale(float x, float y, float z,
float h, float p, float r,
float sx, float sy, float sz);
void set_pos_hpr_scale(const LVecBase3f &pos,
const LVecBase3f &hpr,
const LVecBase3f &scale);
void set_mat(const LMatrix4f &mat);
INLINE void clear_mat();
INLINE bool has_mat() const;
INLINE const LMatrix4f &get_mat() const;
INLINE bool has_color_scale() const;
INLINE void clear_color_scale();
void set_color_scale(const LVecBase4f &sv4);
INLINE void set_color_scale(float sx, float sy, float sz, float sa);
INLINE void set_sr(float sr);
INLINE void set_sg(float sg);
INLINE void set_sb(float sb);
INLINE void set_sa(float sa);
LVecBase4f get_color_scale() const;
INLINE float get_sr() const;
INLINE float get_sg() const;
INLINE float get_sb() const;
INLINE float get_sa() const;
INLINE void look_at(float x, float y, float z);
void look_at(const LPoint3f &point, const LVector3f &up = LVector3f::up());
INLINE void heads_up(float x, float y, float z);
void heads_up(const LPoint3f &point, const LVector3f &up = LVector3f::up());
INLINE void look_at_preserve_scale(float x, float y, float z);
void look_at_preserve_scale(const LPoint3f &point, const LVector3f &up = LVector3f::up());
INLINE void heads_up_preserve_scale(float x, float y, float z);
void heads_up_preserve_scale(const LPoint3f &point, const LVector3f &up = LVector3f::up());
// Methods that get and set the matrix transforms relative to some
// other node in the scene graph. These perform an implicit wrt().
INLINE void set_pos(const qpNodePath &other, float x, float y, float z);
void set_pos(const qpNodePath &other, const LVecBase3f &pos);
void set_x(const qpNodePath &other, float x);
void set_y(const qpNodePath &other, float y);
void set_z(const qpNodePath &other, float z);
INLINE LPoint3f get_pos(const qpNodePath &other) const;
INLINE float get_x(const qpNodePath &other) const;
INLINE float get_y(const qpNodePath &other) const;
INLINE float get_z(const qpNodePath &other) const;
INLINE void set_hpr(const qpNodePath &other, float h, float p, float r);
void set_hpr(const qpNodePath &other, const LVecBase3f &hpr);
void set_h(const qpNodePath &other, float h);
void set_p(const qpNodePath &other, float p);
void set_r(const qpNodePath &other, float r);
LVecBase3f get_hpr(const qpNodePath &other) const;
LVecBase3f get_hpr(const qpNodePath &other, float roll) const;
INLINE float get_h(const qpNodePath &other) const;
INLINE float get_p(const qpNodePath &other) const;
INLINE float get_r(const qpNodePath &other) const;
INLINE void set_scale(const qpNodePath &other, float sx, float sy, float sz);
void set_scale(const qpNodePath &other, const LVecBase3f &scale);
void set_sx(const qpNodePath &other, float sx);
void set_sy(const qpNodePath &other, float sy);
void set_sz(const qpNodePath &other, float sz);
LVecBase3f get_scale(const qpNodePath &other) const;
INLINE float get_sx(const qpNodePath &other) const;
INLINE float get_sy(const qpNodePath &other) const;
INLINE float get_sz(const qpNodePath &other) const;
INLINE void set_pos_hpr(const qpNodePath &other,
float x, float y, float z,
float h, float p, float r);
void set_pos_hpr(const qpNodePath &other,
const LVecBase3f &pos,
const LVecBase3f &hpr);
INLINE void set_hpr_scale(const qpNodePath &other,
float h, float p, float r,
float sx, float sy, float sz);
void set_hpr_scale(const qpNodePath &other,
const LVecBase3f &hpr,
const LVecBase3f &scale);
INLINE void set_pos_hpr_scale(const qpNodePath &other,
float x, float y, float z,
float h, float p, float r,
float sx, float sy, float sz);
void set_pos_hpr_scale(const qpNodePath &other,
const LVecBase3f &pos,
const LVecBase3f &hpr,
const LVecBase3f &scale);
const LMatrix4f &get_mat(const qpNodePath &other) const;
void set_mat(const qpNodePath &other, const LMatrix4f &mat);
LPoint3f get_relative_point(const qpNodePath &other, const LVecBase3f &point);
INLINE void look_at(const qpNodePath &other,
float x, float y, float z);
void look_at(const qpNodePath &other,
const LPoint3f &point = LPoint3f(0.0, 0.0, 0.0),
const LVector3f &up = LVector3f::up());
INLINE void heads_up(const qpNodePath &other,
float x, float y, float z);
void heads_up(const qpNodePath &other,
const LPoint3f &point = LPoint3f(0.0, 0.0, 0.0),
const LVector3f &up = LVector3f::up());
INLINE void look_at_preserve_scale(const qpNodePath &other,
float x, float y, float z);
void look_at_preserve_scale(const qpNodePath &other,
const LPoint3f &point = LPoint3f(0.0, 0.0, 0.0),
const LVector3f &up = LVector3f::up());
INLINE void heads_up_preserve_scale(const qpNodePath &other,
float x, float y, float z);
void heads_up_preserve_scale(const qpNodePath &other,
const LPoint3f &point = LPoint3f(0.0, 0.0, 0.0),
const LVector3f &up = LVector3f::up());
INLINE float get_distance(const qpNodePath &other) const;
// Methods that affect appearance of geometry: color, texture, etc.
// These affect the state at the bottom level only.
void set_color(float r, float g, float b, float a = 1.0,
int priority = 0);
void set_color(const Colorf &color, int priority = 0);
void set_color_off(int priority = 0);
void clear_color();
bool has_color() const;
Colorf get_color() const;
void set_bin(const string &bin_name, int draw_order, int priority = 0);
void clear_bin();
bool has_bin() const;
string get_bin_name() const;
int get_bin_draw_order() const;
void set_texture(Texture *tex, int priority = 0);
void set_texture_off(int priority = 0);
void clear_texture();
bool has_texture() const;
bool has_texture_off() const;
Texture *get_texture() const;
void set_material(Material *tex, int priority = 0);
void set_material_off(int priority = 0);
void clear_material();
bool has_material() const;
PT(Material) get_material() const;
void set_fog(Fog *fog, int priority = 0);
void set_fog_off(int priority = 0);
void clear_fog();
bool has_fog() const;
bool has_fog_off() const;
Fog *get_fog() const;
void set_render_mode_wireframe(int priority = 0);
void set_render_mode_filled(int priority = 0);
void clear_render_mode();
bool has_render_mode() const;
void set_two_sided(bool two_sided, int priority = 0);
void clear_two_sided();
bool has_two_sided() const;
bool get_two_sided() const;
void do_billboard_axis(const qpNodePath &camera, float offset);
void do_billboard_point_eye(const qpNodePath &camera, float offset);
void do_billboard_point_world(const qpNodePath &camera, float offset);
void set_billboard_axis(float offset = 0.0);
void set_billboard_point_eye(float offset = 0.0);
void set_billboard_point_world(float offset = 0.0);
void clear_billboard();
bool has_billboard() const;
void set_transparency(bool transparency, int priority = 0);
void clear_transparency();
bool has_transparency() const;
bool get_transparency() const;
INLINE void adjust_all_priorities(int adjustment);
// Variants on show and hide
INLINE void show();
INLINE void hide();
INLINE void show_collision_solids();
INLINE void hide_collision_solids();
INLINE bool is_hidden() const;
qpNodePath get_hidden_ancestor() const;
INLINE void stash();
INLINE void unstash();
INLINE bool is_stashed() const;
qpNodePath get_stashed_ancestor() const;
// Comparison methods
INLINE bool operator == (const qpNodePath &other) const;
INLINE bool operator != (const qpNodePath &other) const;
INLINE bool operator < (const qpNodePath &other) const;
INLINE int compare_to(const qpNodePath &other) const;
bool verify_complete() const;
private:
void uncollapse_head() const;
static void find_common_ancestor(const qpNodePath &a, const qpNodePath &b,
int &a_count, int &b_count);
CPT(RenderState) r_get_net_state(qpNodePathComponent *comp) const;
CPT(RenderState) r_get_partial_state(qpNodePathComponent *comp, int n) const;
CPT(TransformState) r_get_net_transform(qpNodePathComponent *comp) const;
CPT(TransformState) r_get_partial_transform(qpNodePathComponent *comp, int n) const;
void r_output(ostream &out, qpNodePathComponent *comp) const;
static int r_compare_to(const qpNodePathComponent *a, const qpNodePathComponent *v);
PT(qpNodePathComponent) _head;
ErrorType _error_type;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
register_type(_type_handle, "qpNodePath");
}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const qpNodePath &node_path);
#include "qpnodePath.I"
#endif

View File

@ -0,0 +1,38 @@
// Filename: qpnodePathCollection.I
// Created by: drose (06Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpNodePathCollection::
~qpNodePathCollection() {
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::ls
// Access: Published
// Description: Lists all the nodes at and below each node in the
// collection hierarchically.
////////////////////////////////////////////////////////////////////
INLINE void qpNodePathCollection::
ls() const {
ls(nout);
}

View File

@ -0,0 +1,397 @@
// Filename: qpnodePathCollection.cxx
// Created by: drose (06Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "qpnodePathCollection.h"
//#include "findApproxPath.h"
//#include "findApproxLevel.h"
#include "indent.h"
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpNodePathCollection::
qpNodePathCollection() {
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpNodePathCollection::
qpNodePathCollection(const qpNodePathCollection &copy) :
_node_paths(copy._node_paths)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
operator = (const qpNodePathCollection &copy) {
_node_paths = copy._node_paths;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::add_path
// Access: Published
// Description: Adds a new qpNodePath to the collection.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
add_path(const qpNodePath &node_path) {
// If the pointer to our internal array is shared by any other
// NodePathCollections, we have to copy the array now so we won't
// inadvertently modify any of our brethren NodePathCollection
// objects.
if (_node_paths.get_ref_count() > 1) {
PTA(qpNodePath) old_node_paths = _node_paths;
_node_paths = PTA(qpNodePath)::empty_array(0);
_node_paths.v() = old_node_paths.v();
}
_node_paths.push_back(node_path);
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::remove_path
// Access: Published
// Description: Removes the indicated qpNodePath from the collection.
// Returns true if the path was removed, false if it was
// not a member of the collection.
////////////////////////////////////////////////////////////////////
bool qpNodePathCollection::
remove_path(const qpNodePath &node_path) {
int path_index = -1;
for (int i = 0; path_index == -1 && i < (int)_node_paths.size(); i++) {
if (_node_paths[i] == node_path) {
path_index = i;
}
}
if (path_index == -1) {
// The indicated path was not a member of the collection.
return false;
}
// If the pointer to our internal array is shared by any other
// NodePathCollections, we have to copy the array now so we won't
// inadvertently modify any of our brethren NodePathCollection
// objects.
if (_node_paths.get_ref_count() > 1) {
PTA(qpNodePath) old_node_paths = _node_paths;
_node_paths = PTA(qpNodePath)::empty_array(0);
_node_paths.v() = old_node_paths.v();
}
_node_paths.erase(_node_paths.begin() + path_index);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::add_paths_from
// Access: Published
// Description: Adds all the qpNodePaths indicated in the other
// collection to this path. The other paths are simply
// appended to the end of the paths in this list;
// duplicates are not automatically removed.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
add_paths_from(const qpNodePathCollection &other) {
int other_num_paths = other.get_num_paths();
for (int i = 0; i < other_num_paths; i++) {
add_path(other.get_path(i));
}
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::remove_paths_from
// Access: Published
// Description: Removes from this collection all of the qpNodePaths
// listed in the other collection.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
remove_paths_from(const qpNodePathCollection &other) {
NodePaths new_paths;
int num_paths = get_num_paths();
for (int i = 0; i < num_paths; i++) {
qpNodePath path = get_path(i);
if (!other.has_path(path)) {
new_paths.push_back(path);
}
}
_node_paths = new_paths;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::remove_duplicate_paths
// Access: Published
// Description: Removes any duplicate entries of the same NodePaths
// on this collection. If a qpNodePath appears multiple
// times, the first appearance is retained; subsequent
// appearances are removed.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
remove_duplicate_paths() {
NodePaths new_paths;
int num_paths = get_num_paths();
for (int i = 0; i < num_paths; i++) {
qpNodePath path = get_path(i);
bool duplicated = false;
for (int j = 0; j < i && !duplicated; j++) {
duplicated = (path == get_path(j));
}
if (!duplicated) {
new_paths.push_back(path);
}
}
_node_paths = new_paths;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::has_path
// Access: Published
// Description: Returns true if the indicated qpNodePath appears in
// this collection, false otherwise.
////////////////////////////////////////////////////////////////////
bool qpNodePathCollection::
has_path(const qpNodePath &path) const {
for (int i = 0; i < get_num_paths(); i++) {
if (path == get_path(i)) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::clear
// Access: Published
// Description: Removes all NodePaths from the collection.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
clear() {
_node_paths.clear();
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::is_empty
// Access: Published
// Description: Returns true if there are no NodePaths in the
// collection, false otherwise.
////////////////////////////////////////////////////////////////////
bool qpNodePathCollection::
is_empty() const {
return _node_paths.empty();
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::get_num_paths
// Access: Published
// Description: Returns the number of NodePaths in the collection.
////////////////////////////////////////////////////////////////////
int qpNodePathCollection::
get_num_paths() const {
return _node_paths.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::get_path
// Access: Published
// Description: Returns the nth qpNodePath in the collection.
////////////////////////////////////////////////////////////////////
qpNodePath qpNodePathCollection::
get_path(int index) const {
nassertr(index >= 0 && index < (int)_node_paths.size(), qpNodePath());
return _node_paths[index];
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::operator []
// Access: Published
// Description: Returns the nth qpNodePath in the collection. This is
// the same as get_path(), but it may be a more
// convenient way to access it.
////////////////////////////////////////////////////////////////////
qpNodePath qpNodePathCollection::
operator [] (int index) const {
nassertr(index >= 0 && index < (int)_node_paths.size(), qpNodePath());
return _node_paths[index];
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::ls
// Access: Published
// Description: Lists all the nodes at and below each node in the
// collection hierarchically.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
ls(ostream &out, int indent_level) const {
for (int i = 0; i < get_num_paths(); i++) {
qpNodePath path = get_path(i);
indent(out, indent_level) << path << "\n";
path.ls(out, indent_level + 2);
out << "\n";
}
}
/*
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::find_all_matches
// Access: Published
// Description: Returns the complete set of all NodePaths that begin
// with any qpNodePath in this collection and can be
// extended by path. The shortest paths will be listed
// first.
////////////////////////////////////////////////////////////////////
qpNodePathCollection qpNodePathCollection::
find_all_matches(const string &path) const {
qpNodePathCollection result;
FindApproxPath approx_path;
if (approx_path.add_string(path)) {
if (!is_empty()) {
FindApproxLevel level;
for (int i = 0; i < get_num_paths(); i++) {
FindApproxLevelEntry start(get_path(i), approx_path);
level.add_entry(start);
}
get_path(0).r_find_matches(result, level, -1,
qpNodePath::get_max_search_depth());
}
}
return result;
}
*/
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::reparent_to
// Access: Published
// Description: Reparents all the NodePaths in the collection to the
// indicated node.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
reparent_to(const qpNodePath &other) {
for (int i = 0; i < get_num_paths(); i++) {
get_path(i).reparent_to(other);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::wrt_reparent_to
// Access: Published
// Description: Reparents all the NodePaths in the collection to the
// indicated node, adjusting each transform so as not to
// move in world coordinates.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
wrt_reparent_to(const qpNodePath &other) {
for (int i = 0; i < get_num_paths(); i++) {
get_path(i).wrt_reparent_to(other);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::show
// Access: Published
// Description: Shows all NodePaths in the collection.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
show() {
for (int i = 0; i < get_num_paths(); i++) {
get_path(i).show();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::show
// Access: Published
// Description: Hides all NodePaths in the collection.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
hide() {
for (int i = 0; i < get_num_paths(); i++) {
get_path(i).hide();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::stash
// Access: Published
// Description: Stashes all NodePaths in the collection.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
stash() {
for (int i = 0; i < get_num_paths(); i++) {
get_path(i).stash();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::unstash
// Access: Published
// Description: Unstashes all NodePaths in the collection.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
unstash() {
for (int i = 0; i < get_num_paths(); i++) {
get_path(i).unstash();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::output
// Access: Published
// Description: Writes a brief one-line description of the
// qpNodePathCollection to the indicated output stream.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
output(ostream &out) const {
if (get_num_paths() == 1) {
out << "1 NodePath";
} else {
out << get_num_paths() << " NodePaths";
}
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePathCollection::write
// Access: Published
// Description: Writes a complete multi-line description of the
// qpNodePathCollection to the indicated output stream.
////////////////////////////////////////////////////////////////////
void qpNodePathCollection::
write(ostream &out, int indent_level) const {
for (int i = 0; i < get_num_paths(); i++) {
indent(out, indent_level) << get_path(i) << "\n";
}
}

View File

@ -0,0 +1,83 @@
// Filename: qpnodePathCollection.h
// Created by: drose (06Mar02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef qpNODEPATHCOLLECTION_H
#define qpNODEPATHCOLLECTION_H
#include "pandabase.h"
#include "qpnodePath.h"
#include "pointerToArray.h"
////////////////////////////////////////////////////////////////////
// Class : NodePathCollection
// Description : This is a set of zero or more NodePaths. It's handy
// for returning from functions that need to return
// multiple NodePaths (for instance,
// NodePaths::get_children).
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpNodePathCollection {
PUBLISHED:
qpNodePathCollection();
qpNodePathCollection(const qpNodePathCollection &copy);
void operator = (const qpNodePathCollection &copy);
INLINE ~qpNodePathCollection();
void add_path(const qpNodePath &node_path);
bool remove_path(const qpNodePath &node_path);
void add_paths_from(const qpNodePathCollection &other);
void remove_paths_from(const qpNodePathCollection &other);
void remove_duplicate_paths();
bool has_path(const qpNodePath &path) const;
void clear();
bool is_empty() const;
int get_num_paths() const;
qpNodePath get_path(int index) const;
qpNodePath operator [] (int index) const;
// Handy operations on many NodePaths at once.
INLINE void ls() const;
void ls(ostream &out, int indent_level = 0) const;
// qpNodePathCollection find_all_matches(const string &path) const;
void reparent_to(const qpNodePath &other);
void wrt_reparent_to(const qpNodePath &other);
void show();
void hide();
void stash();
void unstash();
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
private:
typedef PTA(qpNodePath) NodePaths;
NodePaths _node_paths;
};
INLINE ostream &operator << (ostream &out, const qpNodePathCollection &col) {
col.output(out);
return out;
}
#include "qpnodePathCollection.I"
#endif

View File

@ -1,4 +1,4 @@
// Filename: nodeChainComponent.I
// Filename: qpnodePathComponent.I
// Created by: drose (25Feb02)
//
////////////////////////////////////////////////////////////////////
@ -18,36 +18,36 @@
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::CData::Constructor
// Function: qpNodePathComponent::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE NodeChainComponent::CData::
INLINE qpNodePathComponent::CData::
CData() {
_length = 1;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::CData::Copy Constructor
// Function: qpNodePathComponent::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE NodeChainComponent::CData::
CData(const NodeChainComponent::CData &copy) :
INLINE qpNodePathComponent::CData::
CData(const qpNodePathComponent::CData &copy) :
_next(copy._next),
_length(copy._length)
{
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::Constructor
// Function: qpNodePathComponent::Constructor
// Access: Private
// Description: Constructs a new NodeChainComponent from the
// Description: Constructs a new qpNodePathComponent from the
// indicated node. Don't try to call this directly; ask
// the PandaNode to do it for you.
////////////////////////////////////////////////////////////////////
INLINE NodeChainComponent::
NodeChainComponent(PandaNode *node, NodeChainComponent *next) :
INLINE qpNodePathComponent::
qpNodePathComponent(PandaNode *node, qpNodePathComponent *next) :
_node(node)
{
#ifdef DO_MEMORY_USAGE
@ -56,85 +56,85 @@ NodeChainComponent(PandaNode *node, NodeChainComponent *next) :
CDWriter cdata(_cycler);
cdata->_next = next;
if (next != (NodeChainComponent *)NULL) {
if (next != (qpNodePathComponent *)NULL) {
cdata->_length = next->get_length() + 1;
}
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::Copy Constructor
// Function: qpNodePathComponent::Copy Constructor
// Access: Private
// Description: NodeChainComponents should not be copied.
// Description: qpNodePathComponents should not be copied.
////////////////////////////////////////////////////////////////////
INLINE NodeChainComponent::
NodeChainComponent(const NodeChainComponent &copy) {
INLINE qpNodePathComponent::
qpNodePathComponent(const qpNodePathComponent &copy) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::Copy Assignment Operator
// Function: qpNodePathComponent::Copy Assignment Operator
// Access: Private
// Description: NodeChainComponents should not be copied.
// Description: qpNodePathComponents should not be copied.
////////////////////////////////////////////////////////////////////
INLINE void NodeChainComponent::
operator = (const NodeChainComponent &copy) {
INLINE void qpNodePathComponent::
operator = (const qpNodePathComponent &copy) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::Destructor
// Function: qpNodePathComponent::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE NodeChainComponent::
~NodeChainComponent() {
INLINE qpNodePathComponent::
~qpNodePathComponent() {
nassertv(_node != (PandaNode *)NULL);
_node->delete_component(this);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::get_node
// Function: qpNodePathComponent::get_node
// Access: Public
// Description: Returns the node referenced by this component.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *NodeChainComponent::
INLINE PandaNode *qpNodePathComponent::
get_node() const {
return _node;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::is_top_node
// Function: qpNodePathComponent::is_top_node
// Access: Public
// Description: Returns true if this component represents the top
// node in the chain.
////////////////////////////////////////////////////////////////////
INLINE bool NodeChainComponent::
INLINE bool qpNodePathComponent::
is_top_node() const {
CDReader cdata(_cycler);
return (cdata->_next == (NodeChainComponent *)NULL);
return (cdata->_next == (qpNodePathComponent *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::is_collapsed
// Function: qpNodePathComponent::is_collapsed
// Access: Public
// Description: Returns true if this component has been collapsed
// with another component. In this case, the component
// itself is invalid, and the collapsed component should
// be used instead.
////////////////////////////////////////////////////////////////////
INLINE bool NodeChainComponent::
INLINE bool qpNodePathComponent::
is_collapsed() const {
CDReader cdata(_cycler);
return (cdata->_length == 0);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::get_length
// Function: qpNodePathComponent::get_length
// Access: Public
// Description: Returns the length of the chain.
////////////////////////////////////////////////////////////////////
INLINE int NodeChainComponent::
INLINE int qpNodePathComponent::
get_length() const {
CDReader cdata(_cycler);
nassertr(!is_collapsed(), 0);
@ -142,59 +142,59 @@ get_length() const {
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::get_collapsed
// Function: qpNodePathComponent::get_collapsed
// Access: Public
// Description: If is_collapsed() returns true, this is the component
// that this one has been collapsed with, and should be
// replaced with.
////////////////////////////////////////////////////////////////////
INLINE NodeChainComponent *NodeChainComponent::
INLINE qpNodePathComponent *qpNodePathComponent::
get_collapsed() const {
CDReader cdata(_cycler);
nassertr(is_collapsed(), (NodeChainComponent *)NULL);
nassertr(is_collapsed(), (qpNodePathComponent *)NULL);
return cdata->_next;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::set_next
// Function: qpNodePathComponent::set_next
// Access: Private
// Description: Sets the next pointer in the chain.
////////////////////////////////////////////////////////////////////
INLINE void NodeChainComponent::
set_next(NodeChainComponent *next) {
INLINE void qpNodePathComponent::
set_next(qpNodePathComponent *next) {
CDWriter cdata(_cycler);
nassertv(!is_collapsed());
nassertv(next != (NodeChainComponent *)NULL);
nassertv(next != (qpNodePathComponent *)NULL);
cdata->_next = next;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::set_top_node
// Function: qpNodePathComponent::set_top_node
// Access: Private
// Description: Severs any connection to the next pointer in the
// chain and makes this component a top node.
////////////////////////////////////////////////////////////////////
INLINE void NodeChainComponent::
INLINE void qpNodePathComponent::
set_top_node() {
CDWriter cdata(_cycler);
nassertv(!is_collapsed());
cdata->_next = (NodeChainComponent *)NULL;
cdata->_next = (qpNodePathComponent *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::collapse_with
// Function: qpNodePathComponent::collapse_with
// Access: Private
// Description: Indicates that this component pointer is no longer
// valid, and that the indicated component should be
// used instead. This is done whenever two
// NodeChainComponents have been collapsed together due
// qpNodePathComponents have been collapsed together due
// to an instance being removed higher up in the graph.
////////////////////////////////////////////////////////////////////
INLINE void NodeChainComponent::
collapse_with(NodeChainComponent *next) {
INLINE void qpNodePathComponent::
collapse_with(qpNodePathComponent *next) {
CDWriter cdata(_cycler);
nassertv(!is_collapsed());
nassertv(next != (NodeChainComponent *)NULL);
nassertv(next != (qpNodePathComponent *)NULL);
cdata->_next = next;
cdata->_length = 0;

View File

@ -1,4 +1,4 @@
// Filename: nodeChainComponent.cxx
// Filename: qpnodePathComponent.cxx
// Created by: drose (25Feb02)
//
////////////////////////////////////////////////////////////////////
@ -16,54 +16,54 @@
//
////////////////////////////////////////////////////////////////////
#include "nodeChainComponent.h"
#include "qpnodePathComponent.h"
TypeHandle NodeChainComponent::_type_handle;
TypeHandle qpNodePathComponent::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::CData::make_copy
// Function: qpNodePathComponent::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *NodeChainComponent::CData::
CycleData *qpNodePathComponent::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::get_next
// Function: qpNodePathComponent::get_next
// Access: Public
// Description: Returns the next component in the chain.
////////////////////////////////////////////////////////////////////
NodeChainComponent *NodeChainComponent::
qpNodePathComponent *qpNodePathComponent::
get_next() const {
CDReader cdata(_cycler);
nassertr(!is_collapsed(), (NodeChainComponent *)NULL);
nassertr(!is_collapsed(), (qpNodePathComponent *)NULL);
NodeChainComponent *next = cdata->_next;
qpNodePathComponent *next = cdata->_next;
// If the next component has been collapsed, transparently update
// the pointer to get the actual node, and store the new pointer,
// before we return. Collapsing can happen at any time to any
// component in the chain and we have to deal with it.
if (next != (NodeChainComponent *)NULL && next->is_collapsed()) {
if (next != (qpNodePathComponent *)NULL && next->is_collapsed()) {
next = next->uncollapse();
((NodeChainComponent *)this)->set_next(next);
((qpNodePathComponent *)this)->set_next(next);
}
return next;
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::fix_length
// Function: qpNodePathComponent::fix_length
// Access: Public
// Description: Checks that the length indicated by the component is
// one more than the length of its predecessor. If this
// is broken, fixes it and returns true indicating the
// component has been changed; otherwise, returns false.
////////////////////////////////////////////////////////////////////
bool NodeChainComponent::
bool qpNodePathComponent::
fix_length() {
int length_should_be = 1;
if (!is_top_node()) {
@ -79,7 +79,7 @@ fix_length() {
}
////////////////////////////////////////////////////////////////////
// Function: NodeChainComponent::uncollapse
// Function: qpNodePathComponent::uncollapse
// Access: Public
// Description: Returns this component pointer if the component is
// not collapsed; or if it has been collapsed, returns
@ -90,9 +90,9 @@ fix_length() {
// when a node is removed further up the chain that
// results in two instances becoming the same thing.
////////////////////////////////////////////////////////////////////
NodeChainComponent *NodeChainComponent::
qpNodePathComponent *qpNodePathComponent::
uncollapse() {
NodeChainComponent *comp = this;
qpNodePathComponent *comp = this;
while (comp->is_collapsed()) {
comp = comp->get_collapsed();

View File

@ -1,4 +1,4 @@
// Filename: nodeChainComponent.h
// Filename: qpnodePathComponent.h
// Created by: drose (25Feb02)
//
////////////////////////////////////////////////////////////////////
@ -16,8 +16,8 @@
//
////////////////////////////////////////////////////////////////////
#ifndef NODECHAINCOMPONENT_H
#define NODECHAINCOMPONENT_H
#ifndef qpNODEPATHCOMPONENT_H
#define qpNODEPATHCOMPONENT_H
#include "pandabase.h"
@ -29,45 +29,45 @@
#include "cycleDataWriter.h"
////////////////////////////////////////////////////////////////////
// Class : NodeChainComponent
// Description : This is one component of a NodeChain. These are
// Class : qpNodePathComponent
// Description : This is one component of a NodePath. These are
// stored on each PandaNode, as many as one for each of
// the possible instances of the node (but they only
// exist when they are requested, to minimize memory
// waste). A NodeChain represents a singly-linked list
// waste). A NodePath represents a singly-linked list
// of these from an arbitrary component in the graph to
// the root.
//
// This whole NodeChain system is used to disambiguate
// This whole NodePath system is used to disambiguate
// instances in the scene graph, and the
// NodeChainComponents are stored in the nodes
// themselves to allow the nodes to keep these up to
// date as the scene graph is manipulated.
// NodePathComponents are stored in the nodes themselves
// to allow the nodes to keep these up to date as the
// scene graph is manipulated.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA NodeChainComponent : public ReferenceCount {
class EXPCL_PANDA qpNodePathComponent : public ReferenceCount {
private:
INLINE NodeChainComponent(PandaNode *node, NodeChainComponent *next = NULL);
INLINE NodeChainComponent(const NodeChainComponent &copy);
INLINE void operator = (const NodeChainComponent &copy);
INLINE qpNodePathComponent(PandaNode *node, qpNodePathComponent *next = NULL);
INLINE qpNodePathComponent(const qpNodePathComponent &copy);
INLINE void operator = (const qpNodePathComponent &copy);
public:
INLINE ~NodeChainComponent();
INLINE ~qpNodePathComponent();
INLINE PandaNode *get_node() const;
INLINE bool is_top_node() const;
INLINE bool is_collapsed() const;
NodeChainComponent *get_next() const;
qpNodePathComponent *get_next() const;
INLINE int get_length() const;
INLINE NodeChainComponent *get_collapsed() const;
INLINE qpNodePathComponent *get_collapsed() const;
bool fix_length();
NodeChainComponent *uncollapse();
qpNodePathComponent *uncollapse();
private:
INLINE void set_next(NodeChainComponent *next);
INLINE void set_next(qpNodePathComponent *next);
INLINE void set_top_node();
INLINE void collapse_with(NodeChainComponent *next);
INLINE void collapse_with(qpNodePathComponent *next);
PT(PandaNode) _node;
@ -78,7 +78,7 @@ private:
CData(const CData &copy);
virtual CycleData *make_copy() const;
PT(NodeChainComponent) _next;
PT(qpNodePathComponent) _next;
int _length;
};
@ -92,7 +92,7 @@ public:
}
static void init_type() {
ReferenceCount::init_type();
register_type(_type_handle, "NodeChainComponent",
register_type(_type_handle, "qpNodePathComponent",
ReferenceCount::get_class_type());
}
@ -101,6 +101,6 @@ private:
friend class PandaNode;
};
#include "nodeChainComponent.I"
#include "qpnodePathComponent.I"
#endif

View File

@ -17,7 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "pandaNode.h"
#include "nodeChain.h"
#include "qpnodePath.h"
#include "textureAttrib.h"
#include "colorAttrib.h"
#include "transformState.h"
@ -74,20 +74,20 @@ main(int argc, char *argv[]) {
cerr << "\n";
list_hierarchy(root, 0);
NodeChain ch_g1(g1);
qpNodePath ch_g1(g1);
cerr << ch_g1 << "\n";
NodeChain ch_g2(g2);
qpNodePath ch_g2(g2);
cerr << ch_g2 << "\n";
cerr << *ch_g1.get_rel_transform(ch_g2) << "\n";
cerr << *ch_g2.get_rel_transform(ch_g1) << "\n";
cerr << *ch_g1.get_transform(ch_g2) << "\n";
cerr << *ch_g2.get_transform(ch_g1) << "\n";
cerr << *ch_g1.get_rel_state(ch_g2) << "\n";
cerr << *ch_g2.get_rel_state(ch_g1) << "\n";
cerr << *ch_g1.get_state(ch_g2) << "\n";
cerr << *ch_g2.get_state(ch_g1) << "\n";
cerr << *ch_g2.get_rel_transform(ch_g2) << "\n";
cerr << *ch_g2.get_rel_state(ch_g2) << "\n";
cerr << *ch_g2.get_transform(ch_g2) << "\n";
cerr << *ch_g2.get_state(ch_g2) << "\n";
cerr << "\n";
return 0;

View File

@ -128,17 +128,52 @@ has_components() const {
return ((_flags & F_has_components) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::has_pos
// Access: Published
// Description: Returns true if the transform's pos component can be
// extracted out separately. This is generally always
// true.
////////////////////////////////////////////////////////////////////
INLINE bool TransformState::
has_pos() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::has_hpr
// Access: Published
// Description: Returns true if the transform's rotation component
// can be extracted out separately and described as a
// set of Euler angles. This is generally true only
// when has_components() is true.
////////////////////////////////////////////////////////////////////
INLINE bool TransformState::
has_hpr() const {
return has_components();
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::has_scale
// Access: Published
// Description: Returns true if the transform's scale component
// can be extracted out separately. This is generally
// true only when has_components() is true.
////////////////////////////////////////////////////////////////////
INLINE bool TransformState::
has_scale() const {
return has_components();
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_pos
// Access: Published
// Description: Returns the pos component of the transform. It is an
// error to call this if has_components() returned
// false.
// error to call this if has_pos() returned false.
////////////////////////////////////////////////////////////////////
INLINE const LVecBase3f &TransformState::
get_pos() const {
check_components();
nassertr(has_components(), _pos);
return _pos;
}
@ -152,7 +187,7 @@ get_pos() const {
INLINE const LVecBase3f &TransformState::
get_hpr() const {
check_components();
nassertr(has_components(), _hpr);
nassertr(has_hpr(), _hpr);
return _hpr;
}
@ -166,7 +201,7 @@ get_hpr() const {
INLINE const LVecBase3f &TransformState::
get_scale() const {
check_components();
nassertr(has_components(), _scale);
nassertr(has_scale(), _scale);
return _scale;
}

View File

@ -238,6 +238,54 @@ make_mat(const LMatrix4f &mat) {
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::set_pos
// Access: Published
// Description: Returns a new TransformState object that represents the
// original TransformState with its pos component
// replaced with the indicated value.
////////////////////////////////////////////////////////////////////
CPT(TransformState) TransformState::
set_pos(const LVecBase3f &pos) const {
if ((_flags & F_components_given) != 0) {
// If we started with a componentwise transform, we keep it that
// way.
return make_pos_hpr_scale(pos, get_hpr(), get_scale());
} else {
// Otherwise, we have a matrix transform, and we keep it that way.
LMatrix4f mat = get_mat();
mat.set_row(3, pos);
return make_mat(mat);
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::set_hpr
// Access: Published
// Description: Returns a new TransformState object that represents the
// original TransformState with its hpr component
// replaced with the indicated value, if possible.
////////////////////////////////////////////////////////////////////
CPT(TransformState) TransformState::
set_hpr(const LVecBase3f &hpr) const {
nassertr(has_components(), this);
return make_pos_hpr_scale(get_pos(), hpr, get_scale());
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::set_scale
// Access: Published
// Description: Returns a new TransformState object that represents the
// original TransformState with its scale component
// replaced with the indicated value, if possible.
////////////////////////////////////////////////////////////////////
CPT(TransformState) TransformState::
set_scale(const LVecBase3f &scale) const {
nassertr(has_components(), this);
return make_pos_hpr_scale(get_pos(), get_scale(), get_hpr());
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::compose
// Access: Published
@ -532,10 +580,14 @@ calc_components() {
// other explanation is that we were constructed via a matrix.
nassertv((_flags & F_mat_known) != 0);
bool possible = decompose_matrix(get_mat(), _scale, _hpr, _pos);
const LMatrix4f &mat = get_mat();
bool possible = decompose_matrix(mat, _scale, _hpr, _pos);
if (possible) {
// Some matrices can't be decomposed into scale, hpr, pos.
_flags |= F_has_components;
// However, we can always get at least the pos.
mat.get_row3(_pos, 3);
}
}

View File

@ -80,11 +80,18 @@ PUBLISHED:
INLINE bool is_identity() const;
INLINE bool is_singular() const;
INLINE bool has_components() const;
INLINE bool has_pos() const;
INLINE bool has_hpr() const;
INLINE bool has_scale() const;
INLINE const LVecBase3f &get_pos() const;
INLINE const LVecBase3f &get_hpr() const;
INLINE const LVecBase3f &get_scale() const;
INLINE const LMatrix4f &get_mat() const;
CPT(TransformState) set_pos(const LVecBase3f &pos) const;
CPT(TransformState) set_hpr(const LVecBase3f &hpr) const;
CPT(TransformState) set_scale(const LVecBase3f &scale) const;
CPT(TransformState) compose(const TransformState *other) const;
CPT(TransformState) invert_compose(const TransformState *other) const;

View File

@ -144,7 +144,7 @@ make_camera(GraphicsWindow *window) {
PT(Lens) lens = new PerspectiveLens;
lens->set_film_size(win_width, win_height);
camera->set_lens(lens);
dr->set_qpcamera(NodeChain(camera));
dr->set_qpcamera(qpNodePath(camera));
return camera;
}
@ -216,7 +216,7 @@ get_models(PandaNode *parent, int argc, char *argv[]) {
cerr << "Unable to load " << filename << "\n";
} else {
node->ls();
node->ls(cerr, 0);
parent->add_child(node);
}
}
@ -277,7 +277,7 @@ main(int argc, char *argv[]) {
// Now we just need to make a scene graph for the camera to render.
PT(PandaNode) render = new PandaNode("render");
render->add_child(camera);
camera->set_scene(NodeChain(render));
camera->set_scene(qpNodePath(render));
// Set up a data graph for tracking user input. For now, this uses
// the old-style graph interface.