00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "eggCharacterCollection.h"
00020 #include "eggCharacterData.h"
00021 #include "eggJointData.h"
00022 #include "eggSliderData.h"
00023
00024 #include "dcast.h"
00025 #include "eggGroup.h"
00026 #include "eggTable.h"
00027 #include "eggPrimitive.h"
00028 #include "eggVertex.h"
00029 #include "eggMorphList.h"
00030 #include "eggSAnimData.h"
00031 #include "indirectCompareNames.h"
00032 #include "indent.h"
00033
00034 #include <algorithm>
00035
00036
00037
00038
00039
00040
00041
00042 EggCharacterCollection::
00043 EggCharacterCollection() {
00044 _next_model_index = 0;
00045 }
00046
00047
00048
00049
00050
00051
00052 EggCharacterCollection::
00053 ~EggCharacterCollection() {
00054 Characters::iterator ci;
00055
00056 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00057 delete (*ci);
00058 }
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 int EggCharacterCollection::
00076 add_egg(EggData *egg) {
00077 _top_egg_nodes.clear();
00078
00079 if (!scan_hierarchy(egg)) {
00080 return -1;
00081 }
00082
00083 int egg_index = _eggs.size();
00084 _eggs.push_back(EggInfo());
00085 EggInfo &egg_info = _eggs.back();
00086 egg_info._egg = egg;
00087 egg_info._first_model_index = 0;
00088
00089
00090
00091 TopEggNodesByName::iterator tni;
00092 for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) {
00093 string character_name = (*tni).first;
00094 TopEggNodes &top_nodes = (*tni).second;
00095 EggCharacterData *char_data = make_character(character_name);
00096 EggJointData *root_joint = char_data->get_root_joint();
00097
00098 TopEggNodes::iterator ti;
00099 for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) {
00100 EggNode *model_root = (*ti).first;
00101 EggNodeList &egg_nodes = (*ti).second;
00102
00103 int model_index = _next_model_index++;
00104 if (egg_info._models.empty()) {
00105 egg_info._first_model_index = model_index;
00106 }
00107 egg_info._models.push_back(model_root);
00108
00109 char_data->add_model(model_index, model_root);
00110 nassertr(model_index == (int)_characters_by_model_index.size(), -1);
00111 _characters_by_model_index.push_back(char_data);
00112
00113 match_egg_nodes(char_data, root_joint, egg_nodes,
00114 egg_index, model_index);
00115
00116 scan_for_morphs(model_root, model_index, char_data);
00117 scan_for_sliders(model_root, model_index, char_data);
00118 }
00119 }
00120
00121 return egg_index;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 EggCharacterData *EggCharacterCollection::
00131 get_character_by_name(const string &character_name) const {
00132 Characters::const_iterator ci;
00133 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00134 EggCharacterData *char_data = (*ci);
00135 if (char_data->get_name() == character_name) {
00136 return char_data;
00137 }
00138 }
00139
00140 return (EggCharacterData *)NULL;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 EggCharacterData *EggCharacterCollection::
00154 make_character_data() {
00155 return new EggCharacterData(this);
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 EggJointData *EggCharacterCollection::
00168 make_joint_data(EggCharacterData *char_data) {
00169 return new EggJointData(this, char_data);
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 EggSliderData *EggCharacterCollection::
00182 make_slider_data(EggCharacterData *char_data) {
00183 return new EggSliderData(this, char_data);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 EggCharacterData *EggCharacterCollection::
00194 make_character(const string &character_name) {
00195
00196
00197 Characters::iterator ci;
00198 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00199 EggCharacterData *char_data = (*ci);
00200 if (char_data->get_name() == character_name) {
00201 return char_data;
00202 }
00203 }
00204
00205
00206 EggCharacterData *char_data = make_character_data();
00207 char_data->set_name(character_name);
00208 _characters.push_back(char_data);
00209 return char_data;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 bool EggCharacterCollection::
00225 scan_hierarchy(EggNode *egg_node) {
00226 if (egg_node->is_of_type(EggGroup::get_class_type())) {
00227 EggGroup *group = DCAST(EggGroup, egg_node);
00228 if (group->get_dart_type() != EggGroup::DT_none) {
00229
00230 scan_for_top_joints(group, group, group->get_name());
00231 return true;
00232 }
00233
00234 } else if (egg_node->is_of_type(EggTable::get_class_type())) {
00235 EggTable *table = DCAST(EggTable, egg_node);
00236 if (table->get_table_type() == EggTable::TT_bundle) {
00237
00238 scan_for_top_tables(table, table, table->get_name());
00239 return true;
00240 }
00241 }
00242
00243 bool character_found = false;
00244 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00245 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
00246 EggGroupNode::iterator gi;
00247 for (gi = group->begin(); gi != group->end(); ++gi) {
00248 if (scan_hierarchy(*gi)) {
00249 character_found = true;
00250 }
00251 }
00252 }
00253
00254 return character_found;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264 void EggCharacterCollection::
00265 scan_for_top_joints(EggNode *egg_node, EggNode *model_root,
00266 const string &character_name) {
00267 if (egg_node->is_of_type(EggGroup::get_class_type())) {
00268 EggGroup *group = DCAST(EggGroup, egg_node);
00269
00270 if (group->has_lod()) {
00271
00272 model_root = group;
00273 }
00274 if (group->get_group_type() == EggGroup::GT_joint) {
00275
00276 _top_egg_nodes[character_name][model_root].push_back(group);
00277 return;
00278 }
00279 }
00280
00281 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00282 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
00283 EggGroupNode::iterator gi;
00284 for (gi = group->begin(); gi != group->end(); ++gi) {
00285 scan_for_top_joints(*gi, model_root, character_name);
00286 }
00287 }
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297 void EggCharacterCollection::
00298 scan_for_top_tables(EggTable *bundle, EggNode *model_root,
00299 const string &character_name) {
00300
00301
00302 EggGroupNode::iterator gi;
00303 for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
00304 EggNode *child = (*gi);
00305 if (child->is_of_type(EggTable::get_class_type())) {
00306 EggTable *table = DCAST(EggTable, child);
00307 if (table->get_name() == "<skeleton>") {
00308
00309
00310
00311 EggGroupNode::iterator cgi;
00312 for (cgi = table->begin(); cgi != table->end(); ++cgi) {
00313 EggNode *grandchild = (*cgi);
00314 if (grandchild->is_of_type(EggTable::get_class_type())) {
00315 _top_egg_nodes[character_name][model_root].push_back(grandchild);
00316 }
00317 }
00318 }
00319 }
00320 }
00321 }
00322
00323
00324
00325
00326
00327
00328
00329 void EggCharacterCollection::
00330 scan_for_morphs(EggNode *egg_node, int model_index,
00331 EggCharacterData *char_data) {
00332 if (egg_node->is_of_type(EggPrimitive::get_class_type())) {
00333 EggPrimitive *prim = DCAST(EggPrimitive, egg_node);
00334
00335 add_morph_back_pointers(prim, prim, model_index, char_data);
00336
00337
00338 EggPrimitive::const_iterator vi;
00339 for (vi = prim->begin(); vi != prim->end(); ++vi) {
00340 EggVertex *vertex = (*vi);
00341
00342 add_morph_back_pointers(vertex, vertex, model_index, char_data);
00343
00344 EggMorphVertexList::const_iterator mvi;
00345 for (mvi = vertex->_dxyzs.begin();
00346 mvi != vertex->_dxyzs.end();
00347 ++mvi) {
00348 const EggMorphVertex &morph = (*mvi);
00349 char_data->make_slider(morph.get_name())->add_back_pointer(model_index, vertex);
00350 }
00351 }
00352 }
00353
00354 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00355 EggGroupNode *group = DCAST(EggGroupNode, egg_node);
00356 EggGroupNode::iterator gi;
00357 for (gi = group->begin(); gi != group->end(); ++gi) {
00358 scan_for_morphs(*gi, model_index, char_data);
00359 }
00360 }
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 void EggCharacterCollection::
00370 scan_for_sliders(EggNode *egg_node, int model_index,
00371 EggCharacterData *char_data) {
00372 if (egg_node->is_of_type(EggTable::get_class_type())) {
00373 EggTable *bundle = DCAST(EggTable, egg_node);
00374
00375
00376
00377
00378
00379
00380
00381 EggGroupNode::iterator gi;
00382 for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
00383 EggNode *child = (*gi);
00384 if (child->is_of_type(EggTable::get_class_type())) {
00385 EggTable *table = DCAST(EggTable, child);
00386 if (table->get_name() == "morph") {
00387
00388
00389
00390 EggGroupNode::iterator cgi;
00391 for (cgi = table->begin(); cgi != table->end(); ++cgi) {
00392 EggNode *grandchild = (*cgi);
00393 if (grandchild->is_of_type(EggSAnimData::get_class_type())) {
00394 char_data->make_slider(grandchild->get_name())->add_back_pointer(model_index, grandchild);
00395 }
00396 }
00397 }
00398 }
00399 }
00400 }
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 void EggCharacterCollection::
00410 add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object,
00411 int model_index, EggCharacterData *char_data) {
00412 EggMorphNormalList::const_iterator mni;
00413 for (mni = attrib->_dnormals.begin();
00414 mni != attrib->_dnormals.end();
00415 ++mni) {
00416 const EggMorphNormal &morph = (*mni);
00417 char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
00418 }
00419
00420 EggMorphTexCoordList::const_iterator mti;
00421 for (mti = attrib->_duvs.begin();
00422 mti != attrib->_duvs.end();
00423 ++mti) {
00424 const EggMorphTexCoord &morph = (*mti);
00425 char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
00426 }
00427
00428 EggMorphColorList::const_iterator mci;
00429 for (mci = attrib->_drgbas.begin();
00430 mci != attrib->_drgbas.end();
00431 ++mci) {
00432 const EggMorphColor &morph = (*mci);
00433 char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
00434 }
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 void EggCharacterCollection::
00448 match_egg_nodes(EggCharacterData *char_data, EggJointData *joint_data,
00449 EggNodeList &egg_nodes, int egg_index, int model_index) {
00450
00451
00452 sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames<Namable>());
00453
00454 if (joint_data->_children.empty()) {
00455
00456
00457 EggNodeList::iterator ei;
00458 for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) {
00459 EggNode *egg_node = (*ei);
00460 EggJointData *data = make_joint_data(char_data);
00461 joint_data->_children.push_back(data);
00462 data->_parent = joint_data;
00463 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00464 }
00465
00466 } else {
00467
00468
00469
00470 EggNodeList extra_egg_nodes;
00471 EggJointData::Children extra_data;
00472
00473 EggNodeList::iterator ei;
00474 EggJointData::Children::iterator di;
00475
00476 ei = egg_nodes.begin();
00477 di = joint_data->_children.begin();
00478
00479 while (ei != egg_nodes.end() && di != joint_data->_children.end()) {
00480 EggNode *egg_node = (*ei);
00481 EggJointData *data = (*di);
00482
00483 if (egg_node->get_name() < data->get_name()) {
00484
00485 extra_egg_nodes.push_back(egg_node);
00486 ++ei;
00487
00488 } else if (data->get_name() < egg_node->get_name()) {
00489
00490 extra_data.push_back(data);
00491 ++di;
00492
00493 } else {
00494
00495 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00496 ++ei;
00497 ++di;
00498 }
00499 }
00500
00501 while (ei != egg_nodes.end()) {
00502 EggNode *egg_node = (*ei);
00503
00504
00505 extra_egg_nodes.push_back(egg_node);
00506 ++ei;
00507 }
00508
00509 while (di != joint_data->_children.end()) {
00510 EggJointData *data = (*di);
00511
00512
00513 extra_data.push_back(data);
00514 ++di;
00515 }
00516
00517 if (!extra_egg_nodes.empty()) {
00518
00519
00520
00521
00522
00523
00524 EggNodeList more_egg_nodes;
00525
00526 for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
00527 EggNode *egg_node = (*ei);
00528 bool matched = false;
00529 for (di = extra_data.begin();
00530 di != extra_data.end() && !matched;
00531 ++di) {
00532 EggJointData *data = (*di);
00533 if (data->matches_name(egg_node->get_name())) {
00534 matched = true;
00535 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00536 extra_data.erase(di);
00537 }
00538 }
00539
00540 if (!matched) {
00541
00542 more_egg_nodes.push_back(egg_node);
00543 }
00544 }
00545 extra_egg_nodes.swap(more_egg_nodes);
00546 }
00547
00548 if (!extra_egg_nodes.empty()) {
00549
00550
00551 if (extra_egg_nodes.size() == extra_data.size()) {
00552
00553 size_t i;
00554 for (i = 0; i < extra_egg_nodes.size(); i++) {
00555 EggNode *egg_node = extra_egg_nodes[i];
00556 EggJointData *data = extra_data[i];
00557 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00558 }
00559
00560 } else {
00561
00562 EggNodeList::iterator ei;
00563 for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
00564 EggNode *egg_node = (*ei);
00565 EggJointData *data = make_joint_data(char_data);
00566 joint_data->_children.push_back(data);
00567 data->_parent = joint_data;
00568 found_egg_match(char_data, data, egg_node, egg_index, model_index);
00569 }
00570 }
00571 }
00572 }
00573
00574
00575
00576 sort(joint_data->_children.begin(), joint_data->_children.end(),
00577 IndirectCompareNames<Namable>());
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587 void EggCharacterCollection::
00588 found_egg_match(EggCharacterData *char_data, EggJointData *joint_data,
00589 EggNode *egg_node, int egg_index, int model_index) {
00590 if (egg_node->has_name()) {
00591 joint_data->add_name(egg_node->get_name());
00592 }
00593 joint_data->add_back_pointer(model_index, egg_node);
00594
00595 if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00596 EggGroupNode *group_node = DCAST(EggGroupNode, egg_node);
00597
00598
00599
00600 EggNodeList egg_nodes;
00601
00602
00603
00604
00605 if (egg_node->is_of_type(EggGroup::get_class_type())) {
00606
00607 EggGroupNode::iterator gi;
00608 for (gi = group_node->begin(); gi != group_node->end(); ++gi) {
00609 EggNode *child = (*gi);
00610 if (child->is_of_type(EggGroup::get_class_type())) {
00611 EggGroup *group = DCAST(EggGroup, child);
00612 if (group->get_group_type() == EggGroup::GT_joint) {
00613 egg_nodes.push_back(group);
00614 }
00615 }
00616 }
00617
00618 } else {
00619
00620 EggGroupNode::iterator gi;
00621 for (gi = group_node->begin(); gi != group_node->end(); ++gi) {
00622 EggNode *child = (*gi);
00623 if (child->is_of_type(EggTable::get_class_type())) {
00624 EggTable *table = DCAST(EggTable, child);
00625 if (!(table->get_name() == "xform")) {
00626 egg_nodes.push_back(table);
00627 }
00628 }
00629 }
00630 }
00631
00632 if (!egg_nodes.empty()) {
00633 match_egg_nodes(char_data, joint_data, egg_nodes,
00634 egg_index, model_index);
00635 }
00636 }
00637 }
00638
00639
00640
00641
00642
00643
00644 void EggCharacterCollection::
00645 write(ostream &out, int indent_level) const {
00646 Characters::const_iterator ci;
00647
00648 for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
00649 EggCharacterData *char_data = (*ci);
00650 char_data->write(out, indent_level);
00651 }
00652 }