2 // parses xml tree format into internal objects
\r
8 void Patch_XMLParse(patchMesh_t *pPatch, xmlNodePtr surface)
\r
10 char *str, *content;
\r
13 for(xmlNodePtr current = surface->children; current != NULL; current = current->next)
\r
15 if(current->type != XML_ELEMENT_NODE) continue;
\r
16 if(!strcmp((char *)current->name, "matrix"))
\r
18 str = (char *)xmlGetProp(current, (xmlChar *)"width");
\r
19 pPatch->width = atoi(str);
\r
21 str = (char *)xmlGetProp(current, (xmlChar *)"height");
\r
22 pPatch->height = atoi(str);
\r
25 content = Q_StrDup((char *)current->children->content);
\r
27 str = strtok(content, " \n\r\t\v\0");
\r
28 for(i=0; i<pPatch->width; i++)
\r
30 for(j=0; j<pPatch->height; j++)
\r
32 pPatch->ctrl[i][j].xyz[0] = atof(str);
\r
33 str = strtok(NULL, " \n\r\t\v\0");
\r
34 pPatch->ctrl[i][j].xyz[1] = atof(str);
\r
35 str = strtok(NULL, " \n\r\t\v\0");
\r
36 pPatch->ctrl[i][j].xyz[2] = atof(str);
\r
37 str = strtok(NULL, " \n\r\t\v\0");
\r
38 pPatch->ctrl[i][j].st[0] = atof(str);
\r
39 str = strtok(NULL, " \n\r\t\v\0");
\r
40 pPatch->ctrl[i][j].st[1] = atof(str);
\r
41 str = strtok(NULL, " \n\r\t\v\0");
\r
47 else if(!strcmp((char *)current->name, "shader")) {
\r
48 pPatch->pShader = QERApp_Shader_ForName((char*)current->children->content);
\r
49 pPatch->d_texture = pPatch->pShader->getTexture();
\r
54 void Face_XMLParse (face_t *face, xmlNodePtr surface)
\r
56 char *str, *content;
\r
59 for(xmlNodePtr current = surface->children; current != NULL; current = current->next)
\r
61 if(current->type != XML_ELEMENT_NODE) continue;
\r
62 if(!strcmp((char *)current->name, "planepts"))
\r
64 content = Q_StrDup((char *)current->children->content);
\r
66 str = strtok(content, " \n\r\t\v\0");
\r
67 for (i=0 ; i<3 ; i++)
\r
69 for (j=0 ; j<3 ; j++)
\r
71 face->planepts[i][j] = atof(str);
\r
72 str = strtok(NULL, " \n\r\t\v\0");
\r
78 else if(!strcmp((char *)current->name, "texdef"))
\r
80 content = Q_StrDup((char *)current->children->content);
\r
82 str = strtok(content, " \n\r\t\v\0");
\r
83 face->texdef.shift[0] = atof(str);
\r
84 str = strtok(NULL, " \n\r\t\v\0");
\r
85 face->texdef.shift[1] = atof(str);
\r
86 str = strtok(NULL, " \n\r\t\v\0");
\r
87 face->texdef.rotate = atof(str);
\r
88 str = strtok(NULL, " \n\r\t\v\0");
\r
89 face->texdef.scale[0] = atof(str);
\r
90 str = strtok(NULL, " \n\r\t\v\0");
\r
91 face->texdef.scale[1] = atof(str);
\r
95 else if(!strcmp((char *)current->name, "bpmatrix"))
\r
97 content = Q_StrDup((char *)current->children->content);
\r
99 str = strtok(content, " \n\r\t\v\0");
\r
100 face->brushprimit_texdef.coords[0][0] = atof(str);
\r
101 str = strtok(NULL, " \n\r\t\v\0");
\r
102 face->brushprimit_texdef.coords[0][1] = atof(str);
\r
103 str = strtok(NULL, " \n\r\t\v\0");
\r
104 face->brushprimit_texdef.coords[0][2] = atof(str);
\r
105 str = strtok(NULL, " \n\r\t\v\0");
\r
106 face->brushprimit_texdef.coords[1][0] = atof(str);
\r
107 str = strtok(NULL, " \n\r\t\v\0");
\r
108 face->brushprimit_texdef.coords[1][1] = atof(str);
\r
109 str = strtok(NULL, " \n\r\t\v\0");
\r
110 face->brushprimit_texdef.coords[1][2] = atof(str);
\r
114 else if(!strcmp((char *)current->name, "flags"))
\r
116 content = Q_StrDup((char *)current->children->content);
\r
118 str = strtok(content, " \n\r\t\v\0");
\r
119 face->texdef.contents = atoi(str);
\r
120 str = strtok(NULL, " \n\r\t\v\0");
\r
121 face->texdef.flags = atoi(str);
\r
122 str = strtok(NULL, " \n\r\t\v\0");
\r
123 face->texdef.value = atoi(str);
\r
127 else if(!strcmp((char *)current->name, "shader"))
\r
129 face->texdef.SetName((char *)current->children->content);
\r
134 void Brush_XMLParse (brush_t *pBrush, xmlNodePtr primitive)
\r
138 for(xmlNodePtr current = primitive->children; current != NULL; current = current->next)
\r
140 if(current->type != XML_ELEMENT_NODE) continue;
\r
141 f = pBrush->brush_faces;
\r
142 pBrush->brush_faces = Face_Alloc();
\r
143 Face_XMLParse(pBrush->brush_faces, current);
\r
144 pBrush->brush_faces->next = f;
\r
148 void Entity_XMLParse(entity_t *pEntity, xmlNodePtr entity)
\r
152 for(xmlNodePtr current = entity->children; current != NULL; current = current->next)
\r
154 if(current->type != XML_ELEMENT_NODE) continue;
\r
155 if(!strcmp((char *)current->name, "epair"))
\r
157 char *key = (char *)xmlGetProp(current, (xmlChar *)"key");
\r
158 char *value = (char *)xmlGetProp(current, (xmlChar *)"value");
\r
159 SetKeyValue(pEntity, key, value);
\r
163 else if(strcmp((char *)current->name, "brush") == 0)
\r
165 pBrush = Brush_Alloc();
\r
166 Brush_XMLParse(pBrush, current);
\r
167 ((CPtrArray*)pEntity->pData)->Add(pBrush);
\r
169 else if(strcmp((char *)current->name, "patch") == 0)
\r
171 pBrush = Brush_Alloc();
\r
172 pBrush->patchBrush = true;
\r
173 pBrush->pPatch = Patch_Alloc();
\r
174 pBrush->pPatch->pSymbiot = pBrush;
\r
175 Patch_XMLParse(pBrush->pPatch, current);
\r
176 ((CPtrArray*)pEntity->pData)->Add(pBrush);
\r
181 void Map_XMLRead(CPtrArray *map, xmlNodePtr map_node)
\r
184 xmlNodePtr current;
\r
186 for(current = map_node->children; current != NULL; current = current->next)
\r
188 if(current->type != XML_ELEMENT_NODE) continue;
\r
189 pEntity = Entity_Alloc();
\r
190 pEntity->pData = new CPtrArray;
\r
191 Entity_XMLParse(pEntity, current);
\r
197 // temporarily copied from qe3.cpp
\r
198 // duplicate code starts here (note: g_strAppPath swapped for g_FuncTable.m_pfnGetQERPath())
\r
200 void HandleXMLError( void* ctxt, const char* text, ... )
\r
203 static char buf[32768];
\r
205 va_start (argptr,text);
\r
206 vsprintf (buf, text, argptr);
\r
207 Sys_FPrintf (SYS_ERR, "XML %s\n", buf);
\r
211 #define DTD_BUFFER_LENGTH 1024
\r
212 xmlDocPtr ParseXMLStream(IDataStream *stream, bool validate = false)
\r
214 xmlDocPtr doc = NULL;
\r
215 bool wellFormed = false, valid = false;
\r
216 int res, size = 1024;
\r
218 xmlParserCtxtPtr ctxt;
\r
221 // HACK: use AppPath to resolve DTD location
\r
222 // do a buffer-safe string copy and concatenate
\r
226 char buf[DTD_BUFFER_LENGTH];
\r
231 //assert(g_FuncTable.m_pfnGetQERPath() != NULL);
\r
232 for(r = g_FuncTable.m_pfnGetQERPath(); i<DTD_BUFFER_LENGTH && *r != '\0'; i++, r++) w[i] = *r;
\r
234 for(r = "dtds/"; i<DTD_BUFFER_LENGTH && *r != '\0'; i++, r++) w[i] = *r;
\r
238 if(i == DTD_BUFFER_LENGTH)
\r
240 HandleXMLError(NULL, "ERROR: buffer overflow: DTD path length too large\n");
\r
245 // xmlDoValidityCheckingDefaultValue = 1;
\r
247 xmlDoValidityCheckingDefaultValue = 0;
\r
249 xmlSetGenericErrorFunc(NULL, HandleXMLError);
\r
251 res = stream->Read(chars, 4);
\r
254 ctxt = xmlCreatePushParserCtxt(NULL, NULL, chars, res, buf);
\r
256 while ((res = stream->Read(chars, size)) > 0)
\r
258 xmlParseChunk(ctxt, chars, res, 0);
\r
260 xmlParseChunk(ctxt, chars, 0, 1);
\r
263 wellFormed = (ctxt->wellFormed == 1);
\r
264 valid = (ctxt->valid == 1);
\r
266 xmlFreeParserCtxt(ctxt);
\r
269 if(wellFormed && (!validate || (validate && valid)))
\r
278 // duplicate code ends here
\r
280 void Map_Read (IDataStream *in, CPtrArray *map)
\r
284 doc = ParseXMLStream(in, false ); // quick hack while dtd validation is broken
\r
288 xmlNodePtr node=doc->children;
\r
289 while(node != NULL && node->type != XML_ELEMENT_NODE) node=node->next;
\r
291 Map_XMLRead(map, node);
\r