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