Panda3D
|
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 ©); 00082 private: 00083 void operator = (const PandaNode ©); 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 ©); 00358 INLINE void copy_bounds(const BoundsData ©); 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 ©); 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 ©); 00685 INLINE void operator = (const Children ©); 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 ©); 00701 INLINE void operator = (const Stashed ©); 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 ©); 00717 INLINE void operator = (const Parents ©); 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 ¶ms); 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 ©); 00790 INLINE void operator = (const PandaNodePipelineReader ©); 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