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 void PandaNode::
01735 get_tag_keys(vector_string &keys) const {
01736 CDReader cdata(_cycler);
01737 if (!cdata->_tag_data.empty()) {
01738 TagData::const_iterator ti = cdata->_tag_data.begin();
01739 while (ti != cdata->_tag_data.end()) {
01740 keys.push_back((*ti).first);
01741 ++ti;
01742 }
01743 }
01744 }
01745
01746 #ifdef HAVE_PYTHON
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757 void PandaNode::
01758 get_python_tag_keys(vector_string &keys) const {
01759 CDReader cdata(_cycler);
01760 if (!cdata->_python_tag_data.empty()) {
01761 PythonTagData::const_iterator ti = cdata->_python_tag_data.begin();
01762 while (ti != cdata->_python_tag_data.end()) {
01763 keys.push_back((*ti).first);
01764 ++ti;
01765 }
01766 }
01767 }
01768
01769
01770
01771
01772
01773
01774
01775 PyObject *PandaNode::
01776 get_tag_keys() const {
01777 vector_string keys;
01778 get_tag_keys(keys);
01779
01780 PyObject *result = PyList_New(keys.size());
01781 for (size_t i = 0; i < keys.size(); ++i) {
01782 const string &tag_name = keys[i];
01783 #if PY_MAJOR_VERSION >= 3
01784 PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
01785 #else
01786 PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
01787 #endif
01788 PyList_SET_ITEM(result, i, str);
01789 }
01790
01791 return result;
01792 }
01793
01794
01795
01796
01797
01798
01799
01800 PyObject *PandaNode::
01801 get_python_tag_keys() const {
01802 vector_string keys;
01803 get_python_tag_keys(keys);
01804
01805 PyObject *result = PyList_New(keys.size());
01806 for (size_t i = 0; i < keys.size(); ++i) {
01807 const string &tag_name = keys[i];
01808 #if PY_MAJOR_VERSION >= 3
01809 PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
01810 #else
01811 PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
01812 #endif
01813 PyList_SET_ITEM(result, i, str);
01814 }
01815
01816 return result;
01817 }
01818 #endif // HAVE_PYTHON
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831 int PandaNode::
01832 compare_tags(const PandaNode *other) const {
01833 CDReader cdata(_cycler);
01834 CDReader cdata_other(other->_cycler);
01835
01836 TagData::const_iterator ati = cdata->_tag_data.begin();
01837 TagData::const_iterator bti = cdata_other->_tag_data.begin();
01838 while (ati != cdata->_tag_data.end() &&
01839 bti != cdata_other->_tag_data.end()) {
01840 int cmp = strcmp((*ati).first.c_str(), (*bti).first.c_str());
01841 if (cmp != 0) {
01842 return cmp;
01843 }
01844
01845 cmp = strcmp((*ati).second.c_str(), (*bti).second.c_str());
01846 if (cmp != 0) {
01847 return cmp;
01848 }
01849
01850 ++ati;
01851 ++bti;
01852 }
01853 if (ati != cdata->_tag_data.end()) {
01854
01855 return 1;
01856 }
01857 if (bti != cdata_other->_tag_data.end()) {
01858
01859 return -1;
01860 }
01861
01862 #ifdef HAVE_PYTHON
01863 PythonTagData::const_iterator api = cdata->_python_tag_data.begin();
01864 PythonTagData::const_iterator bpi = cdata_other->_python_tag_data.begin();
01865 while (api != cdata->_python_tag_data.end() &&
01866 bpi != cdata_other->_python_tag_data.end()) {
01867 int cmp = strcmp((*api).first.c_str(), (*bpi).first.c_str());
01868 if (cmp != 0) {
01869 return cmp;
01870 }
01871
01872 #if PY_MAJOR_VERSION >= 3
01873 if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_LT) == 1) {
01874 return -1;
01875 } else if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_GT) == 1) {
01876 return 1;
01877 } else if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_EQ) == 1) {
01878 cmp = 0;
01879 } else {
01880 #else
01881 if (PyObject_Cmp((*api).second, (*bpi).second, &cmp) == -1) {
01882 #endif
01883
01884 if ((*api).second != (*bpi).second) {
01885 cmp = (*api).second < (*bpi).second ? -1 : 1;
01886 } else {
01887 cmp = 0;
01888 }
01889 }
01890 if (cmp != 0) {
01891 return cmp;
01892 }
01893
01894 ++api;
01895 ++bpi;
01896 }
01897 if (api != cdata->_python_tag_data.end()) {
01898
01899 return 1;
01900 }
01901 if (bpi != cdata_other->_python_tag_data.end()) {
01902
01903 return -1;
01904 }
01905 #endif // HAVE_PYTHON
01906
01907 return 0;
01908 }
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919 void PandaNode::
01920 copy_all_properties(PandaNode *other) {
01921 if (other == this) {
01922
01923 return;
01924 }
01925
01926
01927 LightMutexHolder holder(_dirty_prev_transforms._lock);
01928
01929 bool any_transform_changed = false;
01930 bool any_state_changed = false;
01931 bool any_draw_mask_changed = false;
01932 Thread *current_thread = Thread::get_current_thread();
01933 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01934 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
01935 CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
01936
01937 if (cdataw->_transform != cdatar->_transform) {
01938 any_transform_changed = true;
01939 }
01940 if (cdataw->_state != cdatar->_state) {
01941 any_state_changed = true;
01942 }
01943 if (cdataw->_draw_control_mask != cdatar->_draw_control_mask ||
01944 cdataw->_draw_show_mask != cdatar->_draw_show_mask) {
01945 any_draw_mask_changed = true;
01946 }
01947
01948 cdataw->_transform = cdatar->_transform;
01949 cdataw->_prev_transform = cdatar->_prev_transform;
01950 cdataw->_state = cdatar->_state;
01951 cdataw->_effects = cdatar->_effects;
01952 cdataw->_draw_control_mask = cdatar->_draw_control_mask;
01953 cdataw->_draw_show_mask = cdatar->_draw_show_mask;
01954
01955
01956
01957
01958 cdataw->_into_collide_mask |= cdatar->_into_collide_mask;
01959
01960 TagData::const_iterator ti;
01961 for (ti = cdatar->_tag_data.begin();
01962 ti != cdatar->_tag_data.end();
01963 ++ti) {
01964 cdataw->_tag_data[(*ti).first] = (*ti).second;
01965 }
01966
01967 #ifdef HAVE_PYTHON
01968 PythonTagData::const_iterator pti;
01969 for (pti = cdatar->_python_tag_data.begin();
01970 pti != cdatar->_python_tag_data.end();
01971 ++pti) {
01972 const string &key = (*pti).first;
01973 PyObject *value = (*pti).second;
01974 Py_XINCREF(value);
01975
01976 pair<PythonTagData::iterator, bool> result;
01977 result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
01978
01979 if (!result.second) {
01980
01981
01982
01983
01984 PythonTagData::iterator wpti = result.first;
01985 PyObject *old_value = (*wpti).second;
01986 Py_XDECREF(old_value);
01987 (*wpti).second = value;
01988 }
01989 }
01990 #endif // HAVE_PYTHON
01991
01992 static const int change_bits = (FB_transform | FB_state | FB_effects |
01993 FB_tag | FB_draw_mask);
01994 cdataw->_fancy_bits =
01995 (cdataw->_fancy_bits & ~change_bits) |
01996 (cdatar->_fancy_bits & change_bits);
01997
01998 if (pipeline_stage == 0) {
01999 if (cdataw->_transform != cdataw->_prev_transform) {
02000 do_set_dirty_prev_transform();
02001 }
02002 }
02003 }
02004 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02005
02006 if (any_transform_changed || any_state_changed || any_draw_mask_changed) {
02007 mark_bounds_stale(current_thread);
02008
02009 if (any_transform_changed) {
02010 transform_changed();
02011 }
02012 if (any_state_changed) {
02013 state_changed();
02014 }
02015 if (any_draw_mask_changed) {
02016 draw_mask_changed();
02017 }
02018 mark_bam_modified();
02019 }
02020 }
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041 void PandaNode::
02042 replace_node(PandaNode *other) {
02043
02044
02045 if (other == this) {
02046
02047 return;
02048 }
02049
02050
02051
02052 PT(PandaNode) keep_other = other;
02053
02054
02055 copy_all_properties(other);
02056
02057
02058 {
02059 LightReMutexHolder holder1(other->_paths_lock);
02060 LightReMutexHolder holder2(_paths_lock);
02061 Paths::iterator pi;
02062 for (pi = other->_paths.begin(); pi != other->_paths.end(); ++pi) {
02063 (*pi)->_node = this;
02064 _paths.insert(*pi);
02065 }
02066 other->_paths.clear();
02067 }
02068
02069
02070 steal_children(other);
02071
02072
02073 Thread *current_thread = Thread::get_current_thread();
02074 Parents other_parents = other->get_parents();
02075 for (int i = 0; i < other_parents.get_num_parents(); ++i) {
02076 PandaNode *parent = other_parents.get_parent(i);
02077 if (find_parent(parent) != -1) {
02078
02079
02080 parent->remove_child(other);
02081 } else {
02082
02083 parent->replace_child(other, this, current_thread);
02084 }
02085 }
02086 }
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107 void PandaNode::
02108 set_unexpected_change(unsigned int flags) {
02109 #ifndef NDEBUG
02110 _unexpected_change_flags |= flags;
02111 #endif // !NDEBUG
02112 }
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128 unsigned int PandaNode::
02129 get_unexpected_change(unsigned int flags) const {
02130 #ifndef NDEBUG
02131 return _unexpected_change_flags & flags;
02132 #else
02133 return 0;
02134 #endif // !NDEBUG
02135 }
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151 void PandaNode::
02152 clear_unexpected_change(unsigned int flags) {
02153 #ifndef NDEBUG
02154 _unexpected_change_flags &= ~flags;
02155 #endif // !NDEBUG
02156 }
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196 void PandaNode::
02197 adjust_draw_mask(DrawMask show_mask, DrawMask hide_mask, DrawMask clear_mask) {
02198 bool any_changed = false;
02199
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
02204 DrawMask draw_control_mask = (cdata->_draw_control_mask | show_mask | hide_mask) & ~clear_mask;
02205 DrawMask draw_show_mask = (cdata->_draw_show_mask | show_mask) & ~hide_mask;
02206
02207 draw_show_mask |= ~draw_control_mask;
02208
02209 if (cdata->_draw_control_mask != draw_control_mask ||
02210 cdata->_draw_show_mask != draw_show_mask) {
02211 cdata->_draw_control_mask = draw_control_mask;
02212 cdata->_draw_show_mask = draw_show_mask;
02213 any_changed = true;
02214 }
02215 cdata->set_fancy_bit(FB_draw_mask, !draw_control_mask.is_zero());
02216 }
02217 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02218
02219 if (any_changed) {
02220 mark_bounds_stale(current_thread);
02221 draw_mask_changed();
02222 mark_bam_modified();
02223 }
02224 }
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238 DrawMask PandaNode::
02239 get_net_draw_control_mask() const {
02240 Thread *current_thread = Thread::get_current_thread();
02241 int pipeline_stage = current_thread->get_pipeline_stage();
02242 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02243 if (cdata->_last_update != cdata->_next_update) {
02244
02245 PStatTimer timer(_update_bounds_pcollector);
02246 CDStageWriter cdataw =
02247 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02248 return cdataw->_net_draw_control_mask;
02249 }
02250 return cdata->_net_draw_control_mask;
02251 }
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269 DrawMask PandaNode::
02270 get_net_draw_show_mask() const {
02271 Thread *current_thread = Thread::get_current_thread();
02272 int pipeline_stage = current_thread->get_pipeline_stage();
02273 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02274 if (cdata->_last_update != cdata->_next_update) {
02275
02276 PStatTimer timer(_update_bounds_pcollector);
02277 CDStageWriter cdataw =
02278 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02279 return cdataw->_net_draw_show_mask;
02280 }
02281 return cdata->_net_draw_show_mask;
02282 }
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301 void PandaNode::
02302 set_into_collide_mask(CollideMask mask) {
02303 mask &= get_legal_collide_mask();
02304
02305 bool any_changed = false;
02306 Thread *current_thread = Thread::get_current_thread();
02307 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02308 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02309 if (cdata->_into_collide_mask != mask) {
02310 cdata->_into_collide_mask = mask;
02311 any_changed = true;
02312 }
02313 }
02314 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02315
02316 if (any_changed) {
02317 mark_bounds_stale(current_thread);
02318 mark_bam_modified();
02319 }
02320 }
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333 CollideMask PandaNode::
02334 get_legal_collide_mask() const {
02335 return CollideMask::all_off();
02336 }
02337
02338
02339
02340
02341
02342
02343
02344 CollideMask PandaNode::
02345 get_net_collide_mask(Thread *current_thread) const {
02346 int pipeline_stage = current_thread->get_pipeline_stage();
02347 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02348 if (cdata->_last_update != cdata->_next_update) {
02349
02350 PStatTimer timer(_update_bounds_pcollector);
02351 CDStageWriter cdataw =
02352 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02353 return cdataw->_net_collide_mask;
02354 }
02355 return cdata->_net_collide_mask;
02356 }
02357
02358
02359
02360
02361
02362
02363
02364
02365 CPT(RenderAttrib) PandaNode::
02366 get_off_clip_planes(Thread *current_thread) const {
02367 int pipeline_stage = current_thread->get_pipeline_stage();
02368 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02369 if (cdata->_last_update != cdata->_next_update) {
02370
02371 PStatTimer timer(_update_bounds_pcollector);
02372 CDStageWriter cdataw =
02373 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02374 return cdataw->_off_clip_planes;
02375 }
02376 return cdata->_off_clip_planes;
02377 }
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394 void PandaNode::
02395 prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state) {
02396 GeomTransformer transformer;
02397 Thread *current_thread = Thread::get_current_thread();
02398 r_prepare_scene(gsg, node_state, transformer, current_thread);
02399 }
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409 bool PandaNode::
02410 is_scene_root() const {
02411
02412
02413
02414 if (_scene_root_func != (SceneRootFunc *)NULL) {
02415 return (*_scene_root_func)(this);
02416 }
02417 return false;
02418 }
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430 bool PandaNode::
02431 is_under_scene_root() const {
02432 if (is_scene_root()) {
02433 return true;
02434 }
02435
02436 Parents parents = get_parents();
02437 for (int i = 0; i < parents.get_num_parents(); ++i) {
02438 PandaNode *parent = parents.get_parent(i);
02439 if (parent->find_stashed((PandaNode *)this) == -1) {
02440 if (parent->is_under_scene_root()) {
02441 return true;
02442 }
02443 }
02444 }
02445 return false;
02446 }
02447
02448
02449
02450
02451
02452
02453 void PandaNode::
02454 output(ostream &out) const {
02455 out << get_type() << " " << get_name();
02456 }
02457
02458
02459
02460
02461
02462
02463 void PandaNode::
02464 write(ostream &out, int indent_level) const {
02465 indent(out, indent_level) << *this;
02466 if (has_tags()) {
02467 out << " [";
02468 list_tags(out, " ");
02469 out << "]";
02470 }
02471 CPT(TransformState) transform = get_transform();
02472 if (!transform->is_identity()) {
02473 out << " " << *transform;
02474 }
02475 CPT(RenderState) state = get_state();
02476 if (!state->is_empty()) {
02477 out << " " << *state;
02478 }
02479 CPT(RenderEffects) effects = get_effects();
02480 if (!effects->is_empty()) {
02481 out << " " << *effects;
02482 }
02483 DrawMask draw_control_mask = get_draw_control_mask();
02484 if (!draw_control_mask.is_zero()) {
02485 DrawMask draw_show_mask = get_draw_show_mask();
02486 if (!(draw_control_mask & _overall_bit).is_zero()) {
02487 if (!(draw_show_mask & _overall_bit).is_zero()) {
02488 out << " (show_through)";
02489 } else {
02490 out << " (hidden)";
02491 }
02492 }
02493 if (!(draw_control_mask & ~_overall_bit).is_zero()) {
02494 draw_control_mask &= ~_overall_bit;
02495 if (!(draw_show_mask & draw_control_mask).is_zero()) {
02496 out << " (per-camera show_through)";
02497 }
02498 if (!(~draw_show_mask & draw_control_mask).is_zero()) {
02499 out << " (per-camera hidden)";
02500 }
02501 }
02502 }
02503 out << "\n";
02504 }
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525 void PandaNode::
02526 set_bounds_type(BoundingVolume::BoundsType bounds_type) {
02527 Thread *current_thread = Thread::get_current_thread();
02528 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02529 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02530 cdata->_bounds_type = bounds_type;
02531 mark_bounds_stale(pipeline_stage, current_thread);
02532
02533
02534
02535
02536 mark_internal_bounds_stale(pipeline_stage, current_thread);
02537 mark_bam_modified();
02538 }
02539 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02540 }
02541
02542
02543
02544
02545
02546
02547
02548 BoundingVolume::BoundsType PandaNode::
02549 get_bounds_type() const {
02550 CDReader cdata(_cycler);
02551 return cdata->_bounds_type;
02552 }
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568 void PandaNode::
02569 set_bounds(const BoundingVolume *volume) {
02570 Thread *current_thread = Thread::get_current_thread();
02571 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02572 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02573 if (volume == NULL) {
02574 cdata->_user_bounds = NULL;
02575 } else {
02576 cdata->_user_bounds = volume->make_copy();
02577 }
02578 mark_bounds_stale(pipeline_stage, current_thread);
02579 mark_bam_modified();
02580 }
02581 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02582 }
02583
02584
02585
02586
02587
02588
02589 void PandaNode::
02590 set_bound(const BoundingVolume *volume) {
02591 pgraph_cat.warning()
02592 << "Deprecated PandaNode::set_bound() called. Use set_bounds() instead.\n";
02593 set_bounds(volume);
02594 }
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604 CPT(BoundingVolume) PandaNode::
02605 get_bounds(Thread *current_thread) const {
02606 int pipeline_stage = current_thread->get_pipeline_stage();
02607 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02608 if (cdata->_last_update != cdata->_next_update) {
02609
02610 CPT(BoundingVolume) result;
02611 {
02612 PStatTimer timer(_update_bounds_pcollector);
02613 CDStageWriter cdataw =
02614 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02615 result = cdataw->_external_bounds;
02616 }
02617 return result;
02618 }
02619 return cdata->_external_bounds;
02620 }
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638 CPT(BoundingVolume) PandaNode::
02639 get_bounds(UpdateSeq &seq, Thread *current_thread) const {
02640 int pipeline_stage = current_thread->get_pipeline_stage();
02641 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02642 if (cdata->_last_update != cdata->_next_update) {
02643
02644 CPT(BoundingVolume) result;
02645 {
02646 PStatTimer timer(_update_bounds_pcollector);
02647 CDStageWriter cdataw =
02648 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02649 result = cdataw->_external_bounds;
02650 seq = cdataw->_last_update;
02651 }
02652 return result;
02653 }
02654 seq = cdata->_last_update;
02655 return cdata->_external_bounds;
02656 }
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671 int PandaNode::
02672 get_nested_vertices(Thread *current_thread) const {
02673 int pipeline_stage = current_thread->get_pipeline_stage();
02674 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02675 if (cdata->_last_update != cdata->_next_update) {
02676
02677 int result;
02678 {
02679 PStatTimer timer(_update_bounds_pcollector);
02680 CDStageWriter cdataw =
02681 ((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
02682 result = cdataw->_nested_vertices;
02683 }
02684 return result;
02685 }
02686 return cdata->_nested_vertices;
02687 }
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707 void PandaNode::
02708 mark_bounds_stale(Thread *current_thread) const {
02709 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02710 mark_bounds_stale(pipeline_stage, current_thread);
02711 }
02712 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02713 }
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731 void PandaNode::
02732 mark_internal_bounds_stale(Thread *current_thread) {
02733 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02734 mark_internal_bounds_stale(pipeline_stage, current_thread);
02735 }
02736 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02737 }
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750 bool PandaNode::
02751 is_geom_node() const {
02752 return false;
02753 }
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765 bool PandaNode::
02766 is_lod_node() const {
02767 return false;
02768 }
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780 bool PandaNode::
02781 is_collision_node() const {
02782 return false;
02783 }
02784
02785
02786
02787
02788
02789
02790
02791
02792 Light *PandaNode::
02793 as_light() {
02794 return NULL;
02795 }
02796
02797
02798
02799
02800
02801
02802
02803 bool PandaNode::
02804 is_ambient_light() const {
02805 return false;
02806 }
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822 PT(PandaNode) PandaNode::
02823 decode_from_bam_stream(const string &data, BamReader *reader) {
02824 TypedWritable *object;
02825 ReferenceCount *ref_ptr;
02826
02827 if (!TypedWritable::decode_raw_from_bam_stream(object, ref_ptr, data, reader)) {
02828 return NULL;
02829 }
02830
02831 return DCAST(PandaNode, object);
02832 }
02833
02834
02835
02836
02837
02838
02839
02840
02841 CPT(BoundingVolume) PandaNode::
02842 get_internal_bounds(int pipeline_stage, Thread *current_thread) const {
02843 while (true) {
02844 UpdateSeq mark;
02845 {
02846 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02847 if (cdata->_user_bounds != (BoundingVolume *)NULL) {
02848 return cdata->_user_bounds;
02849 }
02850
02851 if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
02852 return cdata->_internal_bounds;
02853 }
02854
02855 mark = cdata->_internal_bounds_mark;
02856 }
02857
02858
02859
02860 CPT(BoundingVolume) internal_bounds;
02861 int internal_vertices;
02862 compute_internal_bounds(internal_bounds, internal_vertices,
02863 pipeline_stage, current_thread);
02864 nassertr(!internal_bounds.is_null(), NULL);
02865
02866
02867 CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
02868 if (cdataw->_internal_bounds_mark == mark) {
02869 cdataw->_internal_bounds_computed = mark;
02870 cdataw->_internal_bounds = internal_bounds;
02871 cdataw->_internal_vertices = internal_vertices;
02872 ((PandaNode *)this)->mark_bam_modified();
02873 return cdataw->_internal_bounds;
02874 }
02875
02876
02877
02878
02879 }
02880 }
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892 int PandaNode::
02893 get_internal_vertices(int pipeline_stage, Thread *current_thread) const {
02894 while (true) {
02895 UpdateSeq mark;
02896 {
02897 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02898 if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
02899 return cdata->_internal_vertices;
02900 }
02901
02902 mark = cdata->_internal_bounds_mark;
02903 }
02904
02905
02906
02907 CPT(BoundingVolume) internal_bounds;
02908 int internal_vertices;
02909 compute_internal_bounds(internal_bounds, internal_vertices,
02910 pipeline_stage, current_thread);
02911 nassertr(!internal_bounds.is_null(), 0);
02912
02913
02914 CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
02915 if (cdataw->_internal_bounds_mark == mark) {
02916 cdataw->_internal_bounds_computed = mark;
02917 cdataw->_internal_bounds = internal_bounds;
02918 cdataw->_internal_vertices = internal_vertices;
02919 ((PandaNode *)this)->mark_bam_modified();
02920 return cdataw->_internal_vertices;
02921 }
02922
02923
02924
02925
02926 }
02927 }
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938 void PandaNode::
02939 set_internal_bounds(const BoundingVolume *volume) {
02940 Thread *current_thread = Thread::get_current_thread();
02941 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02942 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
02943 cdataw->_internal_bounds = volume;
02944 cdataw->_internal_bounds_computed = cdataw->_internal_bounds_mark;
02945 }
02946 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02947 mark_bounds_stale(current_thread);
02948 mark_bam_modified();
02949 }
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962 void PandaNode::
02963 force_bounds_stale(Thread *current_thread) {
02964 OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02965 force_bounds_stale(pipeline_stage, current_thread);
02966 }
02967 CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02968 }
02969
02970
02971
02972
02973
02974
02975
02976
02977 void PandaNode::
02978 force_bounds_stale(int pipeline_stage, Thread *current_thread) {
02979 {
02980 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02981 ++cdata->_next_update;
02982 mark_bam_modified();
02983
02984
02985
02986
02987 }
02988
02989
02990
02991
02992 Parents parents;
02993 {
02994 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02995 parents = Parents(cdata);
02996 }
02997 int num_parents = parents.get_num_parents();
02998 for (int i = 0; i < num_parents; ++i) {
02999 PandaNode *parent = parents.get_parent(i);
03000 parent->mark_bounds_stale(pipeline_stage, current_thread);
03001 }
03002 }
03003
03004
03005
03006
03007
03008
03009
03010 void PandaNode::
03011 r_mark_geom_bounds_stale(Thread *current_thread) {
03012 Children children = get_children(current_thread);
03013
03014 int i;
03015 for (i = 0; i < children.get_num_children(); i++) {
03016 PandaNode *child = children.get_child(i);
03017 child->r_mark_geom_bounds_stale(current_thread);
03018 }
03019
03020 Stashed stashed = get_stashed(current_thread);
03021 for (i = 0; i < stashed.get_num_stashed(); i++) {
03022 PandaNode *child = stashed.get_stashed(i);
03023 child->r_mark_geom_bounds_stale(current_thread);
03024 }
03025 }
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035 void PandaNode::
03036 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
03037 int &internal_vertices,
03038 int pipeline_stage,
03039 Thread *current_thread) const {
03040 internal_bounds = new BoundingSphere;
03041 internal_vertices = 0;
03042 }
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053 void PandaNode::
03054 parents_changed() {
03055 nassertv((_unexpected_change_flags & UC_parents) == 0);
03056 }
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067 void PandaNode::
03068 children_changed() {
03069 nassertv((_unexpected_change_flags & UC_children) == 0);
03070 }
03071
03072
03073
03074
03075
03076
03077
03078
03079 void PandaNode::
03080 transform_changed() {
03081 nassertv((_unexpected_change_flags & UC_transform) == 0);
03082 }
03083
03084
03085
03086
03087
03088
03089
03090
03091 void PandaNode::
03092 state_changed() {
03093 nassertv((_unexpected_change_flags & UC_state) == 0);
03094 }
03095
03096
03097
03098
03099
03100
03101
03102
03103 void PandaNode::
03104 draw_mask_changed() {
03105 nassertv((_unexpected_change_flags & UC_draw_mask) == 0);
03106 }
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121 PT(PandaNode) PandaNode::
03122 r_copy_subgraph(PandaNode::InstanceMap &inst_map, Thread *current_thread) const {
03123 PT(PandaNode) copy = make_copy();
03124 nassertr(copy != (PandaNode *)NULL, NULL);
03125 if (copy->get_type() != get_type()) {
03126 pgraph_cat.warning()
03127 << "Don't know how to copy nodes of type " << get_type() << "\n";
03128
03129 if (no_unsupported_copy) {
03130 nassertr(false, NULL);
03131 }
03132 }
03133
03134 copy->r_copy_children(this, inst_map, current_thread);
03135 return copy;
03136 }
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153 void PandaNode::
03154 r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
03155 Thread *current_thread) {
03156 CDReader from_cdata(from->_cycler, current_thread);
03157 CPT(Down) from_down = from_cdata->get_down();
03158 Down::const_iterator di;
03159 for (di = from_down->begin(); di != from_down->end(); ++di) {
03160 int sort = (*di).get_sort();
03161 PandaNode *source_child = (*di).get_child();
03162 PT(PandaNode) dest_child;
03163
03164
03165
03166
03167
03168 InstanceMap::const_iterator ci;
03169 ci = inst_map.find(source_child);
03170 if (ci != inst_map.end()) {
03171 dest_child = (*ci).second;
03172 } else {
03173 dest_child = source_child->r_copy_subgraph(inst_map, current_thread);
03174 inst_map[source_child] = dest_child;
03175 }
03176
03177 quick_add_new_child(dest_child, sort, current_thread);
03178 }
03179 }
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189 void PandaNode::
03190 r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
03191 GeomTransformer &transformer, Thread *current_thread) {
03192 Children children = get_children(current_thread);
03193
03194
03195 int i;
03196 for (i = 0; i < children.get_num_children(); i++) {
03197 PandaNode *child = children.get_child(i);
03198 CPT(RenderState) child_state = node_state->compose(child->get_state());
03199 child->r_prepare_scene(gsg, child_state, transformer, current_thread);
03200 }
03201
03202 Stashed stashed = get_stashed(current_thread);
03203 for (i = 0; i < stashed.get_num_stashed(); i++) {
03204 PandaNode *child = stashed.get_stashed(i);
03205 CPT(RenderState) child_state = node_state->compose(child->get_state());
03206 child->r_prepare_scene(gsg, child_state, transformer, current_thread);
03207 }
03208 }
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218 void PandaNode::
03219 set_cull_callback() {
03220 Thread *current_thread = Thread::get_current_thread();
03221 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03222 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03223 cdata->set_fancy_bit(FB_cull_callback, true);
03224 }
03225 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03226 mark_bam_modified();
03227 }
03228
03229
03230
03231
03232
03233
03234 void PandaNode::
03235 disable_cull_callback() {
03236 Thread *current_thread = Thread::get_current_thread();
03237 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03238 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03239 cdata->set_fancy_bit(FB_cull_callback, false);
03240 }
03241 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03242 mark_bam_modified();
03243 }
03244
03245
03246
03247
03248
03249
03250
03251 bool PandaNode::
03252 stage_remove_child(PandaNode *child_node, int pipeline_stage,
03253 Thread *current_thread) {
03254 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03255
03256
03257
03258 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
03259 current_thread);
03260 int parent_index = child_node->do_find_parent(this, cdata_child);
03261 if (parent_index < 0) {
03262
03263 return false;
03264 }
03265
03266 PT(Down) down = cdata->modify_down();
03267 int child_index = do_find_child(child_node, down);
03268 if (child_index >= 0) {
03269
03270 down->erase(down->begin() + child_index);
03271 int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
03272 nassertr(num_erased == 1, false);
03273 return true;
03274 }
03275
03276 PT(Down) stashed = cdata->modify_stashed();
03277 int stashed_index = do_find_child(child_node, stashed);
03278 if (stashed_index >= 0) {
03279
03280 stashed->erase(stashed->begin() + stashed_index);
03281 int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
03282 nassertr(num_erased == 1, false);
03283 return true;
03284 }
03285
03286
03287
03288
03289 nassertr(false, false);
03290 return false;
03291 }
03292
03293
03294
03295
03296
03297
03298
03299 bool PandaNode::
03300 stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
03301 int pipeline_stage, Thread *current_thread) {
03302 {
03303 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03304 CDStageWriter cdata_orig_child(orig_child->_cycler, pipeline_stage, current_thread);
03305 CDStageWriter cdata_new_child(new_child->_cycler, pipeline_stage, current_thread);
03306
03307
03308
03309 int parent_index = orig_child->do_find_parent(this, cdata_orig_child);
03310 if (parent_index < 0) {
03311
03312 return false;
03313 }
03314
03315 if (orig_child == new_child) {
03316
03317 return true;
03318 }
03319
03320
03321 PT(PandaNode) keep_orig_child = orig_child;
03322
03323
03324 if (stage_remove_child(new_child, pipeline_stage, current_thread)) {
03325 sever_connection(this, new_child, pipeline_stage, current_thread);
03326 }
03327
03328 PT(Down) down = cdata->modify_down();
03329 int child_index = do_find_child(orig_child, down);
03330 if (child_index >= 0) {
03331
03332 DownConnection &dc = (*down)[child_index];
03333 nassertr(dc.get_child() == orig_child, false);
03334 dc.set_child(new_child);
03335
03336 } else {
03337 PT(Down) stashed = cdata->modify_stashed();
03338 int stashed_index = do_find_child(orig_child, stashed);
03339 if (stashed_index >= 0) {
03340
03341 DownConnection &dc = (*stashed)[stashed_index];
03342 nassertr(dc.get_child() == orig_child, false);
03343 dc.set_child(new_child);
03344
03345 } else {
03346
03347
03348
03349 nassertr(false, false);
03350 return false;
03351 }
03352 }
03353
03354
03355 cdata_new_child->modify_up()->insert(UpConnection(this));
03356 int num_erased = cdata_orig_child->modify_up()->erase(UpConnection(this));
03357 nassertr(num_erased == 1, false);
03358 }
03359
03360 sever_connection(this, orig_child, pipeline_stage, current_thread);
03361 new_connection(this, new_child, pipeline_stage, current_thread);
03362
03363 force_bounds_stale(pipeline_stage, current_thread);
03364 orig_child->parents_changed();
03365 new_child->parents_changed();
03366 mark_bam_modified();
03367 orig_child->mark_bam_modified();
03368 new_child->mark_bam_modified();
03369
03370 return true;
03371 }
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383 void PandaNode::
03384 quick_add_new_child(PandaNode *child_node, int sort, Thread *current_thread) {
03385
03386
03387 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03388 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03389 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03390
03391 cdata->modify_down()->insert(DownConnection(child_node, sort));
03392 cdata_child->modify_up()->insert(UpConnection(this));
03393 }
03394 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03395 }
03396
03397
03398
03399
03400
03401
03402
03403 void PandaNode::
03404 report_cycle(PandaNode *child_node) {
03405 ostringstream strm;
03406 strm << "Detected attempt to create a cycle in the scene graph: "
03407 << NodePath::any_path(this) << " : " << *child_node;
03408 nassert_raise(strm.str());
03409 }
03410
03411
03412
03413
03414
03415
03416
03417
03418 bool PandaNode::
03419 find_node_above(PandaNode *node) {
03420 if (node == this) {
03421 return true;
03422 }
03423
03424 Parents parents = get_parents();
03425 for (int i = 0; i < parents.get_num_parents(); ++i) {
03426 PandaNode *parent = parents.get_parent(i);
03427 if (parent->find_node_above(node)) {
03428 return true;
03429 }
03430 }
03431
03432 return false;
03433 }
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446 PT(NodePathComponent) PandaNode::
03447 attach(NodePathComponent *parent, PandaNode *child_node, int sort,
03448 int pipeline_stage, Thread *current_thread) {
03449 if (parent == (NodePathComponent *)NULL) {
03450
03451
03452 PT(NodePathComponent) child =
03453 new NodePathComponent(child_node, (NodePathComponent *)NULL,
03454 pipeline_stage, current_thread);
03455 LightReMutexHolder holder(child_node->_paths_lock);
03456 child_node->_paths.insert(child);
03457 return child;
03458 }
03459
03460
03461
03462 PT(NodePathComponent) child = get_component(parent, child_node, pipeline_stage, current_thread);
03463
03464 if (child == (NodePathComponent *)NULL) {
03465
03466
03467 child = get_top_component(child_node, true, pipeline_stage, current_thread);
03468 }
03469
03470 reparent(parent, child, sort, false, pipeline_stage, current_thread);
03471
03472 return child;
03473 }
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483 void PandaNode::
03484 detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread) {
03485 nassertv(child != (NodePathComponent *)NULL);
03486
03487 for (int pipeline_stage_i = pipeline_stage;
03488 pipeline_stage_i >= 0;
03489 --pipeline_stage_i) {
03490 detach_one_stage(child, pipeline_stage_i, current_thread);
03491 }
03492
03493 child->get_node()->parents_changed();
03494 }
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505 void PandaNode::
03506 detach_one_stage(NodePathComponent *child, int pipeline_stage,
03507 Thread *current_thread) {
03508 nassertv(child != (NodePathComponent *)NULL);
03509 if (child->is_top_node(pipeline_stage, current_thread)) {
03510 return;
03511 }
03512
03513 PT(PandaNode) child_node = child->get_node();
03514 PT(PandaNode) parent_node = child->get_next(pipeline_stage, current_thread)->get_node();
03515
03516 CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
03517 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03518 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03519 if (parent_index >= 0) {
03520
03521
03522
03523
03524 int num_erased = cdata_child->modify_up()->erase(UpConnection(parent_node));
03525 nassertv(num_erased == 1);
03526
03527
03528
03529
03530 Down::iterator di;
03531 bool found = false;
03532 PT(Down) down = cdata_parent->modify_down();
03533 for (di = down->begin(); di != down->end(); ++di) {
03534 if ((*di).get_child() == child_node) {
03535 down->erase(di);
03536 found = true;
03537 break;
03538 }
03539 }
03540 if (!found) {
03541 PT(Down) stashed = cdata_parent->modify_stashed();
03542 for (di = stashed->begin(); di != stashed->end(); ++di) {
03543 if ((*di).get_child() == child_node) {
03544 stashed->erase(di);
03545 found = true;
03546 break;
03547 }
03548 }
03549 }
03550 nassertv(found);
03551 }
03552
03553
03554 sever_connection(parent_node, child_node, pipeline_stage, current_thread);
03555
03556 parent_node->force_bounds_stale(pipeline_stage, current_thread);
03557 parent_node->children_changed();
03558 parent_node->mark_bam_modified();
03559 }
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573 bool PandaNode::
03574 reparent(NodePathComponent *new_parent, NodePathComponent *child, int sort,
03575 bool as_stashed, int pipeline_stage, Thread *current_thread) {
03576 bool any_ok = false;
03577
03578 if (new_parent != (NodePathComponent *)NULL &&
03579 !new_parent->get_node()->verify_child_no_cycles(child->get_node())) {
03580
03581
03582 return false;
03583 }
03584
03585 for (int pipeline_stage_i = pipeline_stage;
03586 pipeline_stage_i >= 0;
03587 --pipeline_stage_i) {
03588 if (reparent_one_stage(new_parent, child, sort, as_stashed,
03589 pipeline_stage_i, current_thread)) {
03590 any_ok = true;
03591 }
03592 }
03593
03594 if (new_parent != (NodePathComponent *)NULL) {
03595 new_parent->get_node()->children_changed();
03596 new_parent->get_node()->mark_bam_modified();
03597 }
03598 child->get_node()->parents_changed();
03599 child->get_node()->mark_bam_modified();
03600
03601 return any_ok;
03602 }
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617 bool PandaNode::
03618 reparent_one_stage(NodePathComponent *new_parent, NodePathComponent *child,
03619 int sort, bool as_stashed, int pipeline_stage,
03620 Thread *current_thread) {
03621 nassertr(child != (NodePathComponent *)NULL, false);
03622
03623
03624
03625 PT(NodePathComponent) keep_parent = new_parent;
03626
03627 if (!child->is_top_node(pipeline_stage, current_thread)) {
03628 detach(child, pipeline_stage, current_thread);
03629 }
03630
03631 if (new_parent != (NodePathComponent *)NULL) {
03632 PandaNode *child_node = child->get_node();
03633 PandaNode *parent_node = new_parent->get_node();
03634
03635 {
03636 CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03637 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03638
03639 if (parent_index >= 0) {
03640
03641 return false;
03642 }
03643 }
03644
03645
03646 child->set_next(new_parent, pipeline_stage, current_thread);
03647
03648
03649 {
03650 CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
03651 CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03652
03653 if (as_stashed) {
03654 cdata_parent->modify_stashed()->insert(DownConnection(child_node, sort));
03655 } else {
03656 cdata_parent->modify_down()->insert(DownConnection(child_node, sort));
03657 }
03658 cdata_child->modify_up()->insert(UpConnection(parent_node));
03659
03660 #ifndef NDEBUG
03661
03662 {
03663 LightReMutexHolder holder(child_node->_paths_lock);
03664 nassertr(child_node->_paths.find(child) != child_node->_paths.end(), false);
03665 }
03666 #endif // NDEBUG
03667 }
03668
03669 child_node->fix_path_lengths(pipeline_stage, current_thread);
03670 parent_node->force_bounds_stale(pipeline_stage, current_thread);
03671 }
03672
03673 return true;
03674 }
03675
03676
03677
03678
03679
03680
03681
03682
03683 PT(NodePathComponent) PandaNode::
03684 get_component(NodePathComponent *parent, PandaNode *child_node,
03685 int pipeline_stage, Thread *current_thread) {
03686 nassertr(parent != (NodePathComponent *)NULL, (NodePathComponent *)NULL);
03687 PandaNode *parent_node = parent->get_node();
03688
03689 LightReMutexHolder holder(child_node->_paths_lock);
03690
03691
03692
03693
03694 Paths::const_iterator pi;
03695 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03696 if ((*pi)->get_next(pipeline_stage, current_thread) == parent) {
03697
03698 return (*pi);
03699 }
03700 }
03701
03702
03703
03704 CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03705 int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03706
03707 if (parent_index >= 0) {
03708
03709 PT(NodePathComponent) child =
03710 new NodePathComponent(child_node, parent, pipeline_stage, current_thread);
03711 child_node->_paths.insert(child);
03712 return child;
03713 } else {
03714
03715 return NULL;
03716 }
03717 }
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733 PT(NodePathComponent) PandaNode::
03734 get_top_component(PandaNode *child_node, bool force, int pipeline_stage,
03735 Thread *current_thread) {
03736 LightReMutexHolder holder(child_node->_paths_lock);
03737
03738
03739
03740 Paths::const_iterator pi;
03741 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03742 if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
03743
03744 return (*pi);
03745 }
03746 }
03747
03748 if (!force) {
03749
03750
03751 return NULL;
03752 }
03753
03754
03755
03756 PT(NodePathComponent) child =
03757 new NodePathComponent(child_node, (NodePathComponent *)NULL,
03758 pipeline_stage, current_thread);
03759 child_node->_paths.insert(child);
03760
03761 return child;
03762 }
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775 PT(NodePathComponent) PandaNode::
03776 get_generic_component(bool accept_ambiguity, int pipeline_stage,
03777 Thread *current_thread) {
03778 bool ambiguity_detected = false;
03779 PT(NodePathComponent) result =
03780 r_get_generic_component(accept_ambiguity, ambiguity_detected,
03781 pipeline_stage, current_thread);
03782
03783 if (!accept_ambiguity && ambiguity_detected) {
03784 pgraph_cat.warning()
03785 << "Chose: " << *result << "\n";
03786 nassertr(!unambiguous_graph, result);
03787 }
03788
03789 return result;
03790 }
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800 PT(NodePathComponent) PandaNode::
03801 r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected,
03802 int pipeline_stage, Thread *current_thread) {
03803 PT(PandaNode) parent_node;
03804
03805 {
03806 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
03807
03808 int num_parents = cdata->get_up()->size();
03809 if (num_parents == 0) {
03810
03811 return get_top_component(this, true, pipeline_stage, current_thread);
03812 }
03813
03814 PT(NodePathComponent) result;
03815 if (num_parents == 1) {
03816
03817 PT(NodePathComponent) parent =
03818 get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
03819 return get_component(parent, this, pipeline_stage, current_thread);
03820 }
03821
03822
03823 if (!accept_ambiguity) {
03824 pgraph_cat.warning()
03825 << *this << " has " << num_parents
03826 << " parents; choosing arbitrary path to root.\n";
03827 }
03828 ambiguity_detected = true;
03829 CPT(Up) up = cdata->get_up();
03830 parent_node = (*up)[0].get_parent();
03831 }
03832
03833
03834 PT(NodePathComponent) parent =
03835 parent_node->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
03836 return get_component(parent, this, pipeline_stage, current_thread);
03837 }
03838
03839
03840
03841
03842
03843
03844
03845
03846 void PandaNode::
03847 delete_component(NodePathComponent *component) {
03848 LightReMutexHolder holder(_paths_lock);
03849 int num_erased = _paths.erase(component);
03850 nassertv(num_erased == 1);
03851 }
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871 void PandaNode::
03872 sever_connection(PandaNode *parent_node, PandaNode *child_node,
03873 int pipeline_stage, Thread *current_thread) {
03874 {
03875 LightReMutexHolder holder(child_node->_paths_lock);
03876 Paths::iterator pi;
03877 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03878 if (!(*pi)->is_top_node(pipeline_stage, current_thread) &&
03879 (*pi)->get_next(pipeline_stage, current_thread)->get_node() == parent_node) {
03880
03881 (*pi)->set_top_node(pipeline_stage, current_thread);
03882 }
03883 }
03884 }
03885 child_node->fix_path_lengths(pipeline_stage, current_thread);
03886 }
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904 void PandaNode::
03905 new_connection(PandaNode *parent_node, PandaNode *child_node,
03906 int pipeline_stage, Thread *current_thread) {
03907 {
03908 LightReMutexHolder holder(child_node->_paths_lock);
03909 Paths::iterator pi;
03910 for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03911 if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
03912 (*pi)->set_next(parent_node->get_generic_component(false, pipeline_stage, current_thread), pipeline_stage, current_thread);
03913 }
03914 }
03915 }
03916 child_node->fix_path_lengths(pipeline_stage, current_thread);
03917 }
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931 void PandaNode::
03932 fix_path_lengths(int pipeline_stage, Thread *current_thread) {
03933 LightReMutexHolder holder(_paths_lock);
03934
03935 bool any_wrong = false;
03936
03937 Paths::const_iterator pi;
03938 for (pi = _paths.begin(); pi != _paths.end(); ++pi) {
03939 if ((*pi)->fix_length(pipeline_stage, current_thread)) {
03940 any_wrong = true;
03941 }
03942 }
03943
03944
03945
03946
03947 if (any_wrong) {
03948 Children children;
03949 Stashed stashed;
03950 {
03951 CDStageReader cdata(_cycler, pipeline_stage, current_thread);
03952 children = Children(cdata);
03953 stashed = Stashed(cdata);
03954 }
03955
03956 int num_children = children.get_num_children();
03957 int i;
03958 for (i = 0; i < num_children; ++i) {
03959 PandaNode *child_node = children.get_child(i);
03960 child_node->fix_path_lengths(pipeline_stage, current_thread);
03961 }
03962 int num_stashed = stashed.get_num_stashed();
03963 for (i = 0; i < num_stashed; ++i) {
03964 PandaNode *child_node = stashed.get_stashed(i);
03965 child_node->fix_path_lengths(pipeline_stage, current_thread);
03966 }
03967 }
03968 }
03969
03970
03971
03972
03973
03974
03975 void PandaNode::
03976 r_list_descendants(ostream &out, int indent_level) const {
03977 write(out, indent_level);
03978
03979 Children children = get_children();
03980 int num_children = children.get_num_children();
03981
03982 for (int i = 0; i < num_children; ++i) {
03983 PandaNode *child = children.get_child(i);
03984 child->r_list_descendants(out, indent_level + 2);
03985 }
03986
03987
03988 int num_stashed = get_num_stashed();
03989 if (num_stashed != 0) {
03990 indent(out, indent_level) << "(" << num_stashed << " stashed)\n";
03991 }
03992 }
03993
03994
03995
03996
03997
03998
03999 int PandaNode::
04000 do_find_child(PandaNode *node, const PandaNode::Down *down) const {
04001 nassertr(node != (PandaNode *)NULL, -1);
04002
04003
04004
04005 Down::const_iterator di;
04006 for (di = down->begin(); di != down->end(); ++di) {
04007 if ((*di).get_child() == node) {
04008 return di - down->begin();
04009 }
04010 }
04011
04012 return -1;
04013 }
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025
04026 PandaNode::CDStageWriter PandaNode::
04027 update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
04028
04029
04030 if (drawmask_cat.is_debug()) {
04031 drawmask_cat.debug(false)
04032 << *this << "::update_bounds() {\n";
04033 }
04034 Thread *current_thread = cdata.get_current_thread();
04035
04036 do {
04037
04038 UpdateSeq last_update = cdata->_last_update;
04039 UpdateSeq next_update = cdata->_next_update;
04040 nassertr(last_update != next_update, CDStageWriter(_cycler, pipeline_stage, cdata));
04041
04042
04043 CollideMask net_collide_mask = cdata->_into_collide_mask;
04044 DrawMask net_draw_control_mask, net_draw_show_mask;
04045 bool renderable = is_renderable();
04046
04047 if (renderable) {
04048
04049
04050 net_draw_control_mask = cdata->_draw_control_mask;
04051 net_draw_show_mask = cdata->_draw_show_mask;
04052 }
04053
04054 if (drawmask_cat.is_debug()) {
04055 drawmask_cat.debug(false)
04056 << "net_draw_control_mask = " << net_draw_control_mask
04057 << "\nnet_draw_show_mask = " << net_draw_show_mask
04058 << "\n";
04059 }
04060 CPT(RenderAttrib) off_clip_planes = cdata->_state->get_attrib(ClipPlaneAttrib::get_class_slot());
04061 if (off_clip_planes == (RenderAttrib *)NULL) {
04062 off_clip_planes = ClipPlaneAttrib::make();
04063 }
04064
04065
04066 Children children(cdata);
04067
04068 int num_vertices = cdata->_internal_vertices;
04069
04070
04071
04072 _cycler.release_read_stage(pipeline_stage, cdata.take_pointer());
04073
04074 int num_children = children.get_num_children();
04075
04076
04077
04078
04079
04080
04081 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04082 pvector<CPT(BoundingVolume) > child_volumes_ref;
04083 child_volumes_ref.reserve(num_children + 1);
04084 #endif
04085 const BoundingVolume **child_volumes = (const BoundingVolume **)alloca(sizeof(BoundingVolume *) * (num_children + 1));
04086 int child_volumes_i = 0;
04087
04088 bool all_box = true;
04089 CPT(BoundingVolume) internal_bounds =
04090 get_internal_bounds(pipeline_stage, current_thread);
04091
04092 if (!internal_bounds->is_empty()) {
04093 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04094 child_volumes_ref.push_back(internal_bounds);
04095 #endif
04096 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04097 child_volumes[child_volumes_i++] = internal_bounds;
04098 if (internal_bounds->as_bounding_box() == NULL) {
04099 all_box = false;
04100 }
04101 }
04102
04103
04104
04105 for (int i = 0; i < num_children; ++i) {
04106 PandaNode *child = children.get_child(i);
04107
04108 const ClipPlaneAttrib *orig_cp = DCAST(ClipPlaneAttrib, off_clip_planes);
04109
04110 CDLockedStageReader child_cdata(child->_cycler, pipeline_stage, current_thread);
04111 if (child_cdata->_last_update != child_cdata->_next_update) {
04112
04113 CDStageWriter child_cdataw = child->update_bounds(pipeline_stage, child_cdata);
04114
04115 net_collide_mask |= child_cdataw->_net_collide_mask;
04116
04117 if (drawmask_cat.is_debug()) {
04118 drawmask_cat.debug(false)
04119 << "\nchild update " << *child << ":\n";
04120 }
04121
04122 DrawMask child_control_mask = child_cdataw->_net_draw_control_mask;
04123 DrawMask child_show_mask = child_cdataw->_net_draw_show_mask;
04124 if (!(child_control_mask | child_show_mask).is_zero()) {
04125
04126
04127 renderable = true;
04128
04129
04130
04131
04132
04133
04134
04135
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145
04146
04147
04148
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161 DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
04162 exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
04163
04164 if (drawmask_cat.is_debug()) {
04165 drawmask_cat.debug(false)
04166 << "exception_mask = " << exception_mask << "\n";
04167 }
04168
04169
04170 net_draw_control_mask |= child_control_mask;
04171 net_draw_show_mask |= child_show_mask;
04172
04173 net_draw_control_mask &= ~exception_mask;
04174 net_draw_show_mask |= exception_mask;
04175 }
04176
04177 if (drawmask_cat.is_debug()) {
04178 drawmask_cat.debug(false)
04179 << "child_control_mask = " << child_control_mask
04180 << "\nchild_show_mask = " << child_show_mask
04181 << "\nnet_draw_control_mask = " << net_draw_control_mask
04182 << "\nnet_draw_show_mask = " << net_draw_show_mask
04183 << "\n";
04184 }
04185
04186 off_clip_planes = orig_cp->compose_off(child_cdataw->_off_clip_planes);
04187 if (!child_cdataw->_external_bounds->is_empty()) {
04188 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04189 child_volumes_ref.push_back(child_cdataw->_external_bounds);
04190 #endif
04191 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04192 child_volumes[child_volumes_i++] = child_cdataw->_external_bounds;
04193 if (child_cdataw->_external_bounds->as_bounding_box() == NULL) {
04194 all_box = false;
04195 }
04196 }
04197 num_vertices += child_cdataw->_nested_vertices;
04198
04199 } else {
04200
04201 net_collide_mask |= child_cdata->_net_collide_mask;
04202
04203
04204 if (drawmask_cat.is_debug()) {
04205 drawmask_cat.debug(false)
04206 << "\nchild fresh " << *child << ":\n";
04207 }
04208 DrawMask child_control_mask = child_cdata->_net_draw_control_mask;
04209 DrawMask child_show_mask = child_cdata->_net_draw_show_mask;
04210 if (!(child_control_mask | child_show_mask).is_zero()) {
04211 renderable = true;
04212
04213 DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
04214 exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
04215
04216 if (drawmask_cat.is_debug()) {
04217 drawmask_cat.debug(false)
04218 << "exception_mask = " << exception_mask << "\n";
04219 }
04220
04221
04222 net_draw_control_mask |= child_control_mask;
04223 net_draw_show_mask |= child_show_mask;
04224
04225 net_draw_control_mask &= ~exception_mask;
04226 net_draw_show_mask |= exception_mask;
04227 }
04228
04229 if (drawmask_cat.is_debug()) {
04230 drawmask_cat.debug(false)
04231 << "child_control_mask = " << child_control_mask
04232 << "\nchild_show_mask = " << child_show_mask
04233 << "\nnet_draw_control_mask = " << net_draw_control_mask
04234 << "\nnet_draw_show_mask = " << net_draw_show_mask
04235 << "\n";
04236 }
04237
04238 off_clip_planes = orig_cp->compose_off(child_cdata->_off_clip_planes);
04239 if (!child_cdata->_external_bounds->is_empty()) {
04240 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04241 child_volumes_ref.push_back(child_cdata->_external_bounds);
04242 #endif
04243 nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04244 child_volumes[child_volumes_i++] = child_cdata->_external_bounds;
04245 if (child_cdata->_external_bounds->as_bounding_box() == NULL) {
04246 all_box = false;
04247 }
04248 }
04249 num_vertices += child_cdata->_nested_vertices;
04250 }
04251 }
04252
04253 {
04254
04255 CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
04256 if (last_update == cdataw->_last_update &&
04257 next_update == cdataw->_next_update) {
04258
04259
04260 cdataw->_net_collide_mask = net_collide_mask;
04261
04262 if (renderable) {
04263
04264
04265 DrawMask draw_control_mask = cdataw->_draw_control_mask;
04266 DrawMask draw_show_mask = cdataw->_draw_show_mask;
04267
04268 DrawMask show_through_mask = net_draw_control_mask & net_draw_show_mask;
04269
04270 net_draw_control_mask |= draw_control_mask;
04271 net_draw_show_mask = (net_draw_show_mask & ~draw_control_mask) | (draw_show_mask & draw_control_mask);
04272
04273 net_draw_show_mask |= show_through_mask;
04274
04275
04276
04277 cdataw->_net_draw_control_mask = net_draw_control_mask;
04278 cdataw->_net_draw_show_mask = net_draw_show_mask | ~net_draw_control_mask;
04279 if (drawmask_cat.is_debug()) {
04280 drawmask_cat.debug(false)
04281 << "renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
04282 }
04283 } else {
04284
04285
04286
04287
04288 cdataw->_net_draw_control_mask = net_draw_control_mask;
04289 cdataw->_net_draw_show_mask = net_draw_show_mask;
04290 if (drawmask_cat.is_debug()) {
04291 drawmask_cat.debug(false)
04292 << "not renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
04293 }
04294 }
04295
04296 cdataw->_off_clip_planes = off_clip_planes;
04297 cdataw->_nested_vertices = num_vertices;
04298
04299 CPT(TransformState) transform = get_transform(current_thread);
04300 PT(GeometricBoundingVolume) gbv;
04301
04302 BoundingVolume::BoundsType btype = cdataw->_bounds_type;
04303 if (btype == BoundingVolume::BT_default) {
04304 btype = bounds_type;
04305 }
04306
04307 if (btype == BoundingVolume::BT_box ||
04308 (btype != BoundingVolume::BT_sphere && all_box && transform->is_identity())) {
04309
04310
04311
04312
04313 gbv = new BoundingBox;
04314 } else {
04315
04316 gbv = new BoundingSphere;
04317 }
04318
04319 if (child_volumes_i > 0) {
04320 const BoundingVolume **child_begin = &child_volumes[0];
04321 const BoundingVolume **child_end = child_begin + child_volumes_i;
04322 ((BoundingVolume *)gbv)->around(child_begin, child_end);
04323 }
04324
04325
04326
04327 if (!transform->is_identity()) {
04328 gbv->xform(transform->get_mat());
04329 }
04330
04331 cdataw->_external_bounds = gbv;
04332 cdataw->_last_update = next_update;
04333
04334 if (drawmask_cat.is_debug()) {
04335 drawmask_cat.debug(false)
04336 << "} " << *this << "::update_bounds();\n";
04337 }
04338
04339 nassertr(cdataw->_last_update == cdataw->_next_update, cdataw);
04340
04341
04342
04343 mark_bam_modified();
04344 return cdataw;
04345 }
04346
04347 if (cdataw->_last_update == cdataw->_next_update) {
04348
04349 return cdataw;
04350 }
04351 }
04352
04353
04354
04355 cdata = CDLockedStageReader(_cycler, pipeline_stage, current_thread);
04356
04357 if (cdata->_last_update == cdata->_next_update) {
04358
04359
04360 return CDStageWriter(_cycler, pipeline_stage, cdata);
04361 }
04362
04363 } while (true);
04364 }
04365
04366
04367
04368
04369
04370
04371
04372
04373
04374
04375
04376 void PandaNode::
04377 set_scene_root_func(SceneRootFunc *func) {
04378 _scene_root_func = func;
04379 }
04380
04381
04382
04383
04384
04385
04386
04387 void PandaNode::
04388 register_with_read_factory() {
04389 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
04390 }
04391
04392
04393
04394
04395
04396
04397
04398 void PandaNode::
04399 write_datagram(BamWriter *manager, Datagram &dg) {
04400 TypedWritable::write_datagram(manager, dg);
04401 dg.add_string(get_name());
04402
04403 manager->write_cdata(dg, _cycler);
04404 }
04405
04406
04407
04408
04409
04410
04411
04412
04413 void PandaNode::
04414 update_bam_nested(BamWriter *manager) {
04415 CDReader cdata(_cycler);
04416 cdata->update_bam_nested(manager);
04417 }
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435 void PandaNode::
04436 write_recorder(BamWriter *, Datagram &dg) {
04437 dg.add_string(get_name());
04438 }
04439
04440
04441
04442
04443
04444
04445
04446
04447
04448 TypedWritable *PandaNode::
04449 make_from_bam(const FactoryParams ¶ms) {
04450 PandaNode *node = new PandaNode("");
04451 DatagramIterator scan;
04452 BamReader *manager;
04453
04454 parse_params(params, scan, manager);
04455 node->fillin(scan, manager);
04456
04457 return node;
04458 }
04459
04460
04461
04462
04463
04464
04465
04466
04467 void PandaNode::
04468 fillin(DatagramIterator &scan, BamReader *manager) {
04469 TypedWritable::fillin(scan, manager);
04470
04471 string name = scan.get_string();
04472 set_name(name);
04473
04474 manager->read_cdata(scan, _cycler);
04475 }
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486 void PandaNode::
04487 fillin_recorder(DatagramIterator &scan, BamReader *) {
04488 string name = scan.get_string();
04489 set_name(name);
04490 }
04491
04492
04493
04494
04495
04496
04497 PandaNode::CData::
04498 CData() :
04499 _state(RenderState::make_empty()),
04500 _transform(TransformState::make_identity()),
04501 _prev_transform(TransformState::make_identity()),
04502
04503 _effects(RenderEffects::make_empty()),
04504 _draw_control_mask(DrawMask::all_off()),
04505 _draw_show_mask(DrawMask::all_on()),
04506 _into_collide_mask(CollideMask::all_off()),
04507 _bounds_type(BoundingVolume::BT_default),
04508 _user_bounds(NULL),
04509 _final_bounds(false),
04510 _fancy_bits(0),
04511
04512 _net_collide_mask(CollideMask::all_off()),
04513 _net_draw_control_mask(DrawMask::all_off()),
04514 _net_draw_show_mask(DrawMask::all_off()),
04515
04516 _down(new PandaNode::Down(PandaNode::get_class_type())),
04517 _stashed(new PandaNode::Down(PandaNode::get_class_type())),
04518 _up(new PandaNode::Up(PandaNode::get_class_type()))
04519 {
04520 ++_next_update;
04521 }
04522
04523
04524
04525
04526
04527
04528 PandaNode::CData::
04529 CData(const PandaNode::CData ©) :
04530 BoundsData(copy),
04531 _state(copy._state),
04532 _transform(copy._transform),
04533 _prev_transform(copy._prev_transform),
04534
04535 _effects(copy._effects),
04536 _tag_data(copy._tag_data),
04537
04538 _draw_control_mask(copy._draw_control_mask),
04539 _draw_show_mask(copy._draw_show_mask),
04540 _into_collide_mask(copy._into_collide_mask),
04541 _bounds_type(copy._bounds_type),
04542 _user_bounds(copy._user_bounds),
04543 _final_bounds(copy._final_bounds),
04544 _fancy_bits(copy._fancy_bits),
04545
04546 _net_collide_mask(copy._net_collide_mask),
04547 _net_draw_control_mask(copy._net_draw_control_mask),
04548 _net_draw_show_mask(copy._net_draw_show_mask),
04549 _off_clip_planes(copy._off_clip_planes),
04550 _nested_vertices(copy._nested_vertices),
04551 _external_bounds(copy._external_bounds),
04552 _last_update(copy._last_update),
04553 _next_update(copy._next_update),
04554
04555 _down(copy._down),
04556 _stashed(copy._stashed),
04557 _up(copy._up)
04558 {
04559
04560
04561
04562
04563 #ifdef HAVE_PYTHON
04564
04565
04566 _python_tag_data = copy._python_tag_data;
04567 inc_py_refs();
04568 #endif // HAVE_PYTHON
04569 }
04570
04571
04572
04573
04574
04575
04576 PandaNode::CData::
04577 ~CData() {
04578 #ifdef HAVE_PYTHON
04579
04580 dec_py_refs();
04581 #endif // HAVE_PYTHON
04582 }
04583
04584
04585
04586
04587
04588
04589 CycleData *PandaNode::CData::
04590 make_copy() const {
04591 return new CData(*this);
04592 }
04593
04594
04595
04596
04597
04598
04599
04600 void PandaNode::CData::
04601 write_datagram(BamWriter *manager, Datagram &dg) const {
04602 manager->write_pointer(dg, _state);
04603 manager->write_pointer(dg, _transform);
04604
04605
04606 manager->write_pointer(dg, _effects);
04607
04608 dg.add_uint32(_draw_control_mask.get_word());
04609 dg.add_uint32(_draw_show_mask.get_word());
04610 dg.add_uint32(_into_collide_mask.get_word());
04611 dg.add_uint8(_bounds_type);
04612
04613 dg.add_uint32(_tag_data.size());
04614 TagData::const_iterator ti;
04615 for (ti = _tag_data.begin(); ti != _tag_data.end(); ++ti) {
04616 dg.add_string((*ti).first);
04617 dg.add_string((*ti).second);
04618 }
04619
04620
04621 write_up_list(*get_up(), manager, dg);
04622 write_down_list(*get_down(), manager, dg);
04623 write_down_list(*get_stashed(), manager, dg);
04624 }
04625
04626
04627
04628
04629
04630
04631
04632
04633 void PandaNode::CData::
04634 update_bam_nested(BamWriter *manager) const {
04635
04636
04637
04638
04639
04640
04641 update_up_list(*get_up(), manager);
04642 update_down_list(*get_down(), manager);
04643 update_down_list(*get_stashed(), manager);
04644 }
04645
04646
04647
04648
04649
04650
04651
04652
04653 int PandaNode::CData::
04654 complete_pointers(TypedWritable **p_list, BamReader *manager) {
04655 int pi = CycleData::complete_pointers(p_list, manager);
04656
04657
04658 _state = DCAST(RenderState, p_list[pi++]);
04659 _transform = DCAST(TransformState, p_list[pi++]);
04660 _prev_transform = _transform;
04661
04662
04663
04664
04665
04666
04667
04668
04669
04670 manager->finalize_now((RenderState *)_state.p());
04671 manager->finalize_now((TransformState *)_transform.p());
04672
04673
04674
04675
04676 _effects = DCAST(RenderEffects, p_list[pi++]);
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686 manager->finalize_now((RenderEffects *)_effects.p());
04687
04688
04689
04690
04691 pi += complete_up_list(*modify_up(), "up", p_list + pi, manager);
04692 pi += complete_down_list(*modify_down(), "down", p_list + pi, manager);
04693 pi += complete_down_list(*modify_stashed(), "stashed", p_list + pi, manager);
04694
04695
04696
04697 set_fancy_bit(FB_transform, !_transform->is_identity());
04698 set_fancy_bit(FB_state, !_state->is_empty());
04699 set_fancy_bit(FB_effects, !_effects->is_empty());
04700 set_fancy_bit(FB_tag, !_tag_data.empty());
04701
04702 return pi;
04703 }
04704
04705
04706
04707
04708
04709
04710
04711
04712 void PandaNode::CData::
04713 fillin(DatagramIterator &scan, BamReader *manager) {
04714
04715 manager->read_pointer(scan);
04716 manager->read_pointer(scan);
04717
04718
04719
04720 manager->read_pointer(scan);
04721
04722 if (manager->get_file_minor_ver() < 2) {
04723 DrawMask draw_mask;
04724 draw_mask.set_word(scan.get_uint32());
04725
04726 if (draw_mask == DrawMask::all_off()) {
04727
04728 _draw_control_mask = _overall_bit;
04729 _draw_show_mask = ~_overall_bit;
04730
04731 } else if (draw_mask == DrawMask::all_on()) {
04732
04733 _draw_control_mask = DrawMask::all_off();
04734 _draw_show_mask = DrawMask::all_on();
04735
04736 } else {
04737
04738 draw_mask &= ~_overall_bit;
04739 _draw_control_mask = ~draw_mask;
04740 _draw_show_mask = draw_mask;
04741 }
04742
04743 } else {
04744 _draw_control_mask.set_word(scan.get_uint32());
04745 _draw_show_mask.set_word(scan.get_uint32());
04746 }
04747
04748 _into_collide_mask.set_word(scan.get_uint32());
04749
04750 _bounds_type = BoundingVolume::BT_default;
04751 if (manager->get_file_minor_ver() >= 19) {
04752 _bounds_type = (BoundingVolume::BoundsType)scan.get_uint8();
04753 }
04754
04755
04756 int num_tags = scan.get_uint32();
04757 for (int i = 0; i < num_tags; i++) {
04758 string key = scan.get_string();
04759 string value = scan.get_string();
04760 _tag_data[key] = value;
04761 }
04762
04763
04764 fillin_up_list(*modify_up(), "up", scan, manager);
04765 fillin_down_list(*modify_down(), "down", scan, manager);
04766 fillin_down_list(*modify_stashed(), "stashed", scan, manager);
04767 }
04768
04769 #ifdef HAVE_PYTHON
04770
04771
04772
04773
04774
04775
04776 void PandaNode::CData::
04777 inc_py_refs() {
04778 if (!_python_tag_data.empty()) {
04779 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04780
04781
04782 PyGILState_STATE gstate;
04783 gstate = PyGILState_Ensure();
04784 #endif
04785 PythonTagData::const_iterator ti;
04786 for (ti = _python_tag_data.begin();
04787 ti != _python_tag_data.end();
04788 ++ti) {
04789 PyObject *value = (*ti).second;
04790 Py_XINCREF(value);
04791 }
04792 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04793 PyGILState_Release(gstate);
04794 #endif
04795 }
04796 }
04797 #endif // HAVE_PYTHON
04798
04799 #ifdef HAVE_PYTHON
04800
04801
04802
04803
04804
04805
04806 void PandaNode::CData::
04807 dec_py_refs() {
04808 if (!_python_tag_data.empty()) {
04809 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04810
04811
04812 PyGILState_STATE gstate;
04813 gstate = PyGILState_Ensure();
04814 #endif
04815
04816 PythonTagData::const_iterator ti;
04817 for (ti = _python_tag_data.begin();
04818 ti != _python_tag_data.end();
04819 ++ti) {
04820 PyObject *value = (*ti).second;
04821 Py_XDECREF(value);
04822 }
04823
04824 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04825 PyGILState_Release(gstate);
04826 #endif
04827 }
04828 }
04829 #endif // HAVE_PYTHON
04830
04831
04832
04833
04834
04835
04836
04837 void PandaNode::CData::
04838 write_up_list(const PandaNode::Up &up_list,
04839 BamWriter *manager, Datagram &dg) const {
04840
04841
04842
04843
04844
04845
04846
04847
04848
04849 int num_parents = 0;
04850 Up::const_iterator ui;
04851 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04852 PandaNode *parent_node = (*ui).get_parent();
04853 if (manager->has_object(parent_node)) {
04854 num_parents++;
04855 }
04856 }
04857 nassertv(num_parents == (int)(PN_uint16)num_parents);
04858 dg.add_uint16(num_parents);
04859 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04860 PandaNode *parent_node = (*ui).get_parent();
04861 if (manager->has_object(parent_node)) {
04862 manager->write_pointer(dg, parent_node);
04863 }
04864 }
04865 }
04866
04867
04868
04869
04870
04871
04872
04873 void PandaNode::CData::
04874 write_down_list(const PandaNode::Down &down_list,
04875 BamWriter *manager, Datagram &dg) const {
04876 int num_children = down_list.size();
04877 nassertv(num_children == (int)(PN_uint16)num_children);
04878 dg.add_uint16(num_children);
04879
04880
04881
04882 Down::const_iterator di;
04883 for (di = down_list.begin(); di != down_list.end(); ++di) {
04884 PandaNode *child_node = (*di).get_child();
04885 int sort = (*di).get_sort();
04886 manager->write_pointer(dg, child_node);
04887 dg.add_int32(sort);
04888 }
04889 }
04890
04891
04892
04893
04894
04895
04896
04897 void PandaNode::CData::
04898 update_up_list(const PandaNode::Up &up_list, BamWriter *manager) const {
04899 Up::const_iterator ui;
04900 for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04901 PandaNode *parent_node = (*ui).get_parent();
04902 if (manager->has_object(parent_node)) {
04903 manager->consider_update(parent_node);
04904 }
04905 }
04906 }
04907
04908
04909
04910
04911
04912
04913
04914 void PandaNode::CData::
04915 update_down_list(const PandaNode::Down &down_list, BamWriter *manager) const {
04916 Down::const_iterator di;
04917 for (di = down_list.begin(); di != down_list.end(); ++di) {
04918 PandaNode *child_node = (*di).get_child();
04919 manager->consider_update(child_node);
04920 }
04921 }
04922
04923
04924
04925
04926
04927
04928
04929 int PandaNode::CData::
04930 complete_up_list(PandaNode::Up &up_list, const string &tag,
04931 TypedWritable **p_list, BamReader *manager) {
04932 int pi = 0;
04933
04934 int num_parents = manager->get_int_tag(tag);
04935 Up new_up_list(PandaNode::get_class_type());
04936 new_up_list.reserve(num_parents);
04937 for (int i = 0; i < num_parents; i++) {
04938 PandaNode *parent_node = DCAST(PandaNode, p_list[pi++]);
04939 UpConnection connection(parent_node);
04940 new_up_list.push_back(connection);
04941 }
04942
04943
04944
04945
04946 new_up_list.sort();
04947
04948
04949 up_list.swap(new_up_list);
04950 new_up_list.clear();
04951
04952 return pi;
04953 }
04954
04955
04956
04957
04958
04959
04960
04961 int PandaNode::CData::
04962 complete_down_list(PandaNode::Down &down_list, const string &tag,
04963 TypedWritable **p_list, BamReader *manager) {
04964 int pi = 0;
04965
04966 BamReaderAuxDataDown *aux;
04967 DCAST_INTO_R(aux, manager->get_aux_tag(tag), pi);
04968
04969 Down &new_down_list = aux->_down_list;
04970 for (Down::iterator di = new_down_list.begin();
04971 di != new_down_list.end();
04972 ++di) {
04973 PandaNode *child_node = DCAST(PandaNode, p_list[pi++]);
04974 (*di).set_child(child_node);
04975 }
04976
04977
04978
04979
04980
04981
04982 down_list.swap(new_down_list);
04983 new_down_list.clear();
04984
04985 return pi;
04986 }
04987
04988
04989
04990
04991
04992
04993
04994
04995 void PandaNode::CData::
04996 fillin_up_list(PandaNode::Up &up_list, const string &tag,
04997 DatagramIterator &scan, BamReader *manager) {
04998 int num_parents = scan.get_uint16();
04999 manager->set_int_tag(tag, num_parents);
05000 manager->read_pointers(scan, num_parents);
05001 }
05002
05003
05004
05005
05006
05007
05008
05009
05010 void PandaNode::CData::
05011 fillin_down_list(PandaNode::Down &down_list, const string &tag,
05012 DatagramIterator &scan, BamReader *manager) {
05013 int num_children = scan.get_uint16();
05014
05015
05016
05017
05018
05019 Down new_down_list(PandaNode::get_class_type());
05020 new_down_list.reserve(num_children);
05021 for (int i = 0; i < num_children; i++) {
05022 manager->read_pointer(scan);
05023 int sort = scan.get_int32();
05024 DownConnection connection(NULL, sort);
05025 new_down_list.push_back(connection);
05026 }
05027
05028
05029
05030 PT(BamReaderAuxDataDown) aux = new BamReaderAuxDataDown;
05031 aux->_down_list.swap(new_down_list);
05032 manager->set_aux_tag(tag, aux);
05033 }
05034
05035
05036
05037
05038
05039
05040
05041 void PandaNodePipelineReader::
05042 check_bounds() const {
05043 if (_cdata->_last_update != _cdata->_next_update) {
05044
05045
05046
05047
05048
05049 #ifdef DO_PIPELINING
05050 node_unref_delete((CycleData *)_cdata);
05051 #endif // DO_PIPELINING
05052 ((PandaNodePipelineReader *)this)->_cdata = NULL;
05053 int pipeline_stage = _current_thread->get_pipeline_stage();
05054 PandaNode::CDLockedStageReader fresh_cdata(_object->_cycler, pipeline_stage, _current_thread);
05055 if (fresh_cdata->_last_update == fresh_cdata->_next_update) {
05056
05057
05058
05059 if (_cdata != (const PandaNode::CData *)fresh_cdata) {
05060 ((PandaNodePipelineReader *)this)->_cdata = fresh_cdata;
05061 #ifdef DO_PIPELINING
05062 _cdata->node_ref();
05063 #endif // DO_PIPELINING
05064 }
05065
05066 } else {
05067
05068
05069 PStatTimer timer(PandaNode::_update_bounds_pcollector);
05070 PandaNode::CDStageWriter cdataw = ((PandaNode *)_object)->update_bounds(pipeline_stage, fresh_cdata);
05071 nassertv(cdataw->_last_update == cdataw->_next_update);
05072
05073
05074 if (_cdata != (const PandaNode::CData *)cdataw) {
05075 ((PandaNodePipelineReader *)this)->_cdata = cdataw;
05076 #ifdef DO_PIPELINING
05077 _cdata->node_ref();
05078 #endif // DO_PIPELINING
05079 }
05080 }
05081 }
05082
05083 nassertv(_cdata->_last_update == _cdata->_next_update);
05084 }