// // parses xml tree format into internal objects // #include "plugin.h" void Patch_XMLParse(patchMesh_t *pPatch, xmlNodePtr surface) { char *str, *content; int i, j; for(xmlNodePtr current = surface->children; current != NULL; current = current->next) { if(current->type != XML_ELEMENT_NODE) continue; if(!strcmp((char *)current->name, "matrix")) { str = (char *)xmlGetProp(current, (xmlChar *)"width"); pPatch->width = atoi(str); xmlFree(str); str = (char *)xmlGetProp(current, (xmlChar *)"height"); pPatch->height = atoi(str); xmlFree(str); content = Q_StrDup((char *)current->children->content); str = strtok(content, " \n\r\t\v\0"); for(i=0; iwidth; i++) { for(j=0; jheight; j++) { pPatch->ctrl[i][j].xyz[0] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); pPatch->ctrl[i][j].xyz[1] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); pPatch->ctrl[i][j].xyz[2] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); pPatch->ctrl[i][j].st[0] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); pPatch->ctrl[i][j].st[1] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); } } delete [] content; } else if(!strcmp((char *)current->name, "shader")) { pPatch->pShader = QERApp_Shader_ForName((char*)current->children->content); pPatch->d_texture = pPatch->pShader->getTexture(); } } } void Face_XMLParse (face_t *face, xmlNodePtr surface) { char *str, *content; int i, j; for(xmlNodePtr current = surface->children; current != NULL; current = current->next) { if(current->type != XML_ELEMENT_NODE) continue; if(!strcmp((char *)current->name, "planepts")) { content = Q_StrDup((char *)current->children->content); str = strtok(content, " \n\r\t\v\0"); for (i=0 ; i<3 ; i++) { for (j=0 ; j<3 ; j++) { face->planepts[i][j] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); } } delete [] content; } else if(!strcmp((char *)current->name, "texdef")) { content = Q_StrDup((char *)current->children->content); str = strtok(content, " \n\r\t\v\0"); face->texdef.shift[0] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->texdef.shift[1] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->texdef.rotate = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->texdef.scale[0] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->texdef.scale[1] = atof(str); delete [] content; } else if(!strcmp((char *)current->name, "bpmatrix")) { content = Q_StrDup((char *)current->children->content); str = strtok(content, " \n\r\t\v\0"); face->brushprimit_texdef.coords[0][0] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->brushprimit_texdef.coords[0][1] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->brushprimit_texdef.coords[0][2] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->brushprimit_texdef.coords[1][0] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->brushprimit_texdef.coords[1][1] = atof(str); str = strtok(NULL, " \n\r\t\v\0"); face->brushprimit_texdef.coords[1][2] = atof(str); delete [] content; } else if(!strcmp((char *)current->name, "flags")) { content = Q_StrDup((char *)current->children->content); str = strtok(content, " \n\r\t\v\0"); face->texdef.contents = atoi(str); str = strtok(NULL, " \n\r\t\v\0"); face->texdef.flags = atoi(str); str = strtok(NULL, " \n\r\t\v\0"); face->texdef.value = atoi(str); delete [] content; } else if(!strcmp((char *)current->name, "shader")) { face->texdef.SetName((char *)current->children->content); } } } void Brush_XMLParse (brush_t *pBrush, xmlNodePtr primitive) { face_t *f; for(xmlNodePtr current = primitive->children; current != NULL; current = current->next) { if(current->type != XML_ELEMENT_NODE) continue; f = pBrush->brush_faces; pBrush->brush_faces = Face_Alloc(); Face_XMLParse(pBrush->brush_faces, current); pBrush->brush_faces->next = f; } } void Entity_XMLParse(entity_t *pEntity, xmlNodePtr entity) { brush_t *pBrush; for(xmlNodePtr current = entity->children; current != NULL; current = current->next) { if(current->type != XML_ELEMENT_NODE) continue; if(!strcmp((char *)current->name, "epair")) { char *key = (char *)xmlGetProp(current, (xmlChar *)"key"); char *value = (char *)xmlGetProp(current, (xmlChar *)"value"); SetKeyValue(pEntity, key, value); xmlFree(key); xmlFree(value); } else if(strcmp((char *)current->name, "brush") == 0) { pBrush = Brush_Alloc(); Brush_XMLParse(pBrush, current); ((CPtrArray*)pEntity->pData)->Add(pBrush); } else if(strcmp((char *)current->name, "patch") == 0) { pBrush = Brush_Alloc(); pBrush->patchBrush = true; pBrush->pPatch = Patch_Alloc(); pBrush->pPatch->pSymbiot = pBrush; Patch_XMLParse(pBrush->pPatch, current); ((CPtrArray*)pEntity->pData)->Add(pBrush); } } } void Map_XMLRead(CPtrArray *map, xmlNodePtr map_node) { entity_t *pEntity; xmlNodePtr current; for(current = map_node->children; current != NULL; current = current->next) { if(current->type != XML_ELEMENT_NODE) continue; pEntity = Entity_Alloc(); pEntity->pData = new CPtrArray; Entity_XMLParse(pEntity, current); map->Add(pEntity); } } // SPoG // temporarily copied from qe3.cpp // duplicate code starts here (note: g_strAppPath swapped for g_FuncTable.m_pfnGetQERPath()) void HandleXMLError( void* ctxt, const char* text, ... ) { va_list argptr; static char buf[32768]; va_start (argptr,text); vsprintf (buf, text, argptr); Sys_FPrintf (SYS_ERR, "XML %s\n", buf); va_end (argptr); } #define DTD_BUFFER_LENGTH 1024 xmlDocPtr ParseXMLStream(IDataStream *stream, bool validate = false) { xmlDocPtr doc = NULL; bool wellFormed = false, valid = false; int res, size = 1024; char chars[1024]; xmlParserCtxtPtr ctxt; // SPoG // HACK: use AppPath to resolve DTD location // do a buffer-safe string copy and concatenate int i; char* w; const char* r; char buf[DTD_BUFFER_LENGTH]; w = buf; i = 0; // copy //assert(g_FuncTable.m_pfnGetQERPath() != NULL); for(r = g_FuncTable.m_pfnGetQERPath(); iRead(chars, 4); if (res > 0) { ctxt = xmlCreatePushParserCtxt(NULL, NULL, chars, res, buf); while ((res = stream->Read(chars, size)) > 0) { xmlParseChunk(ctxt, chars, res, 0); } xmlParseChunk(ctxt, chars, 0, 1); doc = ctxt->myDoc; wellFormed = (ctxt->wellFormed == 1); valid = (ctxt->valid == 1); xmlFreeParserCtxt(ctxt); } if(wellFormed && (!validate || (validate && valid))) return doc; if(doc != NULL) xmlFreeDoc(doc); return NULL; } // duplicate code ends here void Map_Read (IDataStream *in, CPtrArray *map) { xmlDocPtr doc; doc = ParseXMLStream(in, false ); // quick hack while dtd validation is broken if(doc != NULL) { xmlNodePtr node=doc->children; while(node != NULL && node->type != XML_ELEMENT_NODE) node=node->next; if(node != NULL) Map_XMLRead(map, node); } xmlFreeDoc(doc); }