// Filename: nodePath.I // Created by: drose (25Feb02) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // Function: NodePath::Default Constructor // Access: Published // Description: This constructs an empty NodePath with no nodes. //////////////////////////////////////////////////////////////////// INLINE NodePath:: NodePath() : _error_type(ET_ok) { _backup_key = 0; } //////////////////////////////////////////////////////////////////// // Function: NodePath::Constructor // Access: Published // Description: This constructs a new NodePath with a single // node. An ordinary, unattached PandaNode is created // with the indicated name. //////////////////////////////////////////////////////////////////// INLINE NodePath:: NodePath(const string &top_node_name, Thread *current_thread) : _error_type(ET_ok) { PandaNode *top_node = new PandaNode(top_node_name); int pipeline_stage = current_thread->get_pipeline_stage(); _head = top_node->get_generic_component(false, pipeline_stage, current_thread); _backup_key = 0; } //////////////////////////////////////////////////////////////////// // Function: NodePath::Constructor // Access: Published // Description: This constructs a NodePath for the indicated node. // If the node does not have any parents, this creates a // singleton NodePath; otherwise, it automatically finds // the path from the node to the root. If the node has // multiple paths to the root, one path is chosen // arbitrarily and a warning message is printed (but see // also NodePath::any_path(), below). //////////////////////////////////////////////////////////////////// INLINE NodePath:: NodePath(PandaNode *node, Thread *current_thread) : _error_type(ET_ok) { if (node != (PandaNode *)NULL) { int pipeline_stage = current_thread->get_pipeline_stage(); _head = node->get_generic_component(false, pipeline_stage, current_thread); } _backup_key = 0; } //////////////////////////////////////////////////////////////////// // Function: NodePath::any_path named constructor // Access: Published, Static // Description: Returns a new NodePath that represents any arbitrary // path from the root to the indicated node. This is // the same thing that would be returned by // NodePath(node), except that no warning is issued if // the path is ambiguous. //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: any_path(PandaNode *node, Thread *current_thread) { NodePath result; if (node != (PandaNode *)NULL) { int pipeline_stage = current_thread->get_pipeline_stage(); result._head = node->get_generic_component(true, pipeline_stage, current_thread); } return result; } //////////////////////////////////////////////////////////////////// // Function: NodePath::Copy Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE NodePath:: NodePath(const NodePath ©) : _head(copy._head), _backup_key(copy._backup_key), _error_type(copy._error_type) { } //////////////////////////////////////////////////////////////////// // Function: NodePath::Copy Assignment Operator // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE void NodePath:: operator = (const NodePath ©) { _head = copy._head; _backup_key = copy._backup_key; _error_type = copy._error_type; } //////////////////////////////////////////////////////////////////// // Function: NodePath::not_found named constructor // Access: Published, Static // Description: Creates a NodePath with the ET_not_found error type // set. //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: not_found() { NodePath result; result._error_type = ET_not_found; return result; } //////////////////////////////////////////////////////////////////// // Function: NodePath::removed named constructor // Access: Published, Static // Description: Creates a NodePath with the ET_removed error type // set. //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: removed() { NodePath result; result._error_type = ET_removed; return result; } //////////////////////////////////////////////////////////////////// // Function: NodePath::fail named constructor // Access: Published, Static // Description: Creates a NodePath with the ET_fail error type // set. //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: fail() { NodePath result; result._error_type = ET_fail; return result; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_max_search_depth // Access: Published, Static // Description: Certain operations, such as find() or // find_all_matches(), require a traversal of the scene // graph to search for the target node or nodes. This // traversal does not attempt to detect cycles, so an // arbitrary cap is set on the depth of the traversal as // a poor man's cycle detection, in the event that a // cycle has inadvertently been introduced into the // scene graph. // // There may be other reasons you'd want to truncate a // search before the bottom of the scene graph has been // reached. In any event, this function sets the limit // on the number of levels that a traversal will // continue, and hence the maximum length of a path that // may be returned by a traversal. // // This is a static method, and so changing this // parameter affects all of the NodePaths in the // universe. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_max_search_depth(int max_search_depth) { _max_search_depth = max_search_depth; } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_max_search_depth // Access: Published, Static // Description: Returns the current setting of the search depth // limit. See set_max_search_depth. //////////////////////////////////////////////////////////////////// INLINE int NodePath:: get_max_search_depth() { return _max_search_depth; } //////////////////////////////////////////////////////////////////// // Function: NodePath::is_empty // Access: Published // Description: Returns true if the NodePath contains no nodes. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: is_empty() const { return (_head == (NodePathComponent *)NULL); } //////////////////////////////////////////////////////////////////// // Function: NodePath::is_singleton // Access: Published // Description: Returns true if the NodePath contains exactly one // node. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: is_singleton(Thread *current_thread) const { int pipeline_stage = current_thread->get_pipeline_stage(); return (_head != (NodePathComponent *)NULL && _head->is_top_node(pipeline_stage, current_thread)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_error_type // Access: Published // Description: If is_empty() is true, this returns a code that // represents the reason why the NodePath is empty. //////////////////////////////////////////////////////////////////// INLINE NodePath::ErrorType NodePath:: get_error_type() const { return _error_type; } //////////////////////////////////////////////////////////////////// // Function: NodePath::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. //////////////////////////////////////////////////////////////////// INLINE PandaNode *NodePath:: get_top_node(Thread *current_thread) const { if (is_empty()) { return (PandaNode *)NULL; } return get_top(current_thread).node(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::node // Access: Published // Description: Returns the referenced node of the path. //////////////////////////////////////////////////////////////////// INLINE PandaNode *NodePath:: node() const { nassertr_always(!is_empty(), (PandaNode *)NULL); return _head->get_node(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_key // Access: Published // Description: Returns an integer that is guaranteed to be the same // for all NodePaths that represent the same node // instance, and different for all NodePaths that // represent a different node instance. // // The same key will be returned for a particular // instance as long as at least one NodePath exists that // represents that instance; if all NodePaths for a // particular instance destruct and a new one is later // created, it may have a different index. However, a // given key will never be reused for a different // instance (unless the app has been running long enough // that we overflow the integer key value). //////////////////////////////////////////////////////////////////// INLINE int NodePath:: get_key() const { if (is_empty()) { return _backup_key; } return _head->get_key(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::is_same_graph // Access: Published // Description: Returns true if the node represented by this NodePath // is parented within the same graph as that of the // other NodePath. This is essentially the same thing // as asking whether get_top() of both NodePaths is the // same (e.g., both "render"). //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: is_same_graph(const NodePath &other, Thread *current_thread) const { // Actually, it's possible for the top nodes to be the same, but the // NodePaths still to be considered in different graphs. But even // in this case, get_top() will be different for each one. (They'll // be different singleton NodePaths that happen to reference the // same node). // This will happen if one of the top nodes is considered a // different instance--for instance, render.instance_to(NodePath()) // returns a different instance of render that appears to have the // same top node. But this is a very rare thing to do. int a_count, b_count; return (find_common_ancestor(*this, other, a_count, b_count, current_thread) != (NodePathComponent *)NULL); } //////////////////////////////////////////////////////////////////// // Function: NodePath::is_ancestor_of // Access: Published // Description: Returns true if the node represented by this NodePath // is a parent or other ancestor of the other NodePath, // or false if it is not. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: is_ancestor_of(const NodePath &other, Thread *current_thread) const { int a_count, b_count; if (find_common_ancestor(*this, other, a_count, b_count, current_thread) == (NodePathComponent *)NULL) { // Not related. return false; } // They are related; now b is descended from a only if a is the // common ancestor (which is to say, a_count == 0). return (a_count == 0); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_common_ancestor // Access: Published // Description: Returns the lowest NodePath that both of these two // NodePaths have in common: the first ancestor that // both of them share. If the two NodePaths are // unrelated, returns NodePath::not_found(). //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: get_common_ancestor(const NodePath &other, Thread *current_thread) const { int a_count, b_count; NodePathComponent *common = find_common_ancestor(*this, other, a_count, b_count, current_thread); if (common == (NodePathComponent *)NULL) { return NodePath::not_found(); } NodePath result; result._head = common; return result; } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_num_children // Access: Published // Description: Returns the number of children of the referenced node. //////////////////////////////////////////////////////////////////// INLINE int NodePath:: get_num_children(Thread *current_thread) const { nassertr_always(!is_empty(), 0); return _head->get_node()->get_num_children(current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_child // Access: Published // Description: Returns a NodePath representing the nth child of the // referenced node. //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: get_child(int n, Thread *current_thread) const { nassertr_always(n >= 0 && n < get_num_children(current_thread), NodePath()); NodePath child; int pipeline_stage = current_thread->get_pipeline_stage(); child._head = PandaNode::get_component(_head, _head->get_node()->get_child(n, current_thread), pipeline_stage, current_thread); return child; } //////////////////////////////////////////////////////////////////// // Function: NodePath::count_num_descendants // Access: Published // Description: Returns the number of nodes at and below this level. //////////////////////////////////////////////////////////////////// INLINE int NodePath:: count_num_descendants() const { if (is_empty()) { return 0; } return _head->get_node()->count_num_descendants(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::has_parent // Access: Published // Description: Returns true if the referenced node has a parent; // i.e. the NodePath chain contains at least two nodes. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: has_parent(Thread *current_thread) const { return !is_empty() && !is_singleton(current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_parent // Access: Published // Description: Returns the NodePath to the parent of the referenced // node: that is, this NodePath, shortened by one node. // The parent of a singleton NodePath is defined to be // the empty NodePath. //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: get_parent(Thread *current_thread) const { if (!has_parent(current_thread)) { return NodePath(); } int pipeline_stage = current_thread->get_pipeline_stage(); NodePath parent; parent._head = _head->get_next(pipeline_stage, current_thread); return parent; } //////////////////////////////////////////////////////////////////// // Function: NodePath::attach_new_node // Access: Published // Description: Creates an ordinary PandaNode and attaches it below // the current NodePath, returning a new NodePath that // references it. //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: attach_new_node(const string &name, int sort, Thread *current_thread) const { nassertr(verify_complete(current_thread), NodePath::fail()); return attach_new_node(new PandaNode(name), sort, current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::ls // Access: Published // Description: Lists the hierarchy at and below the referenced node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: ls() const { ls(nout); } //////////////////////////////////////////////////////////////////// // Function: NodePath::ls // Access: Published // Description: Lists the hierarchy at and below the referenced node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: ls(ostream &out, int indent_level) const { if (is_empty()) { out << "(empty)\n"; } else { node()->ls(out, indent_level); } } //////////////////////////////////////////////////////////////////// // Function: NodePath::reverse_ls // Access: Published // Description: Lists the hierarchy at and above the referenced node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: reverse_ls() const { reverse_ls(nout); } //////////////////////////////////////////////////////////////////// // Function: NodePath::reverse_ls // Access: Published // Description: Lists the hierarchy at and above the referenced node. //////////////////////////////////////////////////////////////////// INLINE int NodePath:: reverse_ls(ostream &out, int indent_level) const { if (is_empty()) { out << "(empty)\n"; return 0; } else if (has_parent()) { indent_level = get_parent().reverse_ls(out, indent_level); } node()->write(out, indent_level); return indent_level + 2; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_state // Access: Published // Description: Changes the complete state object on this node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_state(const RenderState *state, Thread *current_thread) { nassertv_always(!is_empty()); node()->set_state(state, current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_net_state // Access: Published // Description: Returns the net state on this node from the root. //////////////////////////////////////////////////////////////////// INLINE CPT(RenderState) NodePath:: get_net_state(Thread *current_thread) const { nassertr(_error_type == ET_ok, RenderState::make_empty()); return r_get_net_state(_head, current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_attrib // Access: Published // Description: Adds the indicated render attribute to the scene // graph on this node. This attribute will now apply to // this node and everything below. If there was already // an attribute of the same type, it is replaced. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_attrib(const RenderAttrib *attrib, int priority) { nassertv_always(!is_empty()); node()->set_attrib(attrib, priority); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_attrib // Access: Published // Description: Returns the render attribute of the indicated type, // if it is defined on the node, or NULL if it is not. // This checks only what is set on this particular node // level, and has nothing to do with what render // attributes may be inherited from parent nodes. //////////////////////////////////////////////////////////////////// INLINE const RenderAttrib *NodePath:: get_attrib(TypeHandle type) const { nassertr_always(!is_empty(), NULL); return node()->get_attrib(type); } //////////////////////////////////////////////////////////////////// // Function: NodePath::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 NodePath:: has_attrib(TypeHandle type) const { nassertr_always(!is_empty(), false); return node()->has_attrib(type); } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_attrib // Access: Published // Description: Removes the render attribute of the given type from // this node. This node, and the subgraph below, will // now inherit the indicated render attribute from the // nodes above this one. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_attrib(TypeHandle type) { nassertv_always(!is_empty()); node()->clear_attrib(type); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_effect // Access: Published // Description: Adds the indicated render effect to the scene // graph on this node. If there was already an effect // of the same type, it is replaced. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_effect(const RenderEffect *effect) { nassertv_always(!is_empty()); node()->set_effect(effect); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_effect // Access: Published // Description: Returns the render effect of the indicated type, // if it is defined on the node, or NULL if it is not. //////////////////////////////////////////////////////////////////// INLINE const RenderEffect *NodePath:: get_effect(TypeHandle type) const { nassertr_always(!is_empty(), NULL); return node()->get_effect(type); } //////////////////////////////////////////////////////////////////// // Function: NodePath::has_effect // Access: Published // Description: Returns true if there is a render effect of the // indicated type defined on this node, or false if // there is not. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: has_effect(TypeHandle type) const { nassertr_always(!is_empty(), false); return node()->has_effect(type); } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_effect // Access: Published // Description: Removes the render effect of the given type from // this node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_effect(TypeHandle type) { nassertv_always(!is_empty()); node()->clear_effect(type); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_effects // Access: Published // Description: Sets the complete RenderEffects that will be applied // this node. This completely replaces whatever has // been set on this node via repeated calls to // set_attrib(). //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_effects(const RenderEffects *effects) { nassertv_always(!is_empty()); node()->set_effects(effects); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_effects // Access: Published // Description: Returns the complete RenderEffects that will be // applied to this node. //////////////////////////////////////////////////////////////////// INLINE const RenderEffects *NodePath:: get_effects() const { nassertr_always(!is_empty(), RenderEffects::make_empty()); return node()->get_effects(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_effects // Access: Published // Description: Resets this node to have no render effects. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_effects() { nassertv_always(!is_empty()); node()->clear_effects(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_transform // Access: Published // Description: Sets the transform object on this node to identity. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_transform(Thread *current_thread) { set_transform(TransformState::make_identity(), current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_transform // Access: Published // Description: Changes the complete transform object on this node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_transform(const TransformState *transform, Thread *current_thread) { nassertv_always(!is_empty()); node()->set_transform(transform, current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_transform // Access: Published // Description: Sets the transform object on this node to identity, // relative to the other node. This effectively places // this node at the same position as the other node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_transform(const NodePath &other, Thread *current_thread) { set_transform(other, TransformState::make_identity(), current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_net_transform // Access: Published // Description: Returns the net transform on this node from the root. //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) NodePath:: get_net_transform(Thread *current_thread) const { nassertr(_error_type == ET_ok, TransformState::make_identity()); return r_get_net_transform(_head, current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_prev_transform // Access: Published // Description: Sets the transform that represents this node's // "previous" position, one frame ago, for the purposes // of detecting motion for accurate collision // calculations. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_prev_transform(const TransformState *transform, Thread *current_thread) { nassertv_always(!is_empty()); node()->set_prev_transform(transform, current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_net_prev_transform // Access: Published // Description: Returns the net "previous" transform on this node // from the root. See set_prev_transform(). //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) NodePath:: get_net_prev_transform(Thread *current_thread) const { nassertr(_error_type == ET_ok, TransformState::make_identity()); return r_get_net_prev_transform(_head, current_thread); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos // Access: Published // Description: Sets the translation component of the transform, // leaving rotation and scale untouched. This also // resets the node's "previous" position, so that the // collision system will see the node as having suddenly // appeared in the new position, without passing any // points in between. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_pos(float x, float y, float z) { set_pos(LPoint3f(x, y, z)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_fluid_pos // Access: Published // Description: Sets the translation component, without changing the // "previous" position, so that the collision system // will see the node as moving fluidly from its previous // position to its new position. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_fluid_pos(float x, float y, float z) { set_fluid_pos(LPoint3f(x, y, z)); } INLINE float NodePath:: get_x() const { return get_pos()[0]; } INLINE float NodePath:: get_y() const { return get_pos()[1]; } INLINE float NodePath:: get_z() const { return get_pos()[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_hpr // Access: Published // Description: Sets the rotation component of the transform, // leaving translation and scale untouched. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_hpr(float h, float p, float r) { set_hpr(LVecBase3f(h, p, r)); } INLINE float NodePath:: get_h() const { return get_hpr()[0]; } INLINE float NodePath:: get_p() const { return get_hpr()[1]; } INLINE float NodePath:: get_r() const { return get_hpr()[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_scale // Access: Published // Description: Sets the scale component of the transform, // leaving translation and rotation untouched. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_scale(float scale) { set_scale(LVecBase3f(scale, scale, scale)); } INLINE void NodePath:: set_scale(float sx, float sy, float sz) { set_scale(LVecBase3f(sx, sy, sz)); } INLINE float NodePath:: get_sx() const { return get_scale()[0]; } INLINE float NodePath:: get_sy() const { return get_scale()[1]; } INLINE float NodePath:: get_sz() const { return get_scale()[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_shear // Access: Published // Description: Sets the shear component of the transform, // leaving translation, rotation, and scale untouched. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_shear(float shxy, float shxz, float shyz) { set_shear(LVecBase3f(shxy, shxz, shyz)); } INLINE float NodePath:: get_shxy() const { return get_shear()[0]; } INLINE float NodePath:: get_shxz() const { return get_shear()[1]; } INLINE float NodePath:: get_shyz() const { return get_shear()[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr // Access: Published // Description: Sets the translation and rotation component of the // transform, leaving scale untouched. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_pos_hpr(float x, float y, float z, float h, float p, float r) { set_pos_hpr(LVecBase3f(x, y, z), LVecBase3f(h, p, r)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_hpr_scale // Access: Published // Description: Sets the rotation and scale components of the // transform, leaving translation untouched. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_hpr_scale(float h, float p, float r, float sx, float sy, float sz) { set_hpr_scale(LVecBase3f(h, p, r), LVecBase3f(sx, sy, sz)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr_scale // Access: Published // Description: Completely replaces the transform with new // translation, rotation, and scale components. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_pos_hpr_scale(float x, float y, float z, float h, float p, float r, float sx, float sy, float sz) { set_pos_hpr_scale(LVecBase3f(x, y, z), LVecBase3f(h, p, r), LVecBase3f(sx, sy, sz)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_mat // Access: Published // Description: Completely removes any transform from the referenced // node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_mat() { nassertv_always(!is_empty()); node()->clear_transform(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::has_mat // Access: Published // Description: Returns true if a non-identity transform matrix has // been applied to the referenced node, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: has_mat() const { nassertr_always(!is_empty(), false); return !node()->get_transform()->is_identity(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_mat // Access: Published // Description: Returns the transform matrix that has been applied to // the referenced node, or the identity matrix if no // matrix has been applied. //////////////////////////////////////////////////////////////////// INLINE const LMatrix4f &NodePath:: get_mat() const { nassertr_always(!is_empty(), LMatrix4f::ident_mat()); return node()->get_transform()->get_mat(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::look_at // Access: Published // Description: Sets the transform on this NodePath so that it // rotates to face the indicated point in space. This // will overwrite any previously existing scale on the // node, although it will preserve any translation. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: look_at(float x, float y, float z) { look_at(LPoint3f(x, y, z)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::heads_up // Access: Published // Description: Behaves like look_at(), but with a strong preference // to keeping the up vector oriented in the indicated // "up" direction. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: heads_up(float x, float y, float z) { heads_up(LPoint3f(x, y, z)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos // Access: Published // Description: Sets the translation component of the transform, // relative to the other node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_pos(const NodePath &other, float x, float y, float z) { set_pos(other, LPoint3f(x, y, z)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_fluid_pos // Access: Published // Description: Sets the translation component, without changing the // "previous" position, so that the collision system // will see the node as moving fluidly from its previous // position to its new position. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_fluid_pos(const NodePath &other, float x, float y, float z) { set_fluid_pos(other, LPoint3f(x, y, z)); } INLINE float NodePath:: get_x(const NodePath &other) const { return get_pos(other)[0]; } INLINE float NodePath:: get_y(const NodePath &other) const { return get_pos(other)[1]; } INLINE float NodePath:: get_z(const NodePath &other) const { return get_pos(other)[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_hpr // Access: Published // Description: Sets the rotation component of the transform, // relative to the other node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_hpr(const NodePath &other, float h, float p, float r) { set_hpr(other, LPoint3f(h, p, r)); } INLINE float NodePath:: get_h(const NodePath &other) const { return get_hpr(other)[0]; } INLINE float NodePath:: get_p(const NodePath &other) const { return get_hpr(other)[1]; } INLINE float NodePath:: get_r(const NodePath &other) const { return get_hpr(other)[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_scale // Access: Published // Description: Sets the scale component of the transform, // relative to the other node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_scale(const NodePath &other, float scale) { set_scale(other, LPoint3f(scale, scale, scale)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_scale // Access: Published // Description: Sets the scale component of the transform, // relative to the other node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_scale(const NodePath &other, float sx, float sy, float sz) { set_scale(other, LPoint3f(sx, sy, sz)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_scale // Access: Published // Description: Returns the relative scale of the referenced node // as seen from the other node. //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_sx(const NodePath &other) const { return get_scale(other)[0]; } INLINE float NodePath:: get_sy(const NodePath &other) const { return get_scale(other)[1]; } INLINE float NodePath:: get_sz(const NodePath &other) const { return get_scale(other)[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_shear // Access: Published // Description: Sets the shear component of the transform, // relative to the other node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_shear(const NodePath &other, float shxy, float shxz, float shyz) { set_shear(other, LPoint3f(shxy, shxz, shyz)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_shear // Access: Published // Description: Returns the relative shear of the referenced node // as seen from the other node. //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_shxy(const NodePath &other) const { return get_shear(other)[0]; } INLINE float NodePath:: get_shxz(const NodePath &other) const { return get_shear(other)[1]; } INLINE float NodePath:: get_shyz(const NodePath &other) const { return get_shear(other)[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr // Access: Published // Description: Sets the translation and rotation component of the // transform, relative to the other node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_pos_hpr(const NodePath &other, float x, float y, float z, float h, float p, float r) { set_pos_hpr(other, LVecBase3f(x, y, z), LVecBase3f(h, p, r)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_hpr_scale // Access: Published // Description: Sets the rotation and scale components of the // transform, leaving translation untouched. This, or // set_pos_hpr_scale, is the preferred way to update a // transform when both hpr and scale are to be changed. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_hpr_scale(const NodePath &other, float h, float p, float r, float sx, float sy, float sz) { set_hpr_scale(other, LVecBase3f(h, p, r), LVecBase3f(sx, sy, sz)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_pos_hpr_scale // Access: Published // Description: Completely replaces the transform with new // translation, rotation, and scale components, relative // to the other node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_pos_hpr_scale(const NodePath &other, float x, float y, float z, float h, float p, float r, float sx, float sy, float sz) { set_pos_hpr_scale(other, LVecBase3f(x, y, z), LVecBase3f(h, p, r), LVecBase3f(sx, sy, sz)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::look_at // Access: Published // Description: Sets the hpr on this NodePath so that it rotates to // face the indicated point in space, which is relative // to the other NodePath. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: look_at(const NodePath &other, float x, float y, float z) { look_at(other, LPoint3f(x, y, z)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::heads_up // Access: Published // Description: Behaves like look_at(), but with a strong preference // to keeping the up vector oriented in the indicated // "up" direction. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: heads_up(const NodePath &other, float x, float y, float z) { heads_up(other, LPoint3f(x, y, z)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_distance // Access: Published // Description: Returns the straight-line distance between this // referenced node's coordinate frame's origin, and that // of the other node's origin. //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_distance(const NodePath &other) const { LPoint3f pos = get_pos(other); return length(LVector3f(pos)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_color_scale // Access: Published // Description: Sets the color scale component of the transform //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_color_scale(float sr, float sg, float sb, float sa, int priority) { set_color_scale(LVecBase4f(sr, sg, sb, sa), priority); } //////////////////////////////////////////////////////////////////// // Function: NodePath::compose_color_scale // Access: Published // Description: Sets the color scale component of the transform //////////////////////////////////////////////////////////////////// INLINE void NodePath:: compose_color_scale(float sr, float sg, float sb, float sa, int priority) { compose_color_scale(LVecBase4f(sr, sg, sb, sa), priority); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_sr // Access: Published // Description: Sets the red scale component of the transform //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_sr(float sr) { LVecBase4f new_scale = get_color_scale(); new_scale[0] = sr; set_color_scale(new_scale); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_sg // Access: Published // Description: Sets the alpha scale component of the transform //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_sg(float sg) { LVecBase4f new_scale = get_color_scale(); new_scale[1] = sg; set_color_scale(new_scale); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_sb // Access: Published // Description: Sets the blue scale component of the transform //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_sb(float sb) { LVecBase4f new_scale = get_color_scale(); new_scale[2] = sb; set_color_scale(new_scale); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_sa // Access: Published // Description: Sets the alpha scale component of the transform //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_sa(float sa) { LVecBase4f new_scale = get_color_scale(); new_scale[3] = sa; set_color_scale(new_scale); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_sr // Access: Published // Description: Gets the red scale component of the transform //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_sr() const { return get_color_scale()[0]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_sg // Access: Published // Description: Gets the green scale component of the transform //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_sg() const { return get_color_scale()[1]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_sb // Access: Published // Description: Gets the blue scale component of the transform //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_sb() const { return get_color_scale()[2]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_sa // Access: Published // Description: Gets the alpha scale component of the transform //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_sa() const { return get_color_scale()[3]; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_offset // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated offset to UV's for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_offset(TextureStage *stage, float u, float v) { set_tex_offset(stage, LVecBase2f(u, v)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_offset // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated offset to UV's for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_offset(TextureStage *stage, const LVecBase2f &uv) { nassertv_always(!is_empty()); set_tex_transform(stage, get_tex_transform(stage)->set_pos2d(uv)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_rotate // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated rotation, clockwise in degrees, to UV's // for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_rotate(TextureStage *stage, float r) { nassertv_always(!is_empty()); set_tex_transform(stage, get_tex_transform(stage)->set_rotate2d(r)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UVW's for the given stage. // // This call is appropriate for 2-d or 3-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(TextureStage *stage, float scale) { nassertv_always(!is_empty()); set_tex_transform(stage, get_tex_transform(stage)->set_scale(scale)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UV's for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(TextureStage *stage, float su, float sv) { set_tex_scale(stage, LVecBase2f(su, sv)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UV's for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(TextureStage *stage, const LVecBase2f &scale) { nassertv_always(!is_empty()); set_tex_transform(stage, get_tex_transform(stage)->set_scale2d(scale)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_offset // Access: Published // Description: Returns the offset set for the UV's for the given // stage on the current node. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase2f NodePath:: get_tex_offset(TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase2f::zero()); return get_tex_transform(stage)->get_pos2d(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_rotate // Access: Published // Description: Returns the rotation set for the UV's for the given // stage on the current node. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_tex_rotate(TextureStage *stage) const { nassertr_always(!is_empty(), 0.0f); return get_tex_transform(stage)->get_rotate2d(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_scale // Access: Published // Description: Returns the scale set for the UV's for the given // stage on the current node. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase2f NodePath:: get_tex_scale(TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase2f(1.0f, 1.0f)); return get_tex_transform(stage)->get_scale2d(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_pos // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated offset to UVW's for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_pos(TextureStage *stage, float u, float v, float w) { set_tex_pos(stage, LVecBase3f(u, v, w)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_pos // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated offset to UVW's for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_pos(TextureStage *stage, const LVecBase3f &uvw) { nassertv_always(!is_empty()); set_tex_transform(stage, get_tex_transform(stage)->set_pos(uvw)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_hpr // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated rotation, as a 3-D HPR, to UVW's // for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_hpr(TextureStage *stage, float h, float p, float r) { set_tex_hpr(stage, LVecBase3f(h, p, r)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_hpr // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated rotation, as a 3-D HPR, to UVW's // for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_hpr(TextureStage *stage, const LVecBase3f &hpr) { nassertv_always(!is_empty()); set_tex_transform(stage, get_tex_transform(stage)->set_hpr(hpr)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UVW's for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(TextureStage *stage, float su, float sv, float sw) { set_tex_scale(stage, LVecBase3f(su, sv, sw)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UVW's for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(TextureStage *stage, const LVecBase3f &scale) { nassertv_always(!is_empty()); set_tex_transform(stage, get_tex_transform(stage)->set_scale(scale)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_pos // Access: Published // Description: Returns the offset set for the UVW's for the given // stage on the current node. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase3f NodePath:: get_tex_pos(TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase3f::zero()); return get_tex_transform(stage)->get_pos(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_hpr // Access: Published // Description: Returns the 3-D HPR set for the UVW's for the given // stage on the current node. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase3f NodePath:: get_tex_hpr(TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase3f::zero()); return get_tex_transform(stage)->get_hpr(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_scale_3d // Access: Published // Description: Returns the scale set for the UVW's for the given // stage on the current node. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase3f NodePath:: get_tex_scale_3d(TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase3f(1.0f, 1.0f, 1.0f)); return get_tex_transform(stage)->get_scale(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_offset // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated offset to UV's for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_offset(const NodePath &other, TextureStage *stage, float u, float v) { set_tex_offset(other, stage, LVecBase2f(u, v)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_offset // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated offset to UV's for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_offset(const NodePath &other, TextureStage *stage, const LVecBase2f &uv) { nassertv_always(!is_empty()); set_tex_transform(other, stage, get_tex_transform(other, stage)->set_pos2d(uv)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_rotate // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated rotation, clockwise in degrees, to UV's // for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_rotate(const NodePath &other, TextureStage *stage, float r) { nassertv_always(!is_empty()); set_tex_transform(other, stage, get_tex_transform(other, stage)->set_rotate2d(r)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UV's for the given stage. // // This call is appropriate for 2-d or 3-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(const NodePath &other, TextureStage *stage, float scale) { nassertv_always(!is_empty()); set_tex_transform(other, stage, get_tex_transform(stage)->set_scale(scale)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UV's for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(const NodePath &other, TextureStage *stage, float su, float sv) { set_tex_scale(other, stage, LVecBase2f(su, sv)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UV's for the given stage. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(const NodePath &other, TextureStage *stage, const LVecBase2f &scale) { nassertv_always(!is_empty()); set_tex_transform(other, stage, get_tex_transform(stage)->set_scale2d(scale)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_offset // Access: Published // Description: Returns the offset set for the UV's for the given // stage on the current node. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase2f NodePath:: get_tex_offset(const NodePath &other, TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase2f::zero()); return get_tex_transform(other, stage)->get_pos2d(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_rotate // Access: Published // Description: Returns the rotation set for the UV's for the given // stage on the current node. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE float NodePath:: get_tex_rotate(const NodePath &other, TextureStage *stage) const { nassertr_always(!is_empty(), 0.0f); return get_tex_transform(other, stage)->get_rotate2d(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_scale // Access: Published // Description: Returns the scale set for the UV's for the given // stage on the current node. // // This call is appropriate for ordinary 2-d texture // coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase2f NodePath:: get_tex_scale(const NodePath &other, TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase2f(1.0f, 1.0f)); return get_tex_transform(other, stage)->get_scale2d(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_pos // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated offset to UVW's for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_pos(const NodePath &other, TextureStage *stage, float u, float v, float w) { set_tex_pos(other, stage, LVecBase3f(u, v, w)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_pos // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated offset to UVW's for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_pos(const NodePath &other, TextureStage *stage, const LVecBase3f &uvw) { nassertv_always(!is_empty()); set_tex_transform(other, stage, get_tex_transform(stage)->set_pos(uvw)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_hpr // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated rotation, as a 3-D HPR, to UVW's // for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_hpr(const NodePath &other, TextureStage *stage, float h, float p, float r) { set_tex_hpr(other, stage, LVecBase3f(h, p, r)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_hpr // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated rotation, as a 3-D HPR, to UVW's // for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_hpr(const NodePath &other, TextureStage *stage, const LVecBase3f &hpr) { nassertv_always(!is_empty()); set_tex_transform(other, stage, get_tex_transform(stage)->set_hpr(hpr)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UVW's for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(const NodePath &other, TextureStage *stage, float su, float sv, float sw) { set_tex_scale(other, stage, LVecBase3f(su, sv, sw)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tex_scale // Access: Published // Description: Sets a texture matrix on the current node to apply // the indicated scale to UVW's for the given stage. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tex_scale(const NodePath &other, TextureStage *stage, const LVecBase3f &scale) { nassertv_always(!is_empty()); set_tex_transform(other, stage, get_tex_transform(stage)->set_scale(scale)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_pos // Access: Published // Description: Returns the offset set for the UVW's for the given // stage on the current node. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase3f NodePath:: get_tex_pos(const NodePath &other, TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase3f::zero()); return get_tex_transform(stage)->get_pos(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_hpr // Access: Published // Description: Returns the 3-D HPR set for the UVW's for the given // stage on the current node. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase3f NodePath:: get_tex_hpr(const NodePath &other, TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase3f::zero()); return get_tex_transform(stage)->get_hpr(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tex_scale_3d // Access: Published // Description: Returns the scale set for the UVW's for the given // stage on the current node. // // This call is appropriate for 3-d texture coordinates. //////////////////////////////////////////////////////////////////// INLINE LVecBase3f NodePath:: get_tex_scale_3d(const NodePath &other, TextureStage *stage) const { nassertr_always(!is_empty(), LVecBase3f(1.0f, 1.0f, 1.0f)); return get_tex_transform(stage)->get_scale(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_project_texture // Access: Published // Description: Undoes the effect of project_texture(). //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_project_texture(TextureStage *stage) { clear_texture(stage); clear_tex_gen(stage); clear_tex_projector(stage); } //////////////////////////////////////////////////////////////////// // Function: NodePath::has_texcoord // Access: Published // Description: Returns true if there are at least some vertices at // this node and below that use the named texture // coordinate set, false otherwise. Pass the empty // string for the default texture coordinate set. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: has_texcoord(const string &texcoord_name) const { return has_vertex_column(InternalName::get_texcoord_name(texcoord_name)); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_billboard_axis // Access: Published // Description: Puts a billboard transition on the node such that it // will rotate in two dimensions around the up axis. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_billboard_axis(float offset) { set_billboard_axis(NodePath(), offset); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_billboard_point_eye // Access: Published // Description: Puts a billboard transition on the node such that it // will rotate in three dimensions about the origin, // keeping its up vector oriented to the top of the // camera. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_billboard_point_eye(float offset) { set_billboard_point_eye(NodePath(), offset); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_billboard_point_world // Access: Published // Description: Puts a billboard transition on the node such that it // will rotate in three dimensions about the origin, // keeping its up vector oriented to the sky. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_billboard_point_world(float offset) { set_billboard_point_world(NodePath(), offset); } //////////////////////////////////////////////////////////////////// // Function: NodePath::adjust_all_priorities // Access: Published // Description: Adds the indicated adjustment amount (which may be // negative) to the priority for all transitions on the // referenced node, and for all nodes in the subgraph // below. This can be used to force these nodes not to // be overridden by a high-level state change above. If // the priority would drop below zero, it is set to // zero. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: adjust_all_priorities(int adjustment) { nassertv_always(!is_empty()); r_adjust_all_priorities(node(), adjustment); } //////////////////////////////////////////////////////////////////// // Function: NodePath::show // Access: Published // Description: Undoes the effect of a previous hide() on this node: // makes the referenced node (and the entire subgraph // below this node) visible to all cameras. // // This will not reveal the node if a parent node has // been hidden. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: show() { nassertv_always(!is_empty()); node()->adjust_draw_mask(DrawMask::all_off(), DrawMask::all_off(), PandaNode::get_overall_bit()); } //////////////////////////////////////////////////////////////////// // Function: NodePath::show // Access: Published // Description: Makes the referenced node visible just to the // cameras whose camera_mask shares the indicated bits. // // This undoes the effect of a previous hide() call. It // will not reveal the node if a parent node has been // hidden. However, see show_through(). //////////////////////////////////////////////////////////////////// INLINE void NodePath:: show(DrawMask camera_mask) { nassertv_always(!is_empty()); camera_mask &= ~PandaNode::get_overall_bit(); node()->adjust_draw_mask(DrawMask::all_off(), DrawMask::all_off(), camera_mask); } //////////////////////////////////////////////////////////////////// // Function: NodePath::show_through // Access: Published // Description: Makes the referenced node visible just to the // cameras whose camera_mask shares the indicated bits. // // Unlike show(), this will reveal the node even if a // parent node has been hidden, thus "showing through" a // parent's hide(). //////////////////////////////////////////////////////////////////// INLINE void NodePath:: show_through() { nassertv_always(!is_empty()); node()->adjust_draw_mask(PandaNode::get_overall_bit(), DrawMask::all_off(), DrawMask::all_off()); } //////////////////////////////////////////////////////////////////// // Function: NodePath::show_through // Access: Published // Description: Makes the referenced node visible just to the // cameras whose camera_mask shares the indicated bits. // // Unlike show(), this will reveal the node even if a // parent node has been hidden via the one-parameter // hide() method, thus "showing through" a parent's // hide(). (However, it will not show through a // parent's hide() call if the no-parameter form of // hide() was used.) //////////////////////////////////////////////////////////////////// INLINE void NodePath:: show_through(DrawMask camera_mask) { nassertv_always(!is_empty()); camera_mask &= ~PandaNode::get_overall_bit(); node()->adjust_draw_mask(camera_mask, DrawMask::all_off(), DrawMask::all_off()); } //////////////////////////////////////////////////////////////////// // Function: NodePath::hide // Access: Published // Description: Makes the referenced node (and the entire subgraph // below this node) invisible to all cameras. It // remains part of the scene graph, its bounding volume // still contributes to its parent's bounding volume, // and it will still be involved in collision tests. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: hide() { nassertv_always(!is_empty()); node()->adjust_draw_mask(DrawMask::all_off(), PandaNode::get_overall_bit(), DrawMask::all_off()); } //////////////////////////////////////////////////////////////////// // Function: NodePath::hide // Access: Published // Description: Makes the referenced node invisible just to the // cameras whose camera_mask shares the indicated bits. // // This will also hide any nodes below this node in the // scene graph, including those nodes for which show() // has been called, but it will not hide descendent // nodes for which show_through() has been called. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: hide(DrawMask camera_mask) { nassertv_always(!is_empty()); camera_mask &= ~PandaNode::get_overall_bit(); node()->adjust_draw_mask(DrawMask::all_off(), camera_mask, DrawMask::all_off()); } //////////////////////////////////////////////////////////////////// // Function: NodePath::is_hidden // Access: Published // Description: Returns true if the referenced node is hidden from // the indicated camera(s) either directly, or because // some ancestor is hidden. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: is_hidden(DrawMask camera_mask) const { return !get_hidden_ancestor(camera_mask).is_empty(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::is_stashed // Access: Published // Description: Returns true if the referenced node is stashed either // directly, or because some ancestor is stashed. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: is_stashed() const { return !get_stashed_ancestor().is_empty(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_collide_mask // Access: Published // Description: Returns the union of all of the into_collide_masks // for nodes at this level and below. This is the same // thing as node()->get_net_collide_mask(). // // If you want to return what the into_collide_mask of // this node itself is, without regard to its children, // use node()->get_into_collide_mask(). //////////////////////////////////////////////////////////////////// INLINE CollideMask NodePath:: get_collide_mask() const { nassertr_always(!is_empty(), CollideMask::all_off()); return node()->get_net_collide_mask(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_collide_mask // Access: Published // Description: Recursively applies the indicated CollideMask to the // into_collide_masks for all nodes at this level and // below. If node_type is not TypeHandle::none(), then // only nodes matching (or inheriting from) the // indicated PandaNode subclass are modified. // // The default is to change all bits, but if // bits_to_change is not all bits on, then only the bits // that are set in bits_to_change are modified, allowing // this call to change only a subset of the bits in the // subgraph. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_collide_mask(CollideMask new_mask, CollideMask bits_to_change, TypeHandle node_type) { nassertv_always(!is_empty()); if (node_type == TypeHandle::none()) { node_type = PandaNode::get_class_type(); } r_set_collide_mask(node(), ~bits_to_change, new_mask & bits_to_change, node_type); } //////////////////////////////////////////////////////////////////// // Function: NodePath::operator == // Access: Published // Description: Returns true if the two paths are equivalent; that // is, if they contain the same list of nodes in the same // order. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: operator == (const NodePath &other) const { return _head == other._head; } //////////////////////////////////////////////////////////////////// // Function: NodePath::operator != // Access: Published // Description: Returns true if the two paths are not equivalent. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: operator != (const NodePath &other) const { return _head != other._head; } //////////////////////////////////////////////////////////////////// // Function: NodePath::operator < // Access: Published // Description: Returns true if this NodePath sorts before the other // one, false otherwise. The sorting order of two // nonequivalent NodePaths is consistent but undefined, // and is useful only for storing NodePaths in a sorted // container like an STL set. //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: operator < (const NodePath &other) const { return _head < other._head; } //////////////////////////////////////////////////////////////////// // Function: NodePath::compare_to // Access: Published // Description: Returns a number less than zero if this NodePath // sorts before the other one, greater than zero if it // sorts after, or zero if they are equivalent. // // Two NodePaths are considered equivalent if they // consist of exactly the same list of nodes in the same // order. Otherwise, they are different; different // NodePaths will be ranked in a consistent but // undefined ordering; the ordering is useful only for // placing the NodePaths in a sorted container like an // STL set. //////////////////////////////////////////////////////////////////// INLINE int NodePath:: compare_to(const NodePath &other) const { // Nowadays, the NodePathComponents at the head are pointerwise // equivalent if and only if the NodePaths are equivalent. So we // only have to compare pointers. if (_head != other._head) { return _head < other._head ? -1 : 1; } return 0; } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_model_nodes // Access: Published // Description: Recursively walks through the scene graph at this // level and below, looking for ModelNodes, and calls // model_node->set_preserve_transform(PT_drop_node) on // each one. This allows a subsequent call to // flatten_strong() to eliminate all of the ModelNodes. // // Returns the number of ModelNodes found. //////////////////////////////////////////////////////////////////// INLINE int NodePath:: clear_model_nodes() { nassertr_always(!is_empty(), 0); return r_clear_model_nodes(node()); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tag // Access: Published // Description: Associates a user-defined value with a user-defined // key which is stored on the node. This value has no // meaning to Panda; but it is stored indefinitely on // the node until it is requested again. // // Each unique key stores a different string value. // There is no effective limit on the number of // different keys that may be stored or on the length of // any one key's value. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_tag(const string &key, const string &value) { nassertv_always(!is_empty()); node()->set_tag(key, value); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_tag // Access: Published // Description: Retrieves the user-defined value that was previously // set on this node for the particular key, if any. If // no value has been previously set, returns the empty // string. See also get_net_tag(). //////////////////////////////////////////////////////////////////// INLINE string NodePath:: get_tag(const string &key) const { // An empty NodePath quietly returns no tags. This makes // get_net_tag() easier to implement. if (is_empty()) { return string(); } return node()->get_tag(key); } //////////////////////////////////////////////////////////////////// // Function: NodePath::has_tag // Access: Published // Description: Returns true if a value has been defined on this node // for the particular key (even if that value is the // empty string), or false if no value has been set. // See also has_net_tag(). //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: has_tag(const string &key) const { // An empty NodePath quietly has no tags. This makes has_net_tag() // easier to implement. if (is_empty()) { return false; } return node()->has_tag(key); } //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_tag // Access: Published // Description: Removes the value defined for this key on this // particular node. After a call to clear_tag(), // has_tag() will return false for the indicated key. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_tag(const string &key) { nassertv_always(!is_empty()); node()->clear_tag(key); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_net_tag // Access: Published // Description: Returns the tag value that has been defined on this // node, or the nearest ancestor node, for the indicated // key. If no value has been defined for the indicated // key on any ancestor node, returns the empty string. // See also get_tag(). //////////////////////////////////////////////////////////////////// INLINE string NodePath:: get_net_tag(const string &key) const { return find_net_tag(key).get_tag(key); } //////////////////////////////////////////////////////////////////// // Function: NodePath::has_net_tag // Access: Published // Description: Returns true if the indicated tag value has been // defined on this node or on any ancestor node, or // false otherwise. See also has_tag(). //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: has_net_tag(const string &key) const { return !find_net_tag(key).is_empty(); } #ifdef HAVE_PYTHON //////////////////////////////////////////////////////////////////// // Function: NodePath::set_python_tag // Access: Published // Description: Associates an arbitrary Python object with a // user-defined key which is stored on the node. This // object has no meaning to Panda; but it is stored // indefinitely on the node until it is requested again. // // Each unique key stores a different Python object. // There is no effective limit on the number of // different keys that may be stored or on the nature of // any one key's object. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_python_tag(const string &key, PyObject *value) { nassertv_always(!is_empty()); node()->set_python_tag(key, value); } #endif // HAVE_PYTHON #ifdef HAVE_PYTHON //////////////////////////////////////////////////////////////////// // Function: NodePath::get_python_tag // Access: Published // Description: Retrieves the Python object that was previously // set on this node for the particular key, if any. If // no object has been previously set, returns None. // See also get_net_python_tag(). //////////////////////////////////////////////////////////////////// INLINE PyObject *NodePath:: get_python_tag(const string &key) const { // An empty NodePath quietly returns no tags. This makes // get_net_python_tag() easier to implement. if (is_empty()) { Py_INCREF(Py_None); return Py_None; } return node()->get_python_tag(key); } #endif // HAVE_PYTHON #ifdef HAVE_PYTHON //////////////////////////////////////////////////////////////////// // Function: NodePath::has_python_tag // Access: Published // Description: Returns true if a Python object has been defined on // this node for the particular key (even if that value // is the empty string), or false if no value has been // set. See also has_net_python_tag(). //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: has_python_tag(const string &key) const { // An empty NodePath quietly has no tags. This makes has_net_python_tag() // easier to implement. if (is_empty()) { return false; } return node()->has_python_tag(key); } #endif // HAVE_PYTHON #ifdef HAVE_PYTHON //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_python_tag // Access: Published // Description: Removes the Python object defined for this key on this // particular node. After a call to clear_python_tag(), // has_python_tag() will return false for the indicated // key. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: clear_python_tag(const string &key) { nassertv_always(!is_empty()); node()->clear_python_tag(key); } #endif // HAVE_PYTHON #ifdef HAVE_PYTHON //////////////////////////////////////////////////////////////////// // Function: NodePath::get_net_python_tag // Access: Published // Description: Returns the Python object that has been defined on // this node, or the nearest ancestor node, for the // indicated key. If no value has been defined for the // indicated key on any ancestor node, returns None. // See also get_python_tag(). //////////////////////////////////////////////////////////////////// INLINE PyObject *NodePath:: get_net_python_tag(const string &key) const { return find_net_python_tag(key).get_python_tag(key); } #endif // HAVE_PYTHON #ifdef HAVE_PYTHON //////////////////////////////////////////////////////////////////// // Function: NodePath::has_net_python_tag // Access: Published // Description: Returns true if the indicated Python object has been // defined on this node or on any ancestor node, or // false otherwise. See also has_python_tag(). //////////////////////////////////////////////////////////////////// INLINE bool NodePath:: has_net_python_tag(const string &key) const { return !find_net_python_tag(key).is_empty(); } #endif // HAVE_PYTHON //////////////////////////////////////////////////////////////////// // Function: NodePath::list_tags // Access: Published // Description: Lists the tags to the nout stream, one per line. See // PandaNode::list_tags() for a variant that allows you // to specify the output stream. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: list_tags() const { nassertv_always(!is_empty()); node()->list_tags(nout); nout << "\n"; } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_name // Access: Published // Description: Changes the name of the referenced node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: set_name(const string &name) { nassertv_always(!is_empty()); node()->set_name(name); } //////////////////////////////////////////////////////////////////// // Function: NodePath::get_name // Access: Published // Description: Returns the name of the referenced node. //////////////////////////////////////////////////////////////////// INLINE string NodePath:: get_name() const { nassertr_always(!is_empty(), string()); return node()->get_name(); } //////////////////////////////////////////////////////////////////// // Function: NodePath::encode_to_bam_stream // Access: Published // Description: Converts the NodePath object into a single // stream of data using a BamWriter, and returns that // data as a string string. Returns empty string on // failure. This is similar to write_bam_stream(). // // This method is used by __reduce__ to handle streaming // of NodePaths to a pickle file. //////////////////////////////////////////////////////////////////// INLINE string NodePath:: encode_to_bam_stream() const { string data; if (!encode_to_bam_stream(data)) { return string(); } return data; } INLINE ostream &operator << (ostream &out, const NodePath &node_path) { node_path.output(out); return out; }