22 CDReader cdata(_cycler, current_thread);
23 return cdata->get_up()->size();
33 CDReader cdata(_cycler, current_thread);
34 CPT(Up) up = cdata->get_up();
35 nassertr(n >= 0 && n < (
int)up->size(),
nullptr);
36 return (*up)[n].get_parent();
45 CDReader cdata(_cycler, current_thread);
46 return do_find_parent(node, cdata);
56 CDReader cdata(_cycler, current_thread);
57 return cdata->get_down()->size();
67 CDReader cdata(_cycler, current_thread);
68 CPT(Down) down = cdata->get_down();
69 nassertr(n >= 0 && n < (
int)down->size(),
nullptr);
70 return (*down)[n].get_child();
79 CDReader cdata(_cycler, current_thread);
80 CPT(
Down) down = cdata->get_down();
81 nassertr(n >= 0 && n < (
int)down->size(), -1);
82 return (*down)[n].get_sort();
91 CDReader cdata(_cycler, current_thread);
92 return do_find_child(node, cdata->get_down());
108 int child_index =
find_child(child_node, current_thread);
109 if (child_index < 0) {
129 int stashed_index =
find_stashed(child_node, current_thread);
130 if (stashed_index < 0) {
144 CDReader cdata(_cycler, current_thread);
145 return cdata->get_stashed()->size();
155 CDReader cdata(_cycler, current_thread);
156 CPT(Down) stashed = cdata->get_stashed();
157 nassertr(n >= 0 && n < (
int)stashed->size(),
nullptr);
158 return (*stashed)[n].get_child();
167 CDReader cdata(_cycler, current_thread);
168 CPT(
Down) stashed = cdata->get_stashed();
169 nassertr(n >= 0 && n < (
int)stashed->size(), -1);
170 return (*stashed)[n].get_sort();
179 CDReader cdata(_cycler, current_thread);
180 return do_find_child(node, cdata->get_stashed());
191 CDReader cdata(_cycler);
192 return cdata->_state->get_attrib(type);
202 get_attrib(
int slot)
const {
203 CDReader cdata(_cycler);
204 return cdata->_state->get_attrib(slot);
211 INLINE
bool PandaNode::
213 CDReader cdata(_cycler);
214 return cdata->_state->has_attrib(type);
221 INLINE
bool PandaNode::
222 has_attrib(
int slot)
const {
223 CDReader cdata(_cycler);
224 return cdata->_state->has_attrib(slot);
232 INLINE
void PandaNode::
245 CDReader cdata(_cycler);
246 int index = cdata->_effects->find_effect(type);
248 return cdata->_effects->get_effect(index);
257 INLINE
bool PandaNode::
259 CDReader cdata(_cycler);
260 int index = cdata->_effects->find_effect(type);
271 get_state(
Thread *current_thread)
const {
272 CDReader cdata(_cycler, current_thread);
273 return cdata->_state.p();
281 INLINE
void PandaNode::
282 clear_state(
Thread *current_thread) {
283 set_state(RenderState::make_empty(), current_thread);
290 get_effects(
Thread *current_thread)
const {
291 CDReader cdata(_cycler, current_thread);
292 return cdata->_effects;
298 INLINE
void PandaNode::
299 clear_effects(
Thread *current_thread) {
300 set_effects(RenderEffects::make_empty(), current_thread);
309 get_transform(
Thread *current_thread)
const {
310 CDReader cdata(_cycler, current_thread);
311 return cdata->_transform.p();
317 INLINE
void PandaNode::
318 clear_transform(
Thread *current_thread) {
319 set_transform(TransformState::make_identity(), current_thread);
327 get_prev_transform(
Thread *current_thread)
const {
328 CDReader cdata(_cycler, current_thread);
329 return cdata->_prev_transform.p();
338 INLINE
bool PandaNode::
339 has_dirty_prev_transform()
const {
340 return _dirty_prev_transform;
348 INLINE std::string PandaNode::
349 get_tag(
const std::string &key,
Thread *current_thread)
const {
350 CDReader cdata(_cycler, current_thread);
351 int index = cdata->_tag_data.find(key);
353 return cdata->_tag_data.get_data((
size_t)index);
355 return std::string();
364 INLINE
bool PandaNode::
365 has_tag(
const std::string &key,
Thread *current_thread)
const {
366 CDReader cdata(_cycler, current_thread);
367 return cdata->_tag_data.find(key) >= 0;
373 INLINE
size_t PandaNode::
374 get_num_tags()
const {
375 CDReader cdata(_cycler);
376 return cdata->_tag_data.size();
382 INLINE std::string PandaNode::
383 get_tag_key(
size_t i)
const {
384 CDReader cdata(_cycler);
385 return cdata->_tag_data.get_key(i);
392 INLINE
bool PandaNode::
394 CDReader cdata(_cycler);
395 if (!cdata->_tag_data.is_empty()) {
402 if (!_python_tag_data.is_null()) {
405 #endif // HAVE_PYTHON
412 INLINE
void PandaNode::
413 ls(std::ostream &out,
int indent_level)
const {
414 r_list_descendants(out, indent_level);
432 return ~_overall_bit;
441 CDReader cdata(_cycler);
442 return ((cdata->_draw_show_mask | ~cdata->_draw_control_mask) & _overall_bit).is_zero();
469 CDReader cdata(_cycler);
470 return cdata->_draw_control_mask;
479 CDReader cdata(_cycler);
480 return cdata->_draw_show_mask;
488 CDReader cdata(_cycler);
489 return cdata->_into_collide_mask;
508 get_internal_bounds(
Thread *current_thread)
const {
519 INLINE
int PandaNode::
520 get_internal_vertices(
Thread *current_thread)
const {
531 is_bounds_stale()
const {
532 CDReader cdata(_cycler);
533 return (cdata->_last_bounds_update != cdata->_next_update);
548 INLINE
void PandaNode::
549 set_final(
bool flag) {
550 CDWriter cdata(_cycler);
551 cdata->_final_bounds = flag;
562 CDReader cdata(_cycler, current_thread);
563 return cdata->_final_bounds;
575 CDReader cdata(_cycler, current_thread);
576 return cdata->_fancy_bits;
585 get_user_bounds(
int pipeline_stage,
Thread *current_thread)
const {
586 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
587 return cdata->_user_bounds;
596 INLINE
void PandaNode::
597 mark_bounds_stale(
int pipeline_stage,
Thread *current_thread)
const {
600 bool is_stale_bounds;
602 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
603 is_stale_bounds = (cdata->_last_update != cdata->_next_update);
607 if (!is_stale_bounds) {
608 ((
PandaNode *)
this)->force_bounds_stale(pipeline_stage, current_thread);
617 INLINE
void PandaNode::
618 mark_internal_bounds_stale(
int pipeline_stage,
Thread *current_thread) {
620 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
621 ++cdata->_internal_bounds_mark;
623 mark_bounds_stale(pipeline_stage, current_thread);
640 CDReader cdata(_cycler, current_thread);
641 return Children(cdata);
658 CDReader cdata(_cycler, current_thread);
659 return Stashed(cdata);
668 CDReader cdata(_cycler, current_thread);
669 return Parents(cdata);
675 INLINE
int PandaNode::
676 do_find_parent(
PandaNode *node,
const CData *cdata)
const {
677 CPT(Up) up = cdata->get_up();
678 Up::const_iterator ui = up->find(UpConnection(node));
679 if (ui == up->end()) {
682 return ui - up->begin();
690 INLINE
bool PandaNode::
691 verify_child_no_cycles(
PandaNode *child_node) {
693 if (detect_graph_cycles) {
694 if (!find_node_above(child_node)) {
697 report_cycle(child_node);
709 INLINE
void PandaNode::
710 do_set_dirty_prev_transform() {
712 if (!_dirty_prev_transform) {
713 LinkedListNode::insert_before(&_dirty_prev_transforms);
714 _dirty_prev_transform =
true;
723 INLINE
void PandaNode::
724 do_clear_dirty_prev_transform() {
726 if (_dirty_prev_transform) {
727 LinkedListNode::remove_from_list();
728 _dirty_prev_transform =
false;
735 INLINE PandaNode::DownConnection::
736 DownConnection(
PandaNode *child,
int sort) :
749 return _sort < other._sort;
755 INLINE
PandaNode *PandaNode::DownConnection::
771 INLINE
int PandaNode::DownConnection::
779 INLINE PandaNode::UpConnection::
791 INLINE
bool PandaNode::UpConnection::
792 operator < (
const UpConnection &other)
const {
793 return _parent < other._parent;
799 INLINE
PandaNode *PandaNode::UpConnection::
807 INLINE PandaNode::BoundsData::
809 _internal_bounds(nullptr),
810 _internal_vertices(0)
812 ++_internal_bounds_mark;
818 INLINE PandaNode::BoundsData::
819 BoundsData(
const PandaNode::BoundsData ©) :
820 _internal_bounds(copy._internal_bounds),
821 _internal_vertices(copy._internal_vertices),
822 _internal_bounds_mark(copy._internal_bounds_mark),
823 _internal_bounds_computed(copy._internal_bounds_computed)
830 INLINE
void PandaNode::BoundsData::
831 copy_bounds(
const PandaNode::BoundsData ©) {
832 _internal_bounds = copy._internal_bounds;
833 _internal_vertices = copy._internal_vertices;
834 _internal_bounds_mark = copy._internal_bounds_mark;
835 _internal_bounds_computed = copy._internal_bounds_computed;
842 INLINE
void PandaNode::CData::
843 set_fancy_bit(
int bits,
bool value) {
847 _fancy_bits &= ~bits;
856 return _down.get_read_pointer();
864 return _down.get_write_pointer();
871 get_stashed()
const {
872 return _stashed.get_read_pointer();
880 return _stashed.get_write_pointer();
888 return _up.get_read_pointer();
896 return _up.get_write_pointer();
902 INLINE PandaNode::Children::
909 INLINE PandaNode::Children::
910 Children(
const PandaNode::CData *cdata) :
911 _down(cdata->get_down())
918 INLINE PandaNode::Children::
927 INLINE
void PandaNode::Children::
935 INLINE PandaNode::Children::
937 _down(std::move(from._down))
944 INLINE
void PandaNode::Children::
946 _down = std::move(from._down);
954 nassertr(_down !=
nullptr, 0);
955 return _down->size();
963 nassertr(_down !=
nullptr,
nullptr);
964 nassertr(n < (
size_t)_down->size(),
nullptr);
965 return (*_down)[n].get_child();
974 nassertr(_down !=
nullptr, -1);
975 nassertr(n < _down->size(), -1);
976 return (*_down)[n].get_sort();
982 INLINE PandaNode::Stashed::
989 INLINE PandaNode::Stashed::
990 Stashed(
const PandaNode::CData *cdata) :
998 INLINE PandaNode::Stashed::
1000 _stashed(copy._stashed)
1007 INLINE
void PandaNode::Stashed::
1009 _stashed = copy._stashed;
1015 INLINE PandaNode::Stashed::
1017 _stashed(std::move(from._stashed))
1024 INLINE
void PandaNode::Stashed::
1026 _stashed = std::move(from._stashed);
1034 nassertr(_stashed !=
nullptr, 0);
1035 return _stashed->size();
1043 nassertr(_stashed !=
nullptr,
nullptr);
1044 nassertr(n < _stashed->size(),
nullptr);
1045 return (*_stashed)[n].get_child();
1054 nassertr(_stashed !=
nullptr, -1);
1055 nassertr(n < _stashed->size(), -1);
1056 return (*_stashed)[n].get_sort();
1062 INLINE PandaNode::Parents::
1069 INLINE PandaNode::Parents::
1070 Parents(
const PandaNode::CData *cdata) :
1071 _up(cdata->get_up())
1078 INLINE PandaNode::Parents::
1087 INLINE
void PandaNode::Parents::
1095 INLINE PandaNode::Parents::
1097 _up(std::move(from._up))
1104 INLINE
void PandaNode::Parents::
1106 _up = std::move(from._up);
1114 nassertr(_up !=
nullptr, 0);
1123 nassertr(_up !=
nullptr,
nullptr);
1124 nassertr(n < _up->size(),
nullptr);
1125 return (*_up)[n].get_parent();
1131 INLINE PandaNodePipelineReader::
1132 PandaNodePipelineReader(
const PandaNode *node,
Thread *current_thread) :
1134 _current_thread(current_thread),
1135 _cdata(node->_cycler.read_unlocked(current_thread))
1138 nassertv(_node->test_ref_count_nonzero());
1141 #ifdef DO_PIPELINING
1146 #endif // DO_PIPELINING
1152 INLINE PandaNodePipelineReader::
1155 _current_thread(copy._current_thread),
1158 #ifdef DO_PIPELINING
1160 #endif // DO_PIPELINING
1172 INLINE
void PandaNodePipelineReader::
1174 nassertv(_current_thread == copy._current_thread);
1182 #ifdef DO_PIPELINING
1184 #endif // DO_PIPELINING
1187 _cdata = copy._cdata;
1189 #ifdef DO_PIPELINING
1191 #endif // DO_PIPELINING
1203 INLINE PandaNodePipelineReader::
1204 ~PandaNodePipelineReader() {
1211 #ifdef DO_PIPELINING
1213 #endif // DO_PIPELINING
1224 INLINE
const PandaNode *PandaNodePipelineReader::
1232 INLINE
Thread *PandaNodePipelineReader::
1233 get_current_thread()
const {
1234 return _current_thread;
1257 nassertv(_cdata !=
nullptr);
1258 running_draw_mask = (running_draw_mask & ~_cdata->_draw_control_mask) |
1259 (_cdata->_draw_show_mask & _cdata->_draw_control_mask);
1270 nassertr(_cdata !=
nullptr,
false);
1271 nassertr(_cdata->_last_update == _cdata->_next_update,
false);
1277 if (_cdata->_net_draw_show_mask.is_zero()) {
1281 DrawMask net_draw_control_mask, net_draw_show_mask;
1282 net_draw_control_mask = _cdata->_net_draw_control_mask;
1283 net_draw_show_mask = _cdata->_net_draw_show_mask;
1295 DrawMask compare_mask = (running_draw_mask & ~net_draw_control_mask) | (net_draw_show_mask & net_draw_control_mask);
1297 return !((compare_mask & PandaNode::_overall_bit).is_zero()) && !((compare_mask & camera_mask).is_zero());
1308 return _cdata->get_up()->size();
1319 nassertr(n >= 0 && n < (
int)up->size(),
nullptr);
1320 return (*up)[n].get_parent();
1329 return _node->do_find_parent(node, _cdata);
1339 return _cdata->get_down()->size();
1350 nassertr(n >= 0 && n < (
int)down->size(),
nullptr);
1351 return (*down)[n].get_child();
1361 nassertr(n >= 0 && n < (
int)down->size(), -1);
1362 return (*down)[n].get_sort();
1371 return _node->do_find_child(node, _cdata->get_down());
1381 return _cdata->get_stashed()->size();
1392 nassertr(n >= 0 && n < (
int)stashed->size(),
nullptr);
1393 return (*stashed)[n].get_child();
1403 nassertr(n >= 0 && n < (
int)stashed->size(), -1);
1404 return (*stashed)[n].get_sort();
1413 return _node->do_find_child(node, _cdata->
get_stashed());
1424 return _cdata->_state;
1432 return _cdata->_effects;
1442 return _cdata->_transform;
1451 return _cdata->_prev_transform;
1460 get_tag(
const std::string &key)
const {
1461 int index = _cdata->_tag_data.find(key);
1463 return _cdata->_tag_data.get_data((
size_t)index);
1465 return std::string();
1475 has_tag(
const std::string &key)
const {
1476 return _cdata->_tag_data.find(key) >= 0;
1485 nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_net_collide_mask);
1486 return _cdata->_net_collide_mask;
1495 nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_off_clip_planes);
1496 return _cdata->_off_clip_planes;
1506 nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_external_bounds);
1507 return _cdata->_external_bounds;
1521 nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_nested_vertices);
1522 return _cdata->_nested_vertices;
1532 return _cdata->_final_bounds;
1545 return _cdata->_fancy_bits;
1594 INLINE PandaNode::BamReaderAuxDataDown::
1595 BamReaderAuxDataDown() :