00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "partGroup.h"
00021 #include "animGroup.h"
00022 #include "config_chan.h"
00023
00024 #include <indent.h>
00025 #include <datagram.h>
00026 #include <datagramIterator.h>
00027 #include <bamReader.h>
00028 #include <bamWriter.h>
00029
00030 #include <algorithm>
00031
00032 TypeHandle PartGroup::_type_handle;
00033
00034
00035
00036
00037
00038
00039
00040
00041 PartGroup::
00042 PartGroup(PartGroup *parent, const string &name) : Namable(name) {
00043 nassertv(parent != NULL);
00044
00045 parent->_children.push_back(this);
00046 }
00047
00048
00049
00050
00051
00052
00053 PartGroup::
00054 ~PartGroup() {
00055 }
00056
00057
00058
00059
00060
00061
00062
00063 PartGroup *PartGroup::
00064 make_copy() const {
00065 return new PartGroup(*this);
00066 }
00067
00068
00069
00070
00071
00072
00073
00074 PartGroup *PartGroup::
00075 copy_subgraph() const {
00076 PartGroup *root = make_copy();
00077
00078 if (root->get_type() != get_type()) {
00079 chan_cat.warning()
00080 << "Don't know how to copy " << get_type() << "\n";
00081 }
00082
00083 Children::const_iterator ci;
00084 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00085 PartGroup *child = (*ci)->copy_subgraph();
00086 root->_children.push_back(child);
00087 }
00088
00089 return root;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098 int PartGroup::
00099 get_num_children() const {
00100 return _children.size();
00101 }
00102
00103
00104
00105
00106
00107
00108
00109 PartGroup *PartGroup::
00110 get_child(int n) const {
00111 nassertr(n >= 0 && n < (int)_children.size(), NULL);
00112 return _children[n];
00113 }
00114
00115
00116
00117
00118
00119
00120
00121 PartGroup *PartGroup::
00122 find_child(const string &name) const {
00123 Children::const_iterator ci;
00124 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00125 PartGroup *child = (*ci);
00126 if (child->get_name() == name) {
00127 return child;
00128 }
00129 PartGroup *result = child->find_child(name);
00130 if (result != (PartGroup *)NULL) {
00131 return result;
00132 }
00133 }
00134
00135 return (PartGroup *)NULL;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 TypeHandle PartGroup::
00147 get_value_type() const {
00148 return TypeHandle::none();
00149 }
00150
00151
00152
00153 class PartGroupAlphabeticalOrder {
00154 public:
00155 bool operator()(const PT(PartGroup) &a, const PT(PartGroup) &b) const {
00156 return a->get_name() < b->get_name();
00157 }
00158 };
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 void PartGroup::
00170 sort_descendants() {
00171 sort(_children.begin(), _children.end(), PartGroupAlphabeticalOrder());
00172
00173 Children::iterator ci;
00174 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00175 (*ci)->sort_descendants();
00176 }
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 bool PartGroup::
00196 check_hierarchy(const AnimGroup *anim, const PartGroup *,
00197 int hierarchy_match_flags) const {
00198 if (anim->get_value_type() != get_value_type()) {
00199 if (chan_cat.is_error()) {
00200 chan_cat.error()
00201 << "Part " << get_name() << " expects type " << get_value_type()
00202 << " while matching anim node has type " << anim->get_value_type()
00203 << ".\n";
00204 }
00205 return false;
00206 }
00207
00208 if (chan_cat.is_info()) {
00209
00210
00211
00212
00213 bool match = true;
00214 if (anim->get_num_children() != get_num_children()) {
00215 chan_cat.info()
00216 << "Part " << get_name() << " has " << get_num_children()
00217 << " children, while matching anim node has "
00218 << anim->get_num_children() << ":\n";
00219 match = false;
00220
00221 } else {
00222 for (int i = 0; match && i < get_num_children(); i++) {
00223 PartGroup *pc = get_child(i);
00224 AnimGroup *ac = anim->get_child(i);
00225
00226 match = (pc->get_name() == ac->get_name());
00227 }
00228 if (!match) {
00229 chan_cat.info()
00230 << "Part " << get_name() << " has a different set of children "
00231 << " than matching anim node:\n";
00232 }
00233 }
00234 if (!match) {
00235 int i = 0, j = 0;
00236 while (i < get_num_children() &&
00237 j < anim->get_num_children()) {
00238 PartGroup *pc = get_child(i);
00239 AnimGroup *ac = anim->get_child(j);
00240
00241 if (pc->get_name() < ac->get_name()) {
00242 chan_cat.info()
00243 << " part has " << pc->get_name()
00244 << ", not in anim.\n";
00245 i++;
00246 } else if (ac->get_name() < pc->get_name()) {
00247 chan_cat.info()
00248 << " anim has " << ac->get_name()
00249 << ", not in part.\n";
00250 j++;
00251 } else {
00252
00253 i++;
00254 j++;
00255 }
00256 }
00257
00258 while (i < get_num_children()) {
00259 PartGroup *pc = get_child(i);
00260 chan_cat.info()
00261 << " part has " << pc->get_name()
00262 << ", not in anim.\n";
00263 i++;
00264 }
00265
00266 while (j < anim->get_num_children()) {
00267 AnimGroup *ac = anim->get_child(j);
00268 chan_cat.info()
00269 << " anim has " << ac->get_name()
00270 << ", not in part.\n";
00271 j++;
00272 }
00273 }
00274 }
00275
00276
00277
00278
00279 int i = 0, j = 0;
00280 while (i < get_num_children() &&
00281 j < anim->get_num_children()) {
00282 PartGroup *pc = get_child(i);
00283 AnimGroup *ac = anim->get_child(j);
00284
00285 if (pc->get_name() < ac->get_name()) {
00286 if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) {
00287 return false;
00288 }
00289 i++;
00290 } else if (ac->get_name() < pc->get_name()) {
00291 if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) {
00292 return false;
00293 }
00294 j++;
00295 } else {
00296 if (!pc->check_hierarchy(ac, this, hierarchy_match_flags)) {
00297 return false;
00298 }
00299 i++;
00300 j++;
00301 }
00302 }
00303
00304 if (i < get_num_children()) {
00305
00306 if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) {
00307 return false;
00308 }
00309 }
00310
00311 if (j < anim->get_num_children()) {
00312
00313 if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) {
00314 return false;
00315 }
00316 }
00317
00318 return true;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327 void PartGroup::
00328 write(ostream &out, int indent_level) const {
00329 indent(out, indent_level)
00330 << get_type() << " " << get_name() << " {\n";
00331 write_descendants(out, indent_level + 2);
00332 indent(out, indent_level) << "}\n";
00333 }
00334
00335
00336
00337
00338
00339
00340
00341 void PartGroup::
00342 write_with_value(ostream &out, int indent_level) const {
00343 indent(out, indent_level)
00344 << get_type() << " " << get_name() << " {\n";
00345 write_descendants_with_value(out, indent_level + 2);
00346 indent(out, indent_level) << "}\n";
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 bool PartGroup::
00363 do_update(PartBundle *root, PartGroup *,
00364 bool parent_changed, bool anim_changed) {
00365 bool any_changed = false;
00366
00367 Children::iterator ci;
00368 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00369 if ((*ci)->do_update(root, this, parent_changed, anim_changed)) {
00370 any_changed = true;
00371 }
00372 }
00373
00374 return any_changed;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384 void PartGroup::
00385 write_descendants(ostream &out, int indent_level) const {
00386 Children::const_iterator ci;
00387
00388 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00389 (*ci)->write(out, indent_level);
00390 }
00391 }
00392
00393
00394
00395
00396
00397
00398
00399 void PartGroup::
00400 write_descendants_with_value(ostream &out, int indent_level) const {
00401 Children::const_iterator ci;
00402
00403 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00404 (*ci)->write_with_value(out, indent_level);
00405 }
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 void PartGroup::
00420 pick_channel_index(plist<int> &holes, int &next) const {
00421 Children::const_iterator ci;
00422 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00423 (*ci)->pick_channel_index(holes, next);
00424 }
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434 void PartGroup::
00435 bind_hierarchy(AnimGroup *anim, int channel_index) {
00436 int i = 0, j = 0;
00437 int part_num_children = get_num_children();
00438 int anim_num_children = (anim == NULL) ? 0 : anim->get_num_children();
00439
00440 while (i < part_num_children && j < anim_num_children) {
00441 PartGroup *pc = get_child(i);
00442 AnimGroup *ac = anim->get_child(j);
00443
00444 if (pc->get_name() < ac->get_name()) {
00445
00446
00447 pc->bind_hierarchy(NULL, channel_index);
00448 i++;
00449 } else if (ac->get_name() < pc->get_name()) {
00450 j++;
00451 } else {
00452 pc->bind_hierarchy(ac, channel_index);
00453 i++;
00454 j++;
00455 }
00456 }
00457
00458
00459 while (i < part_num_children) {
00460 PartGroup *pc = get_child(i);
00461 pc->bind_hierarchy(NULL, channel_index);
00462 i++;
00463 }
00464 }
00465
00466
00467
00468
00469
00470
00471
00472 void PartGroup::
00473 write_datagram(BamWriter *manager, Datagram &me)
00474 {
00475 int i;
00476 me.add_string(get_name());
00477 me.add_uint16(_children.size());
00478 for(i = 0; i < (int)_children.size(); i++)
00479 {
00480 manager->write_pointer(me, _children[i]);
00481 }
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 void PartGroup::
00493 fillin(DatagramIterator& scan, BamReader* manager)
00494 {
00495 int i;
00496 set_name(scan.get_string());
00497 _num_children = scan.get_uint16();
00498 for(i = 0; i < _num_children; i++)
00499 {
00500 manager->read_pointer(scan);
00501 }
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511 int PartGroup::
00512 complete_pointers(TypedWritable **p_list, BamReader*)
00513 {
00514 int i;
00515 for(i = 0; i < _num_children; i++)
00516 {
00517 if (p_list[i] == TypedWritable::Null)
00518 {
00519 chan_cat->warning() << get_type().get_name()
00520 << " Ignoring null PartGroup" << endl;
00521 }
00522 else
00523 {
00524 _children.push_back(DCAST(PartGroup, p_list[i]));
00525 }
00526 }
00527
00528 return _num_children;
00529 }
00530
00531
00532
00533
00534
00535
00536 TypedWritable* PartGroup::
00537 make_PartGroup(const FactoryParams ¶ms)
00538 {
00539 PartGroup *me = new PartGroup;
00540 DatagramIterator scan;
00541 BamReader *manager;
00542
00543 parse_params(params, scan, manager);
00544 me->fillin(scan, manager);
00545 return me;
00546 }
00547
00548
00549
00550
00551
00552
00553 void PartGroup::
00554 register_with_read_factory(void)
00555 {
00556 BamReader::get_factory()->register_factory(get_class_type(), make_PartGroup);
00557 }
00558