00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "lightAttrib.h"
00016 #include "pandaNode.h"
00017 #include "nodePath.h"
00018 #include "graphicsStateGuardianBase.h"
00019 #include "bamReader.h"
00020 #include "bamWriter.h"
00021 #include "datagram.h"
00022 #include "datagramIterator.h"
00023 #include "config_pgraph.h"
00024 #include "attribNodeRegistry.h"
00025 #include "indent.h"
00026 #include <iterator>
00027
00028 CPT(RenderAttrib) LightAttrib::_empty_attrib;
00029 int LightAttrib::_attrib_slot;
00030 CPT(RenderAttrib) LightAttrib::_all_off_attrib;
00031 TypeHandle LightAttrib::_type_handle;
00032
00033
00034
00035
00036 class CompareLightPriorities {
00037 public:
00038 bool operator ()(const NodePath &a, const NodePath &b) const {
00039 nassertr(!a.is_empty() && !b.is_empty(), a < b);
00040 Light *la = a.node()->as_light();
00041 Light *lb = b.node()->as_light();
00042 nassertr(la != (Light *)NULL && lb != (Light *)NULL, a < b);
00043
00044 if (la->get_priority() != lb->get_priority()) {
00045 return la->get_priority() > lb->get_priority();
00046 }
00047 return la->get_class_priority() > lb->get_class_priority();
00048 }
00049 };
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 CPT(RenderAttrib) LightAttrib::
00061 make(LightAttrib::Operation op, Light *light) {
00062 pgraph_cat.warning()
00063 << "Using deprecated LightAttrib interface.\n";
00064
00065 CPT(RenderAttrib) attrib;
00066
00067 switch (op) {
00068 case O_set:
00069 attrib = make_all_off();
00070 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light->as_node()));
00071 return attrib;
00072
00073 case O_add:
00074 attrib = make();
00075 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light->as_node()));
00076 return attrib;
00077
00078 case O_remove:
00079 attrib = make();
00080 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light->as_node()));
00081 return attrib;
00082 }
00083
00084 nassertr(false, make());
00085 return make();
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 CPT(RenderAttrib) LightAttrib::
00098 make(LightAttrib::Operation op, Light *light1, Light *light2) {
00099 pgraph_cat.warning()
00100 << "Using deprecated LightAttrib interface.\n";
00101
00102 CPT(RenderAttrib) attrib;
00103
00104 switch (op) {
00105 case O_set:
00106 attrib = make_all_off();
00107 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
00108 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
00109 return attrib;
00110
00111 case O_add:
00112 attrib = make();
00113 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
00114 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
00115 return attrib;
00116
00117 case O_remove:
00118 attrib = make();
00119 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
00120 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
00121 return attrib;
00122 }
00123
00124 nassertr(false, make());
00125 return make();
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 CPT(RenderAttrib) LightAttrib::
00138 make(LightAttrib::Operation op, Light *light1, Light *light2,
00139 Light *light3) {
00140 pgraph_cat.warning()
00141 << "Using deprecated LightAttrib interface.\n";
00142
00143 CPT(RenderAttrib) attrib;
00144
00145 switch (op) {
00146 case O_set:
00147 attrib = make_all_off();
00148 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
00149 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
00150 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
00151 return attrib;
00152
00153 case O_add:
00154 attrib = make();
00155 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
00156 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
00157 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
00158 return attrib;
00159
00160 case O_remove:
00161 attrib = make();
00162 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
00163 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
00164 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light3->as_node()));
00165 return attrib;
00166 }
00167
00168 nassertr(false, make());
00169 return make();
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 CPT(RenderAttrib) LightAttrib::
00182 make(LightAttrib::Operation op, Light *light1, Light *light2,
00183 Light *light3, Light *light4) {
00184 pgraph_cat.warning()
00185 << "Using deprecated LightAttrib interface.\n";
00186
00187 CPT(RenderAttrib) attrib;
00188
00189 switch (op) {
00190 case O_set:
00191 attrib = make_all_off();
00192 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
00193 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
00194 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
00195 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light4->as_node()));
00196 return attrib;
00197
00198 case O_add:
00199 attrib = make();
00200 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light1->as_node()));
00201 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light2->as_node()));
00202 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light3->as_node()));
00203 attrib = DCAST(LightAttrib, attrib)->add_on_light(NodePath(light4->as_node()));
00204 return attrib;
00205
00206 case O_remove:
00207 attrib = make();
00208 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light1->as_node()));
00209 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light2->as_node()));
00210 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light3->as_node()));
00211 attrib = DCAST(LightAttrib, attrib)->add_off_light(NodePath(light4->as_node()));
00212 return attrib;
00213 }
00214
00215 nassertr(false, make());
00216 return make();
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226 CPT(RenderAttrib) LightAttrib::
00227 make_default() {
00228 return return_new(new LightAttrib);
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 LightAttrib::Operation LightAttrib::
00248 get_operation() const {
00249 pgraph_cat.warning()
00250 << "Using deprecated LightAttrib interface.\n";
00251
00252 if (has_all_off()) {
00253 return O_set;
00254
00255 } else if (get_num_off_lights() == 0) {
00256 return O_add;
00257
00258 } else {
00259 return O_remove;
00260 }
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 int LightAttrib::
00274 get_num_lights() const {
00275 pgraph_cat.warning()
00276 << "Using deprecated LightAttrib interface.\n";
00277
00278 if (get_num_off_lights() == 0) {
00279 return get_num_on_lights();
00280 } else {
00281 return get_num_off_lights();
00282 }
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 Light *LightAttrib::
00296 get_light(int n) const {
00297 pgraph_cat.warning()
00298 << "Using deprecated LightAttrib interface.\n";
00299
00300 if (get_num_off_lights() == 0) {
00301 return get_on_light(n).node()->as_light();
00302 } else {
00303 return get_off_light(n).node()->as_light();
00304 }
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 bool LightAttrib::
00319 has_light(Light *light) const {
00320 pgraph_cat.warning()
00321 << "Using deprecated LightAttrib interface.\n";
00322
00323 if (get_num_off_lights() == 0) {
00324 return has_on_light(NodePath(light->as_node()));
00325 } else {
00326 return has_off_light(NodePath(light->as_node()));
00327 }
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 CPT(RenderAttrib) LightAttrib::
00340 add_light(Light *light) const {
00341 pgraph_cat.warning()
00342 << "Using deprecated LightAttrib interface.\n";
00343
00344 if (get_num_off_lights() == 0) {
00345 return add_on_light(NodePath(light->as_node()));
00346 } else {
00347 return add_off_light(NodePath(light->as_node()));
00348 }
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 CPT(RenderAttrib) LightAttrib::
00362 remove_light(Light *light) const {
00363 pgraph_cat.warning()
00364 << "Using deprecated LightAttrib interface.\n";
00365
00366 if (get_num_off_lights() == 0) {
00367 return remove_on_light(NodePath(light->as_node()));
00368 } else {
00369 return remove_off_light(NodePath(light->as_node()));
00370 }
00371 }
00372
00373
00374
00375
00376
00377
00378
00379 CPT(RenderAttrib) LightAttrib::
00380 make() {
00381
00382
00383 if (_empty_attrib == (RenderAttrib *)NULL) {
00384 _empty_attrib = return_new(new LightAttrib);
00385 }
00386
00387 return _empty_attrib;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 CPT(RenderAttrib) LightAttrib::
00397 make_all_off() {
00398
00399
00400 if (_all_off_attrib == (RenderAttrib *)NULL) {
00401 LightAttrib *attrib = new LightAttrib;
00402 attrib->_off_all_lights = true;
00403 _all_off_attrib = return_new(attrib);
00404 }
00405
00406 return _all_off_attrib;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416 CPT(RenderAttrib) LightAttrib::
00417 add_on_light(const NodePath &light) const {
00418 nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
00419 LightAttrib *attrib = new LightAttrib(*this);
00420 attrib->_on_lights.insert(light);
00421 attrib->_off_lights.erase(light);
00422
00423 pair<Lights::iterator, bool> insert_result =
00424 attrib->_on_lights.insert(Lights::value_type(light));
00425 if (insert_result.second) {
00426
00427 attrib->_off_lights.erase(light);
00428 }
00429
00430 return return_new(attrib);
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440 CPT(RenderAttrib) LightAttrib::
00441 remove_on_light(const NodePath &light) const {
00442 nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
00443 LightAttrib *attrib = new LightAttrib(*this);
00444 attrib->_on_lights.erase(light);
00445 return return_new(attrib);
00446 }
00447
00448
00449
00450
00451
00452
00453
00454
00455 CPT(RenderAttrib) LightAttrib::
00456 add_off_light(const NodePath &light) const {
00457 nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
00458 LightAttrib *attrib = new LightAttrib(*this);
00459 if (!_off_all_lights) {
00460 attrib->_off_lights.insert(light);
00461 }
00462 attrib->_on_lights.erase(light);
00463 return return_new(attrib);
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 CPT(RenderAttrib) LightAttrib::
00474 remove_off_light(const NodePath &light) const {
00475 nassertr(!light.is_empty() && light.node()->as_light() != (Light *)NULL, this);
00476 LightAttrib *attrib = new LightAttrib(*this);
00477 attrib->_off_lights.erase(light);
00478 return return_new(attrib);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 CPT(LightAttrib) LightAttrib::
00495 filter_to_max(int max_lights) const {
00496 if (max_lights < 0 || (int)_on_lights.size() <= max_lights) {
00497
00498 return this;
00499 }
00500
00501
00502
00503 check_filtered();
00504
00505 Filtered::const_iterator fi;
00506 fi = _filtered.find(max_lights);
00507 if (fi != _filtered.end()) {
00508
00509
00510 return (*fi).second;
00511 }
00512
00513
00514
00515 Lights priority_lights, ambient_lights;
00516
00517
00518 Lights::const_iterator li;
00519 for (li = _on_lights.begin(); li != _on_lights.end(); ++li) {
00520 const NodePath &np = (*li);
00521 nassertr(!np.is_empty() && np.node()->as_light() != (Light *)NULL, this);
00522 if (np.node()->is_ambient_light()) {
00523 ambient_lights.push_back(np);
00524 } else {
00525 priority_lights.push_back(np);
00526 }
00527 }
00528
00529
00530 sort(priority_lights.begin(), priority_lights.end(),
00531 CompareLightPriorities());
00532
00533
00534 if ((int)priority_lights.size() > max_lights) {
00535 priority_lights.erase(priority_lights.begin() + max_lights,
00536 priority_lights.end());
00537 }
00538
00539
00540 for (li = ambient_lights.begin(); li != ambient_lights.end(); ++li) {
00541 priority_lights.push_back(*li);
00542 }
00543
00544
00545 priority_lights.sort();
00546
00547
00548 PT(LightAttrib) attrib = new LightAttrib;
00549 attrib->_on_lights.swap(priority_lights);
00550
00551 CPT(RenderAttrib) new_attrib = return_new(attrib);
00552
00553
00554
00555 CPT(LightAttrib) light_attrib = (const LightAttrib *)new_attrib.p();
00556 ((LightAttrib *)this)->_filtered[max_lights] = light_attrib;
00557 return light_attrib;
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 NodePath LightAttrib::
00569 get_most_important_light() const {
00570 NodePath best;
00571
00572 CompareLightPriorities compare;
00573
00574 Lights::const_iterator li;
00575 for (li = _on_lights.begin(); li != _on_lights.end(); ++li) {
00576 const NodePath &np = (*li);
00577 nassertr(!np.is_empty() && np.node()->as_light() != (Light *)NULL, NodePath());
00578 if (!np.node()->is_ambient_light()) {
00579 if (best.is_empty() || compare(np, best)) {
00580 best = np;
00581 }
00582 }
00583 }
00584
00585 return best;
00586 }
00587
00588
00589
00590
00591
00592
00593 void LightAttrib::
00594 output(ostream &out) const {
00595 out << get_type() << ":";
00596 if (_off_lights.empty()) {
00597 if (_on_lights.empty()) {
00598 if (_off_all_lights) {
00599 out << "all off";
00600 } else {
00601 out << "identity";
00602 }
00603 } else {
00604 if (_off_all_lights) {
00605 out << "set";
00606 } else {
00607 out << "on";
00608 }
00609 }
00610
00611 } else {
00612 out << "off";
00613 Lights::const_iterator fi;
00614 for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
00615 NodePath light = (*fi);
00616 if (light.is_empty()) {
00617 out << " " << light;
00618 } else {
00619 out << " " << light.get_name();
00620 }
00621 }
00622
00623 if (!_on_lights.empty()) {
00624 out << " on";
00625 }
00626 }
00627
00628 Lights::const_iterator li;
00629 for (li = _on_lights.begin(); li != _on_lights.end(); ++li) {
00630 NodePath light = (*li);
00631 if (light.is_empty()) {
00632 out << " " << light;
00633 } else {
00634 out << " " << light.get_name();
00635 }
00636 }
00637 }
00638
00639
00640
00641
00642
00643
00644 void LightAttrib::
00645 write(ostream &out, int indent_level) const {
00646 indent(out, indent_level) << get_type() << ":";
00647 if (_off_lights.empty()) {
00648 if (_on_lights.empty()) {
00649 if (_off_all_lights) {
00650 out << "all off\n";
00651 } else {
00652 out << "identity\n";
00653 }
00654 } else {
00655 if (_off_all_lights) {
00656 out << "set\n";
00657 } else {
00658 out << "on\n";
00659 }
00660 }
00661
00662 } else {
00663 out << "off\n";
00664 Lights::const_iterator fi;
00665 for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
00666 NodePath light = (*fi);
00667 indent(out, indent_level + 2) << light << "\n";
00668 }
00669
00670 if (!_on_lights.empty()) {
00671 indent(out, indent_level) << "on\n";
00672 }
00673 }
00674
00675 Lights::const_iterator li;
00676 for (li = _on_lights.begin(); li != _on_lights.end(); ++li) {
00677 NodePath light = (*li);
00678 indent(out, indent_level + 2) << light << "\n";
00679 }
00680 }
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697 int LightAttrib::
00698 compare_to_impl(const RenderAttrib *other) const {
00699 const LightAttrib *ta;
00700 DCAST_INTO_R(ta, other, 0);
00701
00702 if (_off_all_lights != ta->_off_all_lights) {
00703 return (int)_off_all_lights - (int)ta->_off_all_lights;
00704 }
00705
00706 Lights::const_iterator li = _on_lights.begin();
00707 Lights::const_iterator oli = ta->_on_lights.begin();
00708
00709 while (li != _on_lights.end() && oli != ta->_on_lights.end()) {
00710 NodePath light = (*li);
00711 NodePath other_light = (*oli);
00712
00713 int compare = light.compare_to(other_light);
00714 if (compare != 0) {
00715 return compare;
00716 }
00717
00718 ++li;
00719 ++oli;
00720 }
00721
00722 if (li != _on_lights.end()) {
00723 return 1;
00724 }
00725 if (oli != ta->_on_lights.end()) {
00726 return -1;
00727 }
00728
00729 Lights::const_iterator fi = _off_lights.begin();
00730 Lights::const_iterator ofi = ta->_off_lights.begin();
00731
00732 while (fi != _off_lights.end() && ofi != ta->_off_lights.end()) {
00733 NodePath light = (*fi);
00734 NodePath other_light = (*ofi);
00735
00736 int compare = light.compare_to(other_light);
00737 if (compare != 0) {
00738 return compare;
00739 }
00740
00741 ++fi;
00742 ++ofi;
00743 }
00744
00745 if (fi != _off_lights.end()) {
00746 return 1;
00747 }
00748 if (ofi != ta->_off_lights.end()) {
00749 return -1;
00750 }
00751
00752 return 0;
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 size_t LightAttrib::
00766 get_hash_impl() const {
00767 size_t hash = 0;
00768
00769 Lights::const_iterator li;
00770 for (li = _on_lights.begin(); li != _on_lights.end(); ++li) {
00771 NodePath light = (*li);
00772 hash = light.add_hash(hash);
00773 }
00774
00775
00776
00777 hash = int_hash::add_hash(hash, (int)_off_all_lights);
00778
00779 for (li = _off_lights.begin(); li != _off_lights.end(); ++li) {
00780 NodePath light = (*li);
00781 hash = light.add_hash(hash);
00782 }
00783
00784 return hash;
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 CPT(RenderAttrib) LightAttrib::
00805 compose_impl(const RenderAttrib *other) const {
00806 const LightAttrib *ta;
00807 DCAST_INTO_R(ta, other, 0);
00808
00809 if (ta->_off_all_lights) {
00810
00811
00812 return ta;
00813 }
00814
00815
00816
00817
00818 Lights::const_iterator ai = _on_lights.begin();
00819 Lights::const_iterator bi = ta->_on_lights.begin();
00820 Lights::const_iterator ci = ta->_off_lights.begin();
00821
00822
00823 LightAttrib *new_attrib = new LightAttrib;
00824 back_insert_iterator<Lights> result =
00825 back_inserter(new_attrib->_on_lights);
00826
00827 while (ai != _on_lights.end() &&
00828 bi != ta->_on_lights.end() &&
00829 ci != ta->_off_lights.end()) {
00830 if ((*ai) < (*bi)) {
00831 if ((*ai) < (*ci)) {
00832
00833
00834 *result = *ai;
00835 ++ai;
00836 ++result;
00837
00838 } else if ((*ci) < (*ai)) {
00839
00840
00841 ++ci;
00842
00843 } else {
00844
00845
00846 ++ai;
00847 ++ci;
00848 }
00849
00850 } else if ((*bi) < (*ai)) {
00851
00852
00853 *result = *bi;
00854 ++bi;
00855 ++result;
00856
00857 } else {
00858
00859 *result = *bi;
00860 ++ai;
00861 ++bi;
00862 ++result;
00863 }
00864 }
00865
00866 while (ai != _on_lights.end() && bi != ta->_on_lights.end()) {
00867 if ((*ai) < (*bi)) {
00868
00869
00870 *result = *ai;
00871 ++ai;
00872 ++result;
00873
00874 } else if ((*bi) < (*ai)) {
00875
00876
00877 *result = *bi;
00878 ++bi;
00879 ++result;
00880
00881 } else {
00882
00883 *result = *bi;
00884 ++ai;
00885 ++bi;
00886 ++result;
00887 }
00888 }
00889
00890 while (ai != _on_lights.end() && ci != ta->_off_lights.end()) {
00891 if ((*ai) < (*ci)) {
00892
00893
00894 *result = *ai;
00895 ++ai;
00896 ++result;
00897
00898 } else if ((*ci) < (*ai)) {
00899
00900
00901 ++ci;
00902
00903 } else {
00904
00905
00906 ++ai;
00907 ++ci;
00908 }
00909 }
00910
00911 while (ai != _on_lights.end()) {
00912 *result = *ai;
00913 ++ai;
00914 ++result;
00915 }
00916
00917 while (bi != ta->_on_lights.end()) {
00918 *result = *bi;
00919 ++bi;
00920 ++result;
00921 }
00922
00923 return return_new(new_attrib);
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 CPT(RenderAttrib) LightAttrib::
00936 invert_compose_impl(const RenderAttrib *other) const {
00937
00938
00939
00940 return other;
00941 }
00942
00943
00944
00945
00946
00947
00948 CPT(RenderAttrib) LightAttrib::
00949 get_auto_shader_attrib_impl(const RenderState *state) const {
00950 return this;
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961 void LightAttrib::
00962 sort_on_lights() {
00963 _sort_seq = Light::get_sort_seq();
00964 _filtered.clear();
00965 }
00966
00967
00968
00969
00970
00971
00972
00973 void LightAttrib::
00974 register_with_read_factory() {
00975 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00976 }
00977
00978
00979
00980
00981
00982
00983
00984 void LightAttrib::
00985 write_datagram(BamWriter *manager, Datagram &dg) {
00986 RenderAttrib::write_datagram(manager, dg);
00987
00988 dg.add_bool(_off_all_lights);
00989
00990
00991 dg.add_uint16(get_num_off_lights());
00992
00993 Lights::const_iterator fi;
00994 for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
00995 NodePath light = (*fi);
00996
00997
00998
00999
01000 manager->write_pointer(dg, light.node());
01001 }
01002
01003
01004 dg.add_uint16(get_num_on_lights());
01005
01006 Lights::const_iterator nti;
01007 for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
01008 NodePath light = (*nti);
01009 manager->write_pointer(dg, light.node());
01010 }
01011 }
01012
01013
01014
01015
01016
01017
01018
01019
01020 int LightAttrib::
01021 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01022 int pi = RenderAttrib::complete_pointers(p_list, manager);
01023
01024 BamAuxData *aux = (BamAuxData *)manager->get_aux_data(this, "lights");
01025 nassertr(aux != NULL, pi);
01026
01027 int i;
01028 aux->_off_list.reserve(aux->_num_off_lights);
01029 for (i = 0; i < aux->_num_off_lights; ++i) {
01030 PandaNode *node;
01031 DCAST_INTO_R(node, p_list[pi++], pi);
01032 aux->_off_list.push_back(node);
01033 }
01034
01035 aux->_on_list.reserve(aux->_num_on_lights);
01036 for (i = 0; i < aux->_num_on_lights; ++i) {
01037 PandaNode *node;
01038 DCAST_INTO_R(node, p_list[pi++], pi);
01039 aux->_on_list.push_back(node);
01040 }
01041
01042 return pi;
01043 }
01044
01045
01046
01047
01048
01049
01050
01051
01052 void LightAttrib::
01053 finalize(BamReader *manager) {
01054
01055 BamAuxData *aux = (BamAuxData *)manager->get_aux_data(this, "lights");
01056 nassertv(aux != NULL);
01057 nassertv(aux->_num_off_lights == (int)aux->_off_list.size());
01058 nassertv(aux->_num_on_lights == (int)aux->_on_list.size());
01059
01060 AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
01061
01062 _off_lights.reserve(aux->_off_list.size());
01063 NodeList::iterator ni;
01064 for (ni = aux->_off_list.begin(); ni != aux->_off_list.end(); ++ni) {
01065 PandaNode *node = (*ni);
01066 int n = areg->find_node(node->get_type(), node->get_name());
01067 if (n != -1) {
01068
01069 _off_lights.push_back(areg->get_node(n));
01070 } else {
01071
01072
01073 _off_lights.push_back(NodePath(node));
01074 }
01075 }
01076 _off_lights.sort();
01077
01078 _on_lights.reserve(aux->_on_list.size());
01079 for (ni = aux->_on_list.begin(); ni != aux->_on_list.end(); ++ni) {
01080 PandaNode *node = (*ni);
01081 int n = areg->find_node(node->get_type(), node->get_name());
01082 if (n != -1) {
01083
01084 _on_lights.push_back(areg->get_node(n));
01085 } else {
01086
01087
01088 _on_lights.push_back(NodePath(node));
01089 }
01090 }
01091 _on_lights.sort();
01092 }
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 TypedWritable *LightAttrib::
01103 make_from_bam(const FactoryParams ¶ms) {
01104 LightAttrib *attrib = new LightAttrib;
01105 DatagramIterator scan;
01106 BamReader *manager;
01107
01108 parse_params(params, scan, manager);
01109 attrib->fillin(scan, manager);
01110
01111 manager->register_finalize(attrib);
01112
01113 return attrib;
01114 }
01115
01116
01117
01118
01119
01120
01121
01122
01123 void LightAttrib::
01124 fillin(DatagramIterator &scan, BamReader *manager) {
01125 RenderAttrib::fillin(scan, manager);
01126
01127 _off_all_lights = scan.get_bool();
01128
01129 BamAuxData *aux = new BamAuxData;
01130 manager->set_aux_data(this, "lights", aux);
01131
01132 aux->_num_off_lights = scan.get_uint16();
01133 manager->read_pointers(scan, aux->_num_off_lights);
01134
01135 aux->_num_on_lights = scan.get_uint16();
01136 manager->read_pointers(scan, aux->_num_on_lights);
01137 }