00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggGroup.h"
00016 #include "eggMiscFuncs.h"
00017 #include "eggVertexPool.h"
00018 #include "eggBin.h"
00019 #include "lexerDefs.h"
00020
00021 #include "indent.h"
00022 #include "string_utils.h"
00023 #include "lmatrix.h"
00024 #include "dcast.h"
00025
00026
00027 TypeHandle EggGroup::_type_handle;
00028
00029
00030
00031
00032
00033
00034 EggGroup::
00035 EggGroup(const string &name) : EggGroupNode(name) {
00036 _flags = 0;
00037 _flags2 = 0;
00038 _fps = 0.0;
00039 _blend_mode = BM_unspecified;
00040 _blend_operand_a = BO_unspecified;
00041 _blend_operand_b = BO_unspecified;
00042 _blend_color = LColor::zero();
00043 _u_speed = 0;
00044 _v_speed = 0;
00045 _r_speed = 0;
00046 }
00047
00048
00049
00050
00051
00052
00053 EggGroup::
00054 EggGroup(const EggGroup ©) {
00055 (*this) = copy;
00056 }
00057
00058
00059
00060
00061
00062
00063 EggGroup &EggGroup::
00064 operator = (const EggGroup ©) {
00065 EggTransform::operator = (copy);
00066 _flags = copy._flags;
00067 _flags2 = copy._flags2;
00068 _collide_mask = copy._collide_mask;
00069 _from_collide_mask = copy._from_collide_mask;
00070 _into_collide_mask = copy._into_collide_mask;
00071 _billboard_center = copy._billboard_center;
00072 _object_types = copy._object_types;
00073 _collision_name = copy._collision_name;
00074 _fps = copy._fps;
00075 _lod = copy._lod;
00076 _blend_mode = copy._blend_mode;
00077 _blend_operand_a = copy._blend_operand_a;
00078 _blend_operand_b = copy._blend_operand_b;
00079 _blend_color = copy._blend_color;
00080 _tag_data = copy._tag_data;
00081 _u_speed = copy._u_speed;
00082 _v_speed = copy._v_speed;
00083 _r_speed = copy._r_speed;
00084 _default_pose = copy._default_pose;
00085
00086 unref_all_vertices();
00087 _vref = copy._vref;
00088
00089
00090
00091 VertexRef::iterator vri;
00092 for (vri = _vref.begin(); vri != _vref.end(); ++vri) {
00093 EggVertex *vert = (*vri).first;
00094
00095 bool inserted = vert->_gref.insert(this).second;
00096
00097
00098
00099 nassertr(inserted, *this);
00100 }
00101
00102
00103
00104
00105 EggGroupNode::operator = (copy);
00106 EggRenderMode::operator = (copy);
00107
00108 return *this;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117 EggGroup::
00118 ~EggGroup() {
00119 unref_all_vertices();
00120 }
00121
00122
00123
00124
00125
00126
00127 void EggGroup::
00128 set_group_type(GroupType type) {
00129 if (type != get_group_type()) {
00130 #ifndef NDEBUG
00131 if (type != GT_instance) {
00132
00133
00134 nassertv(_group_refs.empty());
00135 }
00136 #endif
00137
00138
00139 nassertv((type & ~F_group_type)==0);
00140 _flags = (_flags & ~F_group_type) | type;
00141
00142
00143
00144 update_under(0);
00145 }
00146 }
00147
00148
00149
00150
00151
00152
00153
00154 bool EggGroup::
00155 has_object_type(const string &object_type) const {
00156 vector_string::const_iterator oi;
00157 for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) {
00158 if (cmp_nocase_uh((*oi), object_type) == 0) {
00159 return true;
00160 }
00161 }
00162 return false;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 bool EggGroup::
00174 remove_object_type(const string &object_type) {
00175 vector_string::iterator oi;
00176 for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) {
00177 if (cmp_nocase_uh((*oi), object_type) == 0) {
00178 _object_types.erase(oi);
00179 return true;
00180 }
00181 }
00182 return false;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 void EggGroup::
00192 write(ostream &out, int indent_level) const {
00193 test_under_integrity();
00194
00195 switch (get_group_type()) {
00196 case GT_group:
00197 write_header(out, indent_level, "<Group>");
00198 break;
00199
00200 case GT_instance:
00201 write_header(out, indent_level, "<Instance>");
00202 break;
00203
00204 case GT_joint:
00205 write_header(out, indent_level, "<Joint>");
00206 break;
00207
00208 default:
00209
00210 nassertv(false);
00211 }
00212
00213 if (is_of_type(EggBin::get_class_type())) {
00214 indent(out, indent_level + 2)
00215 << "// Bin " << DCAST(EggBin, this)->get_bin_number() << "\n";
00216 }
00217
00218 if (has_lod()) {
00219 get_lod().write(out, indent_level + 2);
00220 }
00221
00222 write_billboard_flags(out, indent_level + 2);
00223 write_collide_flags(out, indent_level + 2);
00224 write_model_flags(out, indent_level + 2);
00225 write_switch_flags(out, indent_level + 2);
00226
00227 if (has_transform()) {
00228 EggTransform::write(out, indent_level + 2, "<Transform>");
00229 }
00230
00231 if (get_group_type() == GT_joint && _default_pose.has_transform()) {
00232 _default_pose.write(out, indent_level + 2, "<DefaultPose>");
00233 }
00234
00235 if(get_scroll_u() != 0) {
00236 indent(out, indent_level + 2)
00237 << "<Scalar> scroll_u { " << get_scroll_u() << " }\n";
00238
00239 }
00240
00241 if(get_scroll_v() != 0) {
00242 indent(out, indent_level + 2)
00243 << "<Scalar> scroll_v { " << get_scroll_v() << " }\n";
00244
00245 }
00246
00247 if(get_scroll_r() != 0) {
00248 indent(out, indent_level + 2)
00249 << "<Scalar> scroll_r { " << get_scroll_r() << " }\n";
00250
00251 }
00252
00253
00254 write_object_types(out, indent_level + 2);
00255 write_decal_flags(out, indent_level + 2);
00256 write_tags(out, indent_level + 2);
00257 write_render_mode(out, indent_level + 2);
00258
00259 if (get_portal_flag()) {
00260 indent(out, indent_level + 2) << "<Scalar> portal { 1 }\n";
00261 }
00262
00263 if (get_occluder_flag()) {
00264 indent(out, indent_level + 2) << "<Scalar> occluder { 1 }\n";
00265 }
00266
00267 if (get_polylight_flag()) {
00268 indent(out, indent_level + 2) << "<Scalar> polylight { 1 }\n";
00269 }
00270
00271 if (has_indexed_flag()) {
00272 indent(out, indent_level + 2)
00273 << "<Scalar> indexed { " << get_indexed_flag() << " }\n";
00274 }
00275
00276 if (get_blend_mode() != BM_unspecified) {
00277 indent(out, indent_level + 2)
00278 << "<Scalar> blend { " << get_blend_mode() << " }\n";
00279 }
00280
00281 if (get_blend_operand_a() != BO_unspecified) {
00282 indent(out, indent_level + 2)
00283 << "<Scalar> blendop-a { " << get_blend_operand_a() << " }\n";
00284 }
00285
00286 if (get_blend_operand_b() != BO_unspecified) {
00287 indent(out, indent_level + 2)
00288 << "<Scalar> blendop-b { " << get_blend_operand_b() << " }\n";
00289 }
00290
00291 if (has_blend_color()) {
00292 const LColor &c = get_blend_color();
00293 indent(out, indent_level + 2)
00294 << "<Scalar> blendr { " << c[0] << " }\n";
00295 indent(out, indent_level + 2)
00296 << "<Scalar> blendg { " << c[1] << " }\n";
00297 indent(out, indent_level + 2)
00298 << "<Scalar> blendb { " << c[2] << " }\n";
00299 indent(out, indent_level + 2)
00300 << "<Scalar> blenda { " << c[3] << " }\n";
00301 }
00302
00303 GroupRefs::const_iterator gri;
00304 for (gri = _group_refs.begin(); gri != _group_refs.end(); ++gri) {
00305 EggGroup *group_ref = (*gri);
00306 indent(out, indent_level + 2)
00307 << "<Ref> { " << group_ref->get_name() << " }\n";
00308 }
00309
00310
00311
00312
00313 EggGroupNode::write(out, indent_level + 2);
00314 write_vertex_ref(out, indent_level + 2);
00315
00316 indent(out, indent_level) << "}\n";
00317 }
00318
00319
00320
00321
00322
00323
00324
00325 void EggGroup::
00326 write_billboard_flags(ostream &out, int indent_level) const {
00327 if (get_billboard_type() != BT_none) {
00328 indent(out, indent_level)
00329 << "<Billboard> { " << get_billboard_type() << " }\n";
00330 }
00331
00332 if (has_billboard_center()) {
00333 indent(out, indent_level)
00334 << "<BillboardCenter> { " << get_billboard_center() << " }\n";
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343
00344 void EggGroup::
00345 write_collide_flags(ostream &out, int indent_level) const {
00346 if (get_cs_type() != CST_none) {
00347 indent(out, indent_level) << "<Collide> ";
00348 if (has_collision_name()) {
00349 enquote_string(out, get_collision_name()) << " ";
00350 }
00351 out << "{ " << get_cs_type();
00352 if (get_collide_flags() != CF_none) {
00353 out << " " << get_collide_flags();
00354 }
00355 out << " }\n";
00356 }
00357
00358 if (has_collide_mask()) {
00359 indent(out, indent_level)
00360 << "<Scalar> collide-mask { 0x";
00361 get_collide_mask().output_hex(out, 0);
00362 out << " }\n";
00363 }
00364
00365 if (has_from_collide_mask()) {
00366 indent(out, indent_level)
00367 << "<Scalar> from-collide-mask { 0x";
00368 get_from_collide_mask().output_hex(out, 0);
00369 out << " }\n";
00370 }
00371
00372 if (has_into_collide_mask()) {
00373 indent(out, indent_level)
00374 << "<Scalar> into-collide-mask { 0x";
00375 get_into_collide_mask().output_hex(out, 0);
00376 out << " }\n";
00377 }
00378 }
00379
00380
00381
00382
00383
00384
00385
00386 void EggGroup::
00387 write_model_flags(ostream &out, int indent_level) const {
00388 if (get_dcs_type() != DC_unspecified) {
00389 indent(out, indent_level)
00390 << "<DCS> { " << get_dcs_type() << " }\n";
00391 }
00392
00393 if (get_dart_type() != DT_none) {
00394 indent(out, indent_level)
00395 << "<Dart> { " << get_dart_type() << " }\n";
00396 }
00397
00398 if (get_model_flag()) {
00399 indent(out, indent_level) << "<Model> { 1 }\n";
00400 }
00401
00402 if (get_texlist_flag()) {
00403 indent(out, indent_level) << "<TexList> { 1 }\n";
00404 }
00405
00406 if (get_direct_flag()) {
00407 indent(out, indent_level) << "<Scalar> direct { 1 }\n";
00408 }
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 void EggGroup::
00418 write_switch_flags(ostream &out, int indent_level) const {
00419 if (get_switch_flag()) {
00420 indent(out, indent_level) << "<Switch> { 1 }\n";
00421 if (get_switch_fps() != 0.0) {
00422 indent(out, indent_level)
00423 << "<Scalar> fps { " << get_switch_fps() << " }\n";
00424 }
00425 }
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 void EggGroup::
00435 write_object_types(ostream &out, int indent_level) const {
00436 vector_string::const_iterator oi;
00437 for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) {
00438 indent(out, indent_level)
00439 << "<ObjectType> { ";
00440 enquote_string(out, (*oi)) << " }\n";
00441 }
00442 }
00443
00444
00445
00446
00447
00448
00449 void EggGroup::
00450 write_decal_flags(ostream &out, int indent_level) const {
00451 if (get_decal_flag()) {
00452 indent(out, indent_level) << "<Scalar> decal { 1 }\n";
00453 }
00454 }
00455
00456
00457
00458
00459
00460
00461
00462 void EggGroup::
00463 write_tags(ostream &out, int indent_level) const {
00464 TagData::const_iterator ti;
00465 for (ti = _tag_data.begin(); ti != _tag_data.end(); ++ti) {
00466 const string &key = (*ti).first;
00467 const string &value = (*ti).second;
00468
00469 indent(out, indent_level) << "<Tag> ";
00470 enquote_string(out, key) << " {\n";
00471 enquote_string(out, value, indent_level + 2) << "\n";
00472 indent(out, indent_level) << "}\n";
00473 }
00474 }
00475
00476
00477
00478
00479
00480
00481
00482 void EggGroup::
00483 write_render_mode(ostream &out, int indent_level) const {
00484 EggRenderMode::write(out, indent_level);
00485
00486 if (get_nofog_flag()) {
00487 indent(out, indent_level) << "<Scalar> no-fog { 1 }\n";
00488 }
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 bool EggGroup::
00501 is_joint() const {
00502 return (get_group_type() == GT_joint);
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 EggRenderMode *EggGroup::
00515 determine_alpha_mode() {
00516 if (get_alpha_mode() != AM_unspecified) {
00517 return this;
00518 }
00519 return EggGroupNode::determine_alpha_mode();
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 EggRenderMode *EggGroup::
00532 determine_depth_write_mode() {
00533 if (get_depth_write_mode() != DWM_unspecified) {
00534 return this;
00535 }
00536 return EggGroupNode::determine_depth_write_mode();
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 EggRenderMode *EggGroup::
00549 determine_depth_test_mode() {
00550 if (get_depth_test_mode() != DTM_unspecified) {
00551 return this;
00552 }
00553 return EggGroupNode::determine_depth_test_mode();
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 EggRenderMode *EggGroup::
00566 determine_visibility_mode() {
00567 if (get_visibility_mode() != VM_unspecified) {
00568 return this;
00569 }
00570 return EggGroupNode::determine_visibility_mode();
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 EggRenderMode *EggGroup::
00583 determine_depth_offset() {
00584 if (has_depth_offset()) {
00585 return this;
00586 }
00587 return EggGroupNode::determine_depth_offset();
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 EggRenderMode *EggGroup::
00600 determine_draw_order() {
00601 if (has_draw_order()) {
00602 return this;
00603 }
00604 return EggGroupNode::determine_draw_order();
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 EggRenderMode *EggGroup::
00617 determine_bin() {
00618 if (has_bin()) {
00619 return this;
00620 }
00621 return EggGroupNode::determine_bin();
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 bool EggGroup::
00636 determine_indexed() {
00637 if (has_indexed_flag()) {
00638 return get_indexed_flag();
00639 }
00640 return EggGroupNode::determine_indexed();
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654 bool EggGroup::
00655 determine_decal() {
00656 if (get_decal_flag()) {
00657 return true;
00658 }
00659 return EggGroupNode::determine_decal();
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 void EggGroup::
00671 ref_vertex(EggVertex *vert, double membership) {
00672 VertexRef::iterator vri = _vref.find(vert);
00673
00674 if (vri != _vref.end()) {
00675
00676
00677 (*vri).second += membership;
00678
00679
00680 if ((*vri).second == 0.0) {
00681 unref_vertex(vert);
00682 }
00683
00684 } else {
00685
00686 if (membership != 0.0) {
00687 _vref[vert] = membership;
00688
00689 bool inserted = vert->_gref.insert(this).second;
00690
00691
00692
00693 nassertv(inserted);
00694 }
00695 }
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 void EggGroup::
00707 unref_vertex(EggVertex *vert) {
00708 VertexRef::iterator vri = _vref.find(vert);
00709
00710 if (vri != _vref.end()) {
00711 _vref.erase(vri);
00712 int count = vert->_gref.erase(this);
00713
00714
00715 nassertv(count == 1);
00716 }
00717 }
00718
00719
00720
00721
00722
00723
00724 void EggGroup::
00725 unref_all_vertices() {
00726
00727
00728 VertexRef::iterator vri;
00729 for (vri = _vref.begin(); vri != _vref.end(); ++vri) {
00730 EggVertex *vert = (*vri).first;
00731 int count = vert->_gref.erase(this);
00732
00733
00734 nassertv(count == 1);
00735 }
00736
00737 _vref.clear();
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748 double EggGroup::
00749 get_vertex_membership(const EggVertex *vert) const {
00750 VertexRef::const_iterator vri = _vref.find((EggVertex *)vert);
00751
00752 if (vri != _vref.end()) {
00753 return (*vri).second;
00754 } else {
00755 return 0.0;
00756 }
00757 }
00758
00759
00760
00761
00762
00763
00764
00765 void EggGroup::
00766 set_vertex_membership(EggVertex *vert, double membership) {
00767 if (membership == 0.0) {
00768 unref_vertex(vert);
00769 return;
00770 }
00771
00772 VertexRef::iterator vri = _vref.find(vert);
00773
00774 if (vri != _vref.end()) {
00775
00776
00777 (*vri).second = membership;
00778
00779 } else {
00780
00781 _vref[vert] = membership;
00782
00783 bool inserted = vert->_gref.insert(this).second;
00784
00785
00786
00787 nassertv(inserted);
00788 }
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 void EggGroup::
00800 steal_vrefs(EggGroup *other) {
00801 nassertv(other != this);
00802 VertexRef::const_iterator vri;
00803 for (vri = other->vref_begin(); vri != other->vref_end(); ++vri) {
00804 EggVertex *vert = (*vri).first;
00805 double membership = (*vri).second;
00806 ref_vertex(vert, membership);
00807 }
00808 other->unref_all_vertices();
00809 }
00810
00811
00812 #ifdef _DEBUG
00813
00814
00815
00816
00817
00818
00819
00820 void EggGroup::
00821 test_vref_integrity() const {
00822 test_ref_count_integrity();
00823
00824 VertexRef::const_iterator vri;
00825 for (vri = vref_begin(); vri != vref_end(); ++vri) {
00826 const EggVertex *vert = (*vri).first;
00827 vert->test_ref_count_integrity();
00828
00829 nassertv(vert->has_gref(this));
00830 }
00831 }
00832
00833 #endif // _DEBUG
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 void EggGroup::
00844 add_group_ref(EggGroup *group) {
00845 nassertv(get_group_type() == GT_instance);
00846 _group_refs.push_back(group);
00847 }
00848
00849
00850
00851
00852
00853
00854
00855 int EggGroup::
00856 get_num_group_refs() const {
00857 return _group_refs.size();
00858 }
00859
00860
00861
00862
00863
00864
00865
00866 EggGroup *EggGroup::
00867 get_group_ref(int n) const {
00868 nassertr(n >= 0 && n < (int)_group_refs.size(), NULL);
00869 return _group_refs[n];
00870 }
00871
00872
00873
00874
00875
00876
00877
00878 void EggGroup::
00879 remove_group_ref(int n) {
00880 nassertv(n >= 0 && n < (int)_group_refs.size());
00881 _group_refs.erase(_group_refs.begin() + n);
00882 }
00883
00884
00885
00886
00887
00888
00889
00890 void EggGroup::
00891 clear_group_refs() {
00892 _group_refs.clear();
00893 }
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 EggGroup::GroupType EggGroup::
00905 string_group_type(const string &strval) {
00906 if (cmp_nocase_uh(strval, "group") == 0) {
00907 return GT_group;
00908 } else if (cmp_nocase_uh(strval, "instance") == 0) {
00909 return GT_instance;
00910 } else if (cmp_nocase_uh(strval, "joint") == 0) {
00911 return GT_joint;
00912 } else {
00913 return GT_invalid;
00914 }
00915 }
00916
00917
00918
00919
00920
00921
00922
00923
00924 EggGroup::DartType EggGroup::
00925 string_dart_type(const string &strval) {
00926 if (cmp_nocase_uh(strval, "sync") == 0) {
00927 return DT_sync;
00928 } else if (cmp_nocase_uh(strval, "nosync") == 0) {
00929 return DT_nosync;
00930 } else if (cmp_nocase_uh(strval, "default") == 0) {
00931 return DT_default;
00932 } else if (cmp_nocase_uh(strval, "structured") == 0) {
00933 return DT_structured;
00934 } else {
00935 return DT_none;
00936 }
00937 }
00938
00939
00940
00941
00942
00943
00944
00945
00946 EggGroup::DCSType EggGroup::
00947 string_dcs_type(const string &strval) {
00948 if (cmp_nocase_uh(strval, "none") == 0) {
00949 return DC_none;
00950 } else if (cmp_nocase_uh(strval, "local") == 0) {
00951 return DC_local;
00952 } else if (cmp_nocase_uh(strval, "net") == 0) {
00953 return DC_net;
00954 } else if (cmp_nocase_uh(strval, "no_touch") == 0) {
00955 return DC_no_touch;
00956 } else if (cmp_nocase_uh(strval, "default") == 0) {
00957 return DC_default;
00958 } else {
00959 return DC_unspecified;
00960 }
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970 EggGroup::BillboardType EggGroup::
00971 string_billboard_type(const string &strval) {
00972 if (cmp_nocase_uh(strval, "axis") == 0) {
00973 return BT_axis;
00974 } else if (cmp_nocase_uh(strval, "point_eye") == 0) {
00975 return BT_point_camera_relative;
00976 } else if (cmp_nocase_uh(strval, "point_world") == 0) {
00977 return BT_point_world_relative;
00978 } else if (cmp_nocase_uh(strval, "point") == 0) {
00979 return BT_point_world_relative;
00980 } else {
00981 return BT_none;
00982 }
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992 EggGroup::CollisionSolidType EggGroup::
00993 string_cs_type(const string &strval) {
00994 if (cmp_nocase_uh(strval, "plane") == 0) {
00995 return CST_plane;
00996 } else if (cmp_nocase_uh(strval, "polygon") == 0) {
00997 return CST_polygon;
00998 } else if (cmp_nocase_uh(strval, "polyset") == 0) {
00999 return CST_polyset;
01000 } else if (cmp_nocase_uh(strval, "sphere") == 0) {
01001 return CST_sphere;
01002 } else if (cmp_nocase_uh(strval, "inv-sphere") == 0 ||
01003 cmp_nocase_uh(strval, "invsphere") == 0) {
01004 return CST_inv_sphere;
01005 } else if (cmp_nocase_uh(strval, "tube") == 0) {
01006 return CST_tube;
01007 } else if (cmp_nocase_uh(strval, "floor-mesh") == 0 ||
01008 cmp_nocase_uh(strval, "floormesh") == 0) {
01009 return CST_floor_mesh;
01010 } else {
01011 return CST_none;
01012 }
01013 }
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 EggGroup::CollideFlags EggGroup::
01025 string_collide_flags(const string &strval) {
01026 if (cmp_nocase_uh(strval, "intangible") == 0) {
01027 return CF_intangible;
01028 } else if (cmp_nocase_uh(strval, "event") == 0) {
01029 return CF_event;
01030 } else if (cmp_nocase_uh(strval, "descend") == 0) {
01031 return CF_descend;
01032 } else if (cmp_nocase_uh(strval, "keep") == 0) {
01033 return CF_keep;
01034 } else if (cmp_nocase_uh(strval, "solid") == 0) {
01035 return CF_solid;
01036 } else if (cmp_nocase_uh(strval, "center") == 0) {
01037 return CF_center;
01038 } else if (cmp_nocase_uh(strval, "turnstile") == 0) {
01039 return CF_turnstile;
01040 } else if (cmp_nocase_uh(strval, "level") == 0) {
01041 return CF_level;
01042 } else {
01043 return CF_none;
01044 }
01045 }
01046
01047
01048
01049
01050
01051
01052
01053
01054 EggGroup::BlendMode EggGroup::
01055 string_blend_mode(const string &strval) {
01056 if (cmp_nocase_uh(strval, "none") == 0) {
01057 return BM_none;
01058 } else if (cmp_nocase_uh(strval, "add") == 0) {
01059 return BM_add;
01060 } else if (cmp_nocase_uh(strval, "subtract") == 0) {
01061 return BM_subtract;
01062 } else if (cmp_nocase_uh(strval, "inv_subtract") == 0) {
01063 return BM_inv_subtract;
01064 } else if (cmp_nocase_uh(strval, "min") == 0) {
01065 return BM_min;
01066 } else if (cmp_nocase_uh(strval, "max") == 0) {
01067 return BM_max;
01068 } else {
01069 return BM_unspecified;
01070 }
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080 EggGroup::BlendOperand EggGroup::
01081 string_blend_operand(const string &strval) {
01082 if (cmp_nocase_uh(strval, "zero") == 0) {
01083 return BO_zero;
01084 } else if (cmp_nocase_uh(strval, "one") == 0) {
01085 return BO_one;
01086 } else if (cmp_nocase_uh(strval, "incoming_color") == 0) {
01087 return BO_incoming_color;
01088 } else if (cmp_nocase_uh(strval, "one_minus_incoming_color") == 0) {
01089 return BO_one_minus_incoming_color;
01090 } else if (cmp_nocase_uh(strval, "fbuffer_color") == 0) {
01091 return BO_fbuffer_color;
01092 } else if (cmp_nocase_uh(strval, "one_minus_fbuffer_color") == 0) {
01093 return BO_one_minus_fbuffer_color;
01094 } else if (cmp_nocase_uh(strval, "incoming_alpha") == 0) {
01095 return BO_incoming_alpha;
01096 } else if (cmp_nocase_uh(strval, "one_minus_incoming_alpha") == 0) {
01097 return BO_one_minus_incoming_alpha;
01098 } else if (cmp_nocase_uh(strval, "fbuffer_alpha") == 0) {
01099 return BO_fbuffer_alpha;
01100 } else if (cmp_nocase_uh(strval, "one_minus_fbuffer_alpha") == 0) {
01101 return BO_one_minus_fbuffer_alpha;
01102 } else if (cmp_nocase_uh(strval, "constant_color") == 0) {
01103 return BO_constant_color;
01104 } else if (cmp_nocase_uh(strval, "one_minus_constant_color") == 0) {
01105 return BO_one_minus_constant_color;
01106 } else if (cmp_nocase_uh(strval, "constant_alpha") == 0) {
01107 return BO_constant_alpha;
01108 } else if (cmp_nocase_uh(strval, "one_minus_constant_alpha") == 0) {
01109 return BO_one_minus_constant_alpha;
01110 } else if (cmp_nocase_uh(strval, "incoming_color_saturate") == 0) {
01111 return BO_incoming_color_saturate;
01112 } else if (cmp_nocase_uh(strval, "color_scale") == 0) {
01113 return BO_color_scale;
01114 } else if (cmp_nocase_uh(strval, "one_minus_color_scale") == 0) {
01115 return BO_one_minus_color_scale;
01116 } else if (cmp_nocase_uh(strval, "alpha_scale") == 0) {
01117 return BO_alpha_scale;
01118 } else if (cmp_nocase_uh(strval, "one_minus_alpha_scale") == 0) {
01119 return BO_one_minus_alpha_scale;
01120 } else {
01121 return BO_unspecified;
01122 }
01123 }
01124
01125
01126
01127
01128
01129
01130
01131
01132 EggTransform *EggGroup::
01133 as_transform() {
01134 return this;
01135 }
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145 void EggGroup::
01146 write_vertex_ref(ostream &out, int indent_level) const {
01147
01148
01149
01150
01151
01152 typedef pset<int> Indices;
01153 typedef pmap<double, Indices> Memberships;
01154 typedef pmap<EggVertexPool *, Memberships> Pools;
01155
01156 Pools _entries;
01157 bool all_membership_one = true;
01158
01159 VertexRef::const_iterator vri;
01160 for (vri = _vref.begin(); vri != _vref.end(); ++vri) {
01161 EggVertex *vert = (*vri).first;
01162 double membership = (*vri).second;
01163
01164 if (membership != 1.0) {
01165 all_membership_one = false;
01166 }
01167
01168 _entries[vert->get_pool()][membership].insert(vert->get_index());
01169 }
01170
01171
01172
01173 Pools::const_iterator pi;
01174 for (pi = _entries.begin(); pi != _entries.end(); ++pi) {
01175 EggVertexPool *pool = (*pi).first;
01176 const Memberships &memberships = (*pi).second;
01177 Memberships::const_iterator mi;
01178 for (mi = memberships.begin(); mi != memberships.end(); ++mi) {
01179 double membership = (*mi).first;
01180 const Indices &indices = (*mi).second;
01181
01182 indent(out, indent_level)
01183 << "<VertexRef> {\n";
01184 write_long_list(out, indent_level+2, indices.begin(), indices.end(),
01185 "", "", 72);
01186
01187
01188
01189 if (!all_membership_one) {
01190 indent(out, indent_level + 2)
01191 << "<Scalar> membership { " << membership << " }\n";
01192 }
01193 if (pool == (EggVertexPool *)NULL) {
01194 indent(out, indent_level + 2)
01195 << "// Invalid NULL vertex pool.\n";
01196 } else {
01197 indent(out, indent_level + 2)
01198 << "<Ref> { " << pool->get_name() << " }\n";
01199 }
01200 indent(out, indent_level)
01201 << "}\n";
01202 }
01203 }
01204 }
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 bool EggGroup::
01216 egg_start_parse_body() {
01217 egg_start_group_body();
01218 return true;
01219 }
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231 void EggGroup::
01232 adjust_under() {
01233
01234
01235
01236
01237
01238 if (has_transform()) {
01239 _under_flags |= UF_under_transform;
01240
01241
01242 _node_frame =
01243 new MatrixFrame(get_transform3d() * get_node_frame());
01244
01245
01246 LMatrix4d mat;
01247 bool invert_ok = mat.invert_from(get_node_frame());
01248 if (invert_ok) {
01249 _node_frame_inv =
01250 new MatrixFrame(mat);
01251 } else {
01252 _node_frame_inv = NULL;
01253 }
01254
01255 _vertex_to_node =
01256 new MatrixFrame(get_vertex_frame() * get_node_frame_inv());
01257 _node_to_vertex =
01258 new MatrixFrame(get_node_frame() * get_vertex_frame_inv());
01259
01260 }
01261
01262 if (is_instance_type()) {
01263 _under_flags |= UF_under_instance;
01264 if (_under_flags & UF_under_transform) {
01265
01266
01267
01268 _under_flags |= UF_local_coord;
01269 }
01270
01271
01272
01273
01274 _vertex_frame = _node_frame;
01275 _vertex_frame_inv = _node_frame_inv;
01276 _vertex_to_node = NULL;
01277 _node_to_vertex = NULL;
01278 }
01279 }
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 void EggGroup::
01295 r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
01296 CoordinateSystem to_cs) {
01297 if (has_transform() || get_group_type() == GT_joint) {
01298
01299
01300
01301
01302
01303
01304
01305
01306 LMatrix4d mat1 = mat;
01307 LMatrix4d inv1 = inv;
01308
01309
01310
01311
01312 mat1.set_row(3, LVector3d(0.0, 0.0, 0.0));
01313 inv1.set_row(3, LVector3d(0.0, 0.0, 0.0));
01314
01315 internal_set_transform(inv1 * get_transform3d() * mat);
01316
01317 if (_default_pose.has_transform()) {
01318 LMatrix4d t = _default_pose.get_transform3d();
01319 _default_pose.clear_transform();
01320 _default_pose.add_matrix4(inv1 * t * mat);
01321 }
01322
01323 EggGroupNode::r_transform(mat1, inv1, to_cs);
01324 } else {
01325 EggGroupNode::r_transform(mat, inv, to_cs);
01326 }
01327
01328
01329 if (has_lod()) {
01330 _lod->transform(mat);
01331 }
01332 if (has_billboard_center()) {
01333 _billboard_center = _billboard_center * mat;
01334 }
01335 }
01336
01337
01338
01339
01340
01341
01342 void EggGroup::
01343 r_flatten_transforms() {
01344 EggGroupNode::r_flatten_transforms();
01345
01346 if (is_local_coord()) {
01347 LMatrix4d mat = get_vertex_frame();
01348 if (has_lod()) {
01349 _lod->transform(mat);
01350 }
01351
01352 if (get_billboard_type() != BT_none && !has_billboard_center()) {
01353
01354
01355 set_billboard_center(LPoint3d(0.0, 0.0, 0.0) * mat);
01356
01357 } else if (has_billboard_center()) {
01358 _billboard_center = _billboard_center * mat;
01359 }
01360 }
01361
01362 if (get_group_type() == GT_instance) {
01363 set_group_type(GT_group);
01364 }
01365
01366 if (get_group_type() != GT_joint) {
01367 internal_clear_transform();
01368 }
01369 }
01370
01371
01372
01373
01374
01375
01376
01377
01378 void EggGroup::
01379 transform_changed() {
01380
01381
01382
01383
01384 update_under(0);
01385 }
01386
01387
01388
01389
01390
01391
01392
01393 ostream &operator << (ostream &out, EggGroup::GroupType t) {
01394 switch (t) {
01395 case EggGroup::GT_invalid:
01396 return out << "invalid group";
01397 case EggGroup::GT_group:
01398 return out << "group";
01399 case EggGroup::GT_instance:
01400 return out << "instance";
01401 case EggGroup::GT_joint:
01402 return out << "joint";
01403 }
01404
01405 nassertr(false, out);
01406 return out << "(**invalid**)";
01407 }
01408
01409
01410
01411
01412
01413 ostream &operator << (ostream &out, EggGroup::DartType t) {
01414 switch (t) {
01415 case EggGroup::DT_none:
01416 return out << "none";
01417 case EggGroup::DT_sync:
01418 return out << "sync";
01419 case EggGroup::DT_nosync:
01420 return out << "nosync";
01421 case EggGroup::DT_structured:
01422 return out << "structured";
01423 case EggGroup::DT_default:
01424 return out << "1";
01425 }
01426
01427 nassertr(false, out);
01428 return out << "(**invalid**)";
01429 }
01430
01431
01432
01433
01434
01435 ostream &operator << (ostream &out, EggGroup::DCSType t) {
01436 switch (t) {
01437 case EggGroup::DC_unspecified:
01438 return out << "unspecified";
01439 case EggGroup::DC_none:
01440 return out << "none";
01441 case EggGroup::DC_local:
01442 return out << "local";
01443 case EggGroup::DC_net:
01444 return out << "net";
01445 case EggGroup::DC_no_touch:
01446 return out << "no_touch";
01447 case EggGroup::DC_default:
01448 return out << "1";
01449 }
01450
01451 nassertr(false, out);
01452 return out << "(**invalid**)";
01453 }
01454
01455
01456
01457
01458
01459 ostream &operator << (ostream &out, EggGroup::BillboardType t) {
01460 switch (t) {
01461 case EggGroup::BT_none:
01462 return out << "none";
01463 case EggGroup::BT_axis:
01464 return out << "axis";
01465 case EggGroup::BT_point_camera_relative:
01466 return out << "point_eye";
01467 case EggGroup::BT_point_world_relative:
01468 return out << "point_world";
01469 }
01470
01471 nassertr(false, out);
01472 return out << "(**invalid**)";
01473 }
01474
01475
01476
01477
01478
01479 ostream &operator << (ostream &out, EggGroup::CollisionSolidType t) {
01480 switch (t) {
01481 case EggGroup::CST_none:
01482 return out << "None";
01483 case EggGroup::CST_plane:
01484 return out << "Plane";
01485 case EggGroup::CST_polygon:
01486 return out << "Polygon";
01487 case EggGroup::CST_polyset:
01488 return out << "Polyset";
01489 case EggGroup::CST_sphere:
01490 return out << "Sphere";
01491 case EggGroup::CST_inv_sphere:
01492 return out << "InvSphere";
01493 case EggGroup::CST_tube:
01494 return out << "Tube";
01495 case EggGroup::CST_floor_mesh:
01496 return out << "FloorMesh";
01497 }
01498
01499 nassertr(false, out);
01500 return out << "(**invalid**)";
01501 }
01502
01503
01504
01505
01506
01507 ostream &operator << (ostream &out, EggGroup::CollideFlags t) {
01508 if (t == EggGroup::CF_none) {
01509 return out << "none";
01510 }
01511 int bits = (int)t;
01512 const char *space = "";
01513
01514 if (bits & EggGroup::CF_intangible) {
01515 out << space << "intangible";
01516 space = " ";
01517 }
01518 if (bits & EggGroup::CF_event) {
01519 out << space << "event";
01520 space = " ";
01521 }
01522 if (bits & EggGroup::CF_descend) {
01523 out << space << "descend";
01524 space = " ";
01525 }
01526 if (bits & EggGroup::CF_keep) {
01527 out << space << "keep";
01528 space = " ";
01529 }
01530 if (bits & EggGroup::CF_solid) {
01531 out << space << "solid";
01532 space = " ";
01533 }
01534 if (bits & EggGroup::CF_center) {
01535 out << space << "center";
01536 space = " ";
01537 }
01538 if (bits & EggGroup::CF_turnstile) {
01539 out << space << "turnstile";
01540 space = " ";
01541 }
01542 if (bits & EggGroup::CF_level) {
01543 out << space << "level";
01544 space = " ";
01545 }
01546 return out;
01547 }
01548
01549
01550
01551
01552
01553 ostream &
01554 operator << (ostream &out, EggGroup::BlendMode t) {
01555 switch (t) {
01556 case EggGroup::BM_unspecified:
01557 return out << "unspecified";
01558
01559 case EggGroup::BM_none:
01560 return out << "none";
01561
01562 case EggGroup::BM_add:
01563 return out << "add";
01564
01565 case EggGroup::BM_subtract:
01566 return out << "subtract";
01567
01568 case EggGroup::BM_inv_subtract:
01569 return out << "inv_subtract";
01570
01571 case EggGroup::BM_min:
01572 return out << "min";
01573
01574 case EggGroup::BM_max:
01575 return out << "max";
01576 }
01577
01578 return out << "**invalid EggGroup::BlendMode(" << (int)t << ")**";
01579 }
01580
01581
01582
01583
01584
01585 ostream &
01586 operator << (ostream &out, EggGroup::BlendOperand t) {
01587 switch (t) {
01588 case EggGroup::BO_unspecified:
01589 return out << "unspecified";
01590
01591 case EggGroup::BO_zero:
01592 return out << "zero";
01593
01594 case EggGroup::BO_one:
01595 return out << "one";
01596
01597 case EggGroup::BO_incoming_color:
01598 return out << "incomfing_color";
01599
01600 case EggGroup::BO_one_minus_incoming_color:
01601 return out << "one_minus_incoming_color";
01602
01603 case EggGroup::BO_fbuffer_color:
01604 return out << "fbuffer_color";
01605
01606 case EggGroup::BO_one_minus_fbuffer_color:
01607 return out << "one_minus_fbuffer_color";
01608
01609 case EggGroup::BO_incoming_alpha:
01610 return out << "incoming_alpha";
01611
01612 case EggGroup::BO_one_minus_incoming_alpha:
01613 return out << "one_minus_incoming_alpha";
01614
01615 case EggGroup::BO_fbuffer_alpha:
01616 return out << "fbuffer_alpha";
01617
01618 case EggGroup::BO_one_minus_fbuffer_alpha:
01619 return out << "one_minus_fbuffer_alpha";
01620
01621 case EggGroup::BO_constant_color:
01622 return out << "constant_color";
01623
01624 case EggGroup::BO_one_minus_constant_color:
01625 return out << "one_minus_constant_color";
01626
01627 case EggGroup::BO_constant_alpha:
01628 return out << "constant_alpha";
01629
01630 case EggGroup::BO_one_minus_constant_alpha:
01631 return out << "one_minus_constant_alpha";
01632
01633 case EggGroup::BO_incoming_color_saturate:
01634 return out << "incoming_color_saturate";
01635
01636 case EggGroup::BO_color_scale:
01637 return out << "color_scale";
01638
01639 case EggGroup::BO_one_minus_color_scale:
01640 return out << "one_minus_color_scale";
01641
01642 case EggGroup::BO_alpha_scale:
01643 return out << "alpha_scale";
01644
01645 case EggGroup::BO_one_minus_alpha_scale:
01646 return out << "one_minus_alpha_scale";
01647 }
01648
01649 return out << "**invalid EggGroup::BlendOperand(" << (int)t << ")**";
01650 }