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 LMatrix4f &mat);
00101 
00102   virtual CPT(TransformState)
00103     calc_tight_bounds(LPoint3f &min_point, LPoint3f &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 *net_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 Light *as_light();
00296   virtual bool is_ambient_light() const;
00297 
00298   enum FancyBits {
00299     FB_transform            = 0x0001,
00300     FB_state                = 0x0002,
00301     FB_effects              = 0x0004,
00302     FB_tag                  = 0x0010,
00303     FB_draw_mask            = 0x0020,
00304     FB_cull_callback        = 0x0040,
00305   };
00306   INLINE int get_fancy_bits(Thread *current_thread = Thread::get_current_thread()) const;
00307 
00308 
00309 PUBLISHED:
00310   static PT(PandaNode) decode_from_bam_stream(const string &data, BamReader *reader = NULL);
00311 
00312 protected:
00313   class BoundsData;
00314 
00315   INLINE CPT(BoundingVolume) get_user_bounds(int pipeline_stage, Thread *current_thread) const;
00316   CPT(BoundingVolume) get_internal_bounds(int pipeline_stage, Thread *current_thread) const;
00317   int get_internal_vertices(int pipeline_stage, Thread *current_thread) const;
00318   void set_internal_bounds(const BoundingVolume *volume);
00319 
00320   INLINE void mark_bounds_stale(int pipeline_stage, Thread *current_thread) const;
00321   void force_bounds_stale(Thread *current_thread = Thread::get_current_thread());
00322   void force_bounds_stale(int pipeline_stage, Thread *current_thread);
00323   INLINE void mark_internal_bounds_stale(int pipeline_stage, Thread *current_thread);
00324 
00325   virtual void r_mark_geom_bounds_stale(Thread *current_thread);
00326 
00327   virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00328                                        int &internal_vertices,
00329                                        int pipeline_stage,
00330                                        Thread *current_thread) const;
00331   virtual void parents_changed();
00332   virtual void children_changed();
00333   virtual void transform_changed();
00334   virtual void state_changed();
00335   virtual void draw_mask_changed();
00336 
00337   typedef pmap<PandaNode *, PandaNode *> InstanceMap;
00338   virtual PT(PandaNode) r_copy_subgraph(InstanceMap &inst_map,
00339                                         Thread *current_thread) const;
00340   virtual void r_copy_children(const PandaNode *from, InstanceMap &inst_map,
00341                                Thread *current_thread);
00342 
00343   void set_cull_callback();
00344   void disable_cull_callback();
00345 public:
00346   virtual void r_prepare_scene(const RenderState *state,
00347                                PreparedGraphicsObjects *prepared_objects,
00348                                Thread *current_thread);
00349 
00350 protected:
00351   // This is a base class of CData, defined below.  It contains just
00352   // the protected (not private) part of CData that will be needed by
00353   // derived classes to implement compute_internal_bounds().
00354   class EXPCL_PANDA_PGRAPH BoundsData : public CycleData {
00355   protected:
00356     INLINE BoundsData();
00357     INLINE BoundsData(const BoundsData &copy);
00358     INLINE void copy_bounds(const BoundsData &copy);
00359 
00360   public:
00361     // This is the "internal" bounding volume, which is normally
00362     // empty, but which a particular PandaNode subclass may define to
00363     // be any arbitrary volume, by calling set_internal_bounds() or by
00364     // overriding compute_internal_bounds().
00365     CPT(BoundingVolume) _internal_bounds;
00366     int _internal_vertices;
00367     UpdateSeq _internal_bounds_mark;     // incremented on mark_stale
00368     UpdateSeq _internal_bounds_computed; // set to above when computing
00369   };
00370 
00371 private:
00372   class CData;
00373 
00374   INLINE int do_find_parent(PandaNode *node, const CData *cdata) const;
00375   bool stage_remove_child(PandaNode *child_node, int pipeline_stage,
00376                           Thread *current_thread);
00377   bool stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
00378                            int pipeline_stage, Thread *current_thread);
00379 
00380   void quick_add_new_child(PandaNode *child_node, int sort,
00381                            Thread *current_thread);
00382 
00383   INLINE bool verify_child_no_cycles(PandaNode *child_node);
00384   void report_cycle(PandaNode *node);
00385   bool find_node_above(PandaNode *node);
00386 
00387   // parent-child manipulation for NodePath support.  Don't try to
00388   // call these directly.
00389   static PT(NodePathComponent) attach(NodePathComponent *parent, 
00390                                       PandaNode *child, int sort,
00391                                       int pipeline_stage, Thread *current_thread);
00392   static void detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread);
00393   static void detach_one_stage(NodePathComponent *child, int pipeline_stage, Thread *current_thread);
00394   static bool reparent(NodePathComponent *new_parent,
00395                        NodePathComponent *child, int sort, bool as_stashed,
00396                        int pipeline_stage, Thread *current_thread);
00397   static bool reparent_one_stage(NodePathComponent *new_parent,
00398                                  NodePathComponent *child, int sort, 
00399                                  bool as_stashed, int pipeline_stage, Thread *current_thread);
00400   static PT(NodePathComponent) get_component(NodePathComponent *parent,
00401                                              PandaNode *child,
00402                                              int pipeline_stage, Thread *current_thread);
00403   static PT(NodePathComponent) get_top_component(PandaNode *child, bool force,
00404                                                  int pipeline_stage, Thread *current_thread);
00405   PT(NodePathComponent) get_generic_component(bool accept_ambiguity,
00406                                               int pipeline_stage, Thread *current_thread);
00407   PT(NodePathComponent) r_get_generic_component(bool accept_ambiguity, 
00408                                                 bool &ambiguity_detected,
00409                                                 int pipeline_stage, Thread *current_thread);
00410   void delete_component(NodePathComponent *component);
00411   static void sever_connection(PandaNode *parent_node, PandaNode *child_node,
00412                                int pipeline_stage, Thread *current_thread);
00413   static void new_connection(PandaNode *parent_node, PandaNode *child_node,
00414                              int pipeline_stage, Thread *current_thread);
00415   void fix_path_lengths(int pipeline_stage, Thread *current_thread);
00416   void r_list_descendants(ostream &out, int indent_level) const;
00417   
00418   INLINE void set_dirty_prev_transform();
00419   INLINE void clear_dirty_prev_transform();
00420 
00421 public:
00422   // This must be declared public so that VC6 will allow the nested
00423   // CData class to access it.
00424   class EXPCL_PANDA_PGRAPH DownConnection {
00425   public:
00426     INLINE DownConnection(PandaNode *child, int sort);
00427     INLINE bool operator < (const DownConnection &other) const;
00428     INLINE PandaNode *get_child() const;
00429     INLINE void set_child(PandaNode *child);
00430     INLINE int get_sort() const;
00431 
00432   private:
00433     // Child pointers are reference counted.  That way, holding a
00434     // pointer to the root of a subgraph keeps the entire subgraph
00435     // around.
00436     PT(PandaNode) _child;
00437     int _sort;
00438   };
00439 
00440 private:
00441   typedef ov_multiset<DownConnection> DownList;
00442   typedef CopyOnWriteObj1< DownList, TypeHandle > Down;
00443 
00444   // Store a pointer to the down_list during the bam read pass.
00445   class EXPCL_PANDA_PGRAPH BamReaderAuxDataDown : public BamReaderAuxData {
00446   public:
00447     INLINE BamReaderAuxDataDown();
00448     Down _down_list;
00449   public:
00450     virtual TypeHandle get_type() const {
00451       return get_class_type();
00452     }
00453     virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00454     static TypeHandle get_class_type() {
00455       return _type_handle;
00456     }
00457     
00458   public:
00459     static void init_type() {
00460       BamReaderAuxData::init_type();
00461       register_type(_type_handle, "BamReaderAuxDataDown",
00462                     BamReaderAuxData::get_class_type());
00463     }
00464     
00465   private:
00466     static TypeHandle _type_handle;
00467   };
00468 
00469   class EXPCL_PANDA_PGRAPH UpConnection {
00470   public:
00471     INLINE UpConnection(PandaNode *child);
00472     INLINE bool operator < (const UpConnection &other) const;
00473     INLINE PandaNode *get_parent() const;
00474 
00475   private:
00476     // Parent pointers are not reference counted.  That way, parents and
00477     // children do not circularly reference each other.
00478     PandaNode *_parent;
00479   };
00480   typedef ov_set<UpConnection> UpList;
00481   typedef CopyOnWriteObj1< UpList, TypeHandle > Up;
00482 
00483   // We also maintain a set of NodePathComponents in the node.  This
00484   // represents the set of instances of this node that we have
00485   // requested a NodePath for.  We don't keep reference counts; when
00486   // each NodePathComponent destructs, it removes itself from this
00487   // set.
00488   typedef phash_set<NodePathComponent *, pointer_hash> Paths;
00489 
00490   // We don't cycle the set of Paths, since these are across all
00491   // threads.  A NodePathComponent, once created, is always associated
00492   // with the same node.  We do, however, protect the Paths under a mutex.
00493   Paths _paths;
00494   LightReMutex _paths_lock;
00495 
00496   bool _dirty_prev_transform;
00497   static PandaNodeChain _dirty_prev_transforms;
00498 
00499   // This is used to maintain a table of keyed data on each node, for
00500   // the user's purposes.
00501   typedef phash_map<string, string, string_hash> TagData;
00502 #ifdef HAVE_PYTHON
00503   typedef phash_map<string, PyObject *, string_hash> PythonTagData;
00504 #endif  // HAVE_PYTHON
00505 
00506 #ifndef NDEBUG
00507   unsigned int _unexpected_change_flags;
00508 #endif // !NDEBUG
00509   
00510   // This is the data that must be cycled between pipeline stages. 
00511 
00512   class EXPCL_PANDA_PGRAPH CData : public BoundsData {
00513   public:
00514     CData();
00515     CData(const CData &copy);
00516     virtual ~CData();
00517     ALLOC_DELETED_CHAIN(CData);
00518 
00519     virtual CycleData *make_copy() const;
00520     virtual void write_datagram(BamWriter *manager, Datagram &dg) const; 
00521     void update_bam_nested(BamWriter *manager) const;
00522     virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
00523     virtual void fillin(DatagramIterator &scan, BamReader *manager);
00524     virtual TypeHandle get_parent_type() const {
00525       return PandaNode::get_class_type();
00526     }
00527 
00528   public:
00529     // This section contains the lightweight parts of the node that
00530     // are likely to change fairly often: transform and state.
00531 
00532     NCPT(RenderState) _state;
00533     NCPT(TransformState) _transform;
00534     NCPT(TransformState) _prev_transform;
00535 
00536   public:
00537     // This section contains the heavierweight parts of the node that
00538     // are less likely to change as often: tags, collide mask.
00539 
00540     INLINE void set_fancy_bit(int bits, bool value);
00541     
00542 #ifdef HAVE_PYTHON
00543     void inc_py_refs();
00544     void dec_py_refs();
00545 #endif
00546 
00547     CPT(RenderEffects) _effects;
00548 
00549     TagData _tag_data;
00550 #ifdef HAVE_PYTHON
00551     PythonTagData _python_tag_data;
00552 #endif  // HAVE_PYTHON
00553 
00554     // These two together determine the per-camera visibility of this
00555     // node.  See adjust_draw_mask() for details.
00556     DrawMask _draw_control_mask, _draw_show_mask;
00557 
00558     // This is the mask that indicates which CollisionNodes may detect
00559     // a collision with this particular node.  By default it is zero
00560     // for an ordinary PandaNode, and all bits on for a CollisionNode
00561     // or GeomNode.
00562     CollideMask _into_collide_mask;
00563 
00564     // The requested bounding volume type.
00565     BoundingVolume::BoundsType _bounds_type;
00566 
00567     // This is the user bounding volume, which is only specified by a
00568     // user.  It defaults to NULL, which means an empty volume.
00569     CPT(BoundingVolume) _user_bounds;
00570 
00571     // See BoundsData, above, for _internal_bounds.
00572 
00573     // This is true if the external bounds of this node should be
00574     // deemed "final".  See set_final().
00575     bool _final_bounds;
00576 
00577     // This bitmask is maintained automatically by the internal
00578     // PandaNode code; it contains a 1 for each "fancy" attribute that
00579     // is set on the node.  See enum FancyBits, above.
00580     int _fancy_bits;
00581 
00582   public:
00583     // This section contains the data that is accumulated upward from
00584     // the node's children: that is, the external bounding volume, and
00585     // conceptually similar things like the net_collide_mask, etc.
00586     // None of the data in this object is preserved in a bam file.
00587 
00588     // This is the union of all into_collide_mask bits for any nodes
00589     // at and below this level.
00590     CollideMask _net_collide_mask;
00591 
00592     // These are similar, for the draw mask.
00593     DrawMask _net_draw_control_mask, _net_draw_show_mask;
00594 
00595     // This is a ClipPlaneAttrib that represents the union of all clip
00596     // planes that have been turned *off* at and below this level.
00597     // TODO: fix the circular reference counts involved here.
00598     CPT(RenderAttrib) _off_clip_planes;
00599 
00600     // The number of vertices rendered by this node and all child
00601     // nodes.
00602     int _nested_vertices;
00603 
00604     // This is the bounding volume around the _user_bounds, the
00605     // _internal_bounds, and all of the children's external bounding
00606     // volumes.
00607     CPT(BoundingVolume) _external_bounds;
00608 
00609     // When _last_update != _next_update, this cache is stale.
00610     UpdateSeq _last_update, _next_update;
00611 
00612   public:
00613     // This section stores the links to other nodes above and below
00614     // this node in the graph.
00615 
00616     void write_up_list(const Up &up_list,
00617                        BamWriter *manager, Datagram &dg) const;
00618     void write_down_list(const Down &down_list,
00619                          BamWriter *manager, Datagram &dg) const;
00620     void update_up_list(const Up &up_list, BamWriter *manager) const;
00621     void update_down_list(const Down &down_list, BamWriter *manager) const;
00622     int complete_up_list(Up &up_list, const string &tag,
00623                          TypedWritable **p_list, BamReader *manager);
00624     int complete_down_list(Down &down_list, const string &tag,
00625                            TypedWritable **p_list, BamReader *manager);
00626     void fillin_up_list(Up &up_list, const string &tag,
00627                         DatagramIterator &scan, BamReader *manager);
00628     void fillin_down_list(Down &down_list, const string &tag,
00629                           DatagramIterator &scan, BamReader *manager);
00630 
00631     INLINE CPT(Down) get_down() const;
00632     INLINE PT(Down) modify_down();
00633     INLINE CPT(Down) get_stashed() const;
00634     INLINE PT(Down) modify_stashed();
00635     INLINE CPT(Up) get_up() const;
00636     INLINE PT(Up) modify_up();
00637 
00638   private:
00639     // We store the child lists by reference, so we can copy them
00640     // quickly.  We perform copy-on-write when necessary.
00641     COWPT(Down) _down;
00642     COWPT(Down) _stashed;
00643     COWPT(Up) _up;
00644     
00645   public:
00646     static TypeHandle get_class_type() {
00647       return _type_handle;
00648     }
00649     static void init_type() {
00650       register_type(_type_handle, "PandaNode::CData");
00651     }
00652     
00653   private:
00654     static TypeHandle _type_handle;
00655   };
00656 
00657   PipelineCycler<CData> _cycler;
00658   typedef CycleDataReader<CData> CDReader;
00659   typedef CycleDataWriter<CData> CDWriter;
00660   typedef CycleDataLockedStageReader<CData> CDLockedStageReader;
00661   typedef CycleDataStageReader<CData> CDStageReader;
00662   typedef CycleDataStageWriter<CData> CDStageWriter;
00663 
00664   int do_find_child(PandaNode *node, const Down *down) const;
00665   CDStageWriter update_bounds(int pipeline_stage, CDLockedStageReader &cdata);
00666 
00667   static DrawMask _overall_bit;
00668 
00669   static PStatCollector _reset_prev_pcollector;
00670   static PStatCollector _update_bounds_pcollector;
00671 
00672 public:
00673   // This class is returned from get_children().  Use it to walk
00674   // through the list of children.  This is faster, and safer, than
00675   // walking through the children one at a time via
00676   // get_num_children()/get_child(), since the list of children is
00677   // saved out ahead of time, rather than having to reacquire the lock
00678   // with each iteration, or to keep the lock held for the entire
00679   // pass.
00680   class EXPCL_PANDA_PGRAPH Children {
00681   public:
00682     INLINE Children();
00683     INLINE Children(const CData *cdata);
00684     INLINE Children(const Children &copy);
00685     INLINE void operator = (const Children &copy);
00686 
00687     INLINE int get_num_children() const;
00688     INLINE PandaNode *get_child(int n) const;
00689     INLINE int get_child_sort(int n) const;
00690 
00691   private:
00692     CPT(Down) _down;
00693   };
00694 
00695   // Similarly for stashed children.
00696   class EXPCL_PANDA_PGRAPH Stashed {
00697   public:
00698     INLINE Stashed();
00699     INLINE Stashed(const CData *cdata);
00700     INLINE Stashed(const Stashed &copy);
00701     INLINE void operator = (const Stashed &copy);
00702 
00703     INLINE int get_num_stashed() const;
00704     INLINE PandaNode *get_stashed(int n) const;
00705     INLINE int get_stashed_sort(int n) const;
00706 
00707   private:
00708     CPT(Down) _stashed;
00709   };
00710 
00711   // This class is returned from get_parents().
00712   class EXPCL_PANDA_PGRAPH Parents {
00713   public:
00714     INLINE Parents();
00715     INLINE Parents(const CData *cdata);
00716     INLINE Parents(const Parents &copy);
00717     INLINE void operator = (const Parents &copy);
00718 
00719     INLINE int get_num_parents() const;
00720     INLINE PandaNode *get_parent(int n) const;
00721 
00722   private:
00723     CPT(Up) _up;
00724   };
00725 
00726   INLINE Children get_children(Thread *current_thread = Thread::get_current_thread()) const;
00727   INLINE Stashed get_stashed(Thread *current_thread = Thread::get_current_thread()) const;
00728   INLINE Parents get_parents(Thread *current_thread = Thread::get_current_thread()) const;
00729 
00730   typedef bool SceneRootFunc(const PandaNode *);
00731   static void set_scene_root_func(SceneRootFunc *func);
00732 
00733 private:
00734   static SceneRootFunc *_scene_root_func;
00735 
00736 public:
00737   static void register_with_read_factory();
00738   virtual void write_datagram(BamWriter *manager, Datagram &dg);
00739   virtual void update_bam_nested(BamWriter *manager);
00740   void write_recorder(BamWriter *manager, Datagram &dg);
00741 
00742 protected:
00743   static TypedWritable *make_from_bam(const FactoryParams &params);
00744   void fillin(DatagramIterator &scan, BamReader *manager);
00745   void fillin_recorder(DatagramIterator &scan, BamReader *manager);
00746   
00747 public:
00748   static TypeHandle get_class_type() {
00749     return _type_handle;
00750   }
00751   static void init_type() {
00752     TypedWritable::init_type();
00753     ReferenceCount::init_type();
00754     register_type(_type_handle, "PandaNode",
00755                   TypedWritable::get_class_type(),
00756                   ReferenceCount::get_class_type());
00757     CData::init_type();
00758     Down::init_type();
00759     Up::init_type();
00760     BamReaderAuxDataDown::init_type();
00761   }
00762   virtual TypeHandle get_type() const {
00763     return get_class_type();
00764   }
00765   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00766 
00767 private:
00768   static TypeHandle _type_handle;
00769 
00770 #ifndef DO_PIPELINING
00771   friend class PandaNode::Children;
00772   friend class PandaNode::Stashed;
00773 #endif
00774   friend class NodePath;
00775   friend class NodePathComponent;
00776   friend class WorkingNodePath;
00777   friend class PandaNodePipelineReader;
00778   friend class EggLoader;
00779 };
00780 
00781 ////////////////////////////////////////////////////////////////////
00782 //       Class : PandaNodePipelineReader
00783 // Description : Encapsulates the data from a PandaNode,
00784 //               pre-fetched for one stage of the pipeline.
00785 ////////////////////////////////////////////////////////////////////
00786 class EXPCL_PANDA_PGRAPH PandaNodePipelineReader {
00787 public:
00788   INLINE PandaNodePipelineReader(const PandaNode *object, Thread *current_thread);
00789   INLINE PandaNodePipelineReader(const PandaNodePipelineReader &copy);
00790   INLINE void operator = (const PandaNodePipelineReader &copy);
00791 
00792 public:
00793   INLINE ~PandaNodePipelineReader();
00794   ALLOC_DELETED_CHAIN(PandaNodePipelineReader);
00795 
00796   INLINE const PandaNode *get_object() const;
00797   INLINE Thread *get_current_thread() const;
00798 
00799   INLINE void release();
00800 
00801   void check_bounds() const;
00802 
00803   INLINE void compose_draw_mask(DrawMask &running_draw_mask) const;
00804   INLINE bool compare_draw_mask(DrawMask running_draw_mask,
00805                                 DrawMask camera_mask) const;
00806   
00807   INLINE int get_num_parents() const;
00808   INLINE PandaNode *get_parent(int n) const;
00809   INLINE int find_parent(PandaNode *node) const;
00810 
00811   INLINE int get_num_children() const;
00812   INLINE PandaNode *get_child(int n) const;
00813   INLINE int get_child_sort(int n) const;
00814   INLINE int find_child(PandaNode *node) const;
00815 
00816   INLINE int get_num_stashed() const;
00817   INLINE PandaNode *get_stashed(int n) const;
00818   INLINE int get_stashed_sort(int n) const;
00819   INLINE int find_stashed(PandaNode *node) const;
00820 
00821   INLINE const RenderState *get_state() const;
00822   INLINE const RenderEffects *get_effects() const;
00823   INLINE const TransformState *get_transform() const;
00824   INLINE const TransformState *get_prev_transform() const;
00825 
00826   INLINE string get_tag(const string &key) const;
00827   INLINE bool has_tag(const string &key) const;
00828 
00829   INLINE CollideMask get_net_collide_mask() const;
00830   INLINE CPT(RenderAttrib) get_off_clip_planes() const;
00831   INLINE CPT(BoundingVolume) get_bounds() const;
00832   INLINE int get_nested_vertices() const;
00833   INLINE bool is_final() const;
00834   INLINE int get_fancy_bits() const;
00835 
00836   INLINE PandaNode::Children get_children() const;
00837   INLINE PandaNode::Stashed get_stashed() const;
00838   INLINE PandaNode::Parents get_parents() const;
00839 
00840 private:
00841   const PandaNode *_object;
00842   Thread *_current_thread;
00843 
00844   const PandaNode::CData *_cdata;
00845 
00846 public:
00847   static TypeHandle get_class_type() {
00848     return _type_handle;
00849   }
00850   static void init_type() {
00851     register_type(_type_handle, "PandaNodePipelineReader");
00852   }
00853 
00854 private:
00855   static TypeHandle _type_handle;
00856 
00857 };
00858 
00859 INLINE ostream &operator << (ostream &out, const PandaNode &node) {
00860   node.output(out);
00861   return out;
00862 }
00863 
00864 #include "pandaNode.I"
00865 
00866 #endif
00867 
 All Classes Functions Variables Enumerations