Panda3D

pandaNode.h

00001 // Filename: pandaNode.h
00002 // Created by:  drose (20Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifndef PANDANODE_H
00016 #define PANDANODE_H
00017 
00018 #include "pandabase.h"
00019 
00020 #include "cycleData.h"
00021 #include "cycleDataReader.h"
00022 #include "cycleDataWriter.h"
00023 #include "cycleDataLockedStageReader.h"
00024 #include "cycleDataStageReader.h"
00025 #include "cycleDataStageWriter.h"
00026 #include "pipelineCycler.h"
00027 #include "renderState.h"
00028 #include "renderEffects.h"
00029 #include "transformState.h"
00030 #include "drawMask.h"
00031 #include "typedWritable.h"
00032 #include "collideMask.h"
00033 #include "namable.h"
00034 #include "referenceCount.h"
00035 #include "luse.h"
00036 #include "ordered_vector.h"
00037 #include "pointerTo.h"
00038 #include "nodePointerTo.h"
00039 #include "pointerToArray.h"
00040 #include "pnotify.h"
00041 #include "updateSeq.h"
00042 #include "deletedChain.h"
00043 #include "pandaNodeChain.h"
00044 #include "pStatCollector.h"
00045 #include "copyOnWriteObject.h"
00046 #include "copyOnWritePointer.h"
00047 #include "lightReMutex.h"
00048 
00049 #ifdef HAVE_PYTHON
00050 
00051 #undef _POSIX_C_SOURCE
00052 #include <Python.h>
00053 
00054 #endif  // HAVE_PYTHON
00055 
00056 class NodePathComponent;
00057 class CullTraverser;
00058 class CullTraverserData;
00059 class Light;
00060 class FactoryParams;
00061 class AccumulatedAttribs;
00062 class GeomTransformer;
00063 class GraphicsStateGuardianBase;
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //       Class : PandaNode
00067 // Description : A basic node of the scene graph or data graph.  This
00068 //               is the base class of all specialized nodes, and also
00069 //               serves as a generic node with no special properties.
00070 ////////////////////////////////////////////////////////////////////
00071 class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritable, public Namable, 
00072                               public LinkedListNode,
00073                               virtual public ReferenceCount {
00074 PUBLISHED:
00075   PandaNode(const string &name);
00076   virtual ~PandaNode();
00077   //published so that characters can be combined. 
00078   virtual PandaNode *combine_with(PandaNode *other); 
00079 
00080 protected:
00081   PandaNode(const PandaNode &copy);
00082 private:
00083   void operator = (const PandaNode &copy);
00084 
00085 public:
00086   virtual ReferenceCount *as_reference_count();
00087   virtual PandaNode *dupe_for_flatten() const;
00088 
00089   virtual bool safe_to_flatten() const;
00090   virtual bool safe_to_transform() const;
00091   virtual bool safe_to_modify_transform() const;
00092   virtual bool safe_to_combine() const;
00093   virtual bool safe_to_combine_children() const;
00094   virtual bool safe_to_flatten_below() const;
00095   virtual bool preserve_name() const;
00096   virtual int get_unsafe_to_apply_attribs() const;
00097   virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs,
00098                                          int attrib_types,
00099                                          GeomTransformer &transformer);
00100   virtual void xform(const LMatrix4 &mat);
00101 
00102   virtual CPT(TransformState)
00103     calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
00104                       bool &found_any,
00105                       const TransformState *transform,
00106                       Thread *current_thread = Thread::get_current_thread()) const;
00107   
00108   virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
00109   virtual bool has_selective_visibility() const;
00110   virtual int get_first_visible_child() const;
00111   virtual int get_next_visible_child(int n) const;
00112   virtual bool has_single_child_visibility() const;
00113   virtual int get_visible_child() const;
00114   virtual bool is_renderable() const;
00115   virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data);
00116 
00117 PUBLISHED:
00118   virtual PandaNode *make_copy() const;
00119   PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const;
00120 
00121 #ifdef HAVE_PYTHON
00122   PT(PandaNode) __copy__() const;
00123   PyObject *__deepcopy__(PyObject *self, PyObject *memo) const;
00124 #endif
00125 
00126   INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const;
00127   INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const;
00128   INLINE int find_parent(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
00129 
00130   INLINE int get_num_children(Thread *current_thread = Thread::get_current_thread()) const;
00131   INLINE PandaNode *get_child(int n, Thread *current_thread = Thread::get_current_thread()) const;
00132   INLINE int get_child_sort(int n, Thread *current_thread = Thread::get_current_thread()) const;
00133   INLINE int find_child(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
00134 
00135   int count_num_descendants() const;
00136 
00137   void add_child(PandaNode *child_node, int sort = 0,
00138                  Thread *current_thread = Thread::get_current_thread());
00139   void remove_child(int child_index, Thread *current_thread = Thread::get_current_thread());
00140   bool remove_child(PandaNode *child_node, Thread *current_thread = Thread::get_current_thread());
00141   bool replace_child(PandaNode *orig_child, PandaNode *new_child,
00142                      Thread *current_thread = Thread::get_current_thread());
00143 
00144   INLINE bool stash_child(PandaNode *child_node,
00145                           Thread *current_thread = Thread::get_current_thread());
00146   void stash_child(int child_index,
00147                    Thread *current_thread = Thread::get_current_thread());
00148   INLINE bool unstash_child(PandaNode *child_node,
00149                             Thread *current_thread = Thread::get_current_thread());
00150   void unstash_child(int stashed_index,
00151                      Thread *current_thread = Thread::get_current_thread());
00152 
00153   INLINE int get_num_stashed(Thread *current_thread = Thread::get_current_thread()) const;
00154   INLINE PandaNode *get_stashed(int n, Thread *current_thread = Thread::get_current_thread()) const;
00155   INLINE int get_stashed_sort(int n, Thread *current_thread = Thread::get_current_thread()) const;
00156   INLINE int find_stashed(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
00157 
00158   void add_stashed(PandaNode *child_node, int sort = 0, Thread *current_thread = Thread::get_current_thread());
00159   void remove_stashed(int child_index, Thread *current_thread = Thread::get_current_thread());
00160 
00161   void remove_all_children(Thread *current_thread = Thread::get_current_thread());
00162   void steal_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread());
00163   void copy_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread());
00164 
00165   void set_attrib(const RenderAttrib *attrib, int override = 0);
00166   INLINE const RenderAttrib *get_attrib(TypeHandle type) const;
00167   INLINE const RenderAttrib *get_attrib(int slot) const;
00168   INLINE bool has_attrib(TypeHandle type) const;
00169   INLINE bool has_attrib(int slot) const;
00170   INLINE void clear_attrib(TypeHandle type);
00171   void clear_attrib(int slot);
00172 
00173   void set_effect(const RenderEffect *effect);
00174   INLINE const RenderEffect *get_effect(TypeHandle type) const;
00175   INLINE bool has_effect(TypeHandle type) const;
00176   void clear_effect(TypeHandle type);
00177 
00178   void set_state(const RenderState *state, Thread *current_thread = Thread::get_current_thread());
00179   INLINE const RenderState *get_state(Thread *current_thread = Thread::get_current_thread()) const;
00180   INLINE void clear_state(Thread *current_thread = Thread::get_current_thread());
00181 
00182   void set_effects(const RenderEffects *effects, Thread *current_thread = Thread::get_current_thread());
00183   INLINE const RenderEffects *get_effects(Thread *current_thread = Thread::get_current_thread()) const;
00184   INLINE void clear_effects(Thread *current_thread = Thread::get_current_thread());
00185 
00186   void set_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread());
00187   INLINE const TransformState *get_transform(Thread *current_thread = Thread::get_current_thread()) const;
00188   INLINE void clear_transform(Thread *current_thread = Thread::get_current_thread());
00189 
00190   void set_prev_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread());
00191   INLINE const TransformState *get_prev_transform(Thread *current_thread = Thread::get_current_thread()) const;
00192   void reset_prev_transform(Thread *current_thread = Thread::get_current_thread());
00193   INLINE bool has_dirty_prev_transform() const;
00194   static void reset_all_prev_transform(Thread *current_thread = Thread::get_current_thread());
00195 
00196   void set_tag(const string &key, const string &value, 
00197                Thread *current_thread = Thread::get_current_thread());
00198   INLINE string get_tag(const string &key, 
00199                         Thread *current_thread = Thread::get_current_thread()) const;
00200   INLINE bool has_tag(const string &key,
00201                       Thread *current_thread = Thread::get_current_thread()) const;
00202   void clear_tag(const string &key,
00203                  Thread *current_thread = Thread::get_current_thread());
00204 
00205 #ifdef HAVE_PYTHON
00206   void set_python_tag(const string &key, PyObject *value);
00207   PyObject *get_python_tag(const string &key) const;
00208   bool has_python_tag(const string &key) const;
00209   void clear_python_tag(const string &key);
00210 #endif  // HAVE_PYTHON
00211 
00212   INLINE bool has_tags() const;
00213   void copy_tags(PandaNode *other);
00214   void list_tags(ostream &out, const string &separator = "\n") const;
00215 
00216   int compare_tags(const PandaNode *other) const;
00217 
00218   void copy_all_properties(PandaNode *other);
00219   void replace_node(PandaNode *other);
00220 
00221   enum UnexpectedChange {
00222     UC_parents   = 0x001,
00223     UC_children  = 0x002,
00224     UC_transform = 0x004,
00225     UC_state     = 0x008,
00226     UC_draw_mask = 0x010,
00227   };
00228   void set_unexpected_change(unsigned int flags);
00229   unsigned int get_unexpected_change(unsigned int flags) const;
00230   void clear_unexpected_change(unsigned int flags);
00231 
00232   INLINE static DrawMask get_overall_bit();
00233   INLINE static DrawMask get_all_camera_mask();
00234   INLINE bool is_overall_hidden() const;
00235   INLINE void set_overall_hidden(bool overall_hidden);
00236 
00237   void adjust_draw_mask(DrawMask show_mask,
00238                         DrawMask hide_mask,
00239                         DrawMask clear_mask);
00240   INLINE DrawMask get_draw_control_mask() const;
00241   INLINE DrawMask get_draw_show_mask() const;
00242 
00243   DrawMask get_net_draw_control_mask() const;
00244   DrawMask get_net_draw_show_mask() const;
00245 
00246   void set_into_collide_mask(CollideMask mask);
00247   INLINE CollideMask get_into_collide_mask() const;
00248   virtual CollideMask get_legal_collide_mask() const;
00249 
00250   CollideMask get_net_collide_mask(Thread *current_thread = Thread::get_current_thread()) const;
00251   CPT(RenderAttrib) get_off_clip_planes(Thread *current_thread = Thread::get_current_thread()) const;
00252 
00253   void prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state);
00254 
00255   bool is_scene_root() const;
00256   bool is_under_scene_root() const;
00257 
00258   virtual void output(ostream &out) const;
00259   virtual void write(ostream &out, int indent_level) const;
00260 
00261   INLINE void ls(ostream &out, int indent_level) const;
00262 
00263   // A node has three bounding volumes: an "external" bounding volume
00264   // that represents the node and all of its children, an "internal"
00265   // bounding volume which represents only the node itself (and is
00266   // usually empty, unless a specific node type sets it otherwise),
00267   // and a "user" bounding volume which is specified by the user.
00268 
00269   // We define set_bounds() and get_bounds() functions so that
00270   // set_bounds() sets the user bounding volume, while get_bounds()
00271   // returns the external bounding volume.  Although it might seem
00272   // strange and confusing to do this, this is actually the natural
00273   // way the user thinks about nodes and bounding volumes.
00274   void set_bounds_type(BoundingVolume::BoundsType bounds_type);
00275   BoundingVolume::BoundsType get_bounds_type() const;
00276 
00277   void set_bounds(const BoundingVolume *volume);
00278   void set_bound(const BoundingVolume *volume);
00279   INLINE void clear_bounds();
00280   CPT(BoundingVolume) get_bounds(Thread *current_thread = Thread::get_current_thread()) const;
00281   CPT(BoundingVolume) get_bounds(UpdateSeq &seq, Thread *current_thread = Thread::get_current_thread()) const;
00282   int get_nested_vertices(Thread *current_thread = Thread::get_current_thread()) const;
00283   INLINE CPT(BoundingVolume) get_internal_bounds(Thread *current_thread = Thread::get_current_thread()) const;
00284   INLINE int get_internal_vertices(Thread *current_thread = Thread::get_current_thread()) const;
00285 
00286   void mark_bounds_stale(Thread *current_thread = Thread::get_current_thread()) const;
00287   void mark_internal_bounds_stale(Thread *current_thread = Thread::get_current_thread());
00288   INLINE bool is_bounds_stale() const;
00289 
00290   INLINE void set_final(bool flag);
00291   INLINE bool is_final(Thread *current_thread = Thread::get_current_thread()) const;
00292 
00293   virtual bool is_geom_node() const;
00294   virtual bool is_lod_node() const;
00295   virtual bool is_collision_node() const;
00296   virtual Light *as_light();
00297   virtual bool is_ambient_light() const;
00298 
00299   enum FancyBits {
00300     FB_transform            = 0x0001,
00301     FB_state                = 0x0002,
00302     FB_effects              = 0x0004,
00303     FB_tag                  = 0x0010,
00304     FB_draw_mask            = 0x0020,
00305     FB_cull_callback        = 0x0040,
00306   };
00307   INLINE int get_fancy_bits(Thread *current_thread = Thread::get_current_thread()) const;
00308 
00309 
00310 PUBLISHED:
00311   static PT(PandaNode) decode_from_bam_stream(const string &data, BamReader *reader = NULL);
00312 
00313 protected:
00314   class BoundsData;
00315 
00316   INLINE CPT(BoundingVolume) get_user_bounds(int pipeline_stage, Thread *current_thread) const;
00317   CPT(BoundingVolume) get_internal_bounds(int pipeline_stage, Thread *current_thread) const;
00318   int get_internal_vertices(int pipeline_stage, Thread *current_thread) const;
00319   void set_internal_bounds(const BoundingVolume *volume);
00320 
00321   INLINE void mark_bounds_stale(int pipeline_stage, Thread *current_thread) const;
00322   void force_bounds_stale(Thread *current_thread = Thread::get_current_thread());
00323   void force_bounds_stale(int pipeline_stage, Thread *current_thread);
00324   INLINE void mark_internal_bounds_stale(int pipeline_stage, Thread *current_thread);
00325 
00326   virtual void r_mark_geom_bounds_stale(Thread *current_thread);
00327 
00328   virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00329                                        int &internal_vertices,
00330                                        int pipeline_stage,
00331                                        Thread *current_thread) const;
00332   virtual void parents_changed();
00333   virtual void children_changed();
00334   virtual void transform_changed();
00335   virtual void state_changed();
00336   virtual void draw_mask_changed();
00337 
00338   typedef pmap<PandaNode *, PandaNode *> InstanceMap;
00339   virtual PT(PandaNode) r_copy_subgraph(InstanceMap &inst_map,
00340                                         Thread *current_thread) const;
00341   virtual void r_copy_children(const PandaNode *from, InstanceMap &inst_map,
00342                                Thread *current_thread);
00343 
00344   void set_cull_callback();
00345   void disable_cull_callback();
00346 public:
00347   virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg,
00348                                const RenderState *node_state,
00349                                GeomTransformer &transformer,
00350                                Thread *current_thread);
00351 
00352 protected:
00353   // This is a base class of CData, defined below.  It contains just
00354   // the protected (not private) part of CData that will be needed by
00355   // derived classes to implement compute_internal_bounds().
00356   class EXPCL_PANDA_PGRAPH BoundsData : public CycleData {
00357   protected:
00358     INLINE BoundsData();
00359     INLINE BoundsData(const BoundsData &copy);
00360     INLINE void copy_bounds(const BoundsData &copy);
00361 
00362   public:
00363     // This is the "internal" bounding volume, which is normally
00364     // empty, but which a particular PandaNode subclass may define to
00365     // be any arbitrary volume, by calling set_internal_bounds() or by
00366     // overriding compute_internal_bounds().
00367     CPT(BoundingVolume) _internal_bounds;
00368     int _internal_vertices;
00369     UpdateSeq _internal_bounds_mark;     // incremented on mark_stale
00370     UpdateSeq _internal_bounds_computed; // set to above when computing
00371   };
00372 
00373 private:
00374   class CData;
00375 
00376   INLINE int do_find_parent(PandaNode *node, const CData *cdata) const;
00377   bool stage_remove_child(PandaNode *child_node, int pipeline_stage,
00378                           Thread *current_thread);
00379   bool stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
00380                            int pipeline_stage, Thread *current_thread);
00381 
00382   void quick_add_new_child(PandaNode *child_node, int sort,
00383                            Thread *current_thread);
00384 
00385   INLINE bool verify_child_no_cycles(PandaNode *child_node);
00386   void report_cycle(PandaNode *node);
00387   bool find_node_above(PandaNode *node);
00388 
00389   // parent-child manipulation for NodePath support.  Don't try to
00390   // call these directly.
00391   static PT(NodePathComponent) attach(NodePathComponent *parent, 
00392                                       PandaNode *child, int sort,
00393                                       int pipeline_stage, Thread *current_thread);
00394   static void detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread);
00395   static void detach_one_stage(NodePathComponent *child, int pipeline_stage, Thread *current_thread);
00396   static bool reparent(NodePathComponent *new_parent,
00397                        NodePathComponent *child, int sort, bool as_stashed,
00398                        int pipeline_stage, Thread *current_thread);
00399   static bool reparent_one_stage(NodePathComponent *new_parent,
00400                                  NodePathComponent *child, int sort, 
00401                                  bool as_stashed, int pipeline_stage, Thread *current_thread);
00402   static PT(NodePathComponent) get_component(NodePathComponent *parent,
00403                                              PandaNode *child,
00404                                              int pipeline_stage, Thread *current_thread);
00405   static PT(NodePathComponent) get_top_component(PandaNode *child, bool force,
00406                                                  int pipeline_stage, Thread *current_thread);
00407   PT(NodePathComponent) get_generic_component(bool accept_ambiguity,
00408                                               int pipeline_stage, Thread *current_thread);
00409   PT(NodePathComponent) r_get_generic_component(bool accept_ambiguity, 
00410                                                 bool &ambiguity_detected,
00411                                                 int pipeline_stage, Thread *current_thread);
00412   void delete_component(NodePathComponent *component);
00413   static void sever_connection(PandaNode *parent_node, PandaNode *child_node,
00414                                int pipeline_stage, Thread *current_thread);
00415   static void new_connection(PandaNode *parent_node, PandaNode *child_node,
00416                              int pipeline_stage, Thread *current_thread);
00417   void fix_path_lengths(int pipeline_stage, Thread *current_thread);
00418   void r_list_descendants(ostream &out, int indent_level) const;
00419   
00420   INLINE void do_set_dirty_prev_transform();
00421   INLINE void do_clear_dirty_prev_transform();
00422 
00423 public:
00424   // This must be declared public so that VC6 will allow the nested
00425   // CData class to access it.
00426   class EXPCL_PANDA_PGRAPH DownConnection {
00427   public:
00428     INLINE DownConnection(PandaNode *child, int sort);
00429     INLINE bool operator < (const DownConnection &other) const;
00430     INLINE PandaNode *get_child() const;
00431     INLINE void set_child(PandaNode *child);
00432     INLINE int get_sort() const;
00433 
00434   private:
00435     // Child pointers are reference counted.  That way, holding a
00436     // pointer to the root of a subgraph keeps the entire subgraph
00437     // around.
00438     PT(PandaNode) _child;
00439     int _sort;
00440   };
00441 
00442 private:
00443   typedef ov_multiset<DownConnection> DownList;
00444   typedef CopyOnWriteObj1< DownList, TypeHandle > Down;
00445 
00446   // Store a pointer to the down_list during the bam read pass.
00447   class EXPCL_PANDA_PGRAPH BamReaderAuxDataDown : public BamReaderAuxData {
00448   public:
00449     INLINE BamReaderAuxDataDown();
00450     Down _down_list;
00451   public:
00452     virtual TypeHandle get_type() const {
00453       return get_class_type();
00454     }
00455     virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00456     static TypeHandle get_class_type() {
00457       return _type_handle;
00458     }
00459     
00460   public:
00461     static void init_type() {
00462       BamReaderAuxData::init_type();
00463       register_type(_type_handle, "BamReaderAuxDataDown",
00464                     BamReaderAuxData::get_class_type());
00465     }
00466     
00467   private:
00468     static TypeHandle _type_handle;
00469   };
00470 
00471   class EXPCL_PANDA_PGRAPH UpConnection {
00472   public:
00473     INLINE UpConnection(PandaNode *child);
00474     INLINE bool operator < (const UpConnection &other) const;
00475     INLINE PandaNode *get_parent() const;
00476 
00477   private:
00478     // Parent pointers are not reference counted.  That way, parents and
00479     // children do not circularly reference each other.
00480     PandaNode *_parent;
00481   };
00482   typedef ov_set<UpConnection> UpList;
00483   typedef CopyOnWriteObj1< UpList, TypeHandle > Up;
00484 
00485   // We also maintain a set of NodePathComponents in the node.  This
00486   // represents the set of instances of this node that we have
00487   // requested a NodePath for.  We don't keep reference counts; when
00488   // each NodePathComponent destructs, it removes itself from this
00489   // set.
00490   typedef phash_set<NodePathComponent *, pointer_hash> Paths;
00491 
00492   // We don't cycle the set of Paths, since these are across all
00493   // threads.  A NodePathComponent, once created, is always associated
00494   // with the same node.  We do, however, protect the Paths under a mutex.
00495   Paths _paths;
00496   LightReMutex _paths_lock;
00497 
00498   bool _dirty_prev_transform;
00499   static PandaNodeChain _dirty_prev_transforms;
00500 
00501   // This is used to maintain a table of keyed data on each node, for
00502   // the user's purposes.
00503   typedef phash_map<string, string, string_hash> TagData;
00504 #ifdef HAVE_PYTHON
00505   typedef phash_map<string, PyObject *, string_hash> PythonTagData;
00506 #endif  // HAVE_PYTHON
00507 
00508 #ifndef NDEBUG
00509   unsigned int _unexpected_change_flags;
00510 #endif // !NDEBUG
00511   
00512   // This is the data that must be cycled between pipeline stages. 
00513 
00514   class EXPCL_PANDA_PGRAPH CData : public BoundsData {
00515   public:
00516     CData();
00517     CData(const CData &copy);
00518     virtual ~CData();
00519     ALLOC_DELETED_CHAIN(CData);
00520 
00521     virtual CycleData *make_copy() const;
00522     virtual void write_datagram(BamWriter *manager, Datagram &dg) const; 
00523     void update_bam_nested(BamWriter *manager) const;
00524     virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
00525     virtual void fillin(DatagramIterator &scan, BamReader *manager);
00526     virtual TypeHandle get_parent_type() const {
00527       return PandaNode::get_class_type();
00528     }
00529 
00530   public:
00531     // This section contains the lightweight parts of the node that
00532     // are likely to change fairly often: transform and state.
00533 
00534     NCPT(RenderState) _state;
00535     NCPT(TransformState) _transform;
00536     NCPT(TransformState) _prev_transform;
00537 
00538   public:
00539     // This section contains the heavierweight parts of the node that
00540     // are less likely to change as often: tags, collide mask.
00541 
00542     INLINE void set_fancy_bit(int bits, bool value);
00543     
00544 #ifdef HAVE_PYTHON
00545     void inc_py_refs();
00546     void dec_py_refs();
00547 #endif
00548 
00549     CPT(RenderEffects) _effects;
00550 
00551     TagData _tag_data;
00552 #ifdef HAVE_PYTHON
00553     PythonTagData _python_tag_data;
00554 #endif  // HAVE_PYTHON
00555 
00556     // These two together determine the per-camera visibility of this
00557     // node.  See adjust_draw_mask() for details.
00558     DrawMask _draw_control_mask, _draw_show_mask;
00559 
00560     // This is the mask that indicates which CollisionNodes may detect
00561     // a collision with this particular node.  By default it is zero
00562     // for an ordinary PandaNode, and all bits on for a CollisionNode
00563     // or GeomNode.
00564     CollideMask _into_collide_mask;
00565 
00566     // The requested bounding volume type.
00567     BoundingVolume::BoundsType _bounds_type;
00568 
00569     // This is the user bounding volume, which is only specified by a
00570     // user.  It defaults to NULL, which means an empty volume.
00571     CPT(BoundingVolume) _user_bounds;
00572 
00573     // See BoundsData, above, for _internal_bounds.
00574 
00575     // This is true if the external bounds of this node should be
00576     // deemed "final".  See set_final().
00577     bool _final_bounds;
00578 
00579     // This bitmask is maintained automatically by the internal
00580     // PandaNode code; it contains a 1 for each "fancy" attribute that
00581     // is set on the node.  See enum FancyBits, above.
00582     int _fancy_bits;
00583 
00584   public:
00585     // This section contains the data that is accumulated upward from
00586     // the node's children: that is, the external bounding volume, and
00587     // conceptually similar things like the net_collide_mask, etc.
00588     // None of the data in this object is preserved in a bam file.
00589 
00590     // This is the union of all into_collide_mask bits for any nodes
00591     // at and below this level.
00592     CollideMask _net_collide_mask;
00593 
00594     // These are similar, for the draw mask.
00595     DrawMask _net_draw_control_mask, _net_draw_show_mask;
00596 
00597     // This is a ClipPlaneAttrib that represents the union of all clip
00598     // planes that have been turned *off* at and below this level.
00599     // TODO: fix the circular reference counts involved here.
00600     CPT(RenderAttrib) _off_clip_planes;
00601 
00602     // The number of vertices rendered by this node and all child
00603     // nodes.
00604     int _nested_vertices;
00605 
00606     // This is the bounding volume around the _user_bounds, the
00607     // _internal_bounds, and all of the children's external bounding
00608     // volumes.
00609     CPT(BoundingVolume) _external_bounds;
00610 
00611     // When _last_update != _next_update, this cache is stale.
00612     UpdateSeq _last_update, _next_update;
00613 
00614   public:
00615     // This section stores the links to other nodes above and below
00616     // this node in the graph.
00617 
00618     void write_up_list(const Up &up_list,
00619                        BamWriter *manager, Datagram &dg) const;
00620     void write_down_list(const Down &down_list,
00621                          BamWriter *manager, Datagram &dg) const;
00622     void update_up_list(const Up &up_list, BamWriter *manager) const;
00623     void update_down_list(const Down &down_list, BamWriter *manager) const;
00624     int complete_up_list(Up &up_list, const string &tag,
00625                          TypedWritable **p_list, BamReader *manager);
00626     int complete_down_list(Down &down_list, const string &tag,
00627                            TypedWritable **p_list, BamReader *manager);
00628     void fillin_up_list(Up &up_list, const string &tag,
00629                         DatagramIterator &scan, BamReader *manager);
00630     void fillin_down_list(Down &down_list, const string &tag,
00631                           DatagramIterator &scan, BamReader *manager);
00632 
00633     INLINE CPT(Down) get_down() const;
00634     INLINE PT(Down) modify_down();
00635     INLINE CPT(Down) get_stashed() const;
00636     INLINE PT(Down) modify_stashed();
00637     INLINE CPT(Up) get_up() const;
00638     INLINE PT(Up) modify_up();
00639 
00640   private:
00641     // We store the child lists by reference, so we can copy them
00642     // quickly.  We perform copy-on-write when necessary.
00643     COWPT(Down) _down;
00644     COWPT(Down) _stashed;
00645     COWPT(Up) _up;
00646     
00647   public:
00648     static TypeHandle get_class_type() {
00649       return _type_handle;
00650     }
00651     static void init_type() {
00652       register_type(_type_handle, "PandaNode::CData");
00653     }
00654     
00655   private:
00656     static TypeHandle _type_handle;
00657   };
00658 
00659   PipelineCycler<CData> _cycler;
00660   typedef CycleDataReader<CData> CDReader;
00661   typedef CycleDataWriter<CData> CDWriter;
00662   typedef CycleDataLockedStageReader<CData> CDLockedStageReader;
00663   typedef CycleDataStageReader<CData> CDStageReader;
00664   typedef CycleDataStageWriter<CData> CDStageWriter;
00665 
00666   int do_find_child(PandaNode *node, const Down *down) const;
00667   CDStageWriter update_bounds(int pipeline_stage, CDLockedStageReader &cdata);
00668 
00669   static DrawMask _overall_bit;
00670 
00671   static PStatCollector _reset_prev_pcollector;
00672   static PStatCollector _update_bounds_pcollector;
00673 
00674 public:
00675   // This class is returned from get_children().  Use it to walk
00676   // through the list of children.  This is faster, and safer, than
00677   // walking through the children one at a time via
00678   // get_num_children()/get_child(), since the list of children is
00679   // saved out ahead of time, rather than having to reacquire the lock
00680   // with each iteration, or to keep the lock held for the entire
00681   // pass.
00682   class EXPCL_PANDA_PGRAPH Children {
00683   public:
00684     INLINE Children();
00685     INLINE Children(const CData *cdata);
00686     INLINE Children(const Children &copy);
00687     INLINE void operator = (const Children &copy);
00688 
00689     INLINE int get_num_children() const;
00690     INLINE PandaNode *get_child(int n) const;
00691     INLINE int get_child_sort(int n) const;
00692 
00693   private:
00694     CPT(Down) _down;
00695   };
00696 
00697   // Similarly for stashed children.
00698   class EXPCL_PANDA_PGRAPH Stashed {
00699   public:
00700     INLINE Stashed();
00701     INLINE Stashed(const CData *cdata);
00702     INLINE Stashed(const Stashed &copy);
00703     INLINE void operator = (const Stashed &copy);
00704 
00705     INLINE int get_num_stashed() const;
00706     INLINE PandaNode *get_stashed(int n) const;
00707     INLINE int get_stashed_sort(int n) const;
00708 
00709   private:
00710     CPT(Down) _stashed;
00711   };
00712 
00713   // This class is returned from get_parents().
00714   class EXPCL_PANDA_PGRAPH Parents {
00715   public:
00716     INLINE Parents();
00717     INLINE Parents(const CData *cdata);
00718     INLINE Parents(const Parents &copy);
00719     INLINE void operator = (const Parents &copy);
00720 
00721     INLINE int get_num_parents() const;
00722     INLINE PandaNode *get_parent(int n) const;
00723 
00724   private:
00725     CPT(Up) _up;
00726   };
00727 
00728   INLINE Children get_children(Thread *current_thread = Thread::get_current_thread()) const;
00729   INLINE Stashed get_stashed(Thread *current_thread = Thread::get_current_thread()) const;
00730   INLINE Parents get_parents(Thread *current_thread = Thread::get_current_thread()) const;
00731 
00732   typedef bool SceneRootFunc(const PandaNode *);
00733   static void set_scene_root_func(SceneRootFunc *func);
00734 
00735 private:
00736   static SceneRootFunc *_scene_root_func;
00737 
00738 public:
00739   static void register_with_read_factory();
00740   virtual void write_datagram(BamWriter *manager, Datagram &dg);
00741   virtual void update_bam_nested(BamWriter *manager);
00742   void write_recorder(BamWriter *manager, Datagram &dg);
00743 
00744 protected:
00745   static TypedWritable *make_from_bam(const FactoryParams &params);
00746   void fillin(DatagramIterator &scan, BamReader *manager);
00747   void fillin_recorder(DatagramIterator &scan, BamReader *manager);
00748   
00749 public:
00750   static TypeHandle get_class_type() {
00751     return _type_handle;
00752   }
00753   static void init_type() {
00754     TypedWritable::init_type();
00755     ReferenceCount::init_type();
00756     Namable::init_type();
00757     register_type(_type_handle, "PandaNode",
00758                   TypedWritable::get_class_type(),
00759                   ReferenceCount::get_class_type(),
00760                   Namable::get_class_type());
00761     CData::init_type();
00762     Down::init_type();
00763     Up::init_type();
00764     BamReaderAuxDataDown::init_type();
00765   }
00766   virtual TypeHandle get_type() const {
00767     return get_class_type();
00768   }
00769   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00770 
00771 private:
00772   static TypeHandle _type_handle;
00773 
00774 #ifndef DO_PIPELINING
00775   friend class PandaNode::Children;
00776   friend class PandaNode::Stashed;
00777 #endif
00778   friend class NodePath;
00779   friend class NodePathComponent;
00780   friend class WorkingNodePath;
00781   friend class PandaNodePipelineReader;
00782   friend class EggLoader;
00783 };
00784 
00785 ////////////////////////////////////////////////////////////////////
00786 //       Class : PandaNodePipelineReader
00787 // Description : Encapsulates the data from a PandaNode,
00788 //               pre-fetched for one stage of the pipeline.
00789 ////////////////////////////////////////////////////////////////////
00790 class EXPCL_PANDA_PGRAPH PandaNodePipelineReader {
00791 public:
00792   INLINE PandaNodePipelineReader(const PandaNode *object, Thread *current_thread);
00793   INLINE PandaNodePipelineReader(const PandaNodePipelineReader &copy);
00794   INLINE void operator = (const PandaNodePipelineReader &copy);
00795 
00796 public:
00797   INLINE ~PandaNodePipelineReader();
00798   ALLOC_DELETED_CHAIN(PandaNodePipelineReader);
00799 
00800   INLINE const PandaNode *get_object() const;
00801   INLINE Thread *get_current_thread() const;
00802 
00803   INLINE void release();
00804 
00805   void check_bounds() const;
00806 
00807   INLINE void compose_draw_mask(DrawMask &running_draw_mask) const;
00808   INLINE bool compare_draw_mask(DrawMask running_draw_mask,
00809                                 DrawMask camera_mask) const;
00810   
00811   INLINE int get_num_parents() const;
00812   INLINE PandaNode *get_parent(int n) const;
00813   INLINE int find_parent(PandaNode *node) const;
00814 
00815   INLINE int get_num_children() const;
00816   INLINE PandaNode *get_child(int n) const;
00817   INLINE int get_child_sort(int n) const;
00818   INLINE int find_child(PandaNode *node) const;
00819 
00820   INLINE int get_num_stashed() const;
00821   INLINE PandaNode *get_stashed(int n) const;
00822   INLINE int get_stashed_sort(int n) const;
00823   INLINE int find_stashed(PandaNode *node) const;
00824 
00825   INLINE const RenderState *get_state() const;
00826   INLINE const RenderEffects *get_effects() const;
00827   INLINE const TransformState *get_transform() const;
00828   INLINE const TransformState *get_prev_transform() const;
00829 
00830   INLINE string get_tag(const string &key) const;
00831   INLINE bool has_tag(const string &key) const;
00832 
00833   INLINE CollideMask get_net_collide_mask() const;
00834   INLINE CPT(RenderAttrib) get_off_clip_planes() const;
00835   INLINE CPT(BoundingVolume) get_bounds() const;
00836   INLINE int get_nested_vertices() const;
00837   INLINE bool is_final() const;
00838   INLINE int get_fancy_bits() const;
00839 
00840   INLINE PandaNode::Children get_children() const;
00841   INLINE PandaNode::Stashed get_stashed() const;
00842   INLINE PandaNode::Parents get_parents() const;
00843 
00844 private:
00845   const PandaNode *_object;
00846   Thread *_current_thread;
00847 
00848   const PandaNode::CData *_cdata;
00849 
00850 public:
00851   static TypeHandle get_class_type() {
00852     return _type_handle;
00853   }
00854   static void init_type() {
00855     register_type(_type_handle, "PandaNodePipelineReader");
00856   }
00857 
00858 private:
00859   static TypeHandle _type_handle;
00860 
00861 };
00862 
00863 INLINE ostream &operator << (ostream &out, const PandaNode &node) {
00864   node.output(out);
00865   return out;
00866 }
00867 
00868 #include "pandaNode.I"
00869 
00870 #endif
00871 
 All Classes Functions Variables Enumerations