32 using std::ostringstream;
36 NotifyCategoryDecl(drawmask, EXPCL_PANDA_PGRAPH, EXPTP_PANDA_PGRAPH);
37 NotifyCategoryDef(drawmask,
"");
39 TypeHandle PandaNode::BamReaderAuxDataDown::_type_handle;
41 PandaNode::SceneRootFunc *PandaNode::_scene_root_func;
43 PandaNodeChain PandaNode::_dirty_prev_transforms(
"_dirty_prev_transforms");
46 PStatCollector PandaNode::_reset_prev_pcollector(
"App:Collisions:Reset");
51 TypeHandle PandaNodePipelineReader::_type_handle;
76 PandaNode(
const string &name) :
78 _paths_lock(
"PandaNode::_paths_lock"),
79 _dirty_prev_transform(false)
81 if (pgraph_cat.is_debug()) {
83 <<
"Constructing " << (
void *)
this <<
", " << get_name() <<
"\n";
86 #ifdef DO_MEMORY_USAGE
96 if (pgraph_cat.is_debug()) {
98 <<
"Destructing " << (
void *)
this <<
", " << get_name() <<
"\n";
101 if (_dirty_prev_transform) {
104 do_clear_dirty_prev_transform();
133 _paths_lock(
"PandaNode::_paths_lock"),
134 _dirty_prev_transform(false),
135 _python_tag_data(copy._python_tag_data),
136 _unexpected_change_flags(0)
138 if (pgraph_cat.is_debug()) {
140 <<
"Copying " << (
void *)
this <<
", " << get_name() <<
"\n";
142 #ifdef DO_MEMORY_USAGE
151 CDReader copy_cdata(copy._cycler);
152 CDWriter cdata(_cycler,
true);
153 cdata->_state = copy_cdata->_state;
154 cdata->_transform = copy_cdata->_transform;
155 cdata->_prev_transform = copy_cdata->_prev_transform;
156 if (cdata->_transform != cdata->_prev_transform) {
157 do_set_dirty_prev_transform();
160 cdata->_effects = copy_cdata->_effects;
161 cdata->_tag_data = copy_cdata->_tag_data;
162 cdata->_draw_control_mask = copy_cdata->_draw_control_mask;
163 cdata->_draw_show_mask = copy_cdata->_draw_show_mask;
164 cdata->_into_collide_mask = copy_cdata->_into_collide_mask;
165 cdata->_bounds_type = copy_cdata->_bounds_type;
166 cdata->_user_bounds = copy_cdata->_user_bounds;
167 cdata->_internal_bounds =
nullptr;
168 cdata->_internal_bounds_computed = UpdateSeq::initial();
169 cdata->_internal_bounds_mark = UpdateSeq::initial();
170 ++cdata->_internal_bounds_mark;
171 cdata->_final_bounds = copy_cdata->_final_bounds;
172 cdata->_fancy_bits = copy_cdata->_fancy_bits;
284 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
285 const LMatrix4 &mat = attribs._transform->get_mat();
289 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
290 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
291 cdata->_effects = cdata->_effects->xform(mat);
292 cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
294 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
304 xform(
const LMatrix4 &) {
352 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
bool &found_any,
354 CPT(
TransformState) next_transform = transform->compose(get_transform());
357 int num_children = cr.get_num_children();
358 for (
int i = 0; i < num_children; i++) {
359 cr.get_child(i)->calc_tight_bounds(min_point, max_point,
360 found_any, next_transform,
364 return next_transform;
492 copy_subgraph(
Thread *current_thread)
const {
493 InstanceMap inst_map;
494 return r_copy_subgraph(inst_map, current_thread);
501 count_num_descendants()
const {
504 int num_children = children.get_num_children();
506 for (
int i = 0; i < num_children; ++i) {
508 count += child->count_num_descendants();
524 nassertv(child_node !=
nullptr);
526 if (!verify_child_no_cycles(child_node)) {
538 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
539 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
540 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
542 cdata->modify_down()->insert(DownConnection(child_node, sort));
543 cdata_child->modify_up()->insert(UpConnection(
this));
545 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
547 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
548 new_connection(
this, child_node, pipeline_stage, current_thread);
550 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
552 force_bounds_stale();
555 child_node->parents_changed();
566 nassertv(pipeline_stage == 0);
568 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
569 PT(
Down) down = cdata->modify_down();
570 nassertv(child_index >= 0 && child_index < (
int)down->size());
573 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
575 PT(
Up) up = cdata_child->modify_up();
577 down->erase(down->begin() + child_index);
578 int num_erased = up->erase(UpConnection(
this));
579 nassertv(num_erased == 1);
581 sever_connection(
this, child_node, pipeline_stage, current_thread);
582 force_bounds_stale(pipeline_stage, current_thread);
585 child_node->parents_changed();
597 nassertr(child_node !=
nullptr,
false);
604 bool any_removed =
false;
606 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
607 if (stage_remove_child(child_node, pipeline_stage, current_thread)) {
610 sever_connection(
this, child_node, pipeline_stage, current_thread);
611 force_bounds_stale(pipeline_stage, current_thread);
614 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
619 child_node->parents_changed();
634 nassertr(orig_child !=
nullptr,
false);
635 nassertr(new_child !=
nullptr,
false);
637 if (orig_child == new_child) {
642 if (!verify_child_no_cycles(new_child)) {
650 PT(
PandaNode) keep_orig_child = orig_child;
653 bool any_replaced =
false;
655 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
656 if (stage_replace_child(orig_child, new_child, pipeline_stage, current_thread)) {
660 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
664 orig_child->parents_changed();
665 new_child->parents_changed();
684 nassertv(pipeline_stage == 0);
696 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
697 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
699 cdata->modify_stashed()->insert(
DownConnection(child_node, sort));
700 cdata_child->modify_up()->insert(UpConnection(
this));
703 new_connection(
this, child_node, pipeline_stage, current_thread);
704 force_bounds_stale(pipeline_stage, current_thread);
707 child_node->parents_changed();
724 nassertv(pipeline_stage == 0);
739 CDWriter cdata_child(child_node->_cycler);
742 cdata_child->modify_up()->insert(UpConnection(
this));
745 new_connection(
this, child_node, pipeline_stage, current_thread);
747 force_bounds_stale();
749 child_node->parents_changed();
767 nassertv(pipeline_stage == 0);
769 if (!verify_child_no_cycles(child_node)) {
781 CDWriter cdata_child(child_node->_cycler);
783 cdata->modify_stashed()->insert(
DownConnection(child_node, sort));
784 cdata_child->modify_up()->insert(UpConnection(
this));
787 new_connection(
this, child_node, pipeline_stage, current_thread);
791 child_node->parents_changed();
802 nassertv(pipeline_stage == 0);
804 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
805 Down &stashed = *cdata->modify_stashed();
806 nassertv(child_index >= 0 && child_index < (
int)stashed.size());
808 PT(
PandaNode) child_node = stashed[child_index].get_child();
809 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
811 stashed.erase(stashed.begin() + child_index);
812 int num_erased = cdata_child->modify_up()->erase(UpConnection(
this));
813 nassertv(num_erased == 1);
815 sever_connection(
this, child_node, pipeline_stage, current_thread);
816 force_bounds_stale(pipeline_stage, current_thread);
819 child_node->parents_changed();
832 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
833 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
834 PT(
Down) down = cdata->modify_down();
836 for (di = down->begin(); di != down->end(); ++di) {
838 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
840 cdata_child->modify_up()->erase(UpConnection(
this));
842 sever_connection(
this, child_node, pipeline_stage, current_thread);
843 child_node->parents_changed();
848 Down &stashed = *cdata->modify_stashed();
849 for (di = stashed.begin(); di != stashed.end(); ++di) {
851 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
853 cdata_child->modify_up()->erase(UpConnection(
this));
855 sever_connection(
this, child_node, pipeline_stage, current_thread);
856 child_node->parents_changed();
861 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
863 force_bounds_stale();
890 for (i = 0; i < num_children; i++) {
893 add_child(child_node, sort, current_thread);
896 for (i = 0; i < num_stashed; i++) {
919 for (i = 0; i < num_children; i++) {
922 add_child(child_node, sort, current_thread);
925 for (i = 0; i < num_stashed; i++) {
941 bool any_changed =
false;
943 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
944 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
946 CPT(
RenderState) new_state = cdata->_state->set_attrib(attrib,
override);
947 if (cdata->_state != new_state) {
948 cdata->_state = new_state;
949 cdata->set_fancy_bit(FB_state,
true);
953 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
957 mark_bounds_stale(current_thread);
969 clear_attrib(
int slot) {
970 bool any_changed =
false;
973 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
974 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
976 CPT(
RenderState) new_state = cdata->_state->remove_attrib(slot);
977 if (cdata->_state != new_state) {
978 cdata->_state = new_state;
979 cdata->set_fancy_bit(FB_state, !new_state->is_empty());
983 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
988 mark_bounds_stale(current_thread);
1003 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1004 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1005 cdata->_effects = cdata->_effects->add_effect(effect);
1006 cdata->set_fancy_bit(FB_effects,
true);
1008 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1018 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1019 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1020 cdata->_effects = cdata->_effects->remove_effect(type);
1021 cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
1023 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1038 bool any_changed =
false;
1039 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1040 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1041 if (cdata->_state != state) {
1042 cdata->_state = state;
1043 cdata->set_fancy_bit(FB_state, !state->
is_empty());
1047 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1051 mark_bounds_stale(current_thread);
1066 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1067 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1068 cdata->_effects = effects;
1069 cdata->set_fancy_bit(FB_effects, !effects->
is_empty());
1071 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1088 bool any_changed =
false;
1089 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1090 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1091 if (cdata->_transform != transform) {
1092 cdata->_transform = transform;
1093 cdata->set_fancy_bit(FB_transform, !transform->
is_identity());
1096 if (pipeline_stage == 0) {
1097 if (cdata->_transform != cdata->_prev_transform) {
1098 do_set_dirty_prev_transform();
1103 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1106 mark_bounds_stale(current_thread);
1107 transform_changed();
1126 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1127 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1128 cdata->_prev_transform = transform;
1129 if (pipeline_stage == 0) {
1130 if (cdata->_transform != cdata->_prev_transform) {
1131 do_set_dirty_prev_transform();
1133 do_clear_dirty_prev_transform();
1137 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1150 do_clear_dirty_prev_transform();
1155 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1156 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1157 cdata->_prev_transform = cdata->_transform;
1159 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1173 PStatTimer timer(_reset_prev_pcollector, current_thread);
1177 while (list_node != &_dirty_prev_transforms) {
1179 nassertv(panda_node->_dirty_prev_transform);
1180 panda_node->_dirty_prev_transform =
false;
1182 CDStageWriter cdata(panda_node->_cycler, 0, current_thread);
1183 cdata->_prev_transform = cdata->_transform;
1185 list_node = panda_node->_next;
1187 panda_node->_prev =
nullptr;
1188 panda_node->_next =
nullptr;
1193 _dirty_prev_transforms._prev = &_dirty_prev_transforms;
1194 _dirty_prev_transforms._next = &_dirty_prev_transforms;
1207 set_tag(
const string &key,
const string &value,
Thread *current_thread) {
1210 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1211 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1212 cdata->_tag_data.store(key, value);
1213 cdata->set_fancy_bit(FB_tag,
true);
1215 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1225 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1226 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1227 cdata->_tag_data.remove(key);
1228 cdata->set_fancy_bit(FB_tag, !cdata->_tag_data.is_empty());
1230 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1241 if (other ==
this) {
1249 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1250 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
1251 CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
1253 for (
size_t n = 0; n < cdatar->_tag_data.size(); ++n) {
1254 cdataw->_tag_data.store(cdatar->_tag_data.get_key(n), cdatar->_tag_data.get_data(n));
1256 cdataw->set_fancy_bit(FB_tag, !cdataw->_tag_data.is_empty());
1258 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1262 _python_tag_data = other->_python_tag_data;
1277 list_tags(ostream &out,
const string &separator)
const {
1279 for (
size_t n = 0; n < cdata->_tag_data.size(); ++n) {
1283 out << cdata->_tag_data.get_key(n);
1300 for (
size_t n = 0; n < cdata->_tag_data.size(); ++n) {
1301 keys.push_back(cdata->_tag_data.get_key(n));
1315 CDReader cdata_other(other->_cycler);
1317 const TagData &a_data = cdata->_tag_data;
1318 const TagData &b_data = cdata_other->_tag_data;
1322 while (ai < a_data.
size() && bi < b_data.
size()) {
1323 int cmp = strcmp(a_data.
get_key(ai).c_str(), b_data.
get_key(bi).c_str());
1328 cmp = strcmp(a_data.
get_key(ai).c_str(), b_data.
get_key(bi).c_str());
1336 if (ai < a_data.
size()) {
1340 if (bi < b_data.
size()) {
1347 if (_python_tag_data != other->_python_tag_data) {
1348 return (_python_tag_data < other->_python_tag_data) ? -1 : 1;
1362 if (other ==
this) {
1370 bool any_transform_changed =
false;
1371 bool any_state_changed =
false;
1372 bool any_draw_mask_changed =
false;
1374 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1375 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
1376 CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
1378 if (cdataw->_transform != cdatar->_transform) {
1379 any_transform_changed =
true;
1381 if (cdataw->_state != cdatar->_state) {
1382 any_state_changed =
true;
1384 if (cdataw->_draw_control_mask != cdatar->_draw_control_mask ||
1385 cdataw->_draw_show_mask != cdatar->_draw_show_mask) {
1386 any_draw_mask_changed =
true;
1389 cdataw->_transform = cdatar->_transform;
1390 cdataw->_prev_transform = cdatar->_prev_transform;
1391 cdataw->_state = cdatar->_state;
1392 cdataw->_effects = cdatar->_effects;
1393 cdataw->_draw_control_mask = cdatar->_draw_control_mask;
1394 cdataw->_draw_show_mask = cdatar->_draw_show_mask;
1398 cdataw->_into_collide_mask |= cdatar->_into_collide_mask;
1400 for (
size_t n = 0; n < cdatar->_tag_data.size(); ++n) {
1401 cdataw->_tag_data.store(cdatar->_tag_data.get_key(n), cdatar->_tag_data.get_data(n));
1404 static const int change_bits = (FB_transform | FB_state | FB_effects |
1405 FB_tag | FB_draw_mask);
1406 cdataw->_fancy_bits =
1407 (cdataw->_fancy_bits & ~change_bits) |
1408 (cdatar->_fancy_bits & change_bits);
1410 if (pipeline_stage == 0) {
1411 if (cdataw->_transform != cdataw->_prev_transform) {
1412 do_set_dirty_prev_transform();
1416 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1420 _python_tag_data = other->_python_tag_data;
1422 if (any_transform_changed || any_state_changed || any_draw_mask_changed) {
1423 mark_bounds_stale(current_thread);
1425 if (any_transform_changed) {
1426 transform_changed();
1428 if (any_state_changed) {
1431 if (any_draw_mask_changed) {
1432 draw_mask_changed();
1457 if (other ==
this) {
1474 for (pi = other->_paths.begin(); pi != other->_paths.end(); ++pi) {
1475 (*pi)->_node =
this;
1478 other->_paths.clear();
1515 _unexpected_change_flags |= flags;
1531 return _unexpected_change_flags & flags;
1550 _unexpected_change_flags &= ~flags;
1586 bool any_changed =
false;
1589 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1590 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1592 DrawMask draw_control_mask = (cdata->_draw_control_mask | show_mask | hide_mask) & ~clear_mask;
1593 DrawMask draw_show_mask = (cdata->_draw_show_mask | show_mask) & ~hide_mask;
1595 draw_show_mask |= ~draw_control_mask;
1597 if (cdata->_draw_control_mask != draw_control_mask ||
1598 cdata->_draw_show_mask != draw_show_mask) {
1599 cdata->_draw_control_mask = draw_control_mask;
1600 cdata->_draw_show_mask = draw_show_mask;
1603 cdata->set_fancy_bit(FB_draw_mask, !draw_control_mask.
is_zero());
1605 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1608 mark_bounds_stale(current_thread);
1609 draw_mask_changed();
1627 if (cdata->_last_update != cdata->_next_update) {
1631 ((
PandaNode *)
this)->update_cached(
false, pipeline_stage, cdata);
1632 return cdataw->_net_draw_control_mask;
1634 return cdata->_net_draw_control_mask;
1654 if (cdata->_last_update != cdata->_next_update) {
1658 ((
PandaNode *)
this)->update_cached(
false, pipeline_stage, cdata);
1659 return cdataw->_net_draw_show_mask;
1661 return cdata->_net_draw_show_mask;
1680 bool any_changed =
false;
1682 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1683 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1684 if (cdata->_into_collide_mask != mask) {
1685 cdata->_into_collide_mask = mask;
1689 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1692 mark_bounds_stale(current_thread);
1718 if (cdata->_last_update != cdata->_next_update) {
1722 ((
PandaNode *)
this)->update_cached(
false, pipeline_stage, cdata);
1723 return cdataw->_net_collide_mask;
1725 return cdata->_net_collide_mask;
1733 get_off_clip_planes(
Thread *current_thread)
const {
1735 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
1736 if (cdata->_last_update != cdata->_next_update) {
1739 CDStageWriter cdataw =
1740 ((
PandaNode *)
this)->update_cached(
false, pipeline_stage, cdata);
1741 return cdataw->_off_clip_planes;
1743 return cdata->_off_clip_planes;
1773 if (_scene_root_func !=
nullptr) {
1774 return (*_scene_root_func)(
this);
1807 output(ostream &out)
const {
1808 out << get_type() <<
" " << get_name();
1815 write(ostream &out,
int indent_level)
const {
1816 indent(out, indent_level) << *
this;
1824 out <<
" " << *transform;
1828 out <<
" " << *state;
1832 out <<
" " << *effects;
1835 if (!draw_control_mask.
is_zero()) {
1837 if (!(draw_control_mask & _overall_bit).is_zero()) {
1838 if (!(draw_show_mask & _overall_bit).is_zero()) {
1839 out <<
" (show_through)";
1844 if (!(draw_control_mask & ~_overall_bit).is_zero()) {
1845 draw_control_mask &= ~_overall_bit;
1846 if (!(draw_show_mask & draw_control_mask).is_zero()) {
1847 out <<
" (per-camera show_through)";
1849 if (!(~draw_show_mask & draw_control_mask).is_zero()) {
1850 out <<
" (per-camera hidden)";
1874 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1875 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1876 cdata->_bounds_type = bounds_type;
1877 mark_bounds_stale(pipeline_stage, current_thread);
1881 mark_internal_bounds_stale(pipeline_stage, current_thread);
1884 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1892 CDReader cdata(_cycler);
1893 return cdata->_bounds_type;
1909 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1910 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1911 if (volume ==
nullptr) {
1912 cdata->_user_bounds =
nullptr;
1914 cdata->_user_bounds = volume->make_copy();
1916 mark_bounds_stale(pipeline_stage, current_thread);
1919 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1927 pgraph_cat.warning()
1928 <<
"Deprecated PandaNode::set_bound() called. Use set_bounds() instead.\n";
1938 get_bounds(
Thread *current_thread)
const {
1940 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
1941 if (cdata->_last_bounds_update != cdata->_next_update) {
1946 CDStageWriter cdataw =
1947 ((
PandaNode *)
this)->update_cached(
true, pipeline_stage, cdata);
1948 result = cdataw->_external_bounds;
1952 return cdata->_external_bounds;
1969 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
1970 if (cdata->_last_bounds_update != cdata->_next_update) {
1975 CDStageWriter cdataw =
1976 ((
PandaNode *)
this)->update_cached(
true, pipeline_stage, cdata);
1977 result = cdataw->_external_bounds;
1978 seq = cdataw->_last_bounds_update;
1982 seq = cdata->_last_bounds_update;
1983 return cdata->_external_bounds;
1996 get_nested_vertices(
Thread *current_thread)
const {
1998 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
1999 if (cdata->_last_bounds_update != cdata->_next_update) {
2004 CDStageWriter cdataw =
2005 ((
PandaNode *)
this)->update_cached(
true, pipeline_stage, cdata);
2006 result = cdataw->_nested_vertices;
2010 return cdata->_nested_vertices;
2027 mark_bounds_stale(
Thread *current_thread)
const {
2028 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
2029 mark_bounds_stale(pipeline_stage, current_thread);
2031 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
2046 mark_internal_bounds_stale(
Thread *current_thread) {
2047 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
2048 mark_internal_bounds_stale(pipeline_stage, current_thread);
2050 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
2119 decode_from_bam_stream(vector_uchar data,
BamReader *reader) {
2135 get_internal_bounds(
int pipeline_stage,
Thread *current_thread)
const {
2139 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
2140 if (cdata->_user_bounds !=
nullptr) {
2141 return cdata->_user_bounds;
2144 if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
2145 return cdata->_internal_bounds;
2148 mark = cdata->_internal_bounds_mark;
2154 int internal_vertices;
2155 compute_internal_bounds(internal_bounds, internal_vertices,
2156 pipeline_stage, current_thread);
2157 nassertr(!internal_bounds.is_null(),
nullptr);
2160 CDStageWriter cdataw(((
PandaNode *)
this)->_cycler, pipeline_stage);
2161 if (cdataw->_internal_bounds_mark == mark) {
2162 cdataw->_internal_bounds_computed = mark;
2163 cdataw->_internal_bounds = internal_bounds;
2164 cdataw->_internal_vertices = internal_vertices;
2165 ((
PandaNode *)
this)->mark_bam_modified();
2166 return cdataw->_internal_bounds;
2182 get_internal_vertices(
int pipeline_stage,
Thread *current_thread)
const {
2186 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
2187 if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
2188 return cdata->_internal_vertices;
2191 mark = cdata->_internal_bounds_mark;
2197 int internal_vertices;
2198 compute_internal_bounds(internal_bounds, internal_vertices,
2199 pipeline_stage, current_thread);
2200 nassertr(!internal_bounds.is_null(), 0);
2203 CDStageWriter cdataw(((
PandaNode *)
this)->_cycler, pipeline_stage);
2204 if (cdataw->_internal_bounds_mark == mark) {
2205 cdataw->_internal_bounds_computed = mark;
2206 cdataw->_internal_bounds = internal_bounds;
2207 cdataw->_internal_vertices = internal_vertices;
2208 ((
PandaNode *)
this)->mark_bam_modified();
2209 return cdataw->_internal_vertices;
2227 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2228 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
2229 cdataw->_internal_bounds = volume;
2230 cdataw->_internal_bounds_computed = cdataw->_internal_bounds_mark;
2232 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2233 mark_bounds_stale(current_thread);
2245 force_bounds_stale(
Thread *current_thread) {
2246 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
2247 force_bounds_stale(pipeline_stage, current_thread);
2249 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
2257 force_bounds_stale(
int pipeline_stage,
Thread *current_thread) {
2259 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2260 ++cdata->_next_update;
2273 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
2274 parents = Parents(cdata);
2276 int num_parents = parents.get_num_parents();
2277 for (
int i = 0; i < num_parents; ++i) {
2279 parent->mark_bounds_stale(pipeline_stage, current_thread);
2288 r_mark_geom_bounds_stale(
Thread *current_thread) {
2292 for (i = 0; i < children.get_num_children(); i++) {
2294 child->r_mark_geom_bounds_stale(current_thread);
2298 for (i = 0; i < stashed.get_num_stashed(); i++) {
2300 child->r_mark_geom_bounds_stale(current_thread);
2311 int &internal_vertices,
2313 Thread *current_thread)
const {
2315 internal_vertices = 0;
2325 nassertv((_unexpected_change_flags & UC_parents) == 0);
2334 children_changed() {
2335 nassertv((_unexpected_change_flags & UC_children) == 0);
2344 transform_changed() {
2345 nassertv((_unexpected_change_flags & UC_transform) == 0);
2355 nassertv((_unexpected_change_flags & UC_state) == 0);
2363 draw_mask_changed() {
2364 nassertv((_unexpected_change_flags & UC_draw_mask) == 0);
2378 nassertr(copy !=
nullptr,
nullptr);
2379 if (copy->get_type() != get_type()) {
2380 pgraph_cat.warning()
2381 <<
"Don't know how to copy nodes of type " << get_type() <<
"\n";
2383 if (no_unsupported_copy) {
2384 nassert_raise(
"unsupported copy");
2389 copy->r_copy_children(
this, inst_map, current_thread);
2405 Thread *current_thread) {
2406 CDReader from_cdata(from->_cycler, current_thread);
2407 CPT(Down) from_down = from_cdata->get_down();
2408 Down::const_iterator di;
2409 for (di = from_down->begin(); di != from_down->end(); ++di) {
2410 int sort = (*di).get_sort();
2418 InstanceMap::const_iterator ci;
2419 ci = inst_map.find(source_child);
2420 if (ci != inst_map.end()) {
2421 dest_child = (*ci).second;
2423 dest_child = source_child->r_copy_subgraph(inst_map, current_thread);
2424 inst_map[source_child] = dest_child;
2427 quick_add_new_child(dest_child, sort, current_thread);
2444 CPT(
RenderState) child_state = node_state->compose(child->get_state());
2445 child->
r_prepare_scene(gsg, child_state, transformer, current_thread);
2451 CPT(
RenderState) child_state = node_state->compose(child->get_state());
2452 child->
r_prepare_scene(gsg, child_state, transformer, current_thread);
2462 set_cull_callback() {
2464 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2465 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2466 cdata->set_fancy_bit(FB_cull_callback,
true);
2468 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2476 disable_cull_callback() {
2478 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2479 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2480 cdata->set_fancy_bit(FB_cull_callback,
false);
2482 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2491 stage_remove_child(
PandaNode *child_node,
int pipeline_stage,
2492 Thread *current_thread) {
2493 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2497 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
2499 int parent_index = child_node->do_find_parent(
this, cdata_child);
2500 if (parent_index < 0) {
2505 PT(Down) down = cdata->modify_down();
2506 int child_index = do_find_child(child_node, down);
2507 if (child_index >= 0) {
2509 down->erase(down->begin() + child_index);
2510 int num_erased = cdata_child->modify_up()->erase(UpConnection(
this));
2511 nassertr(num_erased == 1,
false);
2515 PT(Down) stashed = cdata->modify_stashed();
2516 int stashed_index = do_find_child(child_node, stashed);
2517 if (stashed_index >= 0) {
2519 stashed->erase(stashed->begin() + stashed_index);
2520 int num_erased = cdata_child->modify_up()->erase(UpConnection(
this));
2521 nassertr(num_erased == 1,
false);
2527 nassertr(
false,
false);
2537 int pipeline_stage,
Thread *current_thread) {
2539 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2540 CDStageWriter cdata_orig_child(orig_child->_cycler, pipeline_stage, current_thread);
2541 CDStageWriter cdata_new_child(new_child->_cycler, pipeline_stage, current_thread);
2545 int parent_index = orig_child->do_find_parent(
this, cdata_orig_child);
2546 if (parent_index < 0) {
2551 if (orig_child == new_child) {
2557 PT(
PandaNode) keep_orig_child = orig_child;
2560 if (stage_remove_child(new_child, pipeline_stage, current_thread)) {
2561 sever_connection(
this, new_child, pipeline_stage, current_thread);
2564 PT(Down) down = cdata->modify_down();
2565 int child_index = do_find_child(orig_child, down);
2566 if (child_index >= 0) {
2568 DownConnection &dc = (*down)[child_index];
2569 nassertr(dc.get_child() == orig_child,
false);
2570 dc.set_child(new_child);
2573 PT(Down) stashed = cdata->modify_stashed();
2574 int stashed_index = do_find_child(orig_child, stashed);
2575 if (stashed_index >= 0) {
2577 DownConnection &dc = (*stashed)[stashed_index];
2578 nassertr(dc.get_child() == orig_child,
false);
2579 dc.set_child(new_child);
2585 nassertr(
false,
false);
2591 cdata_new_child->modify_up()->insert(UpConnection(
this));
2592 int num_erased = cdata_orig_child->modify_up()->erase(UpConnection(
this));
2593 nassertr(num_erased == 1,
false);
2596 sever_connection(
this, orig_child, pipeline_stage, current_thread);
2597 new_connection(
this, new_child, pipeline_stage, current_thread);
2599 force_bounds_stale(pipeline_stage, current_thread);
2600 orig_child->parents_changed();
2601 new_child->parents_changed();
2616 quick_add_new_child(
PandaNode *child_node,
int sort,
Thread *current_thread) {
2619 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2620 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2621 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
2623 cdata->modify_down()->insert(DownConnection(child_node, sort));
2624 cdata_child->modify_up()->insert(UpConnection(
this));
2626 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2635 strm <<
"Detected attempt to create a cycle in the scene graph: "
2637 nassert_raise(strm.str());
2651 for (
size_t i = 0; i < parents.get_num_parents(); ++i) {
2653 if (parent->find_node_above(node)) {
2671 int pipeline_stage,
Thread *current_thread) {
2672 if (parent ==
nullptr) {
2677 pipeline_stage, current_thread);
2679 child_node->_paths.insert(child);
2685 PT(
NodePathComponent) child = get_component(parent, child_node, pipeline_stage, current_thread);
2687 if (child ==
nullptr) {
2690 child = get_top_component(child_node,
true, pipeline_stage, current_thread);
2693 reparent(parent, child, sort,
false, pipeline_stage, current_thread);
2706 nassertv(child !=
nullptr);
2708 for (
int pipeline_stage_i = pipeline_stage;
2709 pipeline_stage_i >= 0;
2710 --pipeline_stage_i) {
2711 detach_one_stage(child, pipeline_stage_i, current_thread);
2714 child->
get_node()->parents_changed();
2725 Thread *current_thread) {
2726 nassertv(child !=
nullptr);
2727 if (child->
is_top_node(pipeline_stage, current_thread)) {
2734 CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
2735 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
2736 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
2737 if (parent_index >= 0) {
2741 int num_erased = cdata_child->modify_up()->erase(UpConnection(parent_node));
2742 nassertv(num_erased == 1);
2749 PT(Down) down = cdata_parent->modify_down();
2750 for (di = down->begin(); di != down->end(); ++di) {
2751 if ((*di).get_child() == child_node) {
2758 PT(Down) stashed = cdata_parent->modify_stashed();
2759 for (di = stashed->begin(); di != stashed->end(); ++di) {
2760 if ((*di).get_child() == child_node) {
2771 sever_connection(parent_node, child_node, pipeline_stage, current_thread);
2773 parent_node->force_bounds_stale(pipeline_stage, current_thread);
2774 parent_node->children_changed();
2775 parent_node->mark_bam_modified();
2789 bool as_stashed,
int pipeline_stage,
Thread *current_thread) {
2790 bool any_ok =
false;
2792 if (new_parent !=
nullptr &&
2799 for (
int pipeline_stage_i = pipeline_stage;
2800 pipeline_stage_i >= 0;
2801 --pipeline_stage_i) {
2802 if (reparent_one_stage(new_parent, child, sort, as_stashed,
2803 pipeline_stage_i, current_thread)) {
2808 if (new_parent !=
nullptr) {
2809 new_parent->
get_node()->children_changed();
2812 child->
get_node()->parents_changed();
2829 int sort,
bool as_stashed,
int pipeline_stage,
2830 Thread *current_thread) {
2831 nassertr(child !=
nullptr,
false);
2837 if (!child->
is_top_node(pipeline_stage, current_thread)) {
2838 detach(child, pipeline_stage, current_thread);
2841 if (new_parent !=
nullptr) {
2846 CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
2847 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
2849 if (parent_index >= 0) {
2856 child->set_next(new_parent, pipeline_stage, current_thread);
2860 CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
2861 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
2864 cdata_parent->modify_stashed()->insert(DownConnection(child_node, sort));
2866 cdata_parent->modify_down()->insert(DownConnection(child_node, sort));
2868 cdata_child->modify_up()->insert(UpConnection(parent_node));
2874 nassertr(child_node->_paths.find(child) != child_node->_paths.end(),
false);
2879 child_node->fix_path_lengths(pipeline_stage, current_thread);
2880 parent_node->force_bounds_stale(pipeline_stage, current_thread);
2892 int pipeline_stage,
Thread *current_thread) {
2893 nassertr(parent !=
nullptr,
nullptr);
2901 Paths::const_iterator pi;
2902 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
2903 if ((*pi)->get_next(pipeline_stage, current_thread) == parent) {
2911 CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
2912 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
2914 if (parent_index >= 0) {
2918 child_node->_paths.insert(child);
2937 get_top_component(
PandaNode *child_node,
bool force,
int pipeline_stage,
2938 Thread *current_thread) {
2943 Paths::const_iterator pi;
2944 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
2945 if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
2961 pipeline_stage, current_thread);
2962 child_node->_paths.insert(child);
2975 get_generic_component(
bool accept_ambiguity,
int pipeline_stage,
2976 Thread *current_thread) {
2977 bool ambiguity_detected =
false;
2979 r_get_generic_component(accept_ambiguity, ambiguity_detected,
2980 pipeline_stage, current_thread);
2982 if (!accept_ambiguity && ambiguity_detected) {
2983 pgraph_cat.warning()
2984 <<
"Chose: " << *result <<
"\n";
2985 nassertr(!unambiguous_graph, result);
2997 r_get_generic_component(
bool accept_ambiguity,
bool &ambiguity_detected,
2998 int pipeline_stage,
Thread *current_thread) {
3002 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
3004 int num_parents = cdata->get_up()->size();
3005 if (num_parents == 0) {
3007 return get_top_component(
this,
true, pipeline_stage, current_thread);
3011 if (num_parents == 1) {
3014 get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
3015 return get_component(parent,
this, pipeline_stage, current_thread);
3019 if (!accept_ambiguity) {
3020 pgraph_cat.warning()
3021 << *
this <<
" has " << num_parents
3022 <<
" parents; choosing arbitrary path to root.\n";
3024 ambiguity_detected =
true;
3025 CPT(Up) up = cdata->get_up();
3031 parent_node->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
3032 return get_component(parent,
this, pipeline_stage, current_thread);
3042 int num_erased = _paths.erase(component);
3043 nassertv(num_erased == 1);
3060 int pipeline_stage,
Thread *current_thread) {
3064 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
3065 if (!(*pi)->is_top_node(pipeline_stage, current_thread) &&
3066 (*pi)->get_next(pipeline_stage, current_thread)->get_node() == parent_node) {
3068 (*pi)->set_top_node(pipeline_stage, current_thread);
3072 child_node->fix_path_lengths(pipeline_stage, current_thread);
3088 int pipeline_stage,
Thread *current_thread) {
3092 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
3093 if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
3094 (*pi)->set_next(parent_node->get_generic_component(
false, pipeline_stage, current_thread), pipeline_stage, current_thread);
3098 child_node->fix_path_lengths(pipeline_stage, current_thread);
3110 fix_path_lengths(
int pipeline_stage,
Thread *current_thread) {
3113 bool any_wrong =
false;
3115 Paths::const_iterator pi;
3116 for (pi = _paths.begin(); pi != _paths.end(); ++pi) {
3117 if ((*pi)->fix_length(pipeline_stage, current_thread)) {
3129 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
3130 children = Children(cdata);
3131 stashed = Stashed(cdata);
3134 int num_children = children.get_num_children();
3136 for (i = 0; i < num_children; ++i) {
3138 child_node->fix_path_lengths(pipeline_stage, current_thread);
3140 int num_stashed = stashed.get_num_stashed();
3141 for (i = 0; i < num_stashed; ++i) {
3143 child_node->fix_path_lengths(pipeline_stage, current_thread);
3152 r_list_descendants(ostream &out,
int indent_level)
const {
3153 write(out, indent_level);
3156 int num_children = children.get_num_children();
3158 for (
int i = 0; i < num_children; ++i) {
3159 PandaNode *child = children.get_child(i);
3160 child->r_list_descendants(out, indent_level + 2);
3165 if (num_stashed != 0) {
3166 indent(out, indent_level) <<
"(" << num_stashed <<
" stashed)\n";
3175 nassertr(node !=
nullptr, -1);
3179 Down::const_iterator di;
3180 for (di = down->begin(); di != down->end(); ++di) {
3181 if ((*di).get_child() == node) {
3182 return di - down->begin();
3204 if (drawmask_cat.is_debug()) {
3205 drawmask_cat.debug(
false)
3206 << *
this <<
"::update_cached() {\n";
3212 UpdateSeq last_update = cdata->_last_update;
3213 UpdateSeq next_update = cdata->_next_update;
3214 UpdateSeq last_bounds_update = cdata->_last_bounds_update;
3215 nassertr(last_update != next_update ||
3216 (update_bounds && last_bounds_update != next_update),
3217 CDStageWriter(_cycler, pipeline_stage, cdata));
3220 CollideMask net_collide_mask = cdata->_into_collide_mask;
3221 DrawMask net_draw_control_mask, net_draw_show_mask;
3227 net_draw_control_mask = cdata->_draw_control_mask;
3228 net_draw_show_mask = cdata->_draw_show_mask;
3231 if (drawmask_cat.is_debug()) {
3232 drawmask_cat.debug(
false)
3233 <<
"net_draw_control_mask = " << net_draw_control_mask
3234 <<
"\nnet_draw_show_mask = " << net_draw_show_mask
3237 CPT(
RenderAttrib) off_clip_planes = cdata->_state->get_attrib(ClipPlaneAttrib::get_class_slot());
3238 if (off_clip_planes ==
nullptr) {
3239 off_clip_planes = ClipPlaneAttrib::make();
3243 Children children(cdata);
3245 int num_vertices = cdata->_internal_vertices;
3251 int num_children = children.get_num_children();
3258 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
3260 if (update_bounds) {
3261 child_volumes_ref.reserve(num_children + 1);
3264 int child_volumes_i = 0;
3266 bool all_box =
true;
3269 if (update_bounds) {
3271 internal_bounds = get_internal_bounds(pipeline_stage, current_thread);
3273 if (!internal_bounds->is_empty()) {
3274 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
3275 child_volumes_ref.push_back(internal_bounds);
3277 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
3278 child_volumes[child_volumes_i++] = internal_bounds;
3279 if (internal_bounds->as_bounding_box() ==
nullptr) {
3287 for (
int i = 0; i < num_children; ++i) {
3292 CDLockedStageReader child_cdata(child->_cycler, pipeline_stage, current_thread);
3294 UpdateSeq last_child_update = update_bounds
3295 ? child_cdata->_last_bounds_update
3296 : child_cdata->_last_update;
3298 if (last_child_update != child_cdata->_next_update) {
3300 CDStageWriter child_cdataw = child->update_cached(update_bounds, pipeline_stage, child_cdata);
3302 net_collide_mask |= child_cdataw->_net_collide_mask;
3304 if (drawmask_cat.is_debug()) {
3305 drawmask_cat.debug(
false)
3306 <<
"\nchild update " << *child <<
":\n";
3309 DrawMask child_control_mask = child_cdataw->_net_draw_control_mask;
3310 DrawMask child_show_mask = child_cdataw->_net_draw_show_mask;
3311 if (!(child_control_mask | child_show_mask).is_zero()) {
3343 DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
3344 exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
3346 if (drawmask_cat.is_debug()) {
3347 drawmask_cat.debug(
false)
3348 <<
"exception_mask = " << exception_mask <<
"\n";
3352 net_draw_control_mask |= child_control_mask;
3353 net_draw_show_mask |= child_show_mask;
3355 net_draw_control_mask &= ~exception_mask;
3356 net_draw_show_mask |= exception_mask;
3359 if (drawmask_cat.is_debug()) {
3360 drawmask_cat.debug(
false)
3361 <<
"child_control_mask = " << child_control_mask
3362 <<
"\nchild_show_mask = " << child_show_mask
3363 <<
"\nnet_draw_control_mask = " << net_draw_control_mask
3364 <<
"\nnet_draw_show_mask = " << net_draw_show_mask
3368 off_clip_planes = orig_cp->compose_off(child_cdataw->_off_clip_planes);
3370 if (update_bounds) {
3371 if (!child_cdataw->_external_bounds->is_empty()) {
3372 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
3373 child_volumes_ref.push_back(child_cdataw->_external_bounds);
3375 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
3376 child_volumes[child_volumes_i++] = child_cdataw->_external_bounds;
3377 if (child_cdataw->_external_bounds->as_bounding_box() ==
nullptr) {
3381 num_vertices += child_cdataw->_nested_vertices;
3386 net_collide_mask |= child_cdata->_net_collide_mask;
3389 if (drawmask_cat.is_debug()) {
3390 drawmask_cat.debug(
false)
3391 <<
"\nchild fresh " << *child <<
":\n";
3393 DrawMask child_control_mask = child_cdata->_net_draw_control_mask;
3394 DrawMask child_show_mask = child_cdata->_net_draw_show_mask;
3395 if (!(child_control_mask | child_show_mask).is_zero()) {
3398 DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
3399 exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
3401 if (drawmask_cat.is_debug()) {
3402 drawmask_cat.debug(
false)
3403 <<
"exception_mask = " << exception_mask <<
"\n";
3407 net_draw_control_mask |= child_control_mask;
3408 net_draw_show_mask |= child_show_mask;
3410 net_draw_control_mask &= ~exception_mask;
3411 net_draw_show_mask |= exception_mask;
3414 if (drawmask_cat.is_debug()) {
3415 drawmask_cat.debug(
false)
3416 <<
"child_control_mask = " << child_control_mask
3417 <<
"\nchild_show_mask = " << child_show_mask
3418 <<
"\nnet_draw_control_mask = " << net_draw_control_mask
3419 <<
"\nnet_draw_show_mask = " << net_draw_show_mask
3423 off_clip_planes = orig_cp->compose_off(child_cdata->_off_clip_planes);
3425 if (update_bounds) {
3426 if (!child_cdata->_external_bounds->is_empty()) {
3427 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
3428 child_volumes_ref.push_back(child_cdata->_external_bounds);
3430 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
3431 child_volumes[child_volumes_i++] = child_cdata->_external_bounds;
3432 if (child_cdata->_external_bounds->as_bounding_box() ==
nullptr) {
3436 num_vertices += child_cdata->_nested_vertices;
3443 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
3444 if (last_update == cdataw->_last_update &&
3445 next_update == cdataw->_next_update) {
3448 cdataw->_net_collide_mask = net_collide_mask;
3453 DrawMask draw_control_mask = cdataw->_draw_control_mask;
3454 DrawMask draw_show_mask = cdataw->_draw_show_mask;
3456 DrawMask show_through_mask = net_draw_control_mask & net_draw_show_mask;
3458 net_draw_control_mask |= draw_control_mask;
3459 net_draw_show_mask = (net_draw_show_mask & ~draw_control_mask) | (draw_show_mask & draw_control_mask);
3461 net_draw_show_mask |= show_through_mask;
3465 cdataw->_net_draw_control_mask = net_draw_control_mask;
3466 cdataw->_net_draw_show_mask = net_draw_show_mask | ~net_draw_control_mask;
3467 if (drawmask_cat.is_debug()) {
3468 drawmask_cat.debug(
false)
3469 <<
"renderable, set mask " << cdataw->_net_draw_show_mask <<
"\n";
3475 cdataw->_net_draw_control_mask = net_draw_control_mask;
3476 cdataw->_net_draw_show_mask = net_draw_show_mask;
3477 if (drawmask_cat.is_debug()) {
3478 drawmask_cat.debug(
false)
3479 <<
"not renderable, set mask " << cdataw->_net_draw_show_mask <<
"\n";
3483 cdataw->_off_clip_planes = off_clip_planes;
3485 if (update_bounds) {
3486 cdataw->_nested_vertices = num_vertices;
3491 BoundingVolume::BoundsType btype = cdataw->_bounds_type;
3492 if (btype == BoundingVolume::BT_default) {
3493 btype = bounds_type;
3496 if (btype == BoundingVolume::BT_box ||
3497 (btype != BoundingVolume::BT_sphere && all_box && transform->
is_identity())) {
3507 if (child_volumes_i > 0) {
3509 const BoundingVolume **child_end = child_begin + child_volumes_i;
3515 gbv->xform(transform->
get_mat());
3519 cdataw->_external_bounds = gbv;
3520 cdataw->_last_bounds_update = next_update;
3523 cdataw->_last_update = next_update;
3525 if (drawmask_cat.is_debug()) {
3526 drawmask_cat.debug(
false)
3527 <<
"} " << *
this <<
"::update_cached();\n";
3530 nassertr(cdataw->_last_update == cdataw->_next_update, cdataw);
3538 if (cdataw->_last_update == cdataw->_next_update &&
3539 (!update_bounds || cdataw->_last_bounds_update == cdataw->_next_update)) {
3547 cdata = CDLockedStageReader(_cycler, pipeline_stage, current_thread);
3549 if (cdata->_last_update == cdata->_next_update &&
3550 (!update_bounds || cdata->_last_bounds_update == cdata->_next_update)) {
3553 return CDStageWriter(_cycler, pipeline_stage, cdata);
3567 _scene_root_func = func;
3597 cdata->update_bam_nested(manager);
3628 node->fillin(scan, manager);
3670 _draw_control_mask(
DrawMask::all_off()),
3671 _draw_show_mask(
DrawMask::all_on()),
3674 _user_bounds(nullptr),
3675 _final_bounds(false),
3679 _net_draw_control_mask(
DrawMask::all_off()),
3680 _net_draw_show_mask(
DrawMask::all_off()),
3693 CData(
const PandaNode::CData ©) :
3695 _state(copy._state),
3696 _transform(copy._transform),
3697 _prev_transform(copy._prev_transform),
3699 _effects(copy._effects),
3700 _tag_data(copy._tag_data),
3701 _draw_control_mask(copy._draw_control_mask),
3702 _draw_show_mask(copy._draw_show_mask),
3703 _into_collide_mask(copy._into_collide_mask),
3704 _bounds_type(copy._bounds_type),
3705 _user_bounds(copy._user_bounds),
3706 _final_bounds(copy._final_bounds),
3707 _fancy_bits(copy._fancy_bits),
3709 _net_collide_mask(copy._net_collide_mask),
3710 _net_draw_control_mask(copy._net_draw_control_mask),
3711 _net_draw_show_mask(copy._net_draw_show_mask),
3712 _off_clip_planes(copy._off_clip_planes),
3713 _nested_vertices(copy._nested_vertices),
3714 _external_bounds(copy._external_bounds),
3715 _last_update(copy._last_update),
3716 _next_update(copy._next_update),
3717 _last_bounds_update(copy._last_bounds_update),
3720 _stashed(copy._stashed),
3740 return new CData(*
this);
3747 void PandaNode::CData::
3755 dg.
add_uint32(_draw_control_mask.get_word());
3757 dg.
add_uint32(_into_collide_mask.get_word());
3761 for (
size_t n = 0; n < _tag_data.size(); ++n) {
3766 write_up_list(*get_up(), manager, dg);
3767 write_down_list(*get_down(), manager, dg);
3768 write_down_list(*get_stashed(), manager, dg);
3775 void PandaNode::CData::
3776 update_bam_nested(
BamWriter *manager)
const {
3781 update_up_list(*get_up(), manager);
3782 update_down_list(*get_down(), manager);
3783 update_down_list(*get_stashed(), manager);
3790 int PandaNode::CData::
3796 DCAST_INTO_R(state, p_list[pi++], pi);
3800 DCAST_INTO_R(transform, p_list[pi++], pi);
3801 _prev_transform = _transform = transform;
3819 DCAST_INTO_R(effects, p_list[pi++], pi);
3836 pi += complete_up_list(*modify_up(),
"up", p_list + pi, manager);
3837 pi += complete_down_list(*modify_down(),
"down", p_list + pi, manager);
3838 pi += complete_down_list(*modify_stashed(),
"stashed", p_list + pi, manager);
3842 set_fancy_bit(FB_transform, !_transform->is_identity());
3843 set_fancy_bit(FB_state, !_state->is_empty());
3844 set_fancy_bit(FB_effects, !_effects->is_empty());
3845 set_fancy_bit(FB_tag, !_tag_data.is_empty());
3850 nassertr(!_transform->is_invalid(), pi);
3851 nassertr(!_prev_transform->is_invalid(), pi);
3860 void PandaNode::CData::
3875 _draw_control_mask = _overall_bit;
3876 _draw_show_mask = ~_overall_bit;
3885 draw_mask &= ~_overall_bit;
3886 _draw_control_mask = ~draw_mask;
3887 _draw_show_mask = draw_mask;
3895 _into_collide_mask.set_word(scan.
get_uint32());
3897 _bounds_type = BoundingVolume::BT_default;
3899 _bounds_type = (BoundingVolume::BoundsType)scan.
get_uint8();
3904 for (
int i = 0; i < num_tags; i++) {
3907 _tag_data.store(key, value);
3911 fillin_up_list(*modify_up(),
"up", scan, manager);
3912 fillin_down_list(*modify_down(),
"down", scan, manager);
3913 fillin_down_list(*modify_stashed(),
"stashed", scan, manager);
3919 void PandaNode::CData::
3932 int num_parents = 0;
3933 Up::const_iterator ui;
3934 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
3940 nassertv(num_parents == (
int)(uint16_t)num_parents);
3942 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
3953 void PandaNode::CData::
3956 int num_children = down_list.size();
3957 nassertv(num_children == (
int)(uint16_t)num_children);
3962 Down::const_iterator di;
3963 for (di = down_list.begin(); di != down_list.end(); ++di) {
3965 int sort = (*di).get_sort();
3974 void PandaNode::CData::
3976 Up::const_iterator ui;
3977 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
3988 void PandaNode::CData::
3990 Down::const_iterator di;
3991 for (di = down_list.begin(); di != down_list.end(); ++di) {
4000 int PandaNode::CData::
4006 Up new_up_list(PandaNode::get_class_type());
4007 new_up_list.reserve(num_parents);
4008 for (
int i = 0; i < num_parents; i++) {
4010 UpConnection connection(parent_node);
4011 new_up_list.push_back(connection);
4019 up_list.swap(new_up_list);
4020 new_up_list.clear();
4028 int PandaNode::CData::
4033 BamReaderAuxDataDown *aux;
4036 Down &new_down_list = aux->_down_list;
4037 for (Down::iterator di = new_down_list.begin();
4038 di != new_down_list.end();
4041 (*di).set_child(child_node);
4049 down_list.swap(new_down_list);
4050 new_down_list.clear();
4059 void PandaNode::CData::
4071 void PandaNode::CData::
4079 Down new_down_list(PandaNode::get_class_type());
4080 new_down_list.reserve(num_children);
4081 for (
int i = 0; i < num_children; i++) {
4084 DownConnection connection(
nullptr, sort);
4085 new_down_list.push_back(connection);
4090 PT(BamReaderAuxDataDown) aux =
new BamReaderAuxDataDown;
4091 aux->_down_list.swap(new_down_list);
4102 ? _cdata->_last_bounds_update
4103 : _cdata->_last_update;
4105 if (last_update != _cdata->_next_update) {
4110 #ifdef DO_PIPELINING
4112 #endif // DO_PIPELINING
4116 if (fresh_cdata->_last_update == fresh_cdata->_next_update &&
4117 (!update_bounds || fresh_cdata->_last_bounds_update == fresh_cdata->_next_update)) {
4120 if (_cdata != (
const PandaNode::CData *)fresh_cdata) {
4122 #ifdef DO_PIPELINING
4124 #endif // DO_PIPELINING
4130 PStatTimer timer(PandaNode::_update_bounds_pcollector);
4132 nassertv(cdataw->_last_update == cdataw->_next_update);
4135 if (_cdata != (
const PandaNode::CData *)cdataw) {
4137 #ifdef DO_PIPELINING
4139 #endif // DO_PIPELINING
4144 nassertv(_cdata->_last_update == _cdata->_next_update);
4145 nassertv(!update_bounds || _cdata->_last_bounds_update == _cdata->_next_update);