79 using std::ostringstream;
84 int NodePath::_max_search_depth = 7000;
87 PStatCollector NodePath::_get_transform_pcollector(
"*:NodePath:get_transform");
88 PStatCollector NodePath::_verify_complete_pcollector(
"*:NodePath:verify_complete");
99 nassertv(child_node !=
nullptr);
104 _head = PandaNode::get_top_component(child_node,
true,
105 pipeline_stage, current_thread);
108 _head = PandaNode::get_component(parent._head, child_node, pipeline_stage,
111 nassertv(_head !=
nullptr);
113 if (_head !=
nullptr) {
124 operator bool ()
const {
137 return _head->get_length(pipeline_stage, current_thread);
162 nassertr(comp !=
nullptr,
nullptr);
163 comp = comp->
get_next(pipeline_stage, current_thread);
169 nassertr(comp !=
nullptr,
nullptr);
191 comp = comp->
get_next(pipeline_stage, current_thread);
217 while (!comp->
is_top_node(pipeline_stage, current_thread)) {
218 comp = comp->
get_next(pipeline_stage, current_thread);
234 nassertr_always(!
is_empty(), result);
242 for (
int i = 0; i < num_children; i++) {
244 child._head = PandaNode::get_component(_head, cr.
get_child(i),
245 pipeline_stage, current_thread);
260 nassertr_always(!
is_empty(), result);
267 for (
int i = 0; i < num_stashed; i++) {
269 stashed._head = PandaNode::get_component(_head, bottom_node->
get_stashed(i),
270 pipeline_stage, current_thread);
291 PandaNode *parent = _head->get_next(pipeline_stage, current_thread)->get_node();
293 nassertr(parent !=
nullptr && child !=
nullptr, 0);
295 if (child_index != -1) {
300 if (child_index != -1) {
314 find(
const string &path)
const {
318 find_matches(col, path, 1);
340 find_matches(col, approx_path, 1);
358 find_matches(col, path, -1);
371 nassertr(
node !=
nullptr, col);
375 find_matches(col, approx_path, -1);
395 nassertv(other._error_type == ET_ok);
401 bool reparented = PandaNode::reparent(other._head, _head, sort,
false,
402 pipeline_stage, current_thread);
403 nassertv(reparented);
416 nassertv(other._error_type == ET_ok);
422 bool reparented = PandaNode::reparent(other._head, _head, sort,
true,
423 pipeline_stage, current_thread);
424 nassertv(reparented);
437 nassertv(other._error_type == ET_ok);
481 new_instance._head = PandaNode::attach(
nullptr,
node(), sort, pipeline_stage,
485 bool reparented = PandaNode::reparent(other._head, new_instance._head,
486 sort,
false, pipeline_stage,
501 nassertr(reparented, new_instance);
519 Thread *current_thread)
const {
539 nassertr(other._error_type == ET_ok,
fail());
542 PT(
PandaNode) copy_node = source_node->copy_subgraph(current_thread);
543 nassertr(copy_node !=
nullptr,
fail());
545 copy_node->reset_prev_transform(current_thread);
570 new_path._head = PandaNode::attach(_head,
node, sort, pipeline_stage,
592 nassertv(_error_type != ET_not_found);
600 PandaNode::detach(_head, pipeline_stage, current_thread);
603 if (
is_empty() || _head->has_key()) {
632 nassertv(_error_type != ET_not_found);
636 PandaNode::detach(_head, pipeline_stage, current_thread);
649 indent_level =
get_parent().reverse_ls(out, indent_level);
651 node()->write(out, indent_level);
652 return indent_level + 2;
661 switch (_error_type) {
663 out <<
"**not found**";
666 out <<
"**removed**";
675 if (_head ==
nullptr) {
689 nassertr_always(!
is_empty(), RenderState::make_empty());
690 return node()->get_state(current_thread);
699 nassertr(_error_type == ET_ok && other._error_type == ET_ok, RenderState::make_empty());
702 return get_net_state(current_thread);
705 return other.get_net_state(current_thread)->invert_compose(RenderState::make_empty());
708 #if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
710 nassertr(other.
verify_complete(current_thread), RenderState::make_empty());
713 int a_count, b_count;
714 if (find_common_ancestor(*
this, other, a_count, b_count, current_thread) ==
nullptr) {
715 if (allow_unrelated_wrt) {
717 << *
this <<
" is not related to " << other <<
"\n";
720 << *
this <<
" is not related to " << other <<
"\n";
721 nassert_raise(
"unrelated nodes");
722 return RenderState::make_empty();
726 CPT(
RenderState) a_state = r_get_partial_state(_head, a_count, current_thread);
727 CPT(
RenderState) b_state = r_get_partial_state(other._head, b_count, current_thread);
728 return b_state->invert_compose(a_state);
739 nassertv(_error_type == ET_ok && other._error_type == ET_ok);
750 CPT(
RenderState) new_state = rel_state->compose(state);
761 nassertr_always(!
is_empty(), TransformState::make_identity());
762 return node()->get_transform(current_thread);
771 nassertr(_error_type == ET_ok && other._error_type == ET_ok, TransformState::make_identity());
775 return get_net_transform(current_thread);
778 return other.get_net_transform(current_thread)->invert_compose(TransformState::make_identity());
781 #if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
782 nassertr(
verify_complete(current_thread), TransformState::make_identity());
783 nassertr(other.
verify_complete(current_thread), TransformState::make_identity());
786 int a_count, b_count;
787 if (find_common_ancestor(*
this, other, a_count, b_count, current_thread) ==
nullptr) {
788 if (allow_unrelated_wrt) {
789 if (pgraph_cat.is_debug()) {
791 << *
this <<
" is not related to " << other <<
"\n";
795 << *
this <<
" is not related to " << other <<
"\n";
796 nassert_raise(
"unrelated nodes");
797 return TransformState::make_identity();
803 a_transform = r_get_partial_transform(_head, a_count, current_thread);
804 if (a_transform !=
nullptr) {
805 b_transform = r_get_partial_transform(other._head, b_count, current_thread);
807 if (b_transform ==
nullptr) {
811 a_transform = r_get_net_transform(_head, current_thread);
812 b_transform = r_get_net_transform(other._head, current_thread);
815 return b_transform->invert_compose(a_transform);
826 nassertv(_error_type == ET_ok && other._error_type == ET_ok);
849 nassertr_always(!
is_empty(), TransformState::make_identity());
850 return node()->get_prev_transform(current_thread);
860 nassertr(_error_type == ET_ok && other._error_type == ET_ok, TransformState::make_identity());
863 return get_net_prev_transform(current_thread);
866 return other.get_net_prev_transform(current_thread)->invert_compose(TransformState::make_identity());
869 #if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
870 nassertr(
verify_complete(current_thread), TransformState::make_identity());
871 nassertr(other.
verify_complete(current_thread), TransformState::make_identity());
874 int a_count, b_count;
875 if (find_common_ancestor(*
this, other, a_count, b_count, current_thread) ==
nullptr) {
876 if (allow_unrelated_wrt) {
878 << *
this <<
" is not related to " << other <<
"\n";
881 << *
this <<
" is not related to " << other <<
"\n";
882 nassert_raise(
"unrelated nodes");
883 return TransformState::make_identity();
887 CPT(
TransformState) a_prev_transform = r_get_partial_prev_transform(_head, a_count, current_thread);
888 CPT(
TransformState) b_prev_transform = r_get_partial_prev_transform(other._head, b_count, current_thread);
889 return b_prev_transform->invert_compose(a_prev_transform);
900 nassertv(_error_type == ET_ok && other._error_type == ET_ok);
912 set_prev_transform(new_trans, current_thread);
923 set_pos(
const LVecBase3 &pos) {
930 set_x(PN_stdfloat x) {
938 set_y(PN_stdfloat y) {
946 set_z(PN_stdfloat z) {
965 set_fluid_x(PN_stdfloat x) {
973 set_fluid_y(PN_stdfloat y) {
981 set_fluid_z(PN_stdfloat z) {
993 nassertr_always(!
is_empty(), LPoint3(0.0f, 0.0f, 0.0f));
1008 nassertr_always(!
is_empty(), LPoint3(0.0f, 0.0f, 0.0f));
1020 nassertv(transform->
has_hpr());
1025 set_h(PN_stdfloat h) {
1028 nassertv(transform->
has_hpr());
1029 LVecBase3 hpr = transform->
get_hpr();
1035 set_p(PN_stdfloat p) {
1038 nassertv(transform->
has_hpr());
1039 LVecBase3 hpr = transform->
get_hpr();
1045 set_r(PN_stdfloat r) {
1048 nassertv(transform->
has_hpr());
1049 LVecBase3 hpr = transform->
get_hpr();
1059 nassertr_always(!
is_empty(), LVecBase3(0.0f, 0.0f, 0.0f));
1061 nassertr(transform->
has_hpr(), LVecBase3(0.0f, 0.0f, 0.0f));
1081 nassertr_always(!
is_empty(), LQuaternion::ident_quat());
1098 set_sx(PN_stdfloat sx) {
1101 LVecBase3 scale = transform->
get_scale();
1107 set_sy(PN_stdfloat sy) {
1110 LVecBase3 scale = transform->
get_scale();
1116 set_sz(PN_stdfloat sz) {
1119 LVecBase3 scale = transform->
get_scale();
1129 nassertr_always(!
is_empty(), LVecBase3(0.0f, 0.0f, 0.0f));
1146 set_shxy(PN_stdfloat shxy) {
1149 LVecBase3 shear = transform->
get_shear();
1155 set_shxz(PN_stdfloat shxz) {
1158 LVecBase3 shear = transform->
get_shear();
1164 set_shyz(PN_stdfloat shyz) {
1167 LVecBase3 shear = transform->
get_shear();
1177 nassertr_always(!
is_empty(), LVecBase3(0.0f, 0.0f, 0.0f));
1190 transform = TransformState::make_pos_hpr_scale_shear
1204 transform = TransformState::make_pos_quat_scale_shear
1218 transform = TransformState::make_pos_hpr_scale_shear
1231 transform = TransformState::make_pos_quat_scale_shear
1242 const LVecBase3 &scale) {
1255 const LVecBase3 &scale) {
1258 (pos, quat, scale));
1268 const LVecBase3 &scale,
const LVecBase3 &shear) {
1271 (pos, hpr, scale, shear));
1281 const LVecBase3 &scale,
const LVecBase3 &shear) {
1284 (pos, quat, scale, shear));
1303 look_at(
const LPoint3 &point,
const LVector3 &up) {
1338 if (orig_transform->has_components()) {
1343 const LVecBase3 &orig_hpr = orig_transform->get_hpr();
1344 const LVecBase3 &orig_scale = orig_transform->get_scale();
1345 const LVecBase3 &orig_shear = orig_transform->get_shear();
1358 set_x(
const NodePath &other, PN_stdfloat x) {
1362 set_pos(other, pos);
1366 set_y(
const NodePath &other, PN_stdfloat y) {
1370 set_pos(other, pos);
1374 set_z(
const NodePath &other, PN_stdfloat z) {
1378 set_pos(other, pos);
1391 if (orig_transform->has_components()) {
1396 const LVecBase3 &orig_hpr = orig_transform->get_hpr();
1397 const LVecBase3 &orig_scale = orig_transform->get_scale();
1398 const LVecBase3 &orig_shear = orig_transform->get_shear();
1413 set_fluid_x(
const NodePath &other, PN_stdfloat x) {
1421 set_fluid_y(
const NodePath &other, PN_stdfloat y) {
1429 set_fluid_z(
const NodePath &other, PN_stdfloat z) {
1442 nassertr_always(!
is_empty(), LPoint3(0.0f, 0.0f, 0.0f));
1457 nassertr_always(!
is_empty(), LPoint3(0.0f, 0.0f, 0.0f));
1468 nassertv(rel_transform->has_hpr());
1476 const LVecBase3 &orig_pos = transform->
get_pos();
1477 const LVecBase3 &orig_scale = transform->
get_scale();
1478 const LVecBase3 &orig_shear = transform->
get_shear();
1484 (orig_pos, transform->
get_hpr(), orig_scale, orig_shear));
1494 set_h(
const NodePath &other, PN_stdfloat h) {
1496 LVecBase3 hpr =
get_hpr(other);
1502 set_p(
const NodePath &other, PN_stdfloat p) {
1504 LVecBase3 hpr =
get_hpr(other);
1510 set_r(
const NodePath &other, PN_stdfloat r) {
1512 LVecBase3 hpr =
get_hpr(other);
1523 nassertr_always(!
is_empty(), LVecBase3(0.0f, 0.0f, 0.0f));
1525 nassertr(transform->
has_hpr(), LVecBase3(0.0f, 0.0f, 0.0f));
1543 const LVecBase3 &orig_pos = transform->
get_pos();
1544 const LVecBase3 &orig_scale = transform->
get_scale();
1545 const LVecBase3 &orig_shear = transform->
get_shear();
1551 (orig_pos, transform->
get_quat(), orig_scale, orig_shear));
1566 nassertr_always(!
is_empty(), LQuaternion::ident_quat());
1585 const LVecBase3 &orig_pos = transform->
get_pos();
1586 const LVecBase3 &orig_hpr = transform->
get_hpr();
1587 const LVecBase3 &orig_shear = transform->
get_shear();
1593 (orig_pos, orig_hpr, transform->
get_scale(), orig_shear));
1603 set_sx(
const NodePath &other, PN_stdfloat sx) {
1611 set_sy(
const NodePath &other, PN_stdfloat sy) {
1619 set_sz(
const NodePath &other, PN_stdfloat sz) {
1631 nassertr_always(!
is_empty(), LVecBase3(0.0f, 0.0f, 0.0f));
1650 const LVecBase3 &orig_pos = transform->
get_pos();
1651 const LVecBase3 &orig_hpr = transform->
get_hpr();
1652 const LVecBase3 &orig_scale = transform->
get_scale();
1658 (orig_pos, orig_hpr, orig_scale, transform->
get_shear()));
1668 set_shxy(
const NodePath &other, PN_stdfloat shxy) {
1676 set_shxz(
const NodePath &other, PN_stdfloat shxz) {
1684 set_shyz(
const NodePath &other, PN_stdfloat shyz) {
1696 nassertr_always(!
is_empty(), LVecBase3(0.0f, 0.0f, 0.0f));
1707 const LVecBase3 &hpr) {
1717 const LVecBase3 &orig_scale = transform->
get_scale();
1718 const LVecBase3 &orig_shear = transform->
get_shear();
1720 set_transform(other, TransformState::make_pos_hpr_scale_shear
1721 (pos, hpr, rel_transform->get_scale(), rel_transform->get_shear()));
1725 orig_scale, orig_shear);
1730 set_transform(other, TransformState::make_pos_hpr_scale_shear
1731 (pos, hpr, rel_transform->get_scale(), rel_transform->get_shear()));
1742 const LQuaternion &quat) {
1752 const LVecBase3 &orig_scale = transform->
get_scale();
1753 const LVecBase3 &orig_shear = transform->
get_shear();
1755 set_transform(other, TransformState::make_pos_quat_scale_shear
1756 (pos, quat, rel_transform->get_scale(), rel_transform->get_shear()));
1760 orig_scale, orig_shear);
1765 set_transform(other, TransformState::make_pos_quat_scale_shear
1766 (pos, quat, rel_transform->get_scale(), rel_transform->get_shear()));
1783 transform = TransformState::make_pos_hpr_scale_shear
1795 const LVecBase3 &scale) {
1801 transform = TransformState::make_pos_quat_scale_shear
1812 const LVecBase3 &pos,
const LVecBase3 &hpr,
1813 const LVecBase3 &scale) {
1826 const LVecBase3 &pos,
const LQuaternion &quat,
1827 const LVecBase3 &scale) {
1830 (pos, quat, scale));
1840 const LVecBase3 &pos,
const LVecBase3 &hpr,
1841 const LVecBase3 &scale,
const LVecBase3 &shear) {
1843 set_transform(other, TransformState::make_pos_hpr_scale_shear
1844 (pos, hpr, scale, shear));
1854 const LVecBase3 &pos,
const LQuaternion &quat,
1855 const LVecBase3 &scale,
const LVecBase3 &shear) {
1857 set_transform(other, TransformState::make_pos_quat_scale_shear
1858 (pos, quat, scale, shear));
1894 LPoint3 rel_point = LPoint3(point) * transform->
get_mat();
1905 LVector3 rel_vector = LVector3(vec) * transform->
get_mat();
1918 LPoint3 rel_point = point * transform->
get_mat();
1936 LPoint3 rel_point = point * transform->
get_mat();
1952 set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a,
1954 set_color(LColor(r, g, b, a), priority);
1988 node()->clear_attrib(ColorAttrib::get_class_slot());
1997 nassertr_always(!
is_empty(),
false);
1998 return node()->has_attrib(ColorAttrib::get_class_slot());
2007 nassertr_always(!
is_empty(),
false);
2009 node()->get_attrib(ColorAttrib::get_class_slot());
2010 if (attrib !=
nullptr) {
2017 pgraph_cat.warning()
2018 <<
"get_color() called on " << *
this <<
" which has no color set.\n";
2020 return LColor(1.0f, 1.0f, 1.0f, 1.0f);
2030 nassertr_always(!
is_empty(),
false);
2031 return node()->has_attrib(ColorScaleAttrib::get_class_slot());
2042 node()->clear_attrib(ColorScaleAttrib::get_class_slot());
2054 node()->get_attrib(ColorScaleAttrib::get_class_slot());
2055 if (attrib !=
nullptr) {
2056 priority = max(priority,
2057 node()->
get_state()->get_override(ColorScaleAttrib::get_class_slot()));
2062 LVecBase4 prev_color_scale = csa->
get_scale();
2063 LVecBase4 new_color_scale(prev_color_scale[0]*scale[0],
2064 prev_color_scale[1]*scale[1],
2065 prev_color_scale[2]*scale[2],
2066 prev_color_scale[3]*scale[3]);
2084 node()->get_attrib(ColorScaleAttrib::get_class_slot());
2085 if (attrib !=
nullptr) {
2086 priority = max(priority,
2087 node()->
get_state()->get_override(ColorScaleAttrib::get_class_slot()));
2126 node()->get_attrib(ColorScaleAttrib::get_class_slot());
2127 if (attrib !=
nullptr) {
2128 priority = max(priority,
2129 node()->
get_state()->get_override(ColorScaleAttrib::get_class_slot()));
2134 node()->
set_attrib(csa->set_scale(LVecBase4(sc[0], sc[1], sc[2], scale)), priority);
2138 node()->
set_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, scale)), priority);
2152 node()->get_attrib(ColorScaleAttrib::get_class_slot());
2153 if (attrib !=
nullptr) {
2154 priority = max(priority,
2155 node()->
get_state()->get_override(ColorScaleAttrib::get_class_slot()));
2160 node()->
set_attrib(csa->set_scale(LVecBase4(scale, scale, scale, sc[3])), priority);
2164 node()->
set_attrib(ColorScaleAttrib::make(LVecBase4(scale, scale, scale, 1.0f)), priority);
2175 static const LVecBase4 ident_scale(1.0f, 1.0f, 1.0f, 1.0f);
2176 nassertr_always(!
is_empty(), ident_scale);
2178 node()->get_attrib(ColorScaleAttrib::get_class_slot());
2179 if (attrib !=
nullptr) {
2198 if (light_obj !=
nullptr) {
2201 node()->get_attrib(LightAttrib::get_class_slot());
2202 if (attrib !=
nullptr) {
2203 priority = max(priority,
2204 node()->
get_state()->get_override(LightAttrib::get_class_slot()));
2217 }
else if (light.
node()->
is_of_type(PolylightNode::get_class_type())) {
2219 if (priority != 0) {
2222 pgraph_cat.warning()
2223 <<
"Ignoring priority on set_light(" << light <<
")\n";
2227 node()->get_effect(PolylightEffect::get_class_type());
2228 if (effect !=
nullptr) {
2242 nassert_raise(
"Not a Light object.");
2276 if (light_obj !=
nullptr) {
2278 node()->get_attrib(LightAttrib::get_class_slot());
2279 if (attrib !=
nullptr) {
2280 priority = max(priority,
2281 node()->
get_state()->get_override(LightAttrib::get_class_slot()));
2298 nassert_raise(
"Not a Light object.");
2308 node()->clear_attrib(LightAttrib::get_class_slot());
2322 if (light_obj !=
nullptr) {
2324 node()->get_attrib(LightAttrib::get_class_slot());
2325 if (attrib !=
nullptr) {
2327 la = DCAST(
LightAttrib, la->remove_on_light(light));
2328 la = DCAST(
LightAttrib, la->remove_off_light(light));
2330 if (la->is_identity()) {
2331 node()->clear_attrib(LightAttrib::get_class_slot());
2334 int priority =
node()->get_state()->get_override(LightAttrib::get_class_slot());
2340 }
else if (light.
node()->
is_of_type(PolylightNode::get_class_type())) {
2342 node()->get_effect(PolylightEffect::get_class_type());
2343 if (effect !=
nullptr) {
2351 nassert_raise(
"Not a Light object.");
2361 nassertr_always(!
is_empty(),
false);
2365 if (light_obj !=
nullptr) {
2367 node()->get_attrib(LightAttrib::get_class_slot());
2368 if (attrib !=
nullptr) {
2374 }
else if (light.
node()->
is_of_type(PolylightNode::get_class_type())) {
2376 node()->get_effect(PolylightEffect::get_class_type());
2377 if (effect !=
nullptr) {
2379 return ple->has_light(light);
2384 nassert_raise(
"Not a Light object.");
2395 nassertr_always(!
is_empty(),
false);
2398 node()->get_attrib(LightAttrib::get_class_slot());
2399 if (attrib !=
nullptr) {
2417 nassertr_always(!
is_empty(),
false);
2420 if (light_obj !=
nullptr) {
2422 node()->get_attrib(LightAttrib::get_class_slot());
2423 if (attrib !=
nullptr) {
2429 nassert_raise(
"Not a Light object.");
2445 node()->get_attrib(ClipPlaneAttrib::get_class_slot());
2446 if (attrib !=
nullptr) {
2447 priority = max(priority,
2448 node()->
get_state()->get_override(ClipPlaneAttrib::get_class_slot()));
2461 nassert_raise(
"Not a PlaneNode object.");
2493 node()->get_attrib(ClipPlaneAttrib::get_class_slot());
2494 if (attrib !=
nullptr) {
2495 priority = max(priority,
2496 node()->
get_state()->get_override(ClipPlaneAttrib::get_class_slot()));
2512 nassert_raise(
"Not a PlaneNode object.");
2522 node()->clear_attrib(ClipPlaneAttrib::get_class_slot());
2534 node()->get_attrib(ClipPlaneAttrib::get_class_slot());
2535 if (attrib !=
nullptr) {
2540 if (la->is_identity()) {
2541 node()->clear_attrib(ClipPlaneAttrib::get_class_slot());
2544 int priority =
node()->get_state()->get_override(ClipPlaneAttrib::get_class_slot());
2550 nassert_raise(
"Not a PlaneNode object.");
2560 nassertr_always(!
is_empty(),
false);
2564 node()->get_attrib(ClipPlaneAttrib::get_class_slot());
2565 if (attrib !=
nullptr) {
2571 nassert_raise(
"Not a PlaneNode object.");
2582 nassertr_always(!
is_empty(),
false);
2585 node()->get_attrib(ClipPlaneAttrib::get_class_slot());
2586 if (attrib !=
nullptr) {
2601 nassertr_always(!
is_empty(),
false);
2604 node()->get_attrib(ClipPlaneAttrib::get_class_slot());
2605 if (attrib !=
nullptr) {
2610 nassert_raise(
"Not a PlaneNode object.");
2626 node()->get_effect(OccluderEffect::get_class_type());
2627 if (effect !=
nullptr) {
2640 nassert_raise(
"Not an OccluderNode object.");
2662 node()->get_effect(OccluderEffect::get_class_type());
2663 if (effect !=
nullptr) {
2667 if (la->is_identity()) {
2676 nassert_raise(
"Not an OccluderNode object.");
2686 nassertr_always(!
is_empty(),
false);
2690 node()->get_effect(OccluderEffect::get_class_type());
2691 if (effect !=
nullptr) {
2697 nassert_raise(
"Not an OccluderNode object.");
2709 set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
2710 set_effect(ScissorEffect::make_screen(LVecBase4(left, right, bottom, top)));
2733 const LPoint3 &c,
const LPoint3 &d) {
2734 set_effect(ScissorEffect::make_node(a, b, c, d));
2745 set_effect(ScissorEffect::make_node(a, b, other));
2757 const LPoint3 &a,
const LPoint3 &b,
2758 const LPoint3 &c,
const LPoint3 &d) {
2759 set_effect(ScissorEffect::make_node(a, b, c, d, other));
2780 return has_effect(ScissorEffect::get_class_type());
2801 set_bin(
const string &bin_name,
int draw_order,
int priority) {
2803 node()->
set_attrib(CullBinAttrib::make(bin_name, draw_order), priority);
2813 node()->clear_attrib(CullBinAttrib::get_class_slot());
2822 nassertr_always(!
is_empty(),
false);
2823 return node()->has_attrib(CullBinAttrib::get_class_slot());
2833 nassertr_always(!
is_empty(),
string());
2835 node()->get_attrib(CullBinAttrib::get_class_slot());
2836 if (attrib !=
nullptr) {
2851 nassertr_always(!
is_empty(),
false);
2853 node()->get_attrib(CullBinAttrib::get_class_slot());
2854 if (attrib !=
nullptr) {
2889 node()->get_attrib(TextureAttrib::get_class_slot());
2890 if (attrib !=
nullptr) {
2892 int sg_priority =
node()->get_state()->get_override(TextureAttrib::get_class_slot());
2895 node()->
set_attrib(tsa->add_on_stage(stage, tex, priority), sg_priority);
2939 node()->get_attrib(TextureAttrib::get_class_slot());
2940 if (attrib !=
nullptr) {
2942 int sg_priority =
node()->get_state()->get_override(TextureAttrib::get_class_slot());
2945 node()->
set_attrib(tsa->add_on_stage(stage, tex, sampler, priority), sg_priority);
2950 node()->
set_attrib(tsa->add_on_stage(stage, tex, sampler, priority));
2977 node()->get_attrib(TextureAttrib::get_class_slot());
2978 if (attrib !=
nullptr) {
2980 int sg_priority =
node()->get_state()->get_override(TextureAttrib::get_class_slot());
2985 node()->
set_attrib(tsa->add_off_stage(stage, priority), sg_priority);
3004 node()->clear_attrib(TextureAttrib::get_class_slot());
3015 node()->get_attrib(TextureAttrib::get_class_slot());
3016 if (attrib !=
nullptr) {
3021 if (tsa->is_identity()) {
3022 node()->clear_attrib(TextureAttrib::get_class_slot());
3025 int priority =
node()->get_state()->get_override(TextureAttrib::get_class_slot());
3050 nassertr_always(!
is_empty(),
false);
3053 node()->get_attrib(TextureAttrib::get_class_slot());
3054 if (attrib !=
nullptr) {
3070 nassertr_always(!
is_empty(),
false);
3072 node()->get_attrib(TextureAttrib::get_class_slot());
3073 if (attrib !=
nullptr) {
3089 nassertr_always(!
is_empty(),
false);
3092 node()->get_attrib(TextureAttrib::get_class_slot());
3093 if (attrib !=
nullptr) {
3111 nassertr_always(!
is_empty(),
nullptr);
3113 node()->get_attrib(TextureAttrib::get_class_slot());
3114 if (attrib !=
nullptr) {
3128 nassertr_always(!
is_empty(),
nullptr);
3130 node()->get_attrib(TextureAttrib::get_class_slot());
3131 if (attrib !=
nullptr) {
3148 nassertv(tex !=
nullptr);
3149 nassertv(new_tex !=
nullptr);
3151 r_replace_texture(
node(), tex, new_tex);
3179 node()->get_attrib(TextureAttrib::get_class_slot());
3190 set_shader(
const Shader *sha,
int priority) {
3194 node()->get_attrib(ShaderAttrib::get_class_slot());
3195 if (attrib !=
nullptr) {
3196 priority = max(priority,
3197 node()->
get_state()->get_override(ShaderAttrib::get_class_slot()));
3211 set_shader_off(
int priority) {
3212 set_shader(
nullptr, priority);
3219 set_shader_auto(
int priority) {
3223 node()->get_attrib(ShaderAttrib::get_class_slot());
3224 if (attrib !=
nullptr) {
3225 priority = max(priority,
3226 node()->
get_state()->get_override(ShaderAttrib::get_class_slot()));
3244 node()->get_attrib(ShaderAttrib::get_class_slot());
3245 if (attrib !=
nullptr) {
3246 priority = max(priority,
3247 node()->
get_state()->get_override(ShaderAttrib::get_class_slot()));
3249 node()->
set_attrib(sa->set_shader_auto(shader_switch, priority));
3253 node()->
set_attrib(sa->set_shader_auto(shader_switch, priority));
3264 node()->get_attrib(ShaderAttrib::get_class_slot());
3265 if (attrib !=
nullptr) {
3275 get_shader()
const {
3276 nassertr_always(!
is_empty(),
nullptr);
3278 node()->get_attrib(ShaderAttrib::get_class_slot());
3279 if (attrib !=
nullptr) {
3281 return sa->get_shader();
3295 pnode->get_attrib(ShaderAttrib::get_class_slot());
3296 if (attrib !=
nullptr) {
3298 pnode->
set_attrib(sa->set_shader_input(inp));
3302 pnode->
set_attrib(sa->set_shader_input(inp));
3315 pnode->get_attrib(ShaderAttrib::get_class_slot());
3316 if (attrib !=
nullptr) {
3318 pnode->
set_attrib(sa->set_shader_input(move(inp)));
3322 pnode->
set_attrib(sa->set_shader_input(move(inp)));
3334 node()->get_attrib(ShaderAttrib::get_class_slot());
3335 if (attrib !=
nullptr) {
3337 return sa->get_shader_input(
id);
3351 node()->get_attrib(ShaderAttrib::get_class_slot());
3353 if (attrib !=
nullptr) {
3369 node()->get_attrib(ShaderAttrib::get_class_slot());
3370 if (attrib !=
nullptr) {
3386 node()->get_attrib(ShaderAttrib::get_class_slot());
3387 if (attrib !=
nullptr) {
3406 node()->get_attrib(TexMatrixAttrib::get_class_slot());
3407 if (attrib !=
nullptr) {
3425 node()->clear_attrib(TexMatrixAttrib::get_class_slot());
3436 node()->get_attrib(TexMatrixAttrib::get_class_slot());
3437 if (attrib !=
nullptr) {
3441 if (tma->is_empty()) {
3442 node()->clear_attrib(TexMatrixAttrib::get_class_slot());
3456 nassertr_always(!
is_empty(),
false);
3459 node()->get_attrib(TexMatrixAttrib::get_class_slot());
3460 if (attrib !=
nullptr) {
3462 return tma->has_stage(stage);
3475 nassertr_always(!
is_empty(),
nullptr);
3478 node()->get_attrib(TexMatrixAttrib::get_class_slot());
3479 if (attrib !=
nullptr) {
3481 return tma->get_transform(stage);
3484 return TransformState::make_identity();
3493 nassertv(_error_type == ET_ok && other._error_type == ET_ok);
3498 state->get_attrib(TexMatrixAttrib::get_class_slot());
3499 if (attrib !=
nullptr) {
3503 state = state->add_attrib(tma->add_stage(stage, transform));
3507 state = state->add_attrib(TexMatrixAttrib::make(stage, transform));
3517 CPT(
RenderState) new_state = rel_state->compose(state);
3521 node()->
set_attrib(new_state->get_attrib(TexMatrixAttrib::get_class_slot()));
3530 nassertr(_error_type == ET_ok && other._error_type == ET_ok, TransformState::make_identity());
3534 state->get_attrib(TexMatrixAttrib::get_class_slot());
3535 if (attrib !=
nullptr) {
3537 return tma->get_transform(stage);
3540 return TransformState::make_identity();
3548 set_tex_gen(
TextureStage *stage, RenderAttrib::TexGenMode mode,
int priority) {
3552 node()->get_attrib(TexGenAttrib::get_class_slot());
3556 if (attrib !=
nullptr) {
3557 priority = max(priority,
3558 node()->
get_state()->get_override(TextureAttrib::get_class_slot()));
3575 const LTexCoord3 &constant_value,
int priority) {
3579 node()->get_attrib(TexGenAttrib::get_class_slot());
3583 if (attrib !=
nullptr) {
3584 priority = max(priority,
3585 node()->
get_state()->get_override(TextureAttrib::get_class_slot()));
3592 node()->
set_attrib(tga->add_stage(stage, mode, constant_value), priority);
3602 node()->clear_attrib(TexGenAttrib::get_class_slot());
3614 node()->get_attrib(TexGenAttrib::get_class_slot());
3615 if (attrib !=
nullptr) {
3619 if (tga->is_empty()) {
3620 node()->clear_attrib(TexGenAttrib::get_class_slot());
3634 nassertr_always(!
is_empty(),
false);
3637 node()->get_attrib(TexGenAttrib::get_class_slot());
3638 if (attrib !=
nullptr) {
3640 return tga->has_stage(stage);
3652 nassertr_always(!
is_empty(), TexGenAttrib::M_off);
3655 node()->get_attrib(TexGenAttrib::get_class_slot());
3656 if (attrib !=
nullptr) {
3658 return tga->get_mode(stage);
3661 return TexGenAttrib::M_off;
3681 node()->get_effect(TexProjectorEffect::get_class_type());
3685 if (effect !=
nullptr) {
3703 node()->get_effect(TexProjectorEffect::get_class_type());
3704 if (effect !=
nullptr) {
3708 if (tpe->is_empty()) {
3732 nassertr_always(!
is_empty(),
false);
3735 node()->get_effect(TexProjectorEffect::get_class_type());
3736 if (effect !=
nullptr) {
3738 return tpe->has_stage(stage);
3754 node()->get_effect(TexProjectorEffect::get_class_type());
3755 if (effect !=
nullptr) {
3757 return tpe->get_from(stage);
3773 node()->get_effect(TexProjectorEffect::get_class_type());
3774 if (effect !=
nullptr) {
3776 return tpe->get_to(stage);
3791 set_tex_gen(stage, TexGenAttrib::M_world_position);
3805 nassertr_always(!
is_empty(),
false);
3806 return r_has_vertex_column(
node(), name);
3816 InternalNames vertex_columns;
3817 r_find_all_vertex_columns(
node(), vertex_columns);
3820 InternalNames::iterator ti;
3821 for (ti = vertex_columns.begin(); ti != vertex_columns.end(); ++ti) {
3835 InternalNames vertex_columns;
3836 r_find_all_vertex_columns(
node(), vertex_columns);
3841 InternalNames::iterator ti;
3842 for (ti = vertex_columns.begin(); ti != vertex_columns.end(); ++ti) {
3858 InternalNames vertex_columns;
3859 r_find_all_vertex_columns(
node(), vertex_columns);
3861 CPT(
InternalName) texcoord_name = InternalName::get_texcoord();
3864 InternalNames::iterator ti;
3865 for (ti = vertex_columns.begin(); ti != vertex_columns.end(); ++ti) {
3866 if ((*ti)->get_top() == texcoord_name) {
3881 InternalNames vertex_columns;
3882 r_find_all_vertex_columns(
node(), vertex_columns);
3888 InternalNames::iterator ti;
3889 for (ti = vertex_columns.begin(); ti != vertex_columns.end(); ++ti) {
3891 if (name->
get_top() == texcoord_name) {
3898 if (glob.
matches(net_basename)) {
3913 nassertr_always(!
is_empty(),
nullptr);
3915 return r_find_texture(
node(), get_net_state(), glob);
3925 nassertr_always(!
is_empty(),
nullptr);
3926 return r_find_texture(
node(), stage);
3936 r_find_all_textures(
node(), get_net_state(), textures);
3939 Textures::iterator ti;
3940 for (ti = textures.begin(); ti != textures.end(); ++ti) {
3954 r_find_all_textures(
node(), get_net_state(), textures);
3959 Textures::iterator ti;
3960 for (ti = textures.begin(); ti != textures.end(); ++ti) {
3962 if (glob.
matches(texture->get_name())) {
3977 r_find_all_textures(
node(), stage, textures);
3980 Textures::iterator ti;
3981 for (ti = textures.begin(); ti != textures.end(); ++ti) {
3995 nassertr_always(!
is_empty(),
nullptr);
3997 return r_find_texture_stage(
node(), get_net_state(), glob);
4007 TextureStages texture_stages;
4008 r_find_all_texture_stages(
node(), get_net_state(), texture_stages);
4011 TextureStages::iterator ti;
4012 for (ti = texture_stages.begin(); ti != texture_stages.end(); ++ti) {
4028 r_unify_texture_stages(
node(), stage);
4039 TextureStages texture_stages;
4040 r_find_all_texture_stages(
node(), get_net_state(), texture_stages);
4045 TextureStages::iterator ti;
4046 for (ti = texture_stages.begin(); ti != texture_stages.end(); ++ti) {
4062 nassertr_always(!
is_empty(),
nullptr);
4064 return r_find_material(
node(), get_net_state(), glob);
4073 Materials materials;
4074 r_find_all_materials(
node(), get_net_state(), materials);
4077 Materials::iterator ti;
4078 for (ti = materials.begin(); ti != materials.end(); ++ti) {
4091 Materials materials;
4092 r_find_all_materials(
node(), get_net_state(), materials);
4097 Materials::iterator ti;
4098 for (ti = materials.begin(); ti != materials.end(); ++ti) {
4100 if (glob.
matches(material->get_name())) {
4117 nassertv(mat !=
nullptr);
4140 node()->clear_attrib(MaterialAttrib::get_class_slot());
4149 nassertr_always(!
is_empty(),
false);
4151 node()->get_attrib(MaterialAttrib::get_class_slot());
4152 if (attrib !=
nullptr) {
4169 get_material()
const {
4170 nassertr_always(!
is_empty(),
nullptr);
4172 node()->get_attrib(MaterialAttrib::get_class_slot());
4173 if (attrib !=
nullptr) {
4188 nassertv(mat !=
nullptr);
4189 nassertv(new_mat !=
nullptr);
4191 CPT(
RenderAttrib) new_attrib = MaterialAttrib::make(new_mat);
4225 node()->clear_attrib(FogAttrib::get_class_slot());
4236 nassertr_always(!
is_empty(),
false);
4238 node()->get_attrib(FogAttrib::get_class_slot());
4239 if (attrib !=
nullptr) {
4255 nassertr_always(!
is_empty(),
false);
4257 node()->get_attrib(FogAttrib::get_class_slot());
4258 if (attrib !=
nullptr) {
4274 nassertr_always(!
is_empty(),
nullptr);
4276 node()->get_attrib(FogAttrib::get_class_slot());
4277 if (attrib !=
nullptr) {
4293 node()->get_state()->get_attrib_def(rma);
4305 node()->get_state()->get_attrib_def(rma);
4318 node()->get_state()->get_attrib_def(rma);
4336 node()->get_state()->get_attrib_def(rma);
4352 node()->get_state()->get_attrib_def(rma);
4364 node()->
set_attrib(RenderModeAttrib::make(mode, thickness), priority);
4374 node()->clear_attrib(RenderModeAttrib::get_class_slot());
4384 nassertr_always(!
is_empty(),
false);
4385 return node()->has_attrib(RenderModeAttrib::get_class_slot());
4394 nassertr_always(!
is_empty(), RenderModeAttrib::M_unchanged);
4396 node()->get_attrib(RenderModeAttrib::get_class_slot());
4397 if (attrib !=
nullptr) {
4402 return RenderModeAttrib::M_unchanged;
4411 nassertr_always(!
is_empty(), 0.0f);
4413 node()->get_attrib(RenderModeAttrib::get_class_slot());
4414 if (attrib !=
nullptr) {
4428 nassertr_always(!
is_empty(), 0.0f);
4430 node()->get_attrib(RenderModeAttrib::get_class_slot());
4431 if (attrib !=
nullptr) {
4448 CullFaceAttrib::Mode mode =
4450 CullFaceAttrib::M_cull_none :
4451 CullFaceAttrib::M_cull_clockwise;
4466 node()->clear_attrib(CullFaceAttrib::get_class_slot());
4476 nassertr_always(!
is_empty(),
false);
4477 return node()->has_attrib(CullFaceAttrib::get_class_slot());
4489 nassertr_always(!
is_empty(),
false);
4491 node()->get_attrib(CullFaceAttrib::get_class_slot());
4492 if (attrib !=
nullptr) {
4509 DepthTestAttrib::PandaCompareFunc mode =
4511 DepthTestAttrib::M_less :
4512 DepthTestAttrib::M_none;
4524 node()->clear_attrib(DepthTestAttrib::get_class_slot());
4534 nassertr_always(!
is_empty(),
false);
4535 return node()->has_attrib(DepthTestAttrib::get_class_slot());
4546 nassertr_always(!
is_empty(),
false);
4548 node()->get_attrib(DepthTestAttrib::get_class_slot());
4549 if (attrib !=
nullptr) {
4551 return (dta->
get_mode() != DepthTestAttrib::M_none);
4566 DepthWriteAttrib::Mode mode =
4568 DepthWriteAttrib::M_on :
4569 DepthWriteAttrib::M_off;
4581 node()->clear_attrib(DepthWriteAttrib::get_class_slot());
4591 nassertr_always(!
is_empty(),
false);
4592 return node()->has_attrib(DepthWriteAttrib::get_class_slot());
4603 nassertr_always(!
is_empty(),
false);
4605 node()->get_attrib(DepthWriteAttrib::get_class_slot());
4606 if (attrib !=
nullptr) {
4608 return (dta->
get_mode() != DepthWriteAttrib::M_off);
4637 node()->clear_attrib(DepthOffsetAttrib::get_class_slot());
4647 nassertr_always(!
is_empty(),
false);
4648 return node()->has_attrib(DepthOffsetAttrib::get_class_slot());
4659 node()->get_attrib(DepthOffsetAttrib::get_class_slot());
4660 if (attrib !=
nullptr) {
4678 const LMatrix4 &rel_mat = transform->
get_mat();
4680 LVector3 up = LVector3::up();
4681 LVector3 rel_pos = -rel_mat.get_row3(3);
4689 if (offset != 0.0f) {
4690 LVector3 translate = rel_mat.get_row3(3);
4691 translate.normalize();
4692 translate *= offset;
4708 const LMatrix4 &rel_mat = transform->
get_mat();
4710 LVector3 up = LVector3::up() * rel_mat;
4711 LVector3 rel_pos = LVector3::forward() * rel_mat;
4719 if (offset != 0.0f) {
4720 LVector3 translate = rel_mat.get_row3(3);
4721 translate.normalize();
4722 translate *= offset;
4737 const LMatrix4 &rel_mat = transform->
get_mat();
4739 LVector3 up = LVector3::up();
4740 LVector3 rel_pos = -rel_mat.get_row3(3);
4748 if (offset != 0.0f) {
4749 LVector3 translate = rel_mat.get_row3(3);
4750 translate.normalize();
4751 translate *= offset;
4765 (LVector3::up(),
false,
true,
4766 offset, camera, LPoint3(0.0f, 0.0f, 0.0f));
4779 (LVector3::up(),
true,
false,
4780 offset, camera, LPoint3(0.0f, 0.0f, 0.0f), fixed_depth);
4793 (LVector3::up(),
false,
false,
4794 offset, camera, LPoint3(0.0f, 0.0f, 0.0f));
4812 nassertr_always(!
is_empty(),
false);
4813 return node()->has_effect(BillboardEffect::get_class_type());
4841 nassertr_always(!
is_empty(),
false);
4842 return node()->has_effect(CompassEffect::get_class_type());
4866 node()->clear_attrib(TransparencyAttrib::get_class_slot());
4877 nassertr_always(!
is_empty(),
false);
4878 return node()->has_attrib(TransparencyAttrib::get_class_slot());
4891 nassertr_always(!
is_empty(), TransparencyAttrib::M_none);
4893 node()->get_attrib(TransparencyAttrib::get_class_slot());
4894 if (attrib !=
nullptr) {
4899 return TransparencyAttrib::M_none;
4922 node()->clear_attrib(LogicOpAttrib::get_class_slot());
4933 nassertr_always(!
is_empty(),
false);
4934 return node()->has_attrib(LogicOpAttrib::get_class_slot());
4947 nassertr_always(!
is_empty(), LogicOpAttrib::O_none);
4949 node()->get_attrib(LogicOpAttrib::get_class_slot());
4950 if (attrib !=
nullptr) {
4955 return LogicOpAttrib::O_none;
4976 node()->clear_attrib(AntialiasAttrib::get_class_slot());
4986 nassertr_always(!
is_empty(),
false);
4987 return node()->has_attrib(AntialiasAttrib::get_class_slot());
4996 nassertr_always(!
is_empty(), AntialiasAttrib::M_none);
4998 node()->get_attrib(AntialiasAttrib::get_class_slot());
4999 if (attrib !=
nullptr) {
5004 return AntialiasAttrib::M_none;
5014 nassertr_always(!
is_empty(),
false);
5015 return node()->has_attrib(AudioVolumeAttrib::get_class_slot());
5026 node()->clear_attrib(AudioVolumeAttrib::get_class_slot());
5037 node()->get_attrib(AudioVolumeAttrib::get_class_slot());
5038 if (attrib !=
nullptr) {
5039 priority = max(priority,
5040 node()->
get_state()->get_override(AudioVolumeAttrib::get_class_slot()));
5075 node()->get_attrib(AudioVolumeAttrib::get_class_slot());
5076 if (attrib !=
nullptr) {
5091 const RenderAttrib *attrib = net_state->get_attrib(AudioVolumeAttrib::get_class_slot());
5092 if (attrib !=
nullptr) {
5094 if (ava !=
nullptr) {
5114 comp = comp->
get_next(pipeline_stage, current_thread)) {
5119 result._head = comp;
5143 bool reparented = PandaNode::reparent(_head->get_next(pipeline_stage, current_thread),
5144 _head, sort,
true, pipeline_stage,
5146 nassertv(reparented);
5160 bool reparented = PandaNode::reparent(_head->get_next(pipeline_stage, current_thread),
5161 _head, sort,
false, pipeline_stage,
5163 nassertv(reparented);
5172 stashed_descendents.
unstash();
5184 if (comp !=
nullptr) {
5188 while (next !=
nullptr) {
5194 result._head = comp;
5199 next = next->
get_next(pipeline_stage, current_thread);
5212 return (other == *
this);
5220 return (other != *
this);
5231 return other.compare_to(*
this) > 0;
5246 return -other.compare_to(*
this);
5267 #endif // HAVE_THREADS
5269 PStatTimer timer(_verify_complete_pcollector);
5272 nassertr(comp !=
nullptr,
false);
5277 nassertr(
node !=
nullptr,
false);
5278 int length = comp->
get_length(pipeline_stage, current_thread);
5280 comp = comp->
get_next(pipeline_stage, current_thread);
5282 while (comp !=
nullptr) {
5284 nassertr(next_node !=
nullptr,
false);
5287 pgraph_cat.warning()
5288 << *
this <<
" is incomplete; " << *
node <<
" is not a child of "
5289 << *next_node <<
"\n";
5293 if (comp->
get_length(pipeline_stage, current_thread) != length) {
5294 pgraph_cat.warning()
5295 << *
this <<
" is incomplete; length at " << *next_node
5296 <<
" indicates " << comp->
get_length(pipeline_stage, current_thread)
5297 <<
" while length at " << *
node <<
" indicates " << length <<
"\n";
5302 comp = comp->
get_next(pipeline_stage, current_thread);
5322 CPT(
RenderState) state = RenderState::make_empty();
5345 node()->prepare_scene(gsg, get_net_state());
5387 get_bounds(
Thread *current_thread)
const {
5404 force_recompute_bounds() {
5406 r_force_recompute_bounds(
node());
5415 get_bounds()->write(out);
5436 min_point.set(0.0f, 0.0f, 0.0f);
5437 max_point.set(0.0f, 0.0f, 0.0f);
5438 nassertr_always(!
is_empty(),
false);
5445 bool found_any =
false;
5446 node()->calc_tight_bounds(min_point, max_point, found_any,
5447 move(transform), current_thread);
5536 if (flatten_geoms) {
5564 if (flatten_geoms) {
5566 gr.
collect_vertex_data(
node(), ~(SceneGraphReducer::CVD_format | SceneGraphReducer::CVD_name | SceneGraphReducer::CVD_animation_type));
5591 gr.
apply_attribs(
node(), SceneGraphReducer::TT_apply_texture_color | SceneGraphReducer::TT_tex_matrix | SceneGraphReducer::TT_other);
5617 nassertr_always(!
is_empty(),
false);
5621 bool okflag =
false;
5641 nassertr_always(!
is_empty(),
false);
5645 bool okflag =
false;
5684 ostringstream stream;
5688 bool used_local_writer =
false;
5689 if (writer ==
nullptr) {
5695 writer = &local_writer;
5696 used_local_writer =
true;
5702 if (used_local_writer && num_nodes > 1) {
5725 for (
int i = 0; i < num_nodes; ++i) {
5727 nassertr(
node !=
nullptr,
false);
5750 if (reader ==
nullptr) {
5754 if (!buffer.
read_header(head, _bam_header.size())) {
5758 if (head != _bam_header) {
5762 reader = &local_reader;
5774 ErrorType error_type = (ErrorType)dgi.
get_uint8();
5776 if (num_nodes == 0) {
5778 result._error_type = error_type;
5782 for (
int i = 0; i < num_nodes; ++i) {
5785 if (
object ==
nullptr ||
5786 !object->
is_of_type(PandaNode::get_class_type())) {
5816 int &a_count,
int &b_count,
Thread *current_thread) {
5826 while (ac->
get_length(pipeline_stage, current_thread) > bc->
get_length(pipeline_stage, current_thread)) {
5827 nassertr(ac !=
nullptr,
nullptr);
5828 ac = ac->
get_next(pipeline_stage, current_thread);
5831 while (bc->
get_length(pipeline_stage, current_thread) > ac->
get_length(pipeline_stage, current_thread)) {
5832 nassertr(bc !=
nullptr,
nullptr);
5833 bc = bc->
get_next(pipeline_stage, current_thread);
5840 nassertr(ac !=
nullptr,
nullptr);
5841 nassertr(bc !=
nullptr,
nullptr);
5842 ac = ac->
get_next(pipeline_stage, current_thread);
5844 bc = bc->
get_next(pipeline_stage, current_thread);
5857 if (comp ==
nullptr) {
5858 return RenderState::make_empty();
5862 return r_get_net_state(comp->
get_next(pipeline_stage, current_thread), current_thread)->compose(state);
5873 Thread *current_thread)
const {
5874 if (n == 0 || comp ==
nullptr) {
5875 return RenderState::make_empty();
5879 return r_get_partial_state(comp->
get_next(pipeline_stage, current_thread), n - 1, current_thread)->compose(state);
5889 if (comp ==
nullptr) {
5890 return TransformState::make_identity();
5894 CPT(
TransformState) net_transform = r_get_net_transform(comp->
get_next(pipeline_stage, current_thread), current_thread);
5897 if (!node_cdata->_effects->has_adjust_transform()) {
5898 if (node_cdata->_transform->is_identity()) {
5899 return net_transform;
5901 return net_transform->compose(node_cdata->_transform);
5905 node_cdata->_effects->adjust_transform(net_transform, transform,
node);
5906 return net_transform->compose(transform);
5921 Thread *current_thread)
const {
5922 if (n == 0 || comp ==
nullptr) {
5923 return TransformState::make_identity();
5927 if (node_cdata->_effects->has_adjust_transform()) {
5931 CPT(
TransformState) partial = r_get_partial_transform(comp->
get_next(pipeline_stage, current_thread), n - 1, current_thread);
5932 if (partial ==
nullptr) {
5935 if (node_cdata->_transform->is_identity()) {
5938 return partial->compose(node_cdata->_transform);
5949 if (comp ==
nullptr) {
5950 return TransformState::make_identity();
5954 return r_get_net_prev_transform(comp->
get_next(pipeline_stage, current_thread), current_thread)->compose(transform);
5965 if (n == 0 || comp ==
nullptr) {
5966 return TransformState::make_identity();
5970 return r_get_partial_prev_transform(comp->
get_next(pipeline_stage, current_thread), n - 1, current_thread)->compose(transform);
5981 int max_matches)
const {
5983 pgraph_cat.warning()
5984 <<
"Attempt to extend an empty NodePath by '" << path
5990 find_matches(result, approx_path, max_matches);
6001 int max_matches)
const {
6003 pgraph_cat.warning()
6004 <<
"Attempt to extend an empty NodePath by: " << approx_path <<
".\n";
6011 nassertv(level->_node_path.
is_valid());
6013 find_matches(result, level, max_matches);
6022 int max_matches)
const {
6024 int num_levels_remaining = _max_search_depth;
6028 while (num_levels_remaining > 0 && level !=
nullptr) {
6029 if (pgraph_cat.is_spam()) {
6031 <<
"find_matches pass: " << result <<
", "
6032 << max_matches <<
", " << num_levels_remaining <<
"\n";
6036 num_levels_remaining--;
6043 while (entry !=
nullptr) {
6044 if (entry->
consider_node(result, next_level, max_matches, 0)) {
6048 while (entry !=
nullptr) {
6053 while (next_level !=
nullptr) {
6058 while (deleted_entries !=
nullptr) {
6060 delete deleted_entries;
6061 deleted_entries = next;
6071 entry->_next = deleted_entries;
6072 deleted_entries = entry;
6079 while (entry !=
nullptr) {
6081 entry->_next = deleted_entries;
6082 deleted_entries = entry;
6091 while (deleted_entries !=
nullptr) {
6093 delete deleted_entries;
6094 deleted_entries = next;
6108 DCAST_INTO_R(mnode,
node, count);
6115 for (
int i = 0; i < num_children; i++) {
6116 count += r_clear_model_nodes(cr.
get_child(i));
6127 r_adjust_all_priorities(
PandaNode *node,
int adjustment) {
6131 DCAST_INTO_V(gnode,
node);
6134 for (
int i = 0; i < num_geoms; i++) {
6141 for (
int i = 0; i < num_children; i++) {
6142 r_adjust_all_priorities(cr.
get_child(i), adjustment);
6150 r_force_recompute_bounds(
PandaNode *node) {
6153 DCAST_INTO_V(gnode,
node);
6156 for (
int i = 0; i < num_geoms; i++) {
6157 const Geom *geom = gnode->get_geom(i);
6158 geom->mark_bounds_stale();
6162 node->mark_bounds_stale();
6167 for (
int i = 0; i < num_children; i++) {
6168 r_force_recompute_bounds(cr.
get_child(i));
6182 into_collide_mask = (into_collide_mask & and_mask) | or_mask;
6188 for (
int i = 0; i < num_children; i++) {
6189 r_set_collide_mask(cr.
get_child(i), and_mask, or_mask, node_type);
6200 DCAST_INTO_R(gnode,
node,
false);
6203 for (
int i = 0; i < num_geoms; i++) {
6204 const Geom *geom = gnode->get_geom(i);
6206 if (vdata->has_column(name)) {
6215 for (
int i = 0; i < num_children; i++) {
6217 if (r_has_vertex_column(child, name)) {
6229 r_find_all_vertex_columns(
PandaNode *node,
6230 NodePath::InternalNames &vertex_columns)
const {
6233 DCAST_INTO_V(gnode,
node);
6236 for (
int i = 0; i < num_geoms; ++i) {
6237 const Geom *geom = gnode->get_geom(i);
6240 for (
int j = 0; j < num_arrays; ++j) {
6243 for (
int k = 0; k < num_columns; ++k) {
6245 vertex_columns.insert(column->
get_name());
6254 for (
int i = 0; i < num_children; i++) {
6256 r_find_all_vertex_columns(child, vertex_columns);
6268 DCAST_INTO_R(gnode,
node,
nullptr);
6271 for (
int i = 0; i < num_geoms; i++) {
6277 geom_state->get_attrib(TextureAttrib::get_class_slot());
6278 if (attrib !=
nullptr) {
6282 if (texture !=
nullptr) {
6283 if (glob.
matches(texture->get_name())) {
6295 for (
int i = 0; i < num_children; i++) {
6297 CPT(
RenderState) next_state = state->compose(child->get_state());
6299 Texture *result = r_find_texture(child, next_state, glob);
6300 if (result !=
nullptr) {
6313 NodePath::Textures &textures)
const {
6316 DCAST_INTO_V(gnode,
node);
6319 for (
int i = 0; i < num_geoms; i++) {
6325 geom_state->get_attrib(TextureAttrib::get_class_slot());
6326 if (attrib !=
nullptr) {
6330 if (texture !=
nullptr) {
6331 textures.insert(texture);
6341 for (
int i = 0; i < num_children; i++) {
6343 CPT(
RenderState) next_state = state->compose(child->get_state());
6344 r_find_all_textures(child, next_state, textures);
6355 node->get_attrib(TextureAttrib::get_class_slot());
6356 if (attrib !=
nullptr) {
6365 DCAST_INTO_R(gnode,
node,
nullptr);
6368 for (
int i = 0; i < num_geoms; i++) {
6373 geom_state->get_attrib(TextureAttrib::get_class_slot());
6374 if (attrib !=
nullptr) {
6386 for (
int i = 0; i < num_children; i++) {
6389 Texture *result = r_find_texture(child, stage);
6390 if (result !=
nullptr) {
6403 NodePath::Textures &textures)
const {
6406 node->get_attrib(TextureAttrib::get_class_slot());
6407 if (attrib !=
nullptr) {
6416 DCAST_INTO_V(gnode,
node);
6419 for (
int i = 0; i < num_geoms; i++) {
6424 geom_state->get_attrib(TextureAttrib::get_class_slot());
6425 if (attrib !=
nullptr) {
6437 for (
int i = 0; i < num_children; i++) {
6439 r_find_all_textures(child, stage, textures);
6453 if (node_state->get_attrib(ta)) {
6454 CPT(
RenderAttrib) new_ta = ta->replace_texture(tex, new_tex);
6464 DCAST_INTO_V(gnode,
node);
6467 for (
int i = 0; i < num_geoms; i++) {
6472 if (geom_state->get_attrib(ta)) {
6473 CPT(
RenderAttrib) new_ta = ta->replace_texture(tex, new_tex);
6484 for (
size_t i = 0; i < num_children; ++i) {
6486 r_replace_texture(child, tex, new_tex);
6498 DCAST_INTO_R(gnode,
node,
nullptr);
6501 for (
int i = 0; i < num_geoms; i++) {
6507 geom_state->get_attrib(TextureAttrib::get_class_slot());
6508 if (attrib !=
nullptr) {
6512 if (texture_stage !=
nullptr) {
6514 return texture_stage;
6525 for (
int i = 0; i < num_children; i++) {
6527 CPT(
RenderState) next_state = state->compose(child->get_state());
6529 TextureStage *result = r_find_texture_stage(child, next_state, glob);
6530 if (result !=
nullptr) {
6543 NodePath::TextureStages &texture_stages)
const {
6546 DCAST_INTO_V(gnode,
node);
6549 for (
int i = 0; i < num_geoms; i++) {
6555 geom_state->get_attrib(TextureAttrib::get_class_slot());
6556 if (attrib !=
nullptr) {
6560 if (texture_stage !=
nullptr) {
6561 texture_stages.insert(texture_stage);
6571 for (
int i = 0; i < num_children; i++) {
6573 CPT(
RenderState) next_state = state->compose(child->get_state());
6574 r_find_all_texture_stages(child, next_state, texture_stages);
6585 node->get_attrib(TextureAttrib::get_class_slot());
6586 if (attrib !=
nullptr) {
6588 CPT(
RenderAttrib) new_attrib = ta->unify_texture_stages(stage);
6589 if (new_attrib != ta) {
6596 DCAST_INTO_V(gnode,
node);
6599 for (
int i = 0; i < num_geoms; i++) {
6604 state->get_attrib(TextureAttrib::get_class_slot());
6605 if (attrib !=
nullptr) {
6607 CPT(
RenderAttrib) new_attrib = ta->unify_texture_stages(stage);
6608 if (new_attrib != ta) {
6609 CPT(
RenderState) new_state = state->add_attrib(new_attrib);
6619 for (
int i = 0; i < num_children; i++) {
6621 r_unify_texture_stages(child, stage);
6633 DCAST_INTO_R(gnode,
node,
nullptr);
6636 for (
int i = 0; i < num_geoms; i++) {
6642 geom_state->get_attrib(MaterialAttrib::get_class_slot());
6643 if (attrib !=
nullptr) {
6647 if (material !=
nullptr) {
6648 if (glob.
matches(material->get_name())) {
6660 for (
int i = 0; i < num_children; i++) {
6662 CPT(
RenderState) next_state = state->compose(child->get_state());
6664 Material *result = r_find_material(child, next_state, glob);
6665 if (result !=
nullptr) {
6678 NodePath::Materials &materials)
const {
6681 DCAST_INTO_V(gnode,
node);
6684 for (
int i = 0; i < num_geoms; i++) {
6690 geom_state->get_attrib(MaterialAttrib::get_class_slot());
6691 if (attrib !=
nullptr) {
6695 if (material !=
nullptr) {
6696 materials.insert(material);
6706 for (
int i = 0; i < num_children; i++) {
6708 CPT(
RenderState) next_state = state->compose(child->get_state());
6709 r_find_all_materials(child, next_state, materials);
6723 if (node_state->get_attrib(ma)) {
6733 DCAST_INTO_V(gnode,
node);
6736 for (
int i = 0; i < num_geoms; i++) {
6741 if (geom_state->get_attrib(ma)) {
6753 for (
size_t i = 0; i < num_children; ++i) {
6755 r_replace_material(child, mat, new_attrib);
6773 if (root ==
nullptr || root ==
node()) {
6785 while (comp !=
nullptr) {
6787 path.push_back(
node);
6793 comp = comp->
get_next(pipeline_stage, current_thread);
6796 if (comp ==
nullptr) {
6804 for (
int i = path.size() - 1; i >= 0; --i) {
6818 if (
node.is_null()) {
6831 nassertd(!comp.is_null()) {
6832 while (p_list[pi++]) {}
6837 while (p_list[pi] !=
nullptr) {
6845 PandaNode::Paths::const_iterator it;
6846 for (it =
node->_paths.begin(); it !=
node->_paths.end(); ++it) {
6847 if ((*it)->get_next(pipeline_stage, current_thread) == comp) {
6854 if (it ==
node->_paths.end()) {
6860 node->_paths.insert(comp);