00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pandaNode.h"
00016 #include "config_pgraph.h"
00017 #include "nodePathComponent.h"
00018 #include "bamReader.h"
00019 #include "bamWriter.h"
00020 #include "indent.h"
00021 #include "geometricBoundingVolume.h"
00022 #include "sceneGraphReducer.h"
00023 #include "accumulatedAttribs.h"
00024 #include "clipPlaneAttrib.h"
00025 #include "boundingSphere.h"
00026 #include "boundingBox.h"
00027 #include "pStatTimer.h"
00028 #include "config_mathutil.h"
00029 #include "lightReMutexHolder.h"
00030 #include "graphicsStateGuardianBase.h"
00031 #include "py_panda.h"
00032
00033
00034 NotifyCategoryDecl(drawmask, EXPCL_PANDA_PGRAPH, EXPTP_PANDA_PGRAPH);
00035 NotifyCategoryDef(drawmask, "");
00036
00037 TypeHandle PandaNode::BamReaderAuxDataDown::_type_handle;
00038
00039 PandaNode::SceneRootFunc *PandaNode::_scene_root_func;
00040
00041 PandaNodeChain PandaNode::_dirty_prev_transforms("_dirty_prev_transforms");
00042 DrawMask PandaNode::_overall_bit = DrawMask::bit(31);
00043
00044 PStatCollector PandaNode::_reset_prev_pcollector("App:Collisions:Reset");
00045 PStatCollector PandaNode::_update_bounds_pcollector("*:Bounds");
00046
00047 TypeHandle PandaNode::_type_handle;
00048 TypeHandle PandaNode::CData::_type_handle;
00049 TypeHandle PandaNodePipelineReader::_type_handle;
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 PandaNode::
00082 PandaNode(const string &name) :
00083 Namable(name),
00084 _paths_lock("PandaNode::_paths_lock"),
00085 _dirty_prev_transform(false)
00086 {
00087 if (pgraph_cat.is_debug()) {
00088 pgraph_cat.debug()
00089 << "Constructing " << (void *)this << ", " << get_name() << "\n";
00090 }
00091 #ifndef NDEBUG
00092 _unexpected_change_flags = 0;
00093 #endif // !NDEBUG
00094
00095 #ifdef DO_MEMORY_USAGE
00096 MemoryUsage::update_type(this, this);
00097 #endif
00098 }
00099
00100
00101
00102
00103
00104
00105 PandaNode::
00106 ~PandaNode() {
00107 if (pgraph_cat.is_debug()) {
00108 pgraph_cat.debug()
00109 << "Destructing " << (void *)this << ", " << get_name() << "\n";
00110 }
00111
00112 if (_dirty_prev_transform) {
00113
00114 LightMutexHolder holder(_dirty_prev_transforms._lock);
00115 do_clear_dirty_prev_transform();
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 remove_all_children();
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143 PandaNode::
00144 PandaNode(const PandaNode ©) :
00145 ReferenceCount(copy),
00146 TypedWritable(copy),
00147 Namable(copy),
00148 _paths_lock("PandaNode::_paths_lock"),
00149 _dirty_prev_transform(false)
00150 {
00151 if (pgraph_cat.is_debug()) {
00152 pgraph_cat.debug()
00153 << "Copying " << (void *)this << ", " << get_name() << "\n";
00154 }
00155 #ifdef DO_MEMORY_USAGE
00156 MemoryUsage::update_type(this, this);
00157 #endif
00158
00159 #ifndef NDEBUG
00160 _unexpected_change_flags = 0;
00161 #endif // !NDEBUG
00162
00163
00164 LightMutexHolder holder(_dirty_prev_transforms._lock);
00165
00166
00167 {
00168 CDReader copy_cdata(copy._cycler);
00169 CDWriter cdata(_cycler, true);
00170 cdata->_state = copy_cdata->_state;
00171 cdata->_transform = copy_cdata->_transform;
00172 cdata->_prev_transform = copy_cdata->_prev_transform;
00173 if (cdata->_transform != cdata->_prev_transform) {
00174 do_set_dirty_prev_transform();
00175 }
00176
00177 cdata->_effects = copy_cdata->_effects;
00178 cdata->_tag_data = copy_cdata->_tag_data;
00179 cdata->_draw_control_mask = copy_cdata->_draw_control_mask;
00180 cdata->_draw_show_mask = copy_cdata->_draw_show_mask;
00181 cdata->_into_collide_mask = copy_cdata->_into_collide_mask;
00182 cdata->_bounds_type = copy_cdata->_bounds_type;
00183 cdata->_user_bounds = copy_cdata->_user_bounds;
00184 cdata->_internal_bounds = NULL;
00185 cdata->_internal_bounds_computed = UpdateSeq::initial();
00186 cdata->_internal_bounds_mark = UpdateSeq::initial();
00187 ++cdata->_internal_bounds_mark;
00188 cdata->_final_bounds = copy_cdata->_final_bounds;
00189 cdata->_fancy_bits = copy_cdata->_fancy_bits;
00190
00191 #ifdef HAVE_PYTHON
00192
00193
00194 cdata->_python_tag_data = copy_cdata->_python_tag_data;
00195 cdata->inc_py_refs();
00196 #endif // HAVE_PYTHON
00197 }
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207 void PandaNode::
00208 operator = (const PandaNode ©) {
00209 nassertv(false);
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 ReferenceCount *PandaNode::
00219 as_reference_count() {
00220 return this;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 PandaNode *PandaNode::
00234 dupe_for_flatten() const {
00235 return make_copy();
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 bool PandaNode::
00249 safe_to_flatten() const {
00250 return true;
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 bool PandaNode::
00261 safe_to_transform() const {
00262 return true;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 bool PandaNode::
00278 safe_to_modify_transform() const {
00279 return true;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 bool PandaNode::
00293 safe_to_combine() const {
00294 return true;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 bool PandaNode::
00307 safe_to_combine_children() const {
00308 return true;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318 bool PandaNode::
00319 safe_to_flatten_below() const {
00320 return true;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330 bool PandaNode::
00331 preserve_name() const {
00332 return false;
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 int PandaNode::
00347 get_unsafe_to_apply_attribs() const {
00348 return 0;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 void PandaNode::
00364 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00365 GeomTransformer &transformer) {
00366 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00367 const LMatrix4 &mat = attribs._transform->get_mat();
00368 xform(mat);
00369
00370 Thread *current_thread = Thread::get_current_thread();
00371 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00372 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00373 cdata->_effects = cdata->_effects->xform(mat);
00374 cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
00375 }
00376 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00377 }
00378 mark_bam_modified();
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388 void PandaNode::
00389 xform(const LMatrix4 &) {
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 PandaNode *PandaNode::
00409 combine_with(PandaNode *other) {
00410
00411
00412
00413
00414 if (is_exact_type(get_class_type())) {
00415
00416 return other;
00417
00418 } else if (other->is_exact_type(get_class_type())) {
00419
00420 return this;
00421 }
00422
00423
00424 return (PandaNode *)NULL;
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 CPT(TransformState) PandaNode::
00448 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
00449 const TransformState *transform, Thread *current_thread) const {
00450 CPT(TransformState) next_transform = transform->compose(get_transform());
00451
00452 Children cr = get_children(current_thread);
00453 int num_children = cr.get_num_children();
00454 for (int i = 0; i < num_children; i++) {
00455 cr.get_child(i)->calc_tight_bounds(min_point, max_point,
00456 found_any, next_transform,
00457 current_thread);
00458 }
00459
00460 return next_transform;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 bool PandaNode::
00489 cull_callback(CullTraverser *, CullTraverserData &) {
00490 return true;
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 bool PandaNode::
00512 has_selective_visibility() const {
00513 return false;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 int PandaNode::
00527 get_first_visible_child() const {
00528 return 0;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 int PandaNode::
00542 get_next_visible_child(int n) const {
00543 return n + 1;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 bool PandaNode::
00563 has_single_child_visibility() const {
00564 return false;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574 int PandaNode::
00575 get_visible_child() const {
00576 return 0;
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 bool PandaNode::
00590 is_renderable() const {
00591 return false;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 void PandaNode::
00603 add_for_draw(CullTraverser *, CullTraverserData &) {
00604 }
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 PandaNode *PandaNode::
00616 make_copy() const {
00617 return new PandaNode(*this);
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 PT(PandaNode) PandaNode::
00630 copy_subgraph(Thread *current_thread) const {
00631 InstanceMap inst_map;
00632 return r_copy_subgraph(inst_map, current_thread);
00633 }
00634
00635 #ifdef HAVE_PYTHON
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 PT(PandaNode) PandaNode::
00648 __copy__() const {
00649 Thread *current_thread = Thread::get_current_thread();
00650
00651 PT(PandaNode) node_dupe = make_copy();
00652
00653 Children children = get_children(current_thread);
00654 int num_children = children.get_num_children();
00655
00656 for (int i = 0; i < num_children; ++i) {
00657 node_dupe->add_child(children.get_child(i), children.get_child_sort(i));
00658 }
00659
00660 return node_dupe;
00661 }
00662 #endif // HAVE_PYTHON
00663
00664 #ifdef HAVE_PYTHON
00665
00666
00667
00668
00669
00670
00671
00672
00673 PyObject *PandaNode::
00674 __deepcopy__(PyObject *self, PyObject *memo) const {
00675 IMPORT_THIS struct Dtool_PyTypedObject Dtool_PandaNode;
00676
00677
00678 PyObject *dupe = PyDict_GetItem(memo, self);
00679 if (dupe != NULL) {
00680
00681 Py_INCREF(dupe);
00682 return dupe;
00683 }
00684
00685 PT(PandaNode) node_dupe = copy_subgraph();
00686
00687
00688 node_dupe->ref();
00689 dupe = DTool_CreatePyInstanceTyped
00690 ((void *)node_dupe.p(), Dtool_PandaNode, true, false,
00691 node_dupe->get_type_index());
00692
00693 if (PyDict_SetItem(memo, self, dupe) != 0) {
00694 Py_DECREF(dupe);
00695 return NULL;
00696 }
00697
00698 return dupe;
00699 }
00700 #endif // HAVE_PYTHON
00701
00702
00703
00704
00705
00706
00707 int PandaNode::
00708 count_num_descendants() const {
00709 int count = 1;
00710 Children children = get_children();
00711 int num_children = children.get_num_children();
00712
00713 for (int i = 0; i < num_children; ++i) {
00714 PandaNode *child = children.get_child(i);
00715 count += child->count_num_descendants();
00716 }
00717
00718 return count;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 void PandaNode::
00733 add_child(PandaNode *child_node, int sort, Thread *current_thread) {
00734 nassertv(child_node != (PandaNode *)NULL);
00735
00736 if (!verify_child_no_cycles(child_node)) {
00737
00738
00739 return;
00740 }
00741
00742
00743 PT(PandaNode) keep_child = child_node;
00744 remove_child(child_node);
00745
00746
00747
00748 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00749 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00750 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
00751
00752 cdata->modify_down()->insert(DownConnection(child_node, sort));
00753 cdata_child->modify_up()->insert(UpConnection(this));
00754 }
00755 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00756
00757 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
00758 new_connection(this, child_node, pipeline_stage, current_thread);
00759 }
00760 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
00761
00762 force_bounds_stale();
00763
00764 children_changed();
00765 child_node->parents_changed();
00766 mark_bam_modified();
00767 child_node->mark_bam_modified();
00768 }
00769
00770
00771
00772
00773
00774
00775 void PandaNode::
00776 remove_child(int child_index, Thread *current_thread) {
00777 int pipeline_stage = current_thread->get_pipeline_stage();
00778 nassertv(pipeline_stage == 0);
00779
00780 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00781 PT(Down) down = cdata->modify_down();
00782 nassertv(child_index >= 0 && child_index < (int)down->size());
00783
00784 PT(PandaNode) child_node = (*down)[child_index].get_child();
00785 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
00786 current_thread);
00787 PT(Up) up = cdata_child->modify_up();
00788
00789 down->erase(down->begin() + child_index);
00790 int num_erased = up->erase(UpConnection(this));
00791 nassertv(num_erased == 1);
00792
00793 sever_connection(this, child_node, pipeline_stage, current_thread);
00794 force_bounds_stale(pipeline_stage, current_thread);
00795
00796 children_changed();
00797 child_node->parents_changed();
00798 mark_bam_modified();
00799 child_node->mark_bam_modified();
00800 }
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810 bool PandaNode::
00811 remove_child(PandaNode *child_node, Thread *current_thread) {
00812 nassertr(child_node != (PandaNode *)NULL, false);
00813
00814
00815
00816 PT(PandaNode) keep_child = child_node;
00817
00818
00819 bool any_removed = false;
00820
00821 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
00822 if (stage_remove_child(child_node, pipeline_stage, current_thread)) {
00823 any_removed = true;
00824
00825 sever_connection(this, child_node, pipeline_stage, current_thread);
00826 force_bounds_stale(pipeline_stage, current_thread);
00827 }
00828 }
00829 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
00830
00831 if (any_removed) {
00832
00833 children_changed();
00834 child_node->parents_changed();
00835 }
00836
00837 return any_removed;
00838 }
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 bool PandaNode::
00850 replace_child(PandaNode *orig_child, PandaNode *new_child,
00851 Thread *current_thread) {
00852 nassertr(orig_child != (PandaNode *)NULL, false);
00853 nassertr(new_child != (PandaNode *)NULL, false);
00854
00855 if (orig_child == new_child) {
00856
00857 return true;
00858 }
00859
00860 if (!verify_child_no_cycles(new_child)) {
00861
00862
00863 return false;
00864 }
00865
00866
00867
00868 PT(PandaNode) keep_orig_child = orig_child;
00869
00870
00871 bool any_replaced = false;
00872
00873 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00874 if (stage_replace_child(orig_child, new_child, pipeline_stage, current_thread)) {
00875 any_replaced = true;
00876 }
00877 }
00878 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00879
00880 if (any_replaced) {
00881 children_changed();
00882 orig_child->parents_changed();
00883 new_child->parents_changed();
00884 }
00885
00886 return any_replaced;
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 void PandaNode::
00905 stash_child(int child_index, Thread *current_thread) {
00906 int pipeline_stage = current_thread->get_pipeline_stage();
00907 nassertv(pipeline_stage == 0);
00908 nassertv(child_index >= 0 && child_index < get_num_children());
00909
00910
00911 PT(PandaNode) self = this;
00912
00913 PT(PandaNode) child_node = get_child(child_index);
00914 int sort = get_child_sort(child_index);
00915
00916 remove_child(child_index);
00917
00918 {
00919 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00920 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
00921
00922 cdata->modify_stashed()->insert(DownConnection(child_node, sort));
00923 cdata_child->modify_up()->insert(UpConnection(this));
00924 }
00925
00926 new_connection(this, child_node, pipeline_stage, current_thread);
00927 force_bounds_stale(pipeline_stage, current_thread);
00928
00929 children_changed();
00930 child_node->parents_changed();
00931 mark_bam_modified();
00932 child_node->mark_bam_modified();
00933 }
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 void PandaNode::
00950 unstash_child(int stashed_index, Thread *current_thread) {
00951 int pipeline_stage = current_thread->get_pipeline_stage();
00952 nassertv(pipeline_stage == 0);
00953 nassertv(stashed_index >= 0 && stashed_index < get_num_stashed());
00954
00955
00956
00957
00958
00959 PT(PandaNode) self = this;
00960
00961 PT(PandaNode) child_node = get_stashed(stashed_index);
00962 int sort = get_stashed_sort(stashed_index);
00963
00964 remove_stashed(stashed_index);
00965
00966 {
00967 CDWriter cdata(_cycler);
00968 CDWriter cdata_child(child_node->_cycler);
00969
00970 cdata->modify_down()->insert(DownConnection(child_node, sort));
00971 cdata_child->modify_up()->insert(UpConnection(this));
00972 }
00973
00974 new_connection(this, child_node, pipeline_stage, current_thread);
00975
00976 force_bounds_stale();
00977 children_changed();
00978 child_node->parents_changed();
00979 mark_bam_modified();
00980 child_node->mark_bam_modified();
00981 }
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 void PandaNode::
00998 add_stashed(PandaNode *child_node, int sort, Thread *current_thread) {
00999 int pipeline_stage = current_thread->get_pipeline_stage();
01000 nassertv(pipeline_stage == 0);
01001
01002 if (!verify_child_no_cycles(child_node)) {
01003
01004
01005 return;
01006 }
01007
01008
01009 PT(PandaNode) keep_child = child_node;
01010 remove_child(child_node);
01011
01012 {
01013 CDWriter cdata(_cycler);
01014 CDWriter cdata_child(child_node->_cycler);
01015
01016 cdata->modify_stashed()->insert(DownConnection(child_node, sort));
01017 cdata_child->modify_up()->insert(UpConnection(this));
01018 }
01019
01020 new_connection(this, child_node, pipeline_stage, current_thread);
01021
01022
01023 children_changed();
01024 child_node->parents_changed();
01025 mark_bam_modified();
01026 child_node->mark_bam_modified();
01027 }
01028
01029
01030
01031
01032
01033
01034 void PandaNode::
01035 remove_stashed(int child_index, Thread *current_thread) {
01036 int pipeline_stage = current_thread->get_pipeline_stage();
01037 nassertv(pipeline_stage == 0);
01038
01039 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01040 Down &stashed = *cdata->modify_stashed();
01041 nassertv(child_index >= 0 && child_index < (int)stashed.size());
01042
01043 PT(PandaNode) child_node = stashed[child_index].get_child();
01044 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
01045
01046 stashed.erase(stashed.begin() + child_index);
01047 int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
01048 nassertv(num_erased == 1);
01049
01050 sever_connection(this, child_node, pipeline_stage, current_thread);
01051 force_bounds_stale(pipeline_stage, current_thread);
01052
01053 children_changed();
01054 child_node->parents_changed();
01055 mark_bam_modified();
01056 child_node->mark_bam_modified();
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 void PandaNode::
01069 remove_all_children(Thread *current_thread) {
01070
01071 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01072 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01073 PT(Down) down = cdata->modify_down();
01074 Down::iterator di;
01075 for (di = down->begin(); di != down->end(); ++di) {
01076 PT(PandaNode) child_node = (*di).get_child();
01077 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
01078 current_thread);
01079 cdata_child->modify_up()->erase(UpConnection(this));
01080
01081 sever_connection(this, child_node, pipeline_stage, current_thread);
01082 child_node->parents_changed();
01083 child_node->mark_bam_modified();
01084 }
01085 down->clear();
01086
01087 Down &stashed = *cdata->modify_stashed();
01088 for (di = stashed.begin(); di != stashed.end(); ++di) {
01089 PT(PandaNode) child_node = (*di).get_child();
01090 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
01091 current_thread);
01092 cdata_child->modify_up()->erase(UpConnection(this));
01093
01094 sever_connection(this, child_node, pipeline_stage, current_thread);
01095 child_node->parents_changed();
01096 child_node->mark_bam_modified();
01097 }
01098 stashed.clear();
01099 }
01100 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01101
01102 force_bounds_stale();
01103 children_changed();
01104 mark_bam_modified();
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 void PandaNode::
01117 steal_children(PandaNode *other, Thread *current_thread) {
01118 if (other == this) {
01119
01120 return;
01121 }
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131 int num_children = other->get_num_children();
01132 int i;
01133 for (i = 0; i < num_children; i++) {
01134 PandaNode *child_node = other->get_child(i);
01135 int sort = other->get_child_sort(i);
01136 add_child(child_node, sort, current_thread);
01137 }
01138 int num_stashed = other->get_num_stashed();
01139 for (i = 0; i < num_stashed; i++) {
01140 PandaNode *child_node = other->get_stashed(i);
01141 int sort = other->get_stashed_sort(i);
01142 add_stashed(child_node, sort, current_thread);
01143 }
01144
01145 other->remove_all_children(current_thread);
01146 }
01147
01148
01149
01150
01151
01152
01153
01154 void PandaNode::
01155 copy_children(PandaNode *other, Thread *current_thread) {
01156 if (other == this) {
01157
01158 return;
01159 }
01160 Children children = other->get_children(current_thread);
01161 Stashed stashed = other->get_stashed(current_thread);
01162 int num_children = children.get_num_children();
01163 int i;
01164 for (i = 0; i < num_children; i++) {
01165 PandaNode *child_node = children.get_child(i);
01166 int sort = children.get_child_sort(i);
01167 add_child(child_node, sort, current_thread);
01168 }
01169 int num_stashed = stashed.get_num_stashed();
01170 for (i = 0; i < num_stashed; i++) {
01171 PandaNode *child_node = stashed.get_stashed(i);
01172 int sort = stashed.get_stashed_sort(i);
01173 add_stashed(child_node, sort, current_thread);
01174 }
01175 }
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185 void PandaNode::
01186 set_attrib(const RenderAttrib *attrib, int override) {
01187
01188
01189 bool any_changed = false;
01190 Thread *current_thread = Thread::get_current_thread();
01191 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01192 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01193
01194 CPT(RenderState) new_state = cdata->_state->set_attrib(attrib, override);
01195 if (cdata->_state != new_state) {
01196 cdata->_state = new_state;
01197 cdata->set_fancy_bit(FB_state, true);
01198 any_changed = true;
01199 }
01200 }
01201 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01202
01203
01204 if (any_changed) {
01205 mark_bounds_stale(current_thread);
01206 state_changed();
01207 mark_bam_modified();
01208 }
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 void PandaNode::
01220 clear_attrib(int slot) {
01221 bool any_changed = false;
01222
01223 Thread *current_thread = Thread::get_current_thread();
01224 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01225 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01226
01227 CPT(RenderState) new_state = cdata->_state->remove_attrib(slot);
01228 if (cdata->_state != new_state) {
01229 cdata->_state = new_state;
01230 cdata->set_fancy_bit(FB_state, !new_state->is_empty());
01231 any_changed = true;
01232 }
01233 }
01234 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01235
01236
01237
01238 if (any_changed) {
01239 mark_bounds_stale(current_thread);
01240 state_changed();
01241 mark_bam_modified();
01242 }
01243 }
01244
01245
01246
01247
01248
01249
01250
01251
01252 void PandaNode::
01253 set_effect(const RenderEffect *effect) {
01254
01255
01256 Thread *current_thread = Thread::get_current_thread();
01257 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01258 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01259 cdata->_effects = cdata->_effects->add_effect(effect);
01260 cdata->set_fancy_bit(FB_effects, true);
01261 }
01262 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01263 mark_bam_modified();
01264 }
01265
01266
01267
01268
01269
01270
01271
01272 void PandaNode::
01273 clear_effect(TypeHandle type) {
01274 Thread *current_thread = Thread::get_current_thread();
01275 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01276 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01277 cdata->_effects = cdata->_effects->remove_effect(type);
01278 cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
01279 }
01280 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01281 mark_bam_modified();
01282 }
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 void PandaNode::
01295 set_state(const RenderState *state, Thread *current_thread) {
01296
01297
01298 bool any_changed = false;
01299 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01300 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01301 if (cdata->_state != state) {
01302 cdata->_state = state;
01303 cdata->set_fancy_bit(FB_state, !state->is_empty());
01304 any_changed = true;
01305 }
01306 }
01307 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01308
01309
01310 if (any_changed) {
01311 mark_bounds_stale(current_thread);
01312 state_changed();
01313 mark_bam_modified();
01314 }
01315 }
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 void PandaNode::
01326 set_effects(const RenderEffects *effects, Thread *current_thread) {
01327
01328
01329 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01330 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01331 cdata->_effects = effects;
01332 cdata->set_fancy_bit(FB_effects, !effects->is_empty());
01333 }
01334 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01335 mark_bam_modified();
01336 }
01337
01338
01339
01340
01341
01342
01343
01344
01345 void PandaNode::
01346 set_transform(const TransformState *transform, Thread *current_thread) {
01347
01348 LightMutexHolder holder(_dirty_prev_transforms._lock);
01349
01350
01351
01352 bool any_changed = false;
01353 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01354 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01355 if (cdata->_transform != transform) {
01356 cdata->_transform = transform;
01357 cdata->set_fancy_bit(FB_transform, !transform->is_identity());
01358 any_changed = true;
01359
01360 if (pipeline_stage == 0) {
01361 if (cdata->_transform != cdata->_prev_transform) {
01362 do_set_dirty_prev_transform();
01363 }
01364 }
01365 }
01366 }
01367 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01368
01369 if (any_changed) {
01370 mark_bounds_stale(current_thread);
01371 transform_changed();
01372 mark_bam_modified();
01373 }
01374 }
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384 void PandaNode::
01385 set_prev_transform(const TransformState *transform, Thread *current_thread) {
01386
01387 LightMutexHolder holder(_dirty_prev_transforms._lock);
01388
01389
01390
01391 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01392 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01393 cdata->_prev_transform = transform;
01394 if (pipeline_stage == 0) {
01395 if (cdata->_transform != cdata->_prev_transform) {
01396 do_set_dirty_prev_transform();
01397 } else {
01398 do_clear_dirty_prev_transform();
01399 }
01400 }
01401 }
01402 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01403 mark_bam_modified();
01404 }
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 void PandaNode::
01415 reset_prev_transform(Thread *current_thread) {
01416
01417 LightMutexHolder holder(_dirty_prev_transforms._lock);
01418 do_clear_dirty_prev_transform();
01419
01420
01421
01422
01423 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01424 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01425 cdata->_prev_transform = cdata->_transform;
01426 }
01427 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01428 mark_bam_modified();
01429 }
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 void PandaNode::
01441 reset_all_prev_transform(Thread *current_thread) {
01442 nassertv(current_thread->get_pipeline_stage() == 0);
01443
01444 PStatTimer timer(_reset_prev_pcollector, current_thread);
01445 LightMutexHolder holder(_dirty_prev_transforms._lock);
01446
01447 LinkedListNode *list_node = _dirty_prev_transforms._next;
01448 while (list_node != &_dirty_prev_transforms) {
01449 PandaNode *panda_node = (PandaNode *)list_node;
01450 nassertv(panda_node->_dirty_prev_transform);
01451 panda_node->_dirty_prev_transform = false;
01452
01453 CDStageWriter cdata(panda_node->_cycler, 0, current_thread);
01454 cdata->_prev_transform = cdata->_transform;
01455
01456 list_node = panda_node->_next;
01457 #ifndef NDEBUG
01458 panda_node->_prev = NULL;
01459 panda_node->_next = NULL;
01460 #endif // NDEBUG
01461 panda_node->mark_bam_modified();
01462 }
01463
01464 _dirty_prev_transforms._prev = &_dirty_prev_transforms;
01465 _dirty_prev_transforms._next = &_dirty_prev_transforms;
01466 }
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481 void PandaNode::
01482 set_tag(const string &key, const string &value, Thread *current_thread) {
01483
01484
01485 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01486 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01487 cdata->_tag_data[key] = value;
01488 cdata->set_fancy_bit(FB_tag, true);
01489 }
01490 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01491 mark_bam_modified();
01492 }
01493
01494
01495
01496
01497
01498
01499
01500
01501 void PandaNode::
01502 clear_tag(const string &key, Thread *current_thread) {
01503 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01504 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01505 cdata->_tag_data.erase(key);
01506 cdata->set_fancy_bit(FB_tag, !cdata->_tag_data.empty());
01507 }
01508 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01509 mark_bam_modified();
01510 }
01511
01512 #ifdef HAVE_PYTHON
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527 void PandaNode::
01528 set_python_tag(const string &key, PyObject *value) {
01529 Thread *current_thread = Thread::get_current_thread();
01530 int pipeline_stage = current_thread->get_pipeline_stage();
01531 nassertv(pipeline_stage == 0);
01532
01533 CDWriter cdata(_cycler);
01534 Py_XINCREF(value);
01535
01536 pair<PythonTagData::iterator, bool> result;
01537 result = cdata->_python_tag_data.insert(PythonTagData::value_type(key, value));
01538
01539 if (!result.second) {
01540
01541
01542
01543
01544 PythonTagData::iterator ti = result.first;
01545 PyObject *old_value = (*ti).second;
01546 Py_XDECREF(old_value);
01547 (*ti).second = value;
01548 }
01549
01550
01551 mark_bam_modified();
01552 }
01553 #endif // HAVE_PYTHON
01554
01555 #ifdef HAVE_PYTHON
01556
01557
01558
01559
01560
01561
01562
01563 PyObject *PandaNode::
01564 get_python_tag(const string &key) const {
01565 CDReader cdata(_cycler);
01566 PythonTagData::const_iterator ti;
01567 ti = cdata->_python_tag_data.find(key);
01568 if (ti != cdata->_python_tag_data.end()) {
01569 PyObject *result = (*ti).second;
01570 Py_XINCREF(result);
01571 return result;
01572 }
01573 Py_INCREF(Py_None);
01574 return Py_None;
01575 }
01576 #endif // HAVE_PYTHON
01577
01578 #ifdef HAVE_PYTHON
01579
01580
01581
01582
01583
01584
01585
01586 bool PandaNode::
01587 has_python_tag(const string &key) const {
01588 CDReader cdata(_cycler);
01589 PythonTagData::const_iterator ti;
01590 ti = cdata->_python_tag_data.find(key);
01591 return (ti != cdata->_python_tag_data.end());
01592 }
01593 #endif // HAVE_PYTHON
01594
01595 #ifdef HAVE_PYTHON
01596
01597
01598
01599
01600
01601
01602
01603
01604 void PandaNode::
01605 clear_python_tag(const string &key) {
01606 Thread *current_thread = Thread::get_current_thread();
01607 int pipeline_stage = current_thread->get_pipeline_stage();
01608 nassertv(pipeline_stage == 0);
01609
01610 CDWriter cdata(_cycler, current_thread);
01611 PythonTagData::iterator ti;
01612 ti = cdata->_python_tag_data.find(key);
01613 if (ti != cdata->_python_tag_data.end()) {
01614 PyObject *value = (*ti).second;
01615 Py_XDECREF(value);
01616 cdata->_python_tag_data.erase(ti);
01617 }
01618
01619
01620 mark_bam_modified();
01621 }
01622 #endif // HAVE_PYTHON
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632 void PandaNode::
01633 copy_tags(PandaNode *other) {
01634 if (other == this) {
01635
01636 return;
01637 }
01638
01639
01640
01641 Thread *current_thread = Thread::get_current_thread();
01642 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01643 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
01644 CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
01645
01646 TagData::const_iterator ti;
01647 for (ti = cdatar->_tag_data.begin();
01648 ti != cdatar->_tag_data.end();
01649 ++ti) {
01650 cdataw->_tag_data[(*ti).first] = (*ti).second;
01651 }
01652 cdataw->set_fancy_bit(FB_tag, !cdataw->_tag_data.empty());
01653
01654 #ifdef HAVE_PYTHON
01655 PythonTagData::const_iterator pti;
01656 for (pti = cdatar->_python_tag_data.begin();
01657 pti != cdatar->_python_tag_data.end();
01658 ++pti) {
01659 const string &key = (*pti).first;
01660 PyObject *value = (*pti).second;
01661 Py_XINCREF(value);
01662
01663 pair<PythonTagData::iterator, bool> result;
01664 result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
01665
01666 if (!result.second) {
01667
01668
01669
01670
01671 PythonTagData::iterator wpti = result.first;
01672 PyObject *old_value = (*wpti).second;
01673 Py_XDECREF(old_value);
01674 (*wpti).second = value;
01675 }
01676 }
01677 #endif // HAVE_PYTHON
01678 }
01679 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01680 mark_bam_modified();
01681 }
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695 void PandaNode::
01696 list_tags(ostream &out, const string &separator) const {
01697 CDReader cdata(_cycler);
01698 if (!cdata->_tag_data.empty()) {
01699 TagData::const_iterator ti = cdata->_tag_data.begin();
01700 out << (*ti).first;
01701 ++ti;
01702 while (ti != cdata->_tag_data.end()) {
01703 out << separator << (*ti).first;
01704 ++ti;
01705 }
01706 }
01707
01708 #ifdef HAVE_PYTHON
01709 if (!cdata->_python_tag_data.empty()) {
01710 if (!cdata->_tag_data.empty()) {
01711 out << separator;
01712 }
01713 PythonTagData::const_iterator ti = cdata->_python_tag_data.begin();
01714 out << (*ti).first;
01715 ++ti;
01716 while (ti != cdata->_python_tag_data.end()) {
01717 out << separator << (*ti).first;
01718 ++ti;
01719 }
01720 }
01721 #endif // HAVE_PYTHON
01722 }
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735 int PandaNode::
01736 compare_tags(const PandaNode *other) const {
01737 CDReader cdata(_cycler);
01738 CDReader cdata_other(other->_cycler);
01739
01740 TagData::const_iterator ati = cdata->_tag_data.begin();
01741 TagData::const_iterator bti = cdata_other->_tag_data.begin();
01742 while (ati != cdata->_tag_data.end() &&
01743 bti != cdata_other->_tag_data.end()) {
01744 int cmp = strcmp((*ati).first.c_str(), (*bti).first.c_str());
01745 if (cmp != 0) {
01746 return cmp;
01747 }
01748
01749 cmp = strcmp((*ati).second.c_str(), (*bti).second.c_str());
01750 if (cmp != 0) {
01751 return cmp;
01752 }
01753
01754 ++ati;
01755 ++bti;
01756 }
01757 if (ati != cdata->_tag_data.end()) {
01758
01759 return 1;
01760 }
01761 if (bti != cdata_other->_tag_data.end()) {
01762
01763 return -1;
01764 }
01765
01766 #ifdef HAVE_PYTHON
01767 PythonTagData::const_iterator api = cdata->_python_tag_data.begin();
01768 PythonTagData::const_iterator bpi = cdata_other->_python_tag_data.begin();
01769 while (api != cdata->_python_tag_data.end() &&
01770 bpi != cdata_other->_python_tag_data.end()) {
01771 int cmp = strcmp((*api).first.c_str(), (*bpi).first.c_str());
01772 if (cmp != 0) {
01773 return cmp;
01774 }
01775
01776 if (PyObject_Cmp((*api).second, (*bpi).second, &cmp) == -1) {
01777
01778 if ((*api).second != (*bpi).second) {
01779 cmp = (*api).second < (*bpi).second ? -1 : 1;
01780 } else {
01781 cmp = 0;
01782 }
01783 }
01784 if (cmp != 0) {
01785 return cmp;
01786 }
01787
01788 ++api;
01789 ++bpi;
01790 }
01791 if (api != cdata->_python_tag_data.end()) {
01792
01793 return 1;
01794 }
01795 if (bpi != cdata_other->_python_tag_data.end()) {
01796
01797 return -1;
01798 }
01799 #endif // HAVE_PYTHON
01800
01801 return 0;
01802 }
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813 void PandaNode::
01814 copy_all_properties(PandaNode *other) {
01815 if (other == this) {
01816
01817 return;
01818 }
01819
01820
01821 LightMutexHolder holder(_dirty_prev_transforms._lock);
01822
01823 bool any_transform_changed = false;
01824 bool any_state_changed = false;
01825 bool any_draw_mask_changed = false;
01826 Thread *current_thread = Thread::get_current_thread();
01827 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01828 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
01829 CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
01830
01831 if (cdataw->_transform != cdatar->_transform) {
01832 any_transform_changed = true;
01833 }
01834 if (cdataw->_state != cdatar->_state) {
01835 any_state_changed = true;
01836 }
01837 if (cdataw->_draw_control_mask != cdatar->_draw_control_mask ||
01838 cdataw->_draw_show_mask != cdatar->_draw_show_mask) {
01839 any_draw_mask_changed = true;
01840 }
01841
01842 cdataw->_transform = cdatar->_transform;
01843 cdataw->_prev_transform = cdatar->_prev_transform;
01844 cdataw->_state = cdatar->_state;
01845 cdataw->_effects = cdatar->_effects;
01846 cdataw->_draw_control_mask = cdatar->_draw_control_mask;
01847 cdataw->_draw_show_mask = cdatar->_draw_show_mask;
01848
01849
01850
01851
01852 cdataw->_into_collide_mask |= cdatar->_into_collide_mask;
01853
01854 TagData::const_iterator ti;
01855 for (ti = cdatar->_tag_data.begin();
01856 ti != cdatar->_tag_data.end();
01857 ++ti) {
01858 cdataw->_tag_data[(*ti).first] = (*ti).second;
01859 }
01860
01861 #ifdef HAVE_PYTHON
01862 PythonTagData::const_iterator pti;
01863 for (pti = cdatar->_python_tag_data.begin();
01864 pti != cdatar->_python_tag_data.end();
01865 ++pti) {
01866 const string &key = (*pti).first;
01867 PyObject *value = (*pti).second;
01868 Py_XINCREF(value);
01869
01870 pair<PythonTagData::iterator, bool> result;
01871 result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
01872
01873 if (!result.second) {
01874
01875
01876
01877
01878 PythonTagData::iterator wpti = result.first;
01879 PyObject *old_value = (*wpti).second;
01880 Py_XDECREF(old_value);
01881 (*wpti).second = value;
01882 }
01883 }
01884 #endif // HAVE_PYTHON
01885
01886 static const int change_bits = (FB_transform | FB_state | FB_effects |
01887 FB_tag | FB_draw_mask);
01888 cdataw->_fancy_bits =
01889 (cdataw->_fancy_bits & ~change_bits) |
01890 (cdatar->_fancy_bits & change_bits);
01891
01892 if (pipeline_stage == 0) {
01893 if (cdataw->_transform != cdataw->_prev_transform) {
01894 do_set_dirty_prev_transform();
01895 }
01896 }
01897 }
01898 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01899
01900 if (any_transform_changed || any_state_changed || any_draw_mask_changed) {
01901 mark_bounds_stale(current_thread);
01902
01903 if (any_transform_changed) {
01904 transform_changed();
01905 }
01906 if (any_state_changed) {
01907 state_changed();
01908 }
01909 if (any_draw_mask_changed) {
01910 draw_mask_changed();
01911 }
01912 mark_bam_modified();
01913 }
01914 }
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 void PandaNode::
01936 replace_node(PandaNode *other) {
01937
01938
01939 if (other == this) {
01940
01941 return;
01942 }
01943
01944
01945
01946 PT(PandaNode) keep_other = other;
01947
01948
01949 copy_all_properties(other);
01950
01951
01952 {
01953 LightReMutexHolder holder1(other->_paths_lock);
01954 LightReMutexHolder holder2(_paths_lock);
01955 Paths::iterator pi;
01956 for (pi = other->_paths.begin(); pi != other->_paths.end(); ++pi) {
01957 (*pi)->_node = this;
01958 _paths.insert(*pi);
01959 }
01960 other->_paths.clear();
01961 }
01962
01963
01964 steal_children(other);
01965
01966
01967 Thread *current_thread = Thread::get_current_thread();
01968 Parents other_parents = other->get_parents();
01969 for (int i = 0; i < other_parents.get_num_parents(); ++i) {
01970 PandaNode *parent = other_parents.get_parent(i);
01971 if (find_parent(parent) != -1) {
01972
01973
01974 parent->remove_child(other);
01975 } else {
01976
01977 parent->replace_child(other, this, current_thread);
01978 }
01979 }
01980 }
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001 void PandaNode::
02002 set_unexpected_change(unsigned int flags) {
02003 #ifndef NDEBUG
02004 _unexpected_change_flags |= flags;
02005 #endif // !NDEBUG
02006 }
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022 unsigned int PandaNode::
02023 get_unexpected_change(unsigned int flags) const {
02024 #ifndef NDEBUG
02025 return _unexpected_change_flags & flags;
02026 #else
02027 return 0;
02028 #endif // !NDEBUG
02029 }
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045 void PandaNode::
02046 clear_unexpected_change(unsigned int flags) {
02047 #ifndef NDEBUG
02048 _unexpected_change_flags &= ~flags;
02049 #endif // !NDEBUG
02050 }
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090 void PandaNode::
02091 adjust_draw_mask(DrawMask show_mask, DrawMask hide_mask, DrawMask clear_mask) {
02092 bool any_changed = false;
02093
02094 Thread *current_thread = Thread::get_current_thread();
02095 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02096 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02097
02098 DrawMask draw_control_mask = (cdata->_draw_control_mask | show_mask | hide_mask) & ~clear_mask;
02099 DrawMask draw_show_mask = (cdata->_draw_show_mask | show_mask) & ~hide_mask;
02100
02101 draw_show_mask |= ~draw_control_mask;
02102
02103 if (cdata->_draw_control_mask != draw_control_mask ||
02104 cdata->_draw_show_mask != draw_show_mask) {
02105 cdata->_draw_control_mask = draw_control_mask;
02106 cdata->_draw_show_mask = draw_show_mask;
02107 any_changed = true;
02108 }
02109 cdata->set_fancy_bit(FB_draw_mask, !draw_control_mask.is_zero());
02110 }
02111 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02112
02113 if (any_changed) {
02114 mark_bounds_stale(current_thread);
02115 draw_mask_changed();
02116 mark_bam_modified();
02117 }
02118 }
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132 DrawMask PandaNode::
02133 get_net_draw_control_mask() const {
02134 Thread *current_thread = Thread::get_current_thread();
02135 int pipeline_stage = current_thread->get_pipeline_stage();
02136 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02137 if (cdata->_last_update != cdata->_next_update) {
02138
02139 PStatTimer timer(_update_bounds_pcollector);
02140 CDStageWriter cdataw =
02141 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02142 return cdataw->_net_draw_control_mask;
02143 }
02144 return cdata->_net_draw_control_mask;
02145 }
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163 DrawMask PandaNode::
02164 get_net_draw_show_mask() const {
02165 Thread *current_thread = Thread::get_current_thread();
02166 int pipeline_stage = current_thread->get_pipeline_stage();
02167 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02168 if (cdata->_last_update != cdata->_next_update) {
02169
02170 PStatTimer timer(_update_bounds_pcollector);
02171 CDStageWriter cdataw =
02172 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02173 return cdataw->_net_draw_show_mask;
02174 }
02175 return cdata->_net_draw_show_mask;
02176 }
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195 void PandaNode::
02196 set_into_collide_mask(CollideMask mask) {
02197 mask &= get_legal_collide_mask();
02198
02199 bool any_changed = false;
02200 Thread *current_thread = Thread::get_current_thread();
02201 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02202 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02203 if (cdata->_into_collide_mask != mask) {
02204 cdata->_into_collide_mask = mask;
02205 any_changed = true;
02206 }
02207 }
02208 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02209
02210 if (any_changed) {
02211 mark_bounds_stale(current_thread);
02212 mark_bam_modified();
02213 }
02214 }
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227 CollideMask PandaNode::
02228 get_legal_collide_mask() const {
02229 return CollideMask::all_off();
02230 }
02231
02232
02233
02234
02235
02236
02237
02238 CollideMask PandaNode::
02239 get_net_collide_mask(Thread *current_thread) const {
02240 int pipeline_stage = current_thread->get_pipeline_stage();
02241 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02242 if (cdata->_last_update != cdata->_next_update) {
02243
02244 PStatTimer timer(_update_bounds_pcollector);
02245 CDStageWriter cdataw =
02246 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02247 return cdataw->_net_collide_mask;
02248 }
02249 return cdata->_net_collide_mask;
02250 }
02251
02252
02253
02254
02255
02256
02257
02258
02259 CPT(RenderAttrib) PandaNode::
02260 get_off_clip_planes(Thread *current_thread) const {
02261 int pipeline_stage = current_thread->get_pipeline_stage();
02262 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02263 if (cdata->_last_update != cdata->_next_update) {
02264
02265 PStatTimer timer(_update_bounds_pcollector);
02266 CDStageWriter cdataw =
02267 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02268 return cdataw->_off_clip_planes;
02269 }
02270 return cdata->_off_clip_planes;
02271 }
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288 void PandaNode::
02289 prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state) {
02290 GeomTransformer transformer;
02291 Thread *current_thread = Thread::get_current_thread();
02292 r_prepare_scene(gsg, node_state, transformer, current_thread);
02293 }
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303 bool PandaNode::
02304 is_scene_root() const {
02305
02306
02307
02308 if (_scene_root_func != (SceneRootFunc *)NULL) {
02309 return (*_scene_root_func)(this);
02310 }
02311 return false;
02312 }
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324 bool PandaNode::
02325 is_under_scene_root() const {
02326 if (is_scene_root()) {
02327 return true;
02328 }
02329
02330 Parents parents = get_parents();
02331 for (int i = 0; i < parents.get_num_parents(); ++i) {
02332 PandaNode *parent = parents.get_parent(i);
02333 if (parent->find_stashed((PandaNode *)this) == -1) {
02334 if (parent->is_under_scene_root()) {
02335 return true;
02336 }
02337 }
02338 }
02339 return false;
02340 }
02341
02342
02343
02344
02345
02346
02347 void PandaNode::
02348 output(ostream &out) const {
02349 out << get_type() << " " << get_name();
02350 }
02351
02352
02353
02354
02355
02356
02357 void PandaNode::
02358 write(ostream &out, int indent_level) const {
02359 indent(out, indent_level) << *this;
02360 if (has_tags()) {
02361 out << " [";
02362 list_tags(out, " ");
02363 out << "]";
02364 }
02365 CPT(TransformState) transform = get_transform();
02366 if (!transform->is_identity()) {
02367 out << " " << *transform;
02368 }
02369 CPT(RenderState) state = get_state();
02370 if (!state->is_empty()) {
02371 out << " " << *state;
02372 }
02373 CPT(RenderEffects) effects = get_effects();
02374 if (!effects->is_empty()) {
02375 out << " " << *effects;
02376 }
02377 DrawMask draw_control_mask = get_draw_control_mask();
02378 if (!draw_control_mask.is_zero()) {
02379 DrawMask draw_show_mask = get_draw_show_mask();
02380 if (!(draw_control_mask & _overall_bit).is_zero()) {
02381 if (!(draw_show_mask & _overall_bit).is_zero()) {
02382 out << " (show_through)";
02383 } else {
02384 out << " (hidden)";
02385 }
02386 }
02387 if (!(draw_control_mask & ~_overall_bit).is_zero()) {
02388 draw_control_mask &= ~_overall_bit;
02389 if (!(draw_show_mask & draw_control_mask).is_zero()) {
02390 out << " (per-camera show_through)";
02391 }
02392 if (!(~draw_show_mask & draw_control_mask).is_zero()) {
02393 out << " (per-camera hidden)";
02394 }
02395 }
02396 }
02397 out << "\n";
02398 }
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419 void PandaNode::
02420 set_bounds_type(BoundingVolume::BoundsType bounds_type) {
02421 Thread *current_thread = Thread::get_current_thread();
02422 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02423 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02424 cdata->_bounds_type = bounds_type;
02425 mark_bounds_stale(pipeline_stage, current_thread);
02426
02427
02428
02429
02430 mark_internal_bounds_stale(pipeline_stage, current_thread);
02431 mark_bam_modified();
02432 }
02433 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02434 }
02435
02436
02437
02438
02439
02440
02441
02442 BoundingVolume::BoundsType PandaNode::
02443 get_bounds_type() const {
02444 CDReader cdata(_cycler);
02445 return cdata->_bounds_type;
02446 }
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462 void PandaNode::
02463 set_bounds(const BoundingVolume *volume) {
02464 Thread *current_thread = Thread::get_current_thread();
02465 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02466 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02467 if (volume == NULL) {
02468 cdata->_user_bounds = NULL;
02469 } else {
02470 cdata->_user_bounds = volume->make_copy();
02471 }
02472 mark_bounds_stale(pipeline_stage, current_thread);
02473 mark_bam_modified();
02474 }
02475 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02476 }
02477
02478
02479
02480
02481
02482
02483 void PandaNode::
02484 set_bound(const BoundingVolume *volume) {
02485 pgraph_cat.warning()
02486 << "Deprecated PandaNode::set_bound() called. Use set_bounds() instead.\n";
02487 set_bounds(volume);
02488 }
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498 CPT(BoundingVolume) PandaNode::
02499 get_bounds(Thread *current_thread) const {
02500 int pipeline_stage = current_thread->get_pipeline_stage();
02501 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02502 if (cdata->_last_update != cdata->_next_update) {
02503
02504 CPT(BoundingVolume) result;
02505 {
02506 PStatTimer timer(_update_bounds_pcollector);
02507 CDStageWriter cdataw =
02508 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02509 result = cdataw->_external_bounds;
02510 }
02511 return result;
02512 }
02513 return cdata->_external_bounds;
02514 }
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532 CPT(BoundingVolume) PandaNode::
02533 get_bounds(UpdateSeq &seq, Thread *current_thread) const {
02534 int pipeline_stage = current_thread->get_pipeline_stage();
02535 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02536 if (cdata->_last_update != cdata->_next_update) {
02537
02538 CPT(BoundingVolume) result;
02539 {
02540 PStatTimer timer(_update_bounds_pcollector);
02541 CDStageWriter cdataw =
02542 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02543 result = cdataw->_external_bounds;
02544 seq = cdataw->_last_update;
02545 }
02546 return result;
02547 }
02548 seq = cdata->_last_update;
02549 return cdata->_external_bounds;
02550 }
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565 int PandaNode::
02566 get_nested_vertices(Thread *current_thread) const {
02567 int pipeline_stage = current_thread->get_pipeline_stage();
02568 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02569 if (cdata->_last_update != cdata->_next_update) {
02570
02571 int result;
02572 {
02573 PStatTimer timer(_update_bounds_pcollector);
02574 CDStageWriter cdataw =
02575 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02576 result = cdataw->_nested_vertices;
02577 }
02578 return result;
02579 }
02580 return cdata->_nested_vertices;
02581 }
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601 void PandaNode::
02602 mark_bounds_stale(Thread *current_thread) const {
02603 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02604 mark_bounds_stale(pipeline_stage, current_thread);
02605 }
02606 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02607 }
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625 void PandaNode::
02626 mark_internal_bounds_stale(Thread *current_thread) {
02627 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02628 mark_internal_bounds_stale(pipeline_stage, current_thread);
02629 }
02630 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02631 }
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644 bool PandaNode::
02645 is_geom_node() const {
02646 return false;
02647 }
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659 bool PandaNode::
02660 is_lod_node() const {
02661 return false;
02662 }
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674 bool PandaNode::
02675 is_collision_node() const {
02676 return false;
02677 }
02678
02679
02680
02681
02682
02683
02684
02685
02686 Light *PandaNode::
02687 as_light() {
02688 return NULL;
02689 }
02690
02691
02692
02693
02694
02695
02696
02697 bool PandaNode::
02698 is_ambient_light() const {
02699 return false;
02700 }
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716 PT(PandaNode) PandaNode::
02717 decode_from_bam_stream(const string &data, BamReader *reader) {
02718 TypedWritable *object;
02719 ReferenceCount *ref_ptr;
02720
02721 if (!TypedWritable::decode_raw_from_bam_stream(object, ref_ptr, data, reader)) {
02722 return NULL;
02723 }
02724
02725 return DCAST(PandaNode, object);
02726 }
02727
02728
02729
02730
02731
02732
02733
02734
02735 CPT(BoundingVolume) PandaNode::
02736 get_internal_bounds(int pipeline_stage, Thread *current_thread) const {
02737 while (true) {
02738 UpdateSeq mark;
02739 {
02740 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02741 if (cdata->_user_bounds != (BoundingVolume *)NULL) {
02742 return cdata->_user_bounds;
02743 }
02744
02745 if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
02746 return cdata->_internal_bounds;
02747 }
02748
02749 mark = cdata->_internal_bounds_mark;
02750 }
02751
02752
02753
02754 CPT(BoundingVolume) internal_bounds;
02755 int internal_vertices;
02756 compute_internal_bounds(internal_bounds, internal_vertices,
02757 pipeline_stage, current_thread);
02758 nassertr(!internal_bounds.is_null(), NULL);
02759
02760
02761 CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
02762 if (cdataw->_internal_bounds_mark == mark) {
02763 cdataw->_internal_bounds_computed = mark;
02764 cdataw->_internal_bounds = internal_bounds;
02765 cdataw->_internal_vertices = internal_vertices;
02766 ((PandaNode *)this)->mark_bam_modified();
02767 return cdataw->_internal_bounds;
02768 }
02769
02770
02771
02772
02773 }
02774 }
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786 int PandaNode::
02787 get_internal_vertices(int pipeline_stage, Thread *current_thread) const {
02788 while (true) {
02789 UpdateSeq mark;
02790 {
02791 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02792 if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
02793 return cdata->_internal_vertices;
02794 }
02795
02796 mark = cdata->_internal_bounds_mark;
02797 }
02798
02799
02800
02801 CPT(BoundingVolume) internal_bounds;
02802 int internal_vertices;
02803 compute_internal_bounds(internal_bounds, internal_vertices,
02804 pipeline_stage, current_thread);
02805 nassertr(!internal_bounds.is_null(), 0);
02806
02807
02808 CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
02809 if (cdataw->_internal_bounds_mark == mark) {
02810 cdataw->_internal_bounds_computed = mark;
02811 cdataw->_internal_bounds = internal_bounds;
02812 cdataw->_internal_vertices = internal_vertices;
02813 ((PandaNode *)this)->mark_bam_modified();
02814 return cdataw->_internal_vertices;
02815 }
02816
02817
02818
02819
02820 }
02821 }
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832 void PandaNode::
02833 set_internal_bounds(const BoundingVolume *volume) {
02834 Thread *current_thread = Thread::get_current_thread();
02835 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02836 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
02837 cdataw->_internal_bounds = volume;
02838 cdataw->_internal_bounds_computed = cdataw->_internal_bounds_mark;
02839 }
02840 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02841 mark_bounds_stale(current_thread);
02842 mark_bam_modified();
02843 }
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856 void PandaNode::
02857 force_bounds_stale(Thread *current_thread) {
02858 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02859 force_bounds_stale(pipeline_stage, current_thread);
02860 }
02861 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02862 }
02863
02864
02865
02866
02867
02868
02869
02870
02871 void PandaNode::
02872 force_bounds_stale(int pipeline_stage, Thread *current_thread) {
02873 {
02874 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02875 ++cdata->_next_update;
02876 mark_bam_modified();
02877
02878
02879
02880
02881 }
02882
02883
02884
02885
02886 Parents parents;
02887 {
02888 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02889 parents = Parents(cdata);
02890 }
02891 int num_parents = parents.get_num_parents();
02892 for (int i = 0; i < num_parents; ++i) {
02893 PandaNode *parent = parents.get_parent(i);
02894 parent->mark_bounds_stale(pipeline_stage, current_thread);
02895 }
02896 }
02897
02898
02899
02900
02901
02902
02903
02904 void PandaNode::
02905 r_mark_geom_bounds_stale(Thread *current_thread) {
02906 Children children = get_children(current_thread);
02907
02908 int i;
02909 for (i = 0; i < children.get_num_children(); i++) {
02910 PandaNode *child = children.get_child(i);
02911 child->r_mark_geom_bounds_stale(current_thread);
02912 }
02913
02914 Stashed stashed = get_stashed(current_thread);
02915 for (i = 0; i < stashed.get_num_stashed(); i++) {
02916 PandaNode *child = stashed.get_stashed(i);
02917 child->r_mark_geom_bounds_stale(current_thread);
02918 }
02919 }
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929 void PandaNode::
02930 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
02931 int &internal_vertices,
02932 int pipeline_stage,
02933 Thread *current_thread) const {
02934 internal_bounds = new BoundingSphere;
02935 internal_vertices = 0;
02936 }
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947 void PandaNode::
02948 parents_changed() {
02949 nassertv((_unexpected_change_flags & UC_parents) == 0);
02950 }
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961 void PandaNode::
02962 children_changed() {
02963 nassertv((_unexpected_change_flags & UC_children) == 0);
02964 }
02965
02966
02967
02968
02969
02970
02971
02972
02973 void PandaNode::
02974 transform_changed() {
02975 nassertv((_unexpected_change_flags & UC_transform) == 0);
02976 }
02977
02978
02979
02980
02981
02982
02983
02984
02985 void PandaNode::
02986 state_changed() {
02987 nassertv((_unexpected_change_flags & UC_state) == 0);
02988 }
02989
02990
02991
02992
02993
02994
02995
02996
02997 void PandaNode::
02998 draw_mask_changed() {
02999 nassertv((_unexpected_change_flags & UC_draw_mask) == 0);
03000 }
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015 PT(PandaNode) PandaNode::
03016 r_copy_subgraph(PandaNode::InstanceMap &inst_map, Thread *current_thread) const {
03017 PT(PandaNode) copy = make_copy();
03018 nassertr(copy != (PandaNode *)NULL, NULL);
03019 if (copy->get_type() != get_type()) {
03020 pgraph_cat.warning()
03021 << "Don't know how to copy nodes of type " << get_type() << "\n";
03022
03023 if (no_unsupported_copy) {
03024 nassertr(false, NULL);
03025 }
03026 }
03027
03028 copy->r_copy_children(this, inst_map, current_thread);
03029 return copy;
03030 }
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047 void PandaNode::
03048 r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
03049 Thread *current_thread) {
03050 CDReader from_cdata(from->_cycler, current_thread);
03051 CPT(Down) from_down = from_cdata->get_down();
03052 Down::const_iterator di;
03053 for (di = from_down->begin(); di != from_down->end(); ++di) {
03054 int sort = (*di).get_sort();
03055 PandaNode *source_child = (*di).get_child();
03056 PT(PandaNode) dest_child;
03057
03058
03059
03060
03061
03062 InstanceMap::const_iterator ci;
03063 ci = inst_map.find(source_child);
03064 if (ci != inst_map.end()) {
03065 dest_child = (*ci).second;
03066 } else {
03067 dest_child = source_child->r_copy_subgraph(inst_map, current_thread);
03068 inst_map[source_child] = dest_child;
03069 }
03070
03071 quick_add_new_child(dest_child, sort, current_thread);
03072 }
03073 }
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083 void PandaNode::
03084 r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
03085 GeomTransformer &transformer, Thread *current_thread) {
03086 Children children = get_children(current_thread);
03087
03088
03089 int i;
03090 for (i = 0; i < children.get_num_children(); i++) {
03091 PandaNode *child = children.get_child(i);
03092 CPT(RenderState) child_state = node_state->compose(child->get_state());
03093 child->r_prepare_scene(gsg, child_state, transformer, current_thread);
03094 }
03095
03096 Stashed stashed = get_stashed(current_thread);
03097 for (i = 0; i < stashed.get_num_stashed(); i++) {
03098 PandaNode *child = stashed.get_stashed(i);
03099 CPT(RenderState) child_state = node_state->compose(child->get_state());
03100 child->r_prepare_scene(gsg, child_state, transformer, current_thread);
03101 }
03102 }
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112 void PandaNode::
03113 set_cull_callback() {
03114 Thread *current_thread = Thread::get_current_thread();
03115 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03116 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03117 cdata->set_fancy_bit(FB_cull_callback, true);
03118 }
03119 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03120 mark_bam_modified();
03121 }
03122
03123
03124
03125
03126
03127
03128 void PandaNode::
03129 disable_cull_callback() {
03130 Thread *current_thread = Thread::get_current_thread();
03131 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03132 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03133 cdata->set_fancy_bit(FB_cull_callback, false);
03134 }
03135 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03136 mark_bam_modified();
03137 }
03138
03139
03140
03141
03142
03143
03144
03145 bool PandaNode::
03146 stage_remove_child(PandaNode *child_node, int pipeline_stage,
03147 Thread *current_thread) {
03148 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03149
03150
03151
03152 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
03153 current_thread);
03154 int parent_index = child_node->do_find_parent(this, cdata_child);
03155 if (parent_index < 0) {
03156
03157 return false;
03158 }
03159
03160 PT(Down) down = cdata->modify_down();
03161 int child_index = do_find_child(child_node, down);
03162 if (child_index >= 0) {
03163
03164 down->erase(down->begin() + child_index);
03165 int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
03166 nassertr(num_erased == 1, false);
03167 return true;
03168 }
03169
03170 PT(Down) stashed = cdata->modify_stashed();
03171 int stashed_index = do_find_child(child_node, stashed);
03172 if (stashed_index >= 0) {
03173
03174 stashed->erase(stashed->begin() + stashed_index);
03175 int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
03176 nassertr(num_erased == 1, false);
03177 return true;
03178 }
03179
03180
03181
03182
03183 nassertr(false, false);
03184 return false;
03185 }
03186
03187
03188
03189
03190
03191
03192
03193 bool PandaNode::
03194 stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
03195 int pipeline_stage, Thread *current_thread) {
03196 {
03197 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03198 CDStageWriter cdata_orig_child(orig_child->_cycler, pipeline_stage, current_thread);
03199 CDStageWriter cdata_new_child(new_child->_cycler, pipeline_stage, current_thread);
03200
03201
03202
03203 int parent_index = orig_child->do_find_parent(this, cdata_orig_child);
03204 if (parent_index < 0) {
03205
03206 return false;
03207 }
03208
03209 if (orig_child == new_child) {
03210
03211 return true;
03212 }
03213
03214
03215 PT(PandaNode) keep_orig_child = orig_child;
03216
03217
03218 if (stage_remove_child(new_child, pipeline_stage, current_thread)) {
03219 sever_connection(this, new_child, pipeline_stage, current_thread);
03220 }
03221
03222 PT(Down) down = cdata->modify_down();
03223 int child_index = do_find_child(orig_child, down);
03224 if (child_index >= 0) {
03225
03226 DownConnection &dc = (*down)[child_index];
03227 nassertr(dc.get_child() == orig_child, false);
03228 dc.set_child(new_child);
03229
03230 } else {
03231 PT(Down) stashed = cdata->modify_stashed();
03232 int stashed_index = do_find_child(orig_child, stashed);
03233 if (stashed_index >= 0) {
03234
03235 DownConnection &dc = (*stashed)[stashed_index];
03236 nassertr(dc.get_child() == orig_child, false);
03237 dc.set_child(new_child);
03238
03239 } else {
03240
03241
03242
03243 nassertr(false, false);
03244 return false;
03245 }
03246 }
03247
03248
03249 cdata_new_child->modify_up()->insert(UpConnection(this));
03250 int num_erased = cdata_orig_child->modify_up()->erase(UpConnection(this));
03251 nassertr(num_erased == 1, false);
03252 }
03253
03254 sever_connection(this, orig_child, pipeline_stage, current_thread);
03255 new_connection(this, new_child, pipeline_stage, current_thread);
03256
03257 force_bounds_stale(pipeline_stage, current_thread);
03258 orig_child->parents_changed();
03259 new_child->parents_changed();
03260 mark_bam_modified();
03261 orig_child->mark_bam_modified();
03262 new_child->mark_bam_modified();
03263
03264 return true;
03265 }
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277 void PandaNode::
03278 quick_add_new_child(PandaNode *child_node, int sort, Thread *current_thread) {
03279
03280
03281 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03282 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03283 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03284
03285 cdata->modify_down()->insert(DownConnection(child_node, sort));
03286 cdata_child->modify_up()->insert(UpConnection(this));
03287 }
03288 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03289 }
03290
03291
03292
03293
03294
03295
03296
03297 void PandaNode::
03298 report_cycle(PandaNode *child_node) {
03299 ostringstream strm;
03300 strm << "Detected attempt to create a cycle in the scene graph: "
03301 << NodePath::any_path(this) << " : " << *child_node;
03302 nassert_raise(strm.str());
03303 }
03304
03305
03306
03307
03308
03309
03310
03311
03312 bool PandaNode::
03313 find_node_above(PandaNode *node) {
03314 if (node == this) {
03315 return true;
03316 }
03317
03318 Parents parents = get_parents();
03319 for (int i = 0; i < parents.get_num_parents(); ++i) {
03320 PandaNode *parent = parents.get_parent(i);
03321 if (parent->find_node_above(node)) {
03322 return true;
03323 }
03324 }
03325
03326 return false;
03327 }
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340 PT(NodePathComponent) PandaNode::
03341 attach(NodePathComponent *parent, PandaNode *child_node, int sort,
03342 int pipeline_stage, Thread *current_thread) {
03343 if (parent == (NodePathComponent *)NULL) {
03344
03345
03346 PT(NodePathComponent) child =
03347 new NodePathComponent(child_node, (NodePathComponent *)NULL,
03348 pipeline_stage, current_thread);
03349 LightReMutexHolder holder(child_node->_paths_lock);
03350 child_node->_paths.insert(child);
03351 return child;
03352 }
03353
03354
03355
03356 PT(NodePathComponent) child = get_component(parent, child_node, pipeline_stage, current_thread);
03357
03358 if (child == (NodePathComponent *)NULL) {
03359
03360
03361 child = get_top_component(child_node, true, pipeline_stage, current_thread);
03362 }
03363
03364 reparent(parent, child, sort, false, pipeline_stage, current_thread);
03365
03366 return child;
03367 }
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377 void PandaNode::
03378 detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread) {
03379 nassertv(child != (NodePathComponent *)NULL);
03380
03381 for (int pipeline_stage_i = pipeline_stage;
03382 pipeline_stage_i >= 0;
03383 --pipeline_stage_i) {
03384 detach_one_stage(child, pipeline_stage_i, current_thread);
03385 }
03386
03387 child->get_node()->parents_changed();
03388 }
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399 void PandaNode::
03400 detach_one_stage(NodePathComponent *child, int pipeline_stage,
03401 Thread *current_thread) {
03402 nassertv(child != (NodePathComponent *)NULL);
03403 if (child->is_top_node(pipeline_stage, current_thread)) {
03404 return;
03405 }
03406
03407 PT(PandaNode) child_node = child->get_node();
03408 PT(PandaNode) parent_node = child->get_next(pipeline_stage, current_thread)->get_node();
03409
03410 CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
03411 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03412 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03413 if (parent_index >= 0) {
03414
03415
03416
03417
03418 int num_erased = cdata_child->modify_up()->erase(UpConnection(parent_node));
03419 nassertv(num_erased == 1);
03420
03421
03422
03423
03424 Down::iterator di;
03425 bool found = false;
03426 PT(Down) down = cdata_parent->modify_down();
03427 for (di = down->begin(); di != down->end(); ++di) {
03428 if ((*di).get_child() == child_node) {
03429 down->erase(di);
03430 found = true;
03431 break;
03432 }
03433 }
03434 if (!found) {
03435 PT(Down) stashed = cdata_parent->modify_stashed();
03436 for (di = stashed->begin(); di != stashed->end(); ++di) {
03437 if ((*di).get_child() == child_node) {
03438 stashed->erase(di);
03439 found = true;
03440 break;
03441 }
03442 }
03443 }
03444 nassertv(found);
03445 }
03446
03447
03448 sever_connection(parent_node, child_node, pipeline_stage, current_thread);
03449
03450 parent_node->force_bounds_stale(pipeline_stage, current_thread);
03451 parent_node->children_changed();
03452 parent_node->mark_bam_modified();
03453 }
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467 bool PandaNode::
03468 reparent(NodePathComponent *new_parent, NodePathComponent *child, int sort,
03469 bool as_stashed, int pipeline_stage, Thread *current_thread) {
03470 bool any_ok = false;
03471
03472 if (new_parent != (NodePathComponent *)NULL &&
03473 !new_parent->get_node()->verify_child_no_cycles(child->get_node())) {
03474
03475
03476 return false;
03477 }
03478
03479 for (int pipeline_stage_i = pipeline_stage;
03480 pipeline_stage_i >= 0;
03481 --pipeline_stage_i) {
03482 if (reparent_one_stage(new_parent, child, sort, as_stashed,
03483 pipeline_stage_i, current_thread)) {
03484 any_ok = true;
03485 }
03486 }
03487
03488 if (new_parent != (NodePathComponent *)NULL) {
03489 new_parent->get_node()->children_changed();
03490 new_parent->get_node()->mark_bam_modified();
03491 }
03492 child->get_node()->parents_changed();
03493 child->get_node()->mark_bam_modified();
03494
03495 return any_ok;
03496 }
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511 bool PandaNode::
03512 reparent_one_stage(NodePathComponent *new_parent, NodePathComponent *child,
03513 int sort, bool as_stashed, int pipeline_stage,
03514 Thread *current_thread) {
03515 nassertr(child != (NodePathComponent *)NULL, false);
03516
03517
03518
03519 PT(NodePathComponent) keep_parent = new_parent;
03520
03521 if (!child->is_top_node(pipeline_stage, current_thread)) {
03522 detach(child, pipeline_stage, current_thread);
03523 }
03524
03525 if (new_parent != (NodePathComponent *)NULL) {
03526 PandaNode *child_node = child->get_node();
03527 PandaNode *parent_node = new_parent->get_node();
03528
03529 {
03530 CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03531 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03532
03533 if (parent_index >= 0) {
03534
03535 return false;
03536 }
03537 }
03538
03539
03540 child->set_next(new_parent, pipeline_stage, current_thread);
03541
03542
03543 {
03544 CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
03545 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03546
03547 if (as_stashed) {
03548 cdata_parent->modify_stashed()->insert(DownConnection(child_node, sort));
03549 } else {
03550 cdata_parent->modify_down()->insert(DownConnection(child_node, sort));
03551 }
03552 cdata_child->modify_up()->insert(UpConnection(parent_node));
03553
03554 #ifndef NDEBUG
03555
03556 {
03557 LightReMutexHolder holder(child_node->_paths_lock);
03558 nassertr(child_node->_paths.find(child) != child_node->_paths.end(), false);
03559 }
03560 #endif // NDEBUG
03561 }
03562
03563 child_node->fix_path_lengths(pipeline_stage, current_thread);
03564 parent_node->force_bounds_stale(pipeline_stage, current_thread);
03565 }
03566
03567 return true;
03568 }
03569
03570
03571
03572
03573
03574
03575
03576
03577 PT(NodePathComponent) PandaNode::
03578 get_component(NodePathComponent *parent, PandaNode *child_node,
03579 int pipeline_stage, Thread *current_thread) {
03580 nassertr(parent != (NodePathComponent *)NULL, (NodePathComponent *)NULL);
03581 PandaNode *parent_node = parent->get_node();
03582
03583 LightReMutexHolder holder(child_node->_paths_lock);
03584
03585
03586
03587
03588 Paths::const_iterator pi;
03589 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03590 if ((*pi)->get_next(pipeline_stage, current_thread) == parent) {
03591
03592 return (*pi);
03593 }
03594 }
03595
03596
03597
03598 CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03599 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03600
03601 if (parent_index >= 0) {
03602
03603 PT(NodePathComponent) child =
03604 new NodePathComponent(child_node, parent, pipeline_stage, current_thread);
03605 child_node->_paths.insert(child);
03606 return child;
03607 } else {
03608
03609 return NULL;
03610 }
03611 }
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627 PT(NodePathComponent) PandaNode::
03628 get_top_component(PandaNode *child_node, bool force, int pipeline_stage,
03629 Thread *current_thread) {
03630 LightReMutexHolder holder(child_node->_paths_lock);
03631
03632
03633
03634 Paths::const_iterator pi;
03635 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03636 if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
03637
03638 return (*pi);
03639 }
03640 }
03641
03642 if (!force) {
03643
03644
03645 return NULL;
03646 }
03647
03648
03649
03650 PT(NodePathComponent) child =
03651 new NodePathComponent(child_node, (NodePathComponent *)NULL,
03652 pipeline_stage, current_thread);
03653 child_node->_paths.insert(child);
03654
03655 return child;
03656 }
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669 PT(NodePathComponent) PandaNode::
03670 get_generic_component(bool accept_ambiguity, int pipeline_stage,
03671 Thread *current_thread) {
03672 bool ambiguity_detected = false;
03673 PT(NodePathComponent) result =
03674 r_get_generic_component(accept_ambiguity, ambiguity_detected,
03675 pipeline_stage, current_thread);
03676
03677 if (!accept_ambiguity && ambiguity_detected) {
03678 pgraph_cat.warning()
03679 << "Chose: " << *result << "\n";
03680 nassertr(!unambiguous_graph, result);
03681 }
03682
03683 return result;
03684 }
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694 PT(NodePathComponent) PandaNode::
03695 r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected,
03696 int pipeline_stage, Thread *current_thread) {
03697 PT(PandaNode) parent_node;
03698
03699 {
03700 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
03701
03702 int num_parents = cdata->get_up()->size();
03703 if (num_parents == 0) {
03704
03705 return get_top_component(this, true, pipeline_stage, current_thread);
03706 }
03707
03708 PT(NodePathComponent) result;
03709 if (num_parents == 1) {
03710
03711 PT(NodePathComponent) parent =
03712 get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
03713 return get_component(parent, this, pipeline_stage, current_thread);
03714 }
03715
03716
03717 if (!accept_ambiguity) {
03718 pgraph_cat.warning()
03719 << *this << " has " << num_parents
03720 << " parents; choosing arbitrary path to root.\n";
03721 }
03722 ambiguity_detected = true;
03723 CPT(Up) up = cdata->get_up();
03724 parent_node = (*up)[0].get_parent();
03725 }
03726
03727
03728 PT(NodePathComponent) parent =
03729 parent_node->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
03730 return get_component(parent, this, pipeline_stage, current_thread);
03731 }
03732
03733
03734
03735
03736
03737
03738
03739
03740 void PandaNode::
03741 delete_component(NodePathComponent *component) {
03742 LightReMutexHolder holder(_paths_lock);
03743 int num_erased = _paths.erase(component);
03744 nassertv(num_erased == 1);
03745 }
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765 void PandaNode::
03766 sever_connection(PandaNode *parent_node, PandaNode *child_node,
03767 int pipeline_stage, Thread *current_thread) {
03768 {
03769 LightReMutexHolder holder(child_node->_paths_lock);
03770 Paths::iterator pi;
03771 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03772 if (!(*pi)->is_top_node(pipeline_stage, current_thread) &&
03773 (*pi)->get_next(pipeline_stage, current_thread)->get_node() == parent_node) {
03774
03775 (*pi)->set_top_node(pipeline_stage, current_thread);
03776 }
03777 }
03778 }
03779 child_node->fix_path_lengths(pipeline_stage, current_thread);
03780 }
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798 void PandaNode::
03799 new_connection(PandaNode *parent_node, PandaNode *child_node,
03800 int pipeline_stage, Thread *current_thread) {
03801 {
03802 LightReMutexHolder holder(child_node->_paths_lock);
03803 Paths::iterator pi;
03804 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03805 if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
03806 (*pi)->set_next(parent_node->get_generic_component(false, pipeline_stage, current_thread), pipeline_stage, current_thread);
03807 }
03808 }
03809 }
03810 child_node->fix_path_lengths(pipeline_stage, current_thread);
03811 }
03812
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825 void PandaNode::
03826 fix_path_lengths(int pipeline_stage, Thread *current_thread) {
03827 LightReMutexHolder holder(_paths_lock);
03828
03829 bool any_wrong = false;
03830
03831 Paths::const_iterator pi;
03832 for (pi = _paths.begin(); pi != _paths.end(); ++pi) {
03833 if ((*pi)->fix_length(pipeline_stage, current_thread)) {
03834 any_wrong = true;
03835 }
03836 }
03837
03838
03839
03840
03841 if (any_wrong) {
03842 Children children;
03843 Stashed stashed;
03844 {
03845 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
03846 children = Children(cdata);
03847 stashed = Stashed(cdata);
03848 }
03849
03850 int num_children = children.get_num_children();
03851 int i;
03852 for (i = 0; i < num_children; ++i) {
03853 PandaNode *child_node = children.get_child(i);
03854 child_node->fix_path_lengths(pipeline_stage, current_thread);
03855 }
03856 int num_stashed = stashed.get_num_stashed();
03857 for (i = 0; i < num_stashed; ++i) {
03858 PandaNode *child_node = stashed.get_stashed(i);
03859 child_node->fix_path_lengths(pipeline_stage, current_thread);
03860 }
03861 }
03862 }
03863
03864
03865
03866
03867
03868
03869 void PandaNode::
03870 r_list_descendants(ostream &out, int indent_level) const {
03871 write(out, indent_level);
03872
03873 Children children = get_children();
03874 int num_children = children.get_num_children();
03875
03876 for (int i = 0; i < num_children; ++i) {
03877 PandaNode *child = children.get_child(i);
03878 child->r_list_descendants(out, indent_level + 2);
03879 }
03880
03881
03882 int num_stashed = get_num_stashed();
03883 if (num_stashed != 0) {
03884 indent(out, indent_level) << "(" << num_stashed << " stashed)\n";
03885 }
03886 }
03887
03888
03889
03890
03891
03892
03893 int PandaNode::
03894 do_find_child(PandaNode *node, const PandaNode::Down *down) const {
03895 nassertr(node != (PandaNode *)NULL, -1);
03896
03897
03898
03899 Down::const_iterator di;
03900 for (di = down->begin(); di != down->end(); ++di) {
03901 if ((*di).get_child() == node) {
03902 return di - down->begin();
03903 }
03904 }
03905
03906 return -1;
03907 }
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920 PandaNode::CDStageWriter PandaNode::
03921 update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
03922
03923
03924 if (drawmask_cat.is_debug()) {
03925 drawmask_cat.debug(false)
03926 << *this << "::update_bounds() {\n";
03927 }
03928 Thread *current_thread = cdata.get_current_thread();
03929
03930 do {
03931
03932 UpdateSeq last_update = cdata->_last_update;
03933 UpdateSeq next_update = cdata->_next_update;
03934 nassertr(last_update != next_update, CDStageWriter(_cycler, pipeline_stage, cdata));
03935
03936
03937 CollideMask net_collide_mask = cdata->_into_collide_mask;
03938 DrawMask net_draw_control_mask, net_draw_show_mask;
03939 bool renderable = is_renderable();
03940
03941 if (renderable) {
03942
03943
03944 net_draw_control_mask = cdata->_draw_control_mask;
03945 net_draw_show_mask = cdata->_draw_show_mask;
03946 }
03947
03948 if (drawmask_cat.is_debug()) {
03949 drawmask_cat.debug(false)
03950 << "net_draw_control_mask = " << net_draw_control_mask
03951 << "\nnet_draw_show_mask = " << net_draw_show_mask
03952 << "\n";
03953 }
03954 CPT(RenderAttrib) off_clip_planes = cdata->_state->get_attrib(ClipPlaneAttrib::get_class_slot());
03955 if (off_clip_planes == (RenderAttrib *)NULL) {
03956 off_clip_planes = ClipPlaneAttrib::make();
03957 }
03958
03959
03960 Children children(cdata);
03961
03962 int num_vertices = cdata->_internal_vertices;
03963
03964
03965
03966 _cycler.release_read_stage(pipeline_stage, cdata.take_pointer());
03967
03968 int num_children = children.get_num_children();
03969
03970
03971
03972
03973
03974
03975 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
03976 pvector<CPT(BoundingVolume) > child_volumes_ref;
03977 child_volumes_ref.reserve(num_children + 1);
03978 #endif
03979 const BoundingVolume **child_volumes = (const BoundingVolume **)alloca(sizeof(BoundingVolume *) * (num_children + 1));
03980 int child_volumes_i = 0;
03981
03982 bool all_box = true;
03983 CPT(BoundingVolume) internal_bounds =
03984 get_internal_bounds(pipeline_stage, current_thread);
03985
03986 if (!internal_bounds->is_empty()) {
03987 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
03988 child_volumes_ref.push_back(internal_bounds);
03989 #endif
03990 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
03991 child_volumes[child_volumes_i++] = internal_bounds;
03992 if (internal_bounds->as_bounding_box() == NULL) {
03993 all_box = false;
03994 }
03995 }
03996
03997
03998
03999 for (int i = 0; i < num_children; ++i) {
04000 PandaNode *child = children.get_child(i);
04001
04002 const ClipPlaneAttrib *orig_cp = DCAST(ClipPlaneAttrib, off_clip_planes);
04003
04004 CDLockedStageReader child_cdata(child->_cycler, pipeline_stage, current_thread);
04005 if (child_cdata->_last_update != child_cdata->_next_update) {
04006
04007 CDStageWriter child_cdataw = child->update_bounds(pipeline_stage, child_cdata);
04008
04009 net_collide_mask |= child_cdataw->_net_collide_mask;
04010
04011 if (drawmask_cat.is_debug()) {
04012 drawmask_cat.debug(false)
04013 << "\nchild update " << *child << ":\n";
04014 }
04015
04016 DrawMask child_control_mask = child_cdataw->_net_draw_control_mask;
04017 DrawMask child_show_mask = child_cdataw->_net_draw_show_mask;
04018 if (!(child_control_mask | child_show_mask).is_zero()) {
04019
04020
04021 renderable = true;
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052
04053
04054
04055 DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
04056 exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
04057
04058 if (drawmask_cat.is_debug()) {
04059 drawmask_cat.debug(false)
04060 << "exception_mask = " << exception_mask << "\n";
04061 }
04062
04063
04064 net_draw_control_mask |= child_control_mask;
04065 net_draw_show_mask |= child_show_mask;
04066
04067 net_draw_control_mask &= ~exception_mask;
04068 net_draw_show_mask |= exception_mask;
04069 }
04070
04071 if (drawmask_cat.is_debug()) {
04072 drawmask_cat.debug(false)
04073 << "child_control_mask = " << child_control_mask
04074 << "\nchild_show_mask = " << child_show_mask
04075 << "\nnet_draw_control_mask = " << net_draw_control_mask
04076 << "\nnet_draw_show_mask = " << net_draw_show_mask
04077 << "\n";
04078 }
04079
04080 off_clip_planes = orig_cp->compose_off(child_cdataw->_off_clip_planes);
04081 if (!child_cdataw->_external_bounds->is_empty()) {
04082 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04083 child_volumes_ref.push_back(child_cdataw->_external_bounds);
04084 #endif
04085 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04086 child_volumes[child_volumes_i++] = child_cdataw->_external_bounds;
04087 if (child_cdataw->_external_bounds->as_bounding_box() == NULL) {
04088 all_box = false;
04089 }
04090 }
04091 num_vertices += child_cdataw->_nested_vertices;
04092
04093 } else {
04094
04095 net_collide_mask |= child_cdata->_net_collide_mask;
04096
04097
04098 if (drawmask_cat.is_debug()) {
04099 drawmask_cat.debug(false)
04100 << "\nchild fresh " << *child << ":\n";
04101 }
04102 DrawMask child_control_mask = child_cdata->_net_draw_control_mask;
04103 DrawMask child_show_mask = child_cdata->_net_draw_show_mask;
04104 if (!(child_control_mask | child_show_mask).is_zero()) {
04105 renderable = true;
04106
04107 DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
04108 exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
04109
04110 if (drawmask_cat.is_debug()) {
04111 drawmask_cat.debug(false)
04112 << "exception_mask = " << exception_mask << "\n";
04113 }
04114
04115
04116 net_draw_control_mask |= child_control_mask;
04117 net_draw_show_mask |= child_show_mask;
04118
04119 net_draw_control_mask &= ~exception_mask;
04120 net_draw_show_mask |= exception_mask;
04121 }
04122
04123 if (drawmask_cat.is_debug()) {
04124 drawmask_cat.debug(false)
04125 << "child_control_mask = " << child_control_mask
04126 << "\nchild_show_mask = " << child_show_mask
04127 << "\nnet_draw_control_mask = " << net_draw_control_mask
04128 << "\nnet_draw_show_mask = " << net_draw_show_mask
04129 << "\n";
04130 }
04131
04132 off_clip_planes = orig_cp->compose_off(child_cdata->_off_clip_planes);
04133 if (!child_cdata->_external_bounds->is_empty()) {
04134 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04135 child_volumes_ref.push_back(child_cdata->_external_bounds);
04136 #endif
04137 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04138 child_volumes[child_volumes_i++] = child_cdata->_external_bounds;
04139 if (child_cdata->_external_bounds->as_bounding_box() == NULL) {
04140 all_box = false;
04141 }
04142 }
04143 num_vertices += child_cdata->_nested_vertices;
04144 }
04145 }
04146
04147 {
04148
04149 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
04150 if (last_update == cdataw->_last_update &&
04151 next_update == cdataw->_next_update) {
04152
04153
04154 cdataw->_net_collide_mask = net_collide_mask;
04155
04156 if (renderable) {
04157
04158
04159 DrawMask draw_control_mask = cdataw->_draw_control_mask;
04160 DrawMask draw_show_mask = cdataw->_draw_show_mask;
04161
04162 DrawMask show_through_mask = net_draw_control_mask & net_draw_show_mask;
04163
04164 net_draw_control_mask |= draw_control_mask;
04165 net_draw_show_mask = (net_draw_show_mask & ~draw_control_mask) | (draw_show_mask & draw_control_mask);
04166
04167 net_draw_show_mask |= show_through_mask;
04168
04169
04170
04171 cdataw->_net_draw_control_mask = net_draw_control_mask;
04172 cdataw->_net_draw_show_mask = net_draw_show_mask | ~net_draw_control_mask;
04173 if (drawmask_cat.is_debug()) {
04174 drawmask_cat.debug(false)
04175 << "renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
04176 }
04177 } else {
04178
04179
04180
04181
04182 cdataw->_net_draw_control_mask = net_draw_control_mask;
04183 cdataw->_net_draw_show_mask = net_draw_show_mask;
04184 if (drawmask_cat.is_debug()) {
04185 drawmask_cat.debug(false)
04186 << "not renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
04187 }
04188 }
04189
04190 cdataw->_off_clip_planes = off_clip_planes;
04191 cdataw->_nested_vertices = num_vertices;
04192
04193 CPT(TransformState) transform = get_transform(current_thread);
04194 PT(GeometricBoundingVolume) gbv;
04195
04196 BoundingVolume::BoundsType btype = cdataw->_bounds_type;
04197 if (btype == BoundingVolume::BT_default) {
04198 btype = bounds_type;
04199 }
04200
04201 if (btype == BoundingVolume::BT_box ||
04202 (btype != BoundingVolume::BT_sphere && all_box && transform->is_identity())) {
04203
04204
04205
04206
04207 gbv = new BoundingBox;
04208 } else {
04209
04210 gbv = new BoundingSphere;
04211 }
04212
04213 if (child_volumes_i > 0) {
04214 const BoundingVolume **child_begin = &child_volumes[0];
04215 const BoundingVolume **child_end = child_begin + child_volumes_i;
04216 ((BoundingVolume *)gbv)->around(child_begin, child_end);
04217 }
04218
04219
04220
04221 if (!transform->is_identity()) {
04222 gbv->xform(transform->get_mat());
04223 }
04224
04225 cdataw->_external_bounds = gbv;
04226 cdataw->_last_update = next_update;
04227
04228 if (drawmask_cat.is_debug()) {
04229 drawmask_cat.debug(false)
04230 << "} " << *this << "::update_bounds();\n";
04231 }
04232
04233 nassertr(cdataw->_last_update == cdataw->_next_update, cdataw);
04234
04235
04236
04237 mark_bam_modified();
04238 return cdataw;
04239 }
04240
04241 if (cdataw->_last_update == cdataw->_next_update) {
04242
04243 return cdataw;
04244 }
04245 }
04246
04247
04248
04249 cdata = CDLockedStageReader(_cycler, pipeline_stage, current_thread);
04250
04251 if (cdata->_last_update == cdata->_next_update) {
04252
04253
04254 return CDStageWriter(_cycler, pipeline_stage, cdata);
04255 }
04256
04257 } while (true);
04258 }
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270 void PandaNode::
04271 set_scene_root_func(SceneRootFunc *func) {
04272 _scene_root_func = func;
04273 }
04274
04275
04276
04277
04278
04279
04280
04281 void PandaNode::
04282 register_with_read_factory() {
04283 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
04284 }
04285
04286
04287
04288
04289
04290
04291
04292 void PandaNode::
04293 write_datagram(BamWriter *manager, Datagram &dg) {
04294 TypedWritable::write_datagram(manager, dg);
04295 dg.add_string(get_name());
04296
04297 manager->write_cdata(dg, _cycler);
04298 }
04299
04300
04301
04302
04303
04304
04305
04306
04307 void PandaNode::
04308 update_bam_nested(BamWriter *manager) {
04309 CDReader cdata(_cycler);
04310 cdata->update_bam_nested(manager);
04311 }
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329 void PandaNode::
04330 write_recorder(BamWriter *, Datagram &dg) {
04331 dg.add_string(get_name());
04332 }
04333
04334
04335
04336
04337
04338
04339
04340
04341
04342 TypedWritable *PandaNode::
04343 make_from_bam(const FactoryParams ¶ms) {
04344 PandaNode *node = new PandaNode("");
04345 DatagramIterator scan;
04346 BamReader *manager;
04347
04348 parse_params(params, scan, manager);
04349 node->fillin(scan, manager);
04350
04351 return node;
04352 }
04353
04354
04355
04356
04357
04358
04359
04360
04361 void PandaNode::
04362 fillin(DatagramIterator &scan, BamReader *manager) {
04363 TypedWritable::fillin(scan, manager);
04364
04365 string name = scan.get_string();
04366 set_name(name);
04367
04368 manager->read_cdata(scan, _cycler);
04369 }
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380 void PandaNode::
04381 fillin_recorder(DatagramIterator &scan, BamReader *) {
04382 string name = scan.get_string();
04383 set_name(name);
04384 }
04385
04386
04387
04388
04389
04390
04391 PandaNode::CData::
04392 CData() :
04393 _state(RenderState::make_empty()),
04394 _transform(TransformState::make_identity()),
04395 _prev_transform(TransformState::make_identity()),
04396
04397 _effects(RenderEffects::make_empty()),
04398 _draw_control_mask(DrawMask::all_off()),
04399 _draw_show_mask(DrawMask::all_on()),
04400 _into_collide_mask(CollideMask::all_off()),
04401 _bounds_type(BoundingVolume::BT_default),
04402 _user_bounds(NULL),
04403 _final_bounds(false),
04404 _fancy_bits(0),
04405
04406 _net_collide_mask(CollideMask::all_off()),
04407 _net_draw_control_mask(DrawMask::all_off()),
04408 _net_draw_show_mask(DrawMask::all_off()),
04409
04410 _down(new PandaNode::Down(PandaNode::get_class_type())),
04411 _stashed(new PandaNode::Down(PandaNode::get_class_type())),
04412 _up(new PandaNode::Up(PandaNode::get_class_type()))
04413 {
04414 ++_next_update;
04415 }
04416
04417
04418
04419
04420
04421
04422 PandaNode::CData::
04423 CData(const PandaNode::CData ©) :
04424 BoundsData(copy),
04425 _state(copy._state),
04426 _transform(copy._transform),
04427 _prev_transform(copy._prev_transform),
04428
04429 _effects(copy._effects),
04430 _tag_data(copy._tag_data),
04431
04432 _draw_control_mask(copy._draw_control_mask),
04433 _draw_show_mask(copy._draw_show_mask),
04434 _into_collide_mask(copy._into_collide_mask),
04435 _bounds_type(copy._bounds_type),
04436 _user_bounds(copy._user_bounds),
04437 _final_bounds(copy._final_bounds),
04438 _fancy_bits(copy._fancy_bits),
04439
04440 _net_collide_mask(copy._net_collide_mask),
04441 _net_draw_control_mask(copy._net_draw_control_mask),
04442 _net_draw_show_mask(copy._net_draw_show_mask),
04443 _off_clip_planes(copy._off_clip_planes),
04444 _nested_vertices(copy._nested_vertices),
04445 _external_bounds(copy._external_bounds),
04446 _last_update(copy._last_update),
04447 _next_update(copy._next_update),
04448
04449 _down(copy._down),
04450 _stashed(copy._stashed),
04451 _up(copy._up)
04452 {
04453
04454
04455
04456
04457 #ifdef HAVE_PYTHON
04458
04459
04460 _python_tag_data = copy._python_tag_data;
04461 inc_py_refs();
04462 #endif // HAVE_PYTHON
04463 }
04464
04465
04466
04467
04468
04469
04470 PandaNode::CData::
04471 ~CData() {
04472 #ifdef HAVE_PYTHON
04473
04474 dec_py_refs();
04475 #endif // HAVE_PYTHON
04476 }
04477
04478
04479
04480
04481
04482
04483 CycleData *PandaNode::CData::
04484 make_copy() const {
04485 return new CData(*this);
04486 }
04487
04488
04489
04490
04491
04492
04493
04494 void PandaNode::CData::
04495 write_datagram(BamWriter *manager, Datagram &dg) const {
04496 manager->write_pointer(dg, _state);
04497 manager->write_pointer(dg, _transform);
04498
04499
04500 manager->write_pointer(dg, _effects);
04501
04502 dg.add_uint32(_draw_control_mask.get_word());
04503 dg.add_uint32(_draw_show_mask.get_word());
04504 dg.add_uint32(_into_collide_mask.get_word());
04505 dg.add_uint8(_bounds_type);
04506
04507 dg.add_uint32(_tag_data.size());
04508 TagData::const_iterator ti;
04509 for (ti = _tag_data.begin(); ti != _tag_data.end(); ++ti) {
04510 dg.add_string((*ti).first);
04511 dg.add_string((*ti).second);
04512 }
04513
04514
04515 write_up_list(*get_up(), manager, dg);
04516 write_down_list(*get_down(), manager, dg);
04517 write_down_list(*get_stashed(), manager, dg);
04518 }
04519
04520
04521
04522
04523
04524
04525
04526
04527 void PandaNode::CData::
04528 update_bam_nested(BamWriter *manager) const {
04529
04530
04531
04532
04533
04534
04535 update_up_list(*get_up(), manager);
04536 update_down_list(*get_down(), manager);
04537 update_down_list(*get_stashed(), manager);
04538 }
04539
04540
04541
04542
04543
04544
04545
04546
04547 int PandaNode::CData::
04548 complete_pointers(TypedWritable **p_list, BamReader *manager) {
04549 int pi = CycleData::complete_pointers(p_list, manager);
04550
04551
04552 _state = DCAST(RenderState, p_list[pi++]);
04553 _transform = DCAST(TransformState, p_list[pi++]);
04554 _prev_transform = _transform;
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564 manager->finalize_now((RenderState *)_state.p());
04565 manager->finalize_now((TransformState *)_transform.p());
04566
04567
04568
04569
04570 _effects = DCAST(RenderEffects, p_list[pi++]);
04571
04572
04573
04574
04575
04576
04577
04578
04579
04580 manager->finalize_now((RenderEffects *)_effects.p());
04581
04582
04583
04584
04585 pi += complete_up_list(*modify_up(), "up", p_list + pi, manager);
04586 pi += complete_down_list(*modify_down(), "down", p_list + pi, manager);
04587 pi += complete_down_list(*modify_stashed(), "stashed", p_list + pi, manager);
04588
04589
04590
04591 set_fancy_bit(FB_transform, !_transform->is_identity());
04592 set_fancy_bit(FB_state, !_state->is_empty());
04593 set_fancy_bit(FB_effects, !_effects->is_empty());
04594 set_fancy_bit(FB_tag, !_tag_data.empty());
04595
04596 return pi;
04597 }
04598
04599
04600
04601
04602
04603
04604
04605
04606 void PandaNode::CData::
04607 fillin(DatagramIterator &scan, BamReader *manager) {
04608
04609 manager->read_pointer(scan);
04610 manager->read_pointer(scan);
04611
04612
04613
04614 manager->read_pointer(scan);
04615
04616 if (manager->get_file_minor_ver() < 2) {
04617 DrawMask draw_mask;
04618 draw_mask.set_word(scan.get_uint32());
04619
04620 if (draw_mask == DrawMask::all_off()) {
04621
04622 _draw_control_mask = _overall_bit;
04623 _draw_show_mask = ~_overall_bit;
04624
04625 } else if (draw_mask == DrawMask::all_on()) {
04626
04627 _draw_control_mask = DrawMask::all_off();
04628 _draw_show_mask = DrawMask::all_on();
04629
04630 } else {
04631
04632 draw_mask &= ~_overall_bit;
04633 _draw_control_mask = ~draw_mask;
04634 _draw_show_mask = draw_mask;
04635 }
04636
04637 } else {
04638 _draw_control_mask.set_word(scan.get_uint32());
04639 _draw_show_mask.set_word(scan.get_uint32());
04640 }
04641
04642 _into_collide_mask.set_word(scan.get_uint32());
04643
04644 _bounds_type = BoundingVolume::BT_default;
04645 if (manager->get_file_minor_ver() >= 19) {
04646 _bounds_type = (BoundingVolume::BoundsType)scan.get_uint8();
04647 }
04648
04649
04650 int num_tags = scan.get_uint32();
04651 for (int i = 0; i < num_tags; i++) {
04652 string key = scan.get_string();
04653 string value = scan.get_string();
04654 _tag_data[key] = value;
04655 }
04656
04657
04658 fillin_up_list(*modify_up(), "up", scan, manager);
04659 fillin_down_list(*modify_down(), "down", scan, manager);
04660 fillin_down_list(*modify_stashed(), "stashed", scan, manager);
04661 }
04662
04663 #ifdef HAVE_PYTHON
04664
04665
04666
04667
04668
04669
04670 void PandaNode::CData::
04671 inc_py_refs() {
04672 if (!_python_tag_data.empty()) {
04673 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04674
04675
04676 PyGILState_STATE gstate;
04677 gstate = PyGILState_Ensure();
04678 #endif
04679 PythonTagData::const_iterator ti;
04680 for (ti = _python_tag_data.begin();
04681 ti != _python_tag_data.end();
04682 ++ti) {
04683 PyObject *value = (*ti).second;
04684 Py_XINCREF(value);
04685 }
04686 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04687 PyGILState_Release(gstate);
04688 #endif
04689 }
04690 }
04691 #endif // HAVE_PYTHON
04692
04693 #ifdef HAVE_PYTHON
04694
04695
04696
04697
04698
04699
04700 void PandaNode::CData::
04701 dec_py_refs() {
04702 if (!_python_tag_data.empty()) {
04703 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04704
04705
04706 PyGILState_STATE gstate;
04707 gstate = PyGILState_Ensure();
04708 #endif
04709
04710 PythonTagData::const_iterator ti;
04711 for (ti = _python_tag_data.begin();
04712 ti != _python_tag_data.end();
04713 ++ti) {
04714 PyObject *value = (*ti).second;
04715 Py_XDECREF(value);
04716 }
04717
04718 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04719 PyGILState_Release(gstate);
04720 #endif
04721 }
04722 }
04723 #endif // HAVE_PYTHON
04724
04725
04726
04727
04728
04729
04730
04731 void PandaNode::CData::
04732 write_up_list(const PandaNode::Up &up_list,
04733 BamWriter *manager, Datagram &dg) const {
04734
04735
04736
04737
04738
04739
04740
04741
04742
04743 int num_parents = 0;
04744 Up::const_iterator ui;
04745 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04746 PandaNode *parent_node = (*ui).get_parent();
04747 if (manager->has_object(parent_node)) {
04748 num_parents++;
04749 }
04750 }
04751 nassertv(num_parents == (int)(PN_uint16)num_parents);
04752 dg.add_uint16(num_parents);
04753 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04754 PandaNode *parent_node = (*ui).get_parent();
04755 if (manager->has_object(parent_node)) {
04756 manager->write_pointer(dg, parent_node);
04757 }
04758 }
04759 }
04760
04761
04762
04763
04764
04765
04766
04767 void PandaNode::CData::
04768 write_down_list(const PandaNode::Down &down_list,
04769 BamWriter *manager, Datagram &dg) const {
04770 int num_children = down_list.size();
04771 nassertv(num_children == (int)(PN_uint16)num_children);
04772 dg.add_uint16(num_children);
04773
04774
04775
04776 Down::const_iterator di;
04777 for (di = down_list.begin(); di != down_list.end(); ++di) {
04778 PandaNode *child_node = (*di).get_child();
04779 int sort = (*di).get_sort();
04780 manager->write_pointer(dg, child_node);
04781 dg.add_int32(sort);
04782 }
04783 }
04784
04785
04786
04787
04788
04789
04790
04791 void PandaNode::CData::
04792 update_up_list(const PandaNode::Up &up_list, BamWriter *manager) const {
04793 Up::const_iterator ui;
04794 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04795 PandaNode *parent_node = (*ui).get_parent();
04796 if (manager->has_object(parent_node)) {
04797 manager->consider_update(parent_node);
04798 }
04799 }
04800 }
04801
04802
04803
04804
04805
04806
04807
04808 void PandaNode::CData::
04809 update_down_list(const PandaNode::Down &down_list, BamWriter *manager) const {
04810 Down::const_iterator di;
04811 for (di = down_list.begin(); di != down_list.end(); ++di) {
04812 PandaNode *child_node = (*di).get_child();
04813 manager->consider_update(child_node);
04814 }
04815 }
04816
04817
04818
04819
04820
04821
04822
04823 int PandaNode::CData::
04824 complete_up_list(PandaNode::Up &up_list, const string &tag,
04825 TypedWritable **p_list, BamReader *manager) {
04826 int pi = 0;
04827
04828 int num_parents = manager->get_int_tag(tag);
04829 Up new_up_list(PandaNode::get_class_type());
04830 new_up_list.reserve(num_parents);
04831 for (int i = 0; i < num_parents; i++) {
04832 PandaNode *parent_node = DCAST(PandaNode, p_list[pi++]);
04833 UpConnection connection(parent_node);
04834 new_up_list.push_back(connection);
04835 }
04836
04837
04838
04839
04840 new_up_list.sort();
04841
04842
04843 up_list.swap(new_up_list);
04844 new_up_list.clear();
04845
04846 return pi;
04847 }
04848
04849
04850
04851
04852
04853
04854
04855 int PandaNode::CData::
04856 complete_down_list(PandaNode::Down &down_list, const string &tag,
04857 TypedWritable **p_list, BamReader *manager) {
04858 int pi = 0;
04859
04860 BamReaderAuxDataDown *aux;
04861 DCAST_INTO_R(aux, manager->get_aux_tag(tag), pi);
04862
04863 Down &new_down_list = aux->_down_list;
04864 for (Down::iterator di = new_down_list.begin();
04865 di != new_down_list.end();
04866 ++di) {
04867 PandaNode *child_node = DCAST(PandaNode, p_list[pi++]);
04868 (*di).set_child(child_node);
04869 }
04870
04871
04872
04873
04874
04875
04876 down_list.swap(new_down_list);
04877 new_down_list.clear();
04878
04879 return pi;
04880 }
04881
04882
04883
04884
04885
04886
04887
04888
04889 void PandaNode::CData::
04890 fillin_up_list(PandaNode::Up &up_list, const string &tag,
04891 DatagramIterator &scan, BamReader *manager) {
04892 int num_parents = scan.get_uint16();
04893 manager->set_int_tag(tag, num_parents);
04894 manager->read_pointers(scan, num_parents);
04895 }
04896
04897
04898
04899
04900
04901
04902
04903
04904 void PandaNode::CData::
04905 fillin_down_list(PandaNode::Down &down_list, const string &tag,
04906 DatagramIterator &scan, BamReader *manager) {
04907 int num_children = scan.get_uint16();
04908
04909
04910
04911
04912
04913 Down new_down_list(PandaNode::get_class_type());
04914 new_down_list.reserve(num_children);
04915 for (int i = 0; i < num_children; i++) {
04916 manager->read_pointer(scan);
04917 int sort = scan.get_int32();
04918 DownConnection connection(NULL, sort);
04919 new_down_list.push_back(connection);
04920 }
04921
04922
04923
04924 PT(BamReaderAuxDataDown) aux = new BamReaderAuxDataDown;
04925 aux->_down_list.swap(new_down_list);
04926 manager->set_aux_tag(tag, aux);
04927 }
04928
04929
04930
04931
04932
04933
04934
04935 void PandaNodePipelineReader::
04936 check_bounds() const {
04937 if (_cdata->_last_update != _cdata->_next_update) {
04938
04939
04940
04941
04942
04943 #ifdef DO_PIPELINING
04944 node_unref_delete((CycleData *)_cdata);
04945 #endif // DO_PIPELINING
04946 ((PandaNodePipelineReader *)this)->_cdata = NULL;
04947 int pipeline_stage = _current_thread->get_pipeline_stage();
04948 PandaNode::CDLockedStageReader fresh_cdata(_object->_cycler, pipeline_stage, _current_thread);
04949 if (fresh_cdata->_last_update == fresh_cdata->_next_update) {
04950
04951
04952
04953 if (_cdata != (const PandaNode::CData *)fresh_cdata) {
04954 ((PandaNodePipelineReader *)this)->_cdata = fresh_cdata;
04955 #ifdef DO_PIPELINING
04956 _cdata->node_ref();
04957 #endif // DO_PIPELINING
04958 }
04959
04960 } else {
04961
04962
04963 PStatTimer timer(PandaNode::_update_bounds_pcollector);
04964 PandaNode::CDStageWriter cdataw = ((PandaNode *)_object)->update_bounds(pipeline_stage, fresh_cdata);
04965 nassertv(cdataw->_last_update == cdataw->_next_update);
04966
04967
04968 if (_cdata != (const PandaNode::CData *)cdataw) {
04969 ((PandaNodePipelineReader *)this)->_cdata = cdataw;
04970 #ifdef DO_PIPELINING
04971 _cdata->node_ref();
04972 #endif // DO_PIPELINING
04973 }
04974 }
04975 }
04976
04977 nassertv(_cdata->_last_update == _cdata->_next_update);
04978 }