00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "xFileNode.h"
00016 #include "windowsGuid.h"
00017 #include "xFile.h"
00018 #include "xLexerDefs.h"
00019 #include "xFileParseData.h"
00020 #include "xFile.h"
00021 #include "xFileDataNodeTemplate.h"
00022 #include "filename.h"
00023 #include "string_utils.h"
00024
00025 TypeHandle XFileNode::_type_handle;
00026
00027
00028
00029
00030
00031
00032 XFileNode::
00033 XFileNode(XFile *x_file, const string &name) :
00034 Namable(),
00035 _x_file(x_file)
00036 {
00037 if (x_file && x_file->_keep_names) {
00038 set_name(name);
00039 } else {
00040 set_name(make_nice_name(name));
00041 }
00042 }
00043
00044
00045
00046
00047
00048
00049 XFileNode::
00050 ~XFileNode() {
00051 clear();
00052 }
00053
00054
00055
00056
00057
00058
00059
00060 XFileNode *XFileNode::
00061 find_child(const string &name) const {
00062 ChildrenByName::const_iterator ni;
00063 ni = _children_by_name.find(downcase(name));
00064 if (ni != _children_by_name.end()) {
00065 return get_child((*ni).second);
00066 }
00067
00068 return NULL;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077 int XFileNode::
00078 find_child_index(const string &name) const {
00079 ChildrenByName::const_iterator ni;
00080 ni = _children_by_name.find(downcase(name));
00081 if (ni != _children_by_name.end()) {
00082 return (*ni).second;
00083 }
00084
00085 return -1;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094 int XFileNode::
00095 find_child_index(const XFileNode *child) const {
00096 for (int i = 0; i < (int)_children.size(); i++) {
00097 if (_children[i] == child) {
00098 return i;
00099 }
00100 }
00101
00102 return -1;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112 XFileNode *XFileNode::
00113 find_descendent(const string &name) const {
00114 XFileNode *child = find_child(name);
00115 if (child != (XFileNode *)NULL) {
00116 return child;
00117 }
00118
00119 Children::const_iterator ci;
00120 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00121 XFileNode *child = (*ci)->find_descendent(name);
00122 if (child != (XFileNode *)NULL){
00123 return child;
00124 }
00125 }
00126
00127 return NULL;
00128 }
00129
00130
00131
00132
00133
00134
00135 bool XFileNode::
00136 has_guid() const {
00137 return false;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146 const WindowsGuid &XFileNode::
00147 get_guid() const {
00148 static WindowsGuid empty;
00149 return empty;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 bool XFileNode::
00166 is_template_def() const {
00167 return false;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 bool XFileNode::
00185 is_reference() const {
00186 return false;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 bool XFileNode::
00203 is_object() const {
00204 return false;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 bool XFileNode::
00220 is_standard_object(const string &template_name) const {
00221 return false;
00222 }
00223
00224
00225
00226
00227
00228
00229 void XFileNode::
00230 add_child(XFileNode *node) {
00231 if (node->has_name()) {
00232 _children_by_name[downcase(node->get_name())] = (int)_children.size();
00233 }
00234 if (node->has_guid()) {
00235 _x_file->_nodes_by_guid[node->get_guid()] = node;
00236 }
00237 if (node->is_of_type(XFileDataNode::get_class_type())) {
00238 _objects.push_back(DCAST(XFileDataNode, node));
00239 }
00240 _children.push_back(node);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249 void XFileNode::
00250 clear() {
00251 _children.clear();
00252 _objects.clear();
00253 _children_by_name.clear();
00254 }
00255
00256
00257
00258
00259
00260
00261
00262 void XFileNode::
00263 write_text(ostream &out, int indent_level) const {
00264 Children::const_iterator ci;
00265 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00266 (*ci)->write_text(out, indent_level);
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 bool XFileNode::
00284 repack_data(XFileDataObject *object,
00285 const XFileParseDataList &parse_data_list,
00286 XFileNode::PrevData &prev_data,
00287 size_t &index, size_t &sub_index) const {
00288
00289
00290
00291
00292
00293 Children::const_iterator ci;
00294 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00295 if (!(*ci)->repack_data(object, parse_data_list,
00296 prev_data, index, sub_index)) {
00297 return false;
00298 }
00299 }
00300
00301 return true;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311 bool XFileNode::
00312 fill_zero_data(XFileDataObject *object) const {
00313 Children::const_iterator ci;
00314 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00315 if (!(*ci)->fill_zero_data(object)) {
00316 return false;
00317 }
00318 }
00319
00320 return true;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 bool XFileNode::
00333 matches(const XFileNode *other) const {
00334 if (other->get_type() != get_type()) {
00335 return false;
00336 }
00337
00338 if (other->get_num_children() != get_num_children()) {
00339 return false;
00340 }
00341
00342 for (int i = 0; i < get_num_children(); i++) {
00343 if (!get_child(i)->matches(other->get_child(i))) {
00344 return false;
00345 }
00346 }
00347
00348 return true;
00349 }
00350
00351
00352
00353
00354
00355
00356 XFileDataNode *XFileNode::
00357 add_Mesh(const string &name) {
00358 XFileTemplate *xtemplate = XFile::find_standard_template("Mesh");
00359 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00360 XFileDataNodeTemplate *node =
00361 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
00362 add_child(node);
00363 node->zero_fill();
00364
00365 return node;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 XFileDataNode *XFileNode::
00375 add_MeshNormals(const string &name) {
00376 XFileTemplate *xtemplate = XFile::find_standard_template("MeshNormals");
00377 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00378 XFileDataNodeTemplate *node =
00379 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
00380 add_child(node);
00381 node->zero_fill();
00382
00383 return node;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392 XFileDataNode *XFileNode::
00393 add_MeshVertexColors(const string &name) {
00394 XFileTemplate *xtemplate = XFile::find_standard_template("MeshVertexColors");
00395 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00396 XFileDataNodeTemplate *node =
00397 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
00398 add_child(node);
00399 node->zero_fill();
00400
00401 return node;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410 XFileDataNode *XFileNode::
00411 add_MeshTextureCoords(const string &name) {
00412 XFileTemplate *xtemplate = XFile::find_standard_template("MeshTextureCoords");
00413 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00414 XFileDataNodeTemplate *node =
00415 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
00416 add_child(node);
00417 node->zero_fill();
00418
00419 return node;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428 XFileDataNode *XFileNode::
00429 add_MeshMaterialList(const string &name) {
00430 XFileTemplate *xtemplate = XFile::find_standard_template("MeshMaterialList");
00431 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00432 XFileDataNodeTemplate *node =
00433 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
00434 add_child(node);
00435 node->zero_fill();
00436
00437 return node;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446 XFileDataNode *XFileNode::
00447 add_Material(const string &name, const LColor &face_color,
00448 double power, const LRGBColor &specular_color,
00449 const LRGBColor &emissive_color) {
00450 XFileTemplate *xtemplate = XFile::find_standard_template("Material");
00451 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00452 XFileDataNodeTemplate *node =
00453 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
00454 add_child(node);
00455 node->zero_fill();
00456
00457 (*node)["faceColor"]["red"] = face_color[0];
00458 (*node)["faceColor"]["green"] = face_color[1];
00459 (*node)["faceColor"]["blue"] = face_color[2];
00460 (*node)["faceColor"]["alpha"] = face_color[3];
00461 (*node)["power"] = power;
00462 (*node)["specularColor"]["red"] = specular_color[0];
00463 (*node)["specularColor"]["green"] = specular_color[1];
00464 (*node)["specularColor"]["blue"] = specular_color[2];
00465 (*node)["emissiveColor"]["red"] = emissive_color[0];
00466 (*node)["emissiveColor"]["green"] = emissive_color[1];
00467 (*node)["emissiveColor"]["blue"] = emissive_color[2];
00468
00469 return node;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478 XFileDataNode *XFileNode::
00479 add_TextureFilename(const string &name, const Filename &filename) {
00480 XFileTemplate *xtemplate = XFile::find_standard_template("TextureFilename");
00481 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00482 XFileDataNodeTemplate *node =
00483 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
00484 add_child(node);
00485 node->zero_fill();
00486
00487 (*node)["filename"] = filename.to_os_specific();
00488
00489 return node;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498 XFileDataNode *XFileNode::
00499 add_Frame(const string &name) {
00500 XFileTemplate *xtemplate = XFile::find_standard_template("Frame");
00501 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00502 XFileDataNodeTemplate *node =
00503 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
00504 add_child(node);
00505 node->zero_fill();
00506
00507 return node;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516 XFileDataNode *XFileNode::
00517 add_FrameTransformMatrix(const LMatrix4d &mat) {
00518 XFileTemplate *xtemplate =
00519 XFile::find_standard_template("FrameTransformMatrix");
00520 nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
00521 XFileDataNodeTemplate *node =
00522 new XFileDataNodeTemplate(get_x_file(), "", xtemplate);
00523 add_child(node);
00524 node->zero_fill();
00525
00526 XFileDataObject &xmat = (*node)["frameMatrix"]["matrix"];
00527 xmat[0] = mat(0, 0);
00528 xmat[1] = mat(0, 1);
00529 xmat[2] = mat(0, 2);
00530 xmat[3] = mat(0, 3);
00531
00532 xmat[4] = mat(1, 0);
00533 xmat[5] = mat(1, 1);
00534 xmat[6] = mat(1, 2);
00535 xmat[7] = mat(1, 3);
00536
00537 xmat[8] = mat(2, 0);
00538 xmat[9] = mat(2, 1);
00539 xmat[10] = mat(2, 2);
00540 xmat[11] = mat(2, 3);
00541
00542 xmat[12] = mat(3, 0);
00543 xmat[13] = mat(3, 1);
00544 xmat[14] = mat(3, 2);
00545 xmat[15] = mat(3, 3);
00546
00547 return node;
00548 }
00549
00550
00551
00552
00553
00554
00555
00556 string XFileNode::
00557 make_nice_name(const string &str) {
00558 string result;
00559
00560 string::const_iterator si;
00561 for (si = str.begin(); si != str.end(); ++si) {
00562 if (isalnum(*si)) {
00563 result += (*si);
00564 } else {
00565 switch (*si) {
00566 case '-':
00567 result += (*si);
00568 break;
00569 default:
00570 result += "_";
00571 }
00572 }
00573 }
00574
00575 if (str.empty() || isdigit(str[0])) {
00576
00577
00578
00579 result = '_' + result;
00580 }
00581
00582 return result;
00583 }