Panda3D
|
00001 /************************************************** 00002 * VRML 2.0 Parser 00003 * Copyright (C) 1996 Silicon Graphics, Inc. 00004 * 00005 * Author(s) : Gavin Bell 00006 * Daniel Woods (first port) 00007 ************************************************** 00008 */ 00009 00010 // 00011 // The VrmlNodeType class is responsible for storing information about node 00012 // or prototype types. 00013 // 00014 00015 #include "vrmlNodeType.h" 00016 #include "vrmlNode.h" 00017 #include "vrmlParser.h" 00018 #include "pnotify.h" 00019 #include "indent.h" 00020 00021 #include <stdio.h> // for sprintf() 00022 00023 00024 // 00025 // Static list of node types. 00026 // 00027 plist<VrmlNodeType*> VrmlNodeType::typeList; 00028 00029 static ostream & 00030 output_array(ostream &out, const MFArray *mf, 00031 int type, int indent_level, int items_per_row) { 00032 if (mf->empty()) { 00033 out << "[ ]"; 00034 } else { 00035 out << "["; 00036 MFArray::const_iterator mi; 00037 int col = 0; 00038 for (mi = mf->begin(); mi != mf->end(); ++mi) { 00039 if (col == 0) { 00040 out << "\n"; 00041 indent(out, indent_level + 2); 00042 } 00043 output_value(out, (*mi), type, indent_level + 2); 00044 if (++col >= items_per_row) { 00045 col = 0; 00046 } else { 00047 out << " "; 00048 } 00049 } 00050 out << "\n"; 00051 indent(out, indent_level) << "]"; 00052 } 00053 return out; 00054 } 00055 00056 ostream & 00057 output_value(ostream &out, const VrmlFieldValue &value, int type, 00058 int indent) { 00059 switch (type) { 00060 case SFBOOL: 00061 return out << (value._sfbool ? "TRUE" : "FALSE"); 00062 00063 case SFFLOAT: 00064 case SFTIME: 00065 return out << value._sffloat; 00066 00067 case SFINT32: 00068 return out << value._sfint32; 00069 00070 case SFSTRING: 00071 { 00072 out << '"'; 00073 for (const char *p = value._sfstring; *p != '\0'; p++) { 00074 if (*p == '"') { 00075 out << "\\\""; 00076 } else { 00077 out << *p; 00078 } 00079 } 00080 return out << '"'; 00081 } 00082 00083 case SFVEC2F: 00084 return out << value._sfvec[0] << " " << value._sfvec[1]; 00085 00086 case SFCOLOR: 00087 case SFVEC3F: 00088 return out << value._sfvec[0] << " " << value._sfvec[1] << " " 00089 << value._sfvec[2]; 00090 00091 case SFROTATION: 00092 return out << value._sfvec[0] << " " << value._sfvec[1] << " " 00093 << value._sfvec[2] << " " << value._sfvec[3]; 00094 00095 case SFNODE: 00096 switch (value._sfnode._type) { 00097 case SFNodeRef::T_null: 00098 return out << "NULL"; 00099 00100 case SFNodeRef::T_unnamed: 00101 nassertr(value._sfnode._p != NULL, out); 00102 value._sfnode._p->output(out, indent); 00103 return out; 00104 00105 case SFNodeRef::T_def: 00106 out << "DEF " << value._sfnode._name << " "; 00107 value._sfnode._p->output(out, indent); 00108 return out; 00109 00110 case SFNodeRef::T_use: 00111 return out << "USE " << value._sfnode._name; 00112 } 00113 return out << "(invalid)"; 00114 00115 case SFIMAGE: 00116 return out << "(image)"; 00117 00118 case MFCOLOR: 00119 return output_array(out, value._mf, SFCOLOR, indent, 1); 00120 00121 case MFFLOAT: 00122 return output_array(out, value._mf, SFFLOAT, indent, 5); 00123 00124 case MFINT32: 00125 return output_array(out, value._mf, SFINT32, indent, 10); 00126 00127 case MFROTATION: 00128 return output_array(out, value._mf, SFROTATION, indent, 1); 00129 00130 case MFSTRING: 00131 return output_array(out, value._mf, SFSTRING, indent, 1); 00132 00133 case MFVEC2F: 00134 return output_array(out, value._mf, SFVEC2F, indent, 1); 00135 00136 case MFVEC3F: 00137 return output_array(out, value._mf, SFVEC3F, indent, 1); 00138 00139 case MFNODE: 00140 return output_array(out, value._mf, SFNODE, indent, 1); 00141 } 00142 00143 return out << "(unknown)"; 00144 } 00145 00146 VrmlNodeType::VrmlNodeType(const char *nm) 00147 { 00148 nassertv(nm != NULL); 00149 name = strdup(nm); 00150 } 00151 00152 VrmlNodeType::~VrmlNodeType() 00153 { 00154 free(name); 00155 00156 // Free strings duplicated when fields/eventIns/eventOuts added: 00157 plist<NameTypeRec*>::iterator i; 00158 00159 for (i = eventIns.begin(); i != eventIns.end(); i++) { 00160 NameTypeRec *r = *i; 00161 free(r->name); 00162 delete r; 00163 } 00164 for (i = eventOuts.begin(); i != eventOuts.end(); i++) { 00165 NameTypeRec *r = *i; 00166 free(r->name); 00167 delete r; 00168 } 00169 for (i = fields.begin(); i != fields.end(); i++) { 00170 NameTypeRec *r = *i; 00171 free(r->name); 00172 delete r; 00173 } 00174 } 00175 00176 void 00177 VrmlNodeType::addToNameSpace(VrmlNodeType *_type) 00178 { 00179 if (find(_type->getName()) != NULL) { 00180 cerr << "PROTO " << _type->getName() << " already defined\n"; 00181 return; 00182 } 00183 typeList.push_front(_type); 00184 } 00185 00186 // 00187 // One list is used to store all the node types. Nested namespaces are 00188 // separated by NULL elements. 00189 // This isn't terribly efficient, but it is nice and simple. 00190 // 00191 void 00192 VrmlNodeType::pushNameSpace() 00193 { 00194 typeList.push_front(NULL); 00195 } 00196 00197 void 00198 VrmlNodeType::popNameSpace() 00199 { 00200 // Remove everything up to and including the next NULL marker: 00201 plist<VrmlNodeType*>::iterator i; 00202 for (i = typeList.begin(); i != typeList.end();) { 00203 VrmlNodeType *nodeType = *i; 00204 ++i; 00205 typeList.pop_front(); 00206 00207 if (nodeType == NULL) { 00208 break; 00209 } 00210 else { 00211 // NOTE: Instead of just deleting the VrmlNodeTypes, you will 00212 // probably want to reference count or garbage collect them, since 00213 // any nodes created as part of the PROTO implementation will 00214 // probably point back to their VrmlNodeType structure. 00215 delete nodeType; 00216 } 00217 } 00218 } 00219 00220 const VrmlNodeType * 00221 VrmlNodeType::find(const char *_name) 00222 { 00223 // Look through the type stack: 00224 plist<VrmlNodeType*>::iterator i; 00225 for (i = typeList.begin(); i != typeList.end(); i++) { 00226 const VrmlNodeType *nt = *i; 00227 if (nt != NULL && strcmp(nt->getName(),_name) == 0) { 00228 return nt; 00229 } 00230 } 00231 return NULL; 00232 } 00233 00234 void 00235 VrmlNodeType::addEventIn(const char *name, int type, 00236 const VrmlFieldValue *dflt) 00237 { 00238 add(eventIns, name, type, dflt); 00239 }; 00240 void 00241 VrmlNodeType::addEventOut(const char *name, int type, 00242 const VrmlFieldValue *dflt) 00243 { 00244 add(eventOuts, name, type, dflt); 00245 }; 00246 void 00247 VrmlNodeType::addField(const char *name, int type, 00248 const VrmlFieldValue *dflt) 00249 { 00250 add(fields, name, type, dflt); 00251 }; 00252 void 00253 VrmlNodeType::addExposedField(const char *name, int type, 00254 const VrmlFieldValue *dflt) 00255 { 00256 char tmp[1000]; 00257 add(fields, name, type, dflt); 00258 sprintf(tmp, "set_%s", name); 00259 add(eventIns, tmp, type, dflt); 00260 sprintf(tmp, "%s_changed", name); 00261 add(eventOuts, tmp, type, dflt); 00262 }; 00263 00264 void 00265 VrmlNodeType::add(plist<NameTypeRec*> &recs, const char *name, int type, 00266 const VrmlFieldValue *dflt) 00267 { 00268 NameTypeRec *r = new NameTypeRec; 00269 r->name = strdup(name); 00270 r->type = type; 00271 if (dflt != NULL) { 00272 r->dflt = *dflt; 00273 } else { 00274 memset(&r->dflt, 0, sizeof(r->dflt)); 00275 } 00276 recs.push_front(r); 00277 } 00278 00279 const VrmlNodeType::NameTypeRec * 00280 VrmlNodeType::hasEventIn(const char *name) const 00281 { 00282 return has(eventIns, name); 00283 } 00284 00285 const VrmlNodeType::NameTypeRec * 00286 VrmlNodeType::hasEventOut(const char *name) const 00287 { 00288 return has(eventOuts, name); 00289 } 00290 00291 const VrmlNodeType::NameTypeRec * 00292 VrmlNodeType::hasField(const char *name) const 00293 { 00294 return has(fields, name); 00295 } 00296 00297 const VrmlNodeType::NameTypeRec * 00298 VrmlNodeType::hasExposedField(const char *name) const 00299 { 00300 // Must have field "name", eventIn "set_name", and eventOut 00301 // "name_changed", all with same type: 00302 char tmp[1000]; 00303 const NameTypeRec *base, *set_name, *name_changed; 00304 00305 base = has(fields, name); 00306 00307 sprintf(tmp, "set_%s\n", name); 00308 nassertr(strlen(tmp) < 1000, NULL); 00309 set_name = has(eventIns, tmp); 00310 00311 sprintf(tmp, "%s_changed\n", name); 00312 nassertr(strlen(tmp) < 1000, NULL); 00313 name_changed = has(eventOuts, tmp); 00314 00315 if (base == NULL || set_name == NULL || name_changed == NULL) { 00316 return NULL; 00317 } 00318 00319 if (base->type != set_name->type || base->type != name_changed->type) { 00320 return NULL; 00321 } 00322 00323 return base; 00324 } 00325 00326 const VrmlNodeType::NameTypeRec * 00327 VrmlNodeType::has(const plist<NameTypeRec*> &recs, const char *name) const 00328 { 00329 plist<NameTypeRec*>::const_iterator i; 00330 for (i = recs.begin(); i != recs.end(); i++) { 00331 if (strcmp((*i)->name, name) == 0) 00332 return (*i); 00333 } 00334 return NULL; 00335 } 00336