Panda3D
pandaNode.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pandaNode.h
10  * @author drose
11  * @date 2002-02-20
12  */
13 
14 #ifndef PANDANODE_H
15 #define PANDANODE_H
16 
17 #include "pandabase.h"
18 
19 #include "cycleData.h"
20 #include "cycleDataReader.h"
21 #include "cycleDataWriter.h"
23 #include "cycleDataStageReader.h"
24 #include "cycleDataStageWriter.h"
25 #include "pipelineCycler.h"
26 #include "renderState.h"
27 #include "renderEffects.h"
28 #include "transformState.h"
29 #include "drawMask.h"
30 #include "typedWritable.h"
31 #include "collideMask.h"
32 #include "namable.h"
33 #include "referenceCount.h"
34 #include "luse.h"
35 #include "ordered_vector.h"
36 #include "pointerTo.h"
37 #include "nodePointerTo.h"
38 #include "pointerToArray.h"
39 #include "pnotify.h"
40 #include "updateSeq.h"
41 #include "deletedChain.h"
42 #include "pandaNodeChain.h"
43 #include "pStatCollector.h"
44 #include "copyOnWriteObject.h"
45 #include "copyOnWritePointer.h"
46 #include "lightReMutex.h"
47 #include "extension.h"
48 #include "simpleHashMap.h"
49 
50 class NodePathComponent;
51 class CullTraverser;
52 class CullTraverserData;
53 class Light;
54 class FactoryParams;
55 class AccumulatedAttribs;
56 class GeomTransformer;
58 
59 /**
60  * A basic node of the scene graph or data graph. This is the base class of
61  * all specialized nodes, and also serves as a generic node with no special
62  * properties.
63  */
64 class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritableReferenceCount,
65  public Namable, public LinkedListNode {
66 PUBLISHED:
67  explicit PandaNode(const std::string &name);
68  virtual ~PandaNode();
69  // published so that characters can be combined.
70  virtual PandaNode *combine_with(PandaNode *other);
71 
72 protected:
73  PandaNode(const PandaNode &copy);
74 
75  PandaNode &operator = (const PandaNode &copy) = delete;
76 
77 public:
78  virtual PandaNode *dupe_for_flatten() const;
79 
80  virtual bool safe_to_flatten() const;
81  virtual bool safe_to_transform() const;
82  virtual bool safe_to_modify_transform() const;
83  virtual bool safe_to_combine() const;
84  virtual bool safe_to_combine_children() const;
85  virtual bool safe_to_flatten_below() const;
86  virtual bool preserve_name() const;
87  virtual int get_unsafe_to_apply_attribs() const;
88  virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs,
89  int attrib_types,
90  GeomTransformer &transformer);
91  virtual void xform(const LMatrix4 &mat);
92 
93  virtual CPT(TransformState)
94  calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
95  bool &found_any,
96  const TransformState *transform,
97  Thread *current_thread = Thread::get_current_thread()) const;
98 
99  virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
100  virtual bool has_selective_visibility() const;
101  virtual int get_first_visible_child() const;
102  virtual int get_next_visible_child(int n) const;
103  virtual bool has_single_child_visibility() const;
104  virtual int get_visible_child() const;
105  virtual bool is_renderable() const;
106  virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data);
107 
108 PUBLISHED:
109  virtual PandaNode *make_copy() const;
110  PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const;
111 
112  EXTENSION(PT(PandaNode) __copy__() const);
113  EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const);
114 
115  INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const;
116  INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const;
117  INLINE int find_parent(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
118  MAKE_SEQ(get_parents, get_num_parents, get_parent);
119 
120  INLINE int get_num_children(Thread *current_thread = Thread::get_current_thread()) const;
121  INLINE PandaNode *get_child(int n, Thread *current_thread = Thread::get_current_thread()) const;
122  INLINE int get_child_sort(int n, Thread *current_thread = Thread::get_current_thread()) const;
123  INLINE int find_child(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
124  MAKE_SEQ(get_children, get_num_children, get_child);
125 
126  int count_num_descendants() const;
127 
128  void add_child(PandaNode *child_node, int sort = 0,
129  Thread *current_thread = Thread::get_current_thread());
130  void remove_child(int child_index, Thread *current_thread = Thread::get_current_thread());
131  bool remove_child(PandaNode *child_node, Thread *current_thread = Thread::get_current_thread());
132  bool replace_child(PandaNode *orig_child, PandaNode *new_child,
133  Thread *current_thread = Thread::get_current_thread());
134 
135  INLINE bool stash_child(PandaNode *child_node,
136  Thread *current_thread = Thread::get_current_thread());
137  void stash_child(int child_index,
138  Thread *current_thread = Thread::get_current_thread());
139  INLINE bool unstash_child(PandaNode *child_node,
140  Thread *current_thread = Thread::get_current_thread());
141  void unstash_child(int stashed_index,
142  Thread *current_thread = Thread::get_current_thread());
143 
144  INLINE int get_num_stashed(Thread *current_thread = Thread::get_current_thread()) const;
145  INLINE PandaNode *get_stashed(int n, Thread *current_thread = Thread::get_current_thread()) const;
146  INLINE int get_stashed_sort(int n, Thread *current_thread = Thread::get_current_thread()) const;
147  INLINE int find_stashed(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
148  MAKE_SEQ(get_stashed, get_num_stashed, get_stashed);
149 
150  void add_stashed(PandaNode *child_node, int sort = 0, Thread *current_thread = Thread::get_current_thread());
151  void remove_stashed(int child_index, Thread *current_thread = Thread::get_current_thread());
152 
153  void remove_all_children(Thread *current_thread = Thread::get_current_thread());
154  void steal_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread());
155  void copy_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread());
156 
157  void set_attrib(const RenderAttrib *attrib, int override = 0);
158  INLINE CPT(RenderAttrib) get_attrib(TypeHandle type) const;
159  INLINE CPT(RenderAttrib) get_attrib(int slot) const;
160  INLINE bool has_attrib(TypeHandle type) const;
161  INLINE bool has_attrib(int slot) const;
162  INLINE void clear_attrib(TypeHandle type);
163  void clear_attrib(int slot);
164 
165  void set_effect(const RenderEffect *effect);
166  INLINE CPT(RenderEffect) get_effect(TypeHandle type) const;
167  INLINE bool has_effect(TypeHandle type) const;
168  void clear_effect(TypeHandle type);
169 
170  void set_state(const RenderState *state, Thread *current_thread = Thread::get_current_thread());
171  INLINE CPT(RenderState) get_state(Thread *current_thread = Thread::get_current_thread()) const;
172  INLINE void clear_state(Thread *current_thread = Thread::get_current_thread());
173  MAKE_PROPERTY(state, get_state, set_state);
174 
175  void set_effects(const RenderEffects *effects, Thread *current_thread = Thread::get_current_thread());
176  INLINE CPT(RenderEffects) get_effects(Thread *current_thread = Thread::get_current_thread()) const;
177  INLINE void clear_effects(Thread *current_thread = Thread::get_current_thread());
178  MAKE_PROPERTY(effects, get_effects, set_effects);
179 
180  void set_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread());
181  INLINE CPT(TransformState) get_transform(Thread *current_thread = Thread::get_current_thread()) const;
182  INLINE void clear_transform(Thread *current_thread = Thread::get_current_thread());
183  MAKE_PROPERTY(transform, get_transform, set_transform);
184 
185  void set_prev_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread());
186  INLINE CPT(TransformState) get_prev_transform(Thread *current_thread = Thread::get_current_thread()) const;
187  void reset_prev_transform(Thread *current_thread = Thread::get_current_thread());
188  INLINE bool has_dirty_prev_transform() const;
189  static void reset_all_prev_transform(Thread *current_thread = Thread::get_current_thread());
190  MAKE_PROPERTY(prev_transform, get_prev_transform);
191 
192  void set_tag(const std::string &key, const std::string &value,
193  Thread *current_thread = Thread::get_current_thread());
194  INLINE std::string get_tag(const std::string &key,
195  Thread *current_thread = Thread::get_current_thread()) const;
196  INLINE bool has_tag(const std::string &key,
197  Thread *current_thread = Thread::get_current_thread()) const;
198  void clear_tag(const std::string &key,
199  Thread *current_thread = Thread::get_current_thread());
200 
201 public:
202  void get_tag_keys(vector_string &keys) const;
203  INLINE size_t get_num_tags() const;
204  INLINE std::string get_tag_key(size_t i) const;
205 
206 PUBLISHED:
207  MAKE_MAP_PROPERTY(tags, has_tag, get_tag, set_tag, clear_tag);
208  MAKE_MAP_KEYS_SEQ(tags, get_num_tags, get_tag_key);
209 
210  EXTENSION(PyObject *get_tag_keys() const);
211 
212  EXTENSION(PyObject *get_python_tags());
213  EXTENSION(void set_python_tag(PyObject *key, PyObject *value));
214  EXTENSION(PyObject *get_python_tag(PyObject *key) const);
215  EXTENSION(bool has_python_tag(PyObject *key) const);
216  EXTENSION(void clear_python_tag(PyObject *key));
217  EXTENSION(PyObject *get_python_tag_keys() const);
218  MAKE_PROPERTY(python_tags, get_python_tags);
219 
220  EXTENSION(int __traverse__(visitproc visit, void *arg));
221 
222  INLINE bool has_tags() const;
223  void copy_tags(PandaNode *other);
224  void list_tags(std::ostream &out, const std::string &separator = "\n") const;
225 
226  int compare_tags(const PandaNode *other) const;
227 
228  void copy_all_properties(PandaNode *other);
229  void replace_node(PandaNode *other);
230 
231  enum UnexpectedChange {
232  UC_parents = 0x001,
233  UC_children = 0x002,
234  UC_transform = 0x004,
235  UC_state = 0x008,
236  UC_draw_mask = 0x010,
237  };
238  void set_unexpected_change(unsigned int flags);
239  unsigned int get_unexpected_change(unsigned int flags) const;
240  void clear_unexpected_change(unsigned int flags);
241 
242  INLINE static DrawMask get_overall_bit();
243  INLINE static DrawMask get_all_camera_mask();
244  INLINE bool is_overall_hidden() const;
245  INLINE void set_overall_hidden(bool overall_hidden);
246  MAKE_PROPERTY(overall_bit, get_overall_bit);
247  MAKE_PROPERTY(all_camera_mask, get_all_camera_mask);
248  MAKE_PROPERTY(overall_hidden, is_overall_hidden, set_overall_hidden);
249 
250  void adjust_draw_mask(DrawMask show_mask,
251  DrawMask hide_mask,
252  DrawMask clear_mask);
253  INLINE DrawMask get_draw_control_mask() const;
254  INLINE DrawMask get_draw_show_mask() const;
255  MAKE_PROPERTY(draw_control_mask, get_draw_control_mask);
256  MAKE_PROPERTY(draw_show_mask, get_draw_show_mask);
257 
258  DrawMask get_net_draw_control_mask() const;
259  DrawMask get_net_draw_show_mask() const;
260 
261  void set_into_collide_mask(CollideMask mask);
262  INLINE CollideMask get_into_collide_mask() const;
263  virtual CollideMask get_legal_collide_mask() const;
264  MAKE_PROPERTY(into_collide_mask, get_into_collide_mask, set_into_collide_mask);
265  MAKE_PROPERTY(legal_collide_mask, get_legal_collide_mask);
266 
267  CollideMask get_net_collide_mask(Thread *current_thread = Thread::get_current_thread()) const;
268  CPT(RenderAttrib) get_off_clip_planes(Thread *current_thread = Thread::get_current_thread()) const;
269 
270  void prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state);
271 
272  bool is_scene_root() const;
273  bool is_under_scene_root() const;
274 
275  virtual void output(std::ostream &out) const;
276  virtual void write(std::ostream &out, int indent_level) const;
277 
278  INLINE void ls(std::ostream &out, int indent_level) const;
279 
280  // A node has three bounding volumes: an "external" bounding volume that
281  // represents the node and all of its children, an "internal" bounding
282  // volume which represents only the node itself (and is usually empty,
283  // unless a specific node type sets it otherwise), and a "user" bounding
284  // volume which is specified by the user.
285 
286  // We define set_bounds() and get_bounds() functions so that set_bounds()
287  // sets the user bounding volume, while get_bounds() returns the external
288  // bounding volume. Although it might seem strange and confusing to do
289  // this, this is actually the natural way the user thinks about nodes and
290  // bounding volumes.
291  void set_bounds_type(BoundingVolume::BoundsType bounds_type);
292  BoundingVolume::BoundsType get_bounds_type() const;
293  MAKE_PROPERTY(bounds_type, get_bounds_type);
294 
295  void set_bounds(const BoundingVolume *volume);
296  void set_bound(const BoundingVolume *volume);
297  INLINE void clear_bounds();
298  CPT(BoundingVolume) get_bounds(Thread *current_thread = Thread::get_current_thread()) const;
299  CPT(BoundingVolume) get_bounds(UpdateSeq &seq, Thread *current_thread = Thread::get_current_thread()) const;
300  int get_nested_vertices(Thread *current_thread = Thread::get_current_thread()) const;
301  INLINE CPT(BoundingVolume) get_internal_bounds(Thread *current_thread = Thread::get_current_thread()) const;
302  INLINE int get_internal_vertices(Thread *current_thread = Thread::get_current_thread()) const;
303  MAKE_PROPERTY(nested_vertices, get_nested_vertices);
304  MAKE_PROPERTY(internal_bounds, get_internal_bounds);
305  MAKE_PROPERTY(internal_vertices, get_internal_vertices);
306 
307  void mark_bounds_stale(Thread *current_thread = Thread::get_current_thread()) const;
308  void mark_internal_bounds_stale(Thread *current_thread = Thread::get_current_thread());
309  INLINE bool is_bounds_stale() const;
310  MAKE_PROPERTY(bounds_stale, is_bounds_stale);
311 
312  INLINE void set_final(bool flag);
313  INLINE bool is_final(Thread *current_thread = Thread::get_current_thread()) const;
314  MAKE_PROPERTY(final, is_final, set_final);
315 
316  virtual bool is_geom_node() const;
317  virtual bool is_lod_node() const;
318  virtual bool is_collision_node() const;
319  virtual Light *as_light();
320  virtual bool is_ambient_light() const;
321 
322  enum FancyBits {
323  FB_transform = 0x0001,
324  FB_state = 0x0002,
325  FB_effects = 0x0004,
326  FB_tag = 0x0010,
327  FB_draw_mask = 0x0020,
328  FB_cull_callback = 0x0040,
329  };
330  INLINE int get_fancy_bits(Thread *current_thread = Thread::get_current_thread()) const;
331 
332 PUBLISHED:
333  static PT(PandaNode) decode_from_bam_stream(vector_uchar data, BamReader *reader = nullptr);
334 
335 protected:
336  class BoundsData;
337 
338  INLINE CPT(BoundingVolume) get_user_bounds(int pipeline_stage, Thread *current_thread) const;
339  CPT(BoundingVolume) get_internal_bounds(int pipeline_stage, Thread *current_thread) const;
340  int get_internal_vertices(int pipeline_stage, Thread *current_thread) const;
341  void set_internal_bounds(const BoundingVolume *volume);
342 
343  INLINE void mark_bounds_stale(int pipeline_stage, Thread *current_thread) const;
344  void force_bounds_stale(Thread *current_thread = Thread::get_current_thread());
345  void force_bounds_stale(int pipeline_stage, Thread *current_thread);
346  INLINE void mark_internal_bounds_stale(int pipeline_stage, Thread *current_thread);
347 
348  virtual void r_mark_geom_bounds_stale(Thread *current_thread);
349 
350  virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
351  int &internal_vertices,
352  int pipeline_stage,
353  Thread *current_thread) const;
354  virtual void parents_changed();
355  virtual void children_changed();
356  virtual void transform_changed();
357  virtual void state_changed();
358  virtual void draw_mask_changed();
359 
360  typedef pmap<PandaNode *, PandaNode *> InstanceMap;
361  virtual PT(PandaNode) r_copy_subgraph(InstanceMap &inst_map,
362  Thread *current_thread) const;
363  virtual void r_copy_children(const PandaNode *from, InstanceMap &inst_map,
364  Thread *current_thread);
365 
366  void set_cull_callback();
367  void disable_cull_callback();
368 public:
369  virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg,
370  const RenderState *node_state,
371  GeomTransformer &transformer,
372  Thread *current_thread);
373 
374 protected:
375  // This is a base class of CData, defined below. It contains just the
376  // protected (not private) part of CData that will be needed by derived
377  // classes to implement compute_internal_bounds().
378  class EXPCL_PANDA_PGRAPH BoundsData : public CycleData {
379  protected:
380  INLINE BoundsData();
381  INLINE BoundsData(const BoundsData &copy);
382  INLINE void copy_bounds(const BoundsData &copy);
383 
384  public:
385  // This is the "internal" bounding volume, which is normally empty, but
386  // which a particular PandaNode subclass may define to be any arbitrary
387  // volume, by calling set_internal_bounds() or by overriding
388  // compute_internal_bounds().
389  CPT(BoundingVolume) _internal_bounds;
390  int _internal_vertices;
391  UpdateSeq _internal_bounds_mark; // incremented on mark_stale
392  UpdateSeq _internal_bounds_computed; // set to above when computing
393  };
394 
395 private:
396  class CData;
397 
398  INLINE int do_find_parent(PandaNode *node, const CData *cdata) const;
399  bool stage_remove_child(PandaNode *child_node, int pipeline_stage,
400  Thread *current_thread);
401  bool stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
402  int pipeline_stage, Thread *current_thread);
403 
404  void quick_add_new_child(PandaNode *child_node, int sort,
405  Thread *current_thread);
406 
407  INLINE bool verify_child_no_cycles(PandaNode *child_node);
408  void report_cycle(PandaNode *node);
409  bool find_node_above(PandaNode *node);
410 
411  // parent-child manipulation for NodePath support. Don't try to call these
412  // directly.
413  static PT(NodePathComponent) attach(NodePathComponent *parent,
414  PandaNode *child, int sort,
415  int pipeline_stage, Thread *current_thread);
416  static void detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread);
417  static void detach_one_stage(NodePathComponent *child, int pipeline_stage, Thread *current_thread);
418  static bool reparent(NodePathComponent *new_parent,
419  NodePathComponent *child, int sort, bool as_stashed,
420  int pipeline_stage, Thread *current_thread);
421  static bool reparent_one_stage(NodePathComponent *new_parent,
422  NodePathComponent *child, int sort,
423  bool as_stashed, int pipeline_stage, Thread *current_thread);
424  static PT(NodePathComponent) get_component(NodePathComponent *parent,
425  PandaNode *child,
426  int pipeline_stage, Thread *current_thread);
427  static PT(NodePathComponent) get_top_component(PandaNode *child, bool force,
428  int pipeline_stage, Thread *current_thread);
429  PT(NodePathComponent) get_generic_component(bool accept_ambiguity,
430  int pipeline_stage, Thread *current_thread);
431  PT(NodePathComponent) r_get_generic_component(bool accept_ambiguity,
432  bool &ambiguity_detected,
433  int pipeline_stage, Thread *current_thread);
434  void delete_component(NodePathComponent *component);
435  static void sever_connection(PandaNode *parent_node, PandaNode *child_node,
436  int pipeline_stage, Thread *current_thread);
437  static void new_connection(PandaNode *parent_node, PandaNode *child_node,
438  int pipeline_stage, Thread *current_thread);
439  void fix_path_lengths(int pipeline_stage, Thread *current_thread);
440  void r_list_descendants(std::ostream &out, int indent_level) const;
441 
442  INLINE void do_set_dirty_prev_transform();
443  INLINE void do_clear_dirty_prev_transform();
444 
445 public:
446  // This must be declared public so that VC6 will allow the nested CData
447  // class to access it.
448  class EXPCL_PANDA_PGRAPH DownConnection {
449  public:
450  INLINE DownConnection(PandaNode *child, int sort);
451  INLINE bool operator < (const DownConnection &other) const;
452  INLINE PandaNode *get_child() const;
453  INLINE void set_child(PandaNode *child);
454  INLINE int get_sort() const;
455 
456  private:
457  // Child pointers are reference counted. That way, holding a pointer to
458  // the root of a subgraph keeps the entire subgraph around.
459  PT(PandaNode) _child;
460  int _sort;
461  };
462 
463 private:
466 
467  // Store a pointer to the down_list during the bam read pass.
468  class EXPCL_PANDA_PGRAPH BamReaderAuxDataDown : public BamReaderAuxData {
469  public:
470  INLINE BamReaderAuxDataDown();
471  Down _down_list;
472  public:
473  virtual TypeHandle get_type() const {
474  return get_class_type();
475  }
476  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
477  static TypeHandle get_class_type() {
478  return _type_handle;
479  }
480 
481  public:
482  static void init_type() {
483  BamReaderAuxData::init_type();
484  register_type(_type_handle, "BamReaderAuxDataDown",
485  BamReaderAuxData::get_class_type());
486  }
487 
488  private:
489  static TypeHandle _type_handle;
490  };
491 
492  class EXPCL_PANDA_PGRAPH UpConnection {
493  public:
494  INLINE UpConnection(PandaNode *child);
495  INLINE bool operator < (const UpConnection &other) const;
496  INLINE PandaNode *get_parent() const;
497 
498  private:
499  // Parent pointers are not reference counted. That way, parents and
500  // children do not circularly reference each other.
501  PandaNode *_parent;
502  };
503  typedef ov_set<UpConnection> UpList;
505 
506  // We also maintain a set of NodePathComponents in the node. This
507  // represents the set of instances of this node that we have requested a
508  // NodePath for. We don't keep reference counts; when each
509  // NodePathComponent destructs, it removes itself from this set.
510  typedef phash_set<NodePathComponent *, pointer_hash> Paths;
511 
512  // We don't cycle the set of Paths, since these are across all threads. A
513  // NodePathComponent, once created, is always associated with the same node.
514  // We do, however, protect the Paths under a mutex.
515  Paths _paths;
516  LightReMutex _paths_lock;
517 
518  bool _dirty_prev_transform;
519  static PandaNodeChain _dirty_prev_transforms;
520 
521  // This is used to maintain a table of keyed data on each node, for the
522  // user's purposes.
524 
525  // This is actually implemented in pandaNode_ext.h, but defined here so
526  // that we can destruct it from the C++ side. Note that it isn't cycled,
527  // because I imagine it's rare to see a Python thread on a stage other than
528  // stage 0, and let's not make things unnecessarily complicated.
529  class PythonTagData : public ReferenceCount {
530  public:
531  virtual ~PythonTagData() {};
532  };
533  PT(PythonTagData) _python_tag_data;
534 
535  unsigned int _unexpected_change_flags = 0;
536 
537  // This is the data that must be cycled between pipeline stages.
538 
539  class EXPCL_PANDA_PGRAPH CData : public BoundsData {
540  public:
541  CData();
542  CData(const CData &copy);
543  virtual ~CData();
544  ALLOC_DELETED_CHAIN(CData);
545 
546  virtual CycleData *make_copy() const;
547  virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
548  void update_bam_nested(BamWriter *manager) const;
549  virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
550  virtual void fillin(DatagramIterator &scan, BamReader *manager);
551  virtual TypeHandle get_parent_type() const {
552  return PandaNode::get_class_type();
553  }
554 
555  public:
556  // This section contains the lightweight parts of the node that are likely
557  // to change fairly often: transform and state.
558 
559  NCPT(RenderState) _state;
560  NCPT(TransformState) _transform;
561  NCPT(TransformState) _prev_transform;
562 
563  public:
564  // This section contains the heavierweight parts of the node that are less
565  // likely to change as often: tags, collide mask.
566 
567  INLINE void set_fancy_bit(int bits, bool value);
568 
569 #ifdef HAVE_PYTHON
570  void inc_py_refs();
571  void dec_py_refs();
572 #endif
573 
574  CPT(RenderEffects) _effects;
575 
576  TagData _tag_data;
577 
578  // These two together determine the per-camera visibility of this node.
579  // See adjust_draw_mask() for details.
580  DrawMask _draw_control_mask, _draw_show_mask;
581 
582  // This is the mask that indicates which CollisionNodes may detect a
583  // collision with this particular node. By default it is zero for an
584  // ordinary PandaNode, and all bits on for a CollisionNode or GeomNode.
585  CollideMask _into_collide_mask;
586 
587  // The requested bounding volume type.
588  BoundingVolume::BoundsType _bounds_type;
589 
590  // This is the user bounding volume, which is only specified by a user.
591  // It defaults to NULL, which means an empty volume.
592  CPT(BoundingVolume) _user_bounds;
593 
594  // See BoundsData, above, for _internal_bounds.
595 
596  // This is true if the external bounds of this node should be deemed
597  // "final". See set_final().
598  bool _final_bounds;
599 
600  // This bitmask is maintained automatically by the internal PandaNode
601  // code; it contains a 1 for each "fancy" attribute that is set on the
602  // node. See enum FancyBits, above.
603  int _fancy_bits;
604 
605  public:
606  // This section contains the data that is accumulated upward from the
607  // node's children: that is, the external bounding volume, and
608  // conceptually similar things like the net_collide_mask, etc. None of
609  // the data in this object is preserved in a bam file.
610 
611  // This is the union of all into_collide_mask bits for any nodes at and
612  // below this level.
613  CollideMask _net_collide_mask;
614 
615  // These are similar, for the draw mask.
616  DrawMask _net_draw_control_mask, _net_draw_show_mask;
617 
618  // This is a ClipPlaneAttrib that represents the union of all clip planes
619  // that have been turned *off* at and below this level. TODO: fix the
620  // circular reference counts involved here.
621  CPT(RenderAttrib) _off_clip_planes;
622 
623  // The number of vertices rendered by this node and all child nodes.
624  int _nested_vertices;
625 
626  // This is the bounding volume around the _user_bounds, the
627  // _internal_bounds, and all of the children's external bounding volumes.
628  CPT(BoundingVolume) _external_bounds;
629 
630  // When _last_update != _next_update, this cache is stale.
631  UpdateSeq _last_update, _next_update;
632 
633  // We don't always update the bounding volume and number of nested
634  // vertices. This indicates the last time they were changed. It is never
635  // higher than _last_update.
636  UpdateSeq _last_bounds_update;
637 
638  public:
639  // This section stores the links to other nodes above and below this node
640  // in the graph.
641 
642  void write_up_list(const Up &up_list,
643  BamWriter *manager, Datagram &dg) const;
644  void write_down_list(const Down &down_list,
645  BamWriter *manager, Datagram &dg) const;
646  void update_up_list(const Up &up_list, BamWriter *manager) const;
647  void update_down_list(const Down &down_list, BamWriter *manager) const;
648  int complete_up_list(Up &up_list, const std::string &tag,
649  TypedWritable **p_list, BamReader *manager);
650  int complete_down_list(Down &down_list, const std::string &tag,
651  TypedWritable **p_list, BamReader *manager);
652  void fillin_up_list(Up &up_list, const std::string &tag,
653  DatagramIterator &scan, BamReader *manager);
654  void fillin_down_list(Down &down_list, const std::string &tag,
655  DatagramIterator &scan, BamReader *manager);
656 
657  INLINE CPT(Down) get_down() const;
658  INLINE PT(Down) modify_down();
659  INLINE CPT(Down) get_stashed() const;
660  INLINE PT(Down) modify_stashed();
661  INLINE CPT(Up) get_up() const;
662  INLINE PT(Up) modify_up();
663 
664  private:
665  // We store the child lists by reference, so we can copy them quickly. We
666  // perform copy-on-write when necessary.
667  COWPT(Down) _down;
668  COWPT(Down) _stashed;
669  COWPT(Up) _up;
670 
671  public:
672  static TypeHandle get_class_type() {
673  return _type_handle;
674  }
675  static void init_type() {
676  register_type(_type_handle, "PandaNode::CData");
677  }
678 
679  private:
680  static TypeHandle _type_handle;
681  };
682 
683  PipelineCycler<CData> _cycler;
684  typedef CycleDataReader<CData> CDReader;
685  typedef CycleDataWriter<CData> CDWriter;
686  typedef CycleDataLockedStageReader<CData> CDLockedStageReader;
687  typedef CycleDataStageReader<CData> CDStageReader;
688  typedef CycleDataStageWriter<CData> CDStageWriter;
689 
690  int do_find_child(PandaNode *node, const Down *down) const;
691  CDStageWriter update_cached(bool update_bounds, int pipeline_stage,
692  CDLockedStageReader &cdata);
693 
694  static DrawMask _overall_bit;
695 
696  static PStatCollector _reset_prev_pcollector;
697  static PStatCollector _update_bounds_pcollector;
698 
699 PUBLISHED:
700  // This class is returned from get_children(). Use it to walk through the
701  // list of children. This is faster, and safer, than walking through the
702  // children one at a time via get_num_children()/get_child(), since the list
703  // of children is saved out ahead of time, rather than having to reacquire
704  // the lock with each iteration, or to keep the lock held for the entire
705  // pass.
706  class EXPCL_PANDA_PGRAPH Children {
707  public:
708  INLINE Children();
709  INLINE Children(const CData *cdata);
710  INLINE Children(const Children &copy);
711  INLINE Children(Children &&from) noexcept;
712 
713  INLINE void operator = (const Children &copy);
714  INLINE void operator = (Children &&from) noexcept;
715 
716  INLINE size_t get_num_children() const;
717  INLINE PandaNode *get_child(size_t n) const;
718  INLINE int get_child_sort(size_t n) const;
719 
720  PUBLISHED:
721  INLINE PandaNode *operator [](size_t n) const { return get_child(n); }
722  INLINE size_t size() const { return get_num_children(); }
723 
724  private:
725  CPT(Down) _down;
726  };
727 
728  // Similarly for stashed children.
729  class EXPCL_PANDA_PGRAPH Stashed {
730  public:
731  INLINE Stashed();
732  INLINE Stashed(const CData *cdata);
733  INLINE Stashed(const Stashed &copy);
734  INLINE Stashed(Stashed &&from) noexcept;
735 
736  INLINE void operator = (const Stashed &copy);
737  INLINE void operator = (Stashed &&from) noexcept;
738 
739  INLINE size_t get_num_stashed() const;
740  INLINE PandaNode *get_stashed(size_t n) const;
741  INLINE int get_stashed_sort(size_t n) const;
742 
743  PUBLISHED:
744  INLINE PandaNode *operator [](size_t n) const { return get_stashed(n); }
745  INLINE size_t size() const { return get_num_stashed(); }
746 
747  private:
748  CPT(Down) _stashed;
749  };
750 
751  // This class is returned from get_parents().
752  class EXPCL_PANDA_PGRAPH Parents {
753  public:
754  INLINE Parents();
755  INLINE Parents(const CData *cdata);
756  INLINE Parents(const Parents &copy);
757  INLINE Parents(Parents &&from) noexcept;
758 
759  INLINE void operator = (const Parents &copy);
760  INLINE void operator = (Parents &&from) noexcept;
761 
762  INLINE size_t get_num_parents() const;
763  INLINE PandaNode *get_parent(size_t n) const;
764 
765  PUBLISHED:
766  INLINE PandaNode *operator [](size_t n) const { return get_parent(n); }
767  INLINE size_t size() const { return get_num_parents(); }
768 
769  private:
770  CPT(Up) _up;
771  };
772 
773 public:
774  INLINE Children get_children(Thread *current_thread = Thread::get_current_thread()) const;
775  INLINE Stashed get_stashed(Thread *current_thread = Thread::get_current_thread()) const;
776  INLINE Parents get_parents(Thread *current_thread = Thread::get_current_thread()) const;
777 
778  typedef bool SceneRootFunc(const PandaNode *);
779  static void set_scene_root_func(SceneRootFunc *func);
780 
781 PUBLISHED:
782  MAKE_PROPERTY(children, get_children);
783  MAKE_PROPERTY(stashed, get_stashed);
784  MAKE_PROPERTY(parents, get_parents);
785 
786 private:
787  static SceneRootFunc *_scene_root_func;
788 
789 public:
790  static void register_with_read_factory();
791  virtual void write_datagram(BamWriter *manager, Datagram &dg);
792  virtual void update_bam_nested(BamWriter *manager);
793  void write_recorder(BamWriter *manager, Datagram &dg);
794 
795 protected:
796  static TypedWritable *make_from_bam(const FactoryParams &params);
797  void fillin(DatagramIterator &scan, BamReader *manager);
798  void fillin_recorder(DatagramIterator &scan, BamReader *manager);
799 
800 public:
801  static TypeHandle get_class_type() {
802  return _type_handle;
803  }
804  static void init_type() {
805  TypedWritableReferenceCount::init_type();
806  Namable::init_type();
807  register_type(_type_handle, "PandaNode",
808  TypedWritableReferenceCount::get_class_type(),
809  Namable::get_class_type());
810  CData::init_type();
811  Down::init_type();
812  Up::init_type();
813  BamReaderAuxDataDown::init_type();
814  }
815  virtual TypeHandle get_type() const {
816  return get_class_type();
817  }
818  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
819 
820 private:
821  static TypeHandle _type_handle;
822 
823 #ifndef DO_PIPELINING
824  friend class PandaNode::Children;
825  friend class PandaNode::Stashed;
826 #endif
827  friend class NodePath;
828  friend class NodePathComponent;
829  friend class WorkingNodePath;
830  friend class PandaNodePipelineReader;
831  friend class EggLoader;
832  friend class Extension<PandaNode>;
833  friend class CullTraverserData;
834 };
835 
836 /**
837  * Encapsulates the data from a PandaNode, pre-fetched for one stage of the
838  * pipeline.
839  */
840 class EXPCL_PANDA_PGRAPH PandaNodePipelineReader {
841 public:
842  INLINE PandaNodePipelineReader(const PandaNode *object, Thread *current_thread);
844  INLINE void operator = (const PandaNodePipelineReader &copy);
845 
846 public:
847  INLINE ~PandaNodePipelineReader();
848  ALLOC_DELETED_CHAIN(PandaNodePipelineReader);
849 
850  INLINE const PandaNode *get_node() const;
851  INLINE Thread *get_current_thread() const;
852 
853  INLINE void release();
854 
855  void check_cached(bool update_bounds) const;
856 
857  INLINE void compose_draw_mask(DrawMask &running_draw_mask) const;
858  INLINE bool compare_draw_mask(DrawMask running_draw_mask,
859  DrawMask camera_mask) const;
860 
861  INLINE int get_num_parents() const;
862  INLINE PandaNode *get_parent(int n) const;
863  INLINE int find_parent(PandaNode *node) const;
864 
865  INLINE int get_num_children() const;
866  INLINE PandaNode *get_child(int n) const;
867  INLINE int get_child_sort(int n) const;
868  INLINE int find_child(PandaNode *node) const;
869 
870  INLINE int get_num_stashed() const;
871  INLINE PandaNode *get_stashed(int n) const;
872  INLINE int get_stashed_sort(int n) const;
873  INLINE int find_stashed(PandaNode *node) const;
874 
875  INLINE const RenderState *get_state() const;
876  INLINE const RenderEffects *get_effects() const;
877  INLINE const TransformState *get_transform() const;
878  INLINE const TransformState *get_prev_transform() const;
879 
880  INLINE std::string get_tag(const std::string &key) const;
881  INLINE bool has_tag(const std::string &key) const;
882 
883  INLINE CollideMask get_net_collide_mask() const;
884  INLINE const RenderAttrib *get_off_clip_planes() const;
885  INLINE const BoundingVolume *get_bounds() const;
886  INLINE int get_nested_vertices() const;
887  INLINE bool is_final() const;
888  INLINE int get_fancy_bits() const;
889 
890  INLINE PandaNode::Children get_children() const;
891  INLINE PandaNode::Stashed get_stashed() const;
892  INLINE PandaNode::Parents get_parents() const;
893 
894 private:
895  const PandaNode *_node;
896  Thread *_current_thread;
897 
898  const PandaNode::CData *_cdata;
899 
900 public:
901  static TypeHandle get_class_type() {
902  return _type_handle;
903  }
904  static void init_type() {
905  register_type(_type_handle, "PandaNodePipelineReader");
906  }
907 
908 private:
909  static TypeHandle _type_handle;
910 
911 };
912 
913 // We can safely redefine this as a no-op.
914 template<>
915 INLINE void PointerToBase<PandaNode>::update_type(To *ptr) {}
916 
917 INLINE std::ostream &operator << (std::ostream &out, const PandaNode &node) {
918  node.output(out);
919  return out;
920 }
921 
922 #include "pandaNode.I"
923 
924 #endif
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
Stores auxiliary data that may be piggybacked on the BamReader during each object's read pass.
Definition: bamReader.h:61
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
This class is similar to CycleDataLockedReader, except it allows reading from a particular stage of t...
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
A class to retrieve the individual data elements previously stored in a Datagram.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
Converts an egg data structure, possibly read from an egg file but not necessarily,...
Definition: eggLoader.h:67
The default class template does not define any methods.
Definition: extension.h:34
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
An object specifically designed to transform the vertices of a Geom without disturbing indexing or af...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
A lightweight reentrant mutex.
Definition: lightReMutex.h:32
The abstract interface to all kinds of lights.
Definition: light.h:38
This just stores the pointers to implement a doubly-linked list of some kind of object.
A base class for all things which can have a name.
Definition: namable.h:26
void output(std::ostream &out) const
Outputs the Namable.
Definition: namable.I:61
This is one component of a NodePath.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
A lightweight class that represents a single element that may be timed and/or counted via stats.
This class maintains a linked list of PandaNodes.
Encapsulates the data from a PandaNode, pre-fetched for one stage of the pipeline.
Definition: pandaNode.h:840
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
This is the base class for PointerTo and ConstPointerTo.
Definition: pointerToBase.h:29
A base class for all things that want to be reference-counted.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
This is the base class for a number of special render effects that may be set on scene graph nodes to...
Definition: renderEffect.h:48
This represents a unique collection of RenderEffect objects that correspond to a particular renderabl...
Definition: renderEffects.h:41
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
A thread; that is, a lightweight process.
Definition: thread.h:46
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
Indicates a coordinate-system transform on vertices.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
virtual void update_bam_nested(BamWriter *manager)
Called by the BamWriter when this object has not itself been modified recently, but it should check i...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
This is a class designed to support low-overhead traversals of the complete scene graph,...
A specialization of ordered_vector that emulates a standard STL set: many copies of each element are ...
A specialization of ordered_vector that emulates a standard STL set: one copy of each element is allo...
This is our own Panda specialization on the default STL list.
Definition: plist.h:35
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...
Definition: register_type.I:22
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.