static void start_wm(void *userData, const char *name, const char **atts) { int post_ns = 0; if ((post_ns = is_ns(name,xcl_ns_uri))) { if (!strcmp(name+post_ns,"l")) { wm_lineword(findAttr(atts, "ref")); wm_unitlemm(xml_id(atts)); unit_map_entry(); } } else if ((post_ns = is_ns(name,xtf_ns_uri))) { name = name + post_ns; if (!strcmp(name,"w")) { wm_lineword(xml_id(atts)); kwic_map_entry(); } } else if ((post_ns = is_ns(name,norm_ns_uri))) { name = name + post_ns; if (!strcmp(name,"w")) { wm_lineword(xml_id(atts)); kwic_map_entry(); } } charData_discard(); }
const char * get_xml_id(const char **atts) { /*Different versions of the expat library handle the xml: prefix differently :( */ /*And now Oracc harvest uses '|' for the delimiter not :, :(( */ static const char *xml_id1 = "xml:id"; static const char *xml_id2 = "http://www.w3.org/XML/1998/namespace:id"; static const char *xml_id3 = "xml|id"; static const char *xml_id4 = "http://www.w3.org/XML/1998/namespace|id"; const char *x = findAttr(atts,xml_id1); if (!*x) x = findAttr(atts,xml_id2); if (!*x) x = findAttr(atts,xml_id3); if (!*x) x = findAttr(atts,xml_id4); return x; }
void Cities::readFromXMLFile(const std::string &filename) { auto xr = XmlReader::FromFile(filename); if (!xr) { Server::debug()("Failed to load data from " + filename, Color::CHAT_ERROR); return; } for (auto elem : xr.getChildren("city")) { City::Name name; if (!xr.findAttr(elem, "name", name)) continue; createCity(name); City &city = _container[name]; for (auto memberElem : xr.getChildren("member", elem)) { std::string username; if (!xr.findAttr(memberElem, "username", username)) continue; city.addPlayerWithoutAlerting(username); _usersToCities[username] = name; } } }
void TerrainType::load(Container &container, const std::string &filename) { auto xr = XmlReader::FromFile(filename); for (auto elem : xr.getChildren("terrain")) { auto t = TerrainType{}; xr.findAttr(elem, "index", t.index); xr.findAttr(elem, "id", t.id); xr.findAttr(elem, "color", t.color); auto numFrames = 1; xr.findAttr(elem, "frames", numFrames); auto filename = t.id; if (numFrames > 1) filename += "00"; t.image = {"../../Images/Terrain/" + filename + ".png"}; container[t.index] = t; } }
/* * INDEXING CODE */ static void startElement(void *userData, const char *name, const char **atts) { const char *curr_id = NULL; if (!strcmp(name,"o:record")) { curr_id = findAttr(atts, "xml:id"); vid_new_id(vidp, curr_id); fprintf(pqidsf,"%s\n",curr_id); loc8(vid_map_id(vidp,curr_id), 0, lang_mask(atts), &l8); indexing = 1; } }
/* * INDEXING CODE */ static void startElement(void *userData, const char *name, const char **atts) { const char *curr_text_pq, *curr_text_proj; if (!strcmp(name,"xmd"/*"key"*/)) { curr_text_pq = findAttr(atts, "xml:id"); if (l2) { static char qualified_id[128]; curr_text_proj = findAttr(atts, "project"); sprintf(qualified_id, "%s:%s", curr_text_proj, curr_text_pq); fprintf(pqidsf,"%s\n",qualified_id); loc8(vid_map_id(vidp,qualified_id), 0, lang_mask(atts), &l8); } else { fprintf(pqidsf,"%s\n",curr_text_pq); loc8(curr_text_pq, 0, lang_mask(atts), &l8); } indexing = 1; } }
void gdf_sH(void *userData, const char *name, const char **atts) { const char *xid = (htmlid ? findAttr(atts, "id") : get_xml_id(atts)); if (unwrap_html) { if (cued_printStart) { cued_printStart = 0; printStart(userData, name, atts); } else if (!strcmp(name, "body")) { charData_discard(); cued_printStart = 1; } else if (((struct frag*)userData)->nesting) printStart(userData, name, atts); else charData_discard(); } else if (xid && !strcmp(((struct frag*)userData)->xid, xid)) { charData_discard(); printStart(userData, name, atts); } else if (((struct frag*)userData)->nesting) printStart(userData, name, atts); else if (!strcmp(name, "o:records")) { printStart(userData, "o:records", atts); need_gdf_closer = 1; ((struct frag*)userData)->nesting = 0; } else if (html_mode && !strcmp(name, "head")) { fputs("<html xmlns=\"http://www.w3.org/1999/xhtml\">", ((struct frag*)userData)->fp); printStart(userData, name, atts); } else charData_discard(); }
static void sH(void *userData, const char *name, const char **atts) { if (name[22] == 'f' && (!strcmp(name, "http://oracc.org/ns/xtf/1.0:transliteration") || !strcmp(name, "http://oracc.org/ns/xtf/1.0:composite"))) { strcpy(curr_project, findAttr(atts,"project")); strcpy(curr_text_id, get_xml_id(atts)); } else { const char *utf8 = findAttr(atts,"http://oracc.org/ns/gdl/1.0:utf8"); if (*utf8) { static wchar_t wbuf[128]; static size_t n, i; char sbuf[512], xbuf[1024], *hex; unsigned char *sn = NULL; const char *form = NULL; if (*(const unsigned char *)utf8 > 127) { n = mbstowcs(wbuf,utf8,128); hex = malloc(n * 8); *hex = '\0'; for (i = 0; i < n; ++i) { if (i) strcat(hex, "."); sprintf(hex+strlen(hex),"x%05X",wbuf[i]); } } else { hex = strdup(utf8); } if (!(sn = psl_hex_to_sign(hex))) sn = (unsigned char *)hex; sprintf(sbuf,"%s:%s",hex,sn); sprintf(xbuf,"%s:%s:%s:%s",curr_project,curr_text_id,hex,sn); free(hex); if (!(curr_sig_hash = hash_find(signiary,(unsigned char*)sbuf))) { curr_sig_hash = hash_create(1); hash_add(signiary,npool_copy((unsigned char*)sbuf,sig_pool),curr_sig_hash); } incr_val(curr_sig_hash, (const unsigned char *)"#count"); ++total_sign_instances; if (!(curr_hash = hash_find(pertext,(unsigned char*)xbuf))) { curr_hash = hash_create(1); hash_add(pertext,npool_copy((unsigned char*)xbuf,sig_pool),curr_hash); } incr_val(curr_hash, (const unsigned char *)"#count"); form = findAttr(atts, "form"); if (form && *form) { incr_val(curr_sig_hash, (const unsigned char *)form); incr_val(curr_hash, (const unsigned char *)form); curr_sig_hash = curr_hash = NULL; } } } }
DrawCount PointArray::drawPoints(QGLShaderProgram& prog, const TransformState& transState, double quality, bool incrementalDraw) const { TransformState relativeTrans = transState.translate(offset()); relativeTrans.setUniforms(prog.programId()); //printActiveShaderAttributes(prog.programId()); std::vector<ShaderAttribute> activeAttrs = activeShaderAttributes(prog.programId()); // Figure out shader locations for each point field // TODO: attributeLocation() forces the OpenGL usage here to be // synchronous. Does this matter? (Alternative: bind them ourselves.) std::vector<const ShaderAttribute*> attributes; for (size_t i = 0; i < m_fields.size(); ++i) { const GeomField& field = m_fields[i]; if (field.spec.isArray()) { for (int j = 0; j < field.spec.count; ++j) { std::string name = tfm::format("%s[%d]", field.name, j); attributes.push_back(findAttr(name, activeAttrs)); } } else { attributes.push_back(findAttr(field.name, activeAttrs)); } } // Zero out active attributes in case they don't have associated fields GLfloat zeros[16] = {0}; for (size_t i = 0; i < activeAttrs.size(); ++i) { prog.setAttributeValue((int)i, zeros, activeAttrs[i].rows, activeAttrs[i].cols); } // Enable attributes which have associated fields for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i]) prog.enableAttributeArray(attributes[i]->location); } DrawCount drawCount; ClipBox clipBox(relativeTrans); // Draw points in each bucket, with total number drawn depending on how far // away the bucket is. Since the points are shuffled, this corresponds to // a stochastic simplification of the full point cloud. V3f relCamera = relativeTrans.cameraPos(); std::vector<const OctreeNode*> nodeStack; nodeStack.push_back(m_rootNode.get()); while (!nodeStack.empty()) { const OctreeNode* node = nodeStack.back(); nodeStack.pop_back(); if (clipBox.canCull(node->bbox)) continue; if (!node->isLeaf()) { for (int i = 0; i < 8; ++i) { OctreeNode* n = node->children[i]; if (n) nodeStack.push_back(n); } continue; } size_t idx = node->beginIndex; if (!incrementalDraw) node->nextBeginIndex = node->beginIndex; DrawCount nodeDrawCount = node->drawCount(relCamera, quality, incrementalDraw); drawCount += nodeDrawCount; idx = node->nextBeginIndex; if (nodeDrawCount.numVertices == 0) continue; for (size_t i = 0, k = 0; i < m_fields.size(); k+=m_fields[i].spec.arraySize(), ++i) { const GeomField& field = m_fields[i]; int arraySize = field.spec.arraySize(); int vecSize = field.spec.vectorSize(); for (int j = 0; j < arraySize; ++j) { const ShaderAttribute* attr = attributes[k+j]; if (!attr) continue; char* data = field.data.get() + idx*field.spec.size() + j*field.spec.elsize; if (attr->baseType == TypeSpec::Int || attr->baseType == TypeSpec::Uint) { glVertexAttribIPointer(attr->location, vecSize, glBaseType(field.spec), 0, data); } else { glVertexAttribPointer(attr->location, vecSize, glBaseType(field.spec), field.spec.fixedPoint, 0, data); } } } glDrawArrays(GL_POINTS, 0, (GLsizei)nodeDrawCount.numVertices); node->nextBeginIndex += nodeDrawCount.numVertices; } //tfm::printf("Drew %d of total points %d, quality %f\n", totDraw, m_npoints, quality); // Disable all attribute arrays - leaving these enabled seems to screw with // the OpenGL fixed function pipeline in unusual ways. for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i]) prog.disableAttributeArray(attributes[i]->location); } return drawCount; }
static void loc_project(const char **atts) { strcpy(loc_project_buf, findAttr(atts, "project")); }
__INLINE bool ElementRef::hasAttr (KeyId keyId) { return (bool) findAttr(keyId); }
static void xcl_sH(void *userData, const char *name, const char **atts) { static struct ilem_form *curr_form = NULL; const char *vbar = strchr(name,EXPAT_NS_CHAR); struct xcl_context *xcp = userData; if (!strncmp("http://oracc.org/ns/xcl/1.0",name,vbar-name)) { curr_lnum = atoi(findAttr(atts,"lnum")); ++vbar; if (vbar[0] == 'l') { if (!vbar[1]) { curr_xml_id = xpool_copy(findAttr(atts,"xml:id"),xcp->pool); curr_inst = xpool_copy(findAttr(atts,"inst"),xcp->pool); curr_ref = findAttr(atts,"ref"); if (*curr_ref) curr_ref = xpool_copy(curr_ref,xcp->pool); curr_sig = xpool_copy(findAttr(atts,"sig"),xcp->pool); } else if (vbar[1] == 'l' && !vbar[2]) { in_ll = 1; } else if (!strcmp(vbar,"linkset")) { } else if (!strcmp(vbar,"link")) { } } else if (!strcmp(vbar, "xcl")) { xcp->project = xpool_copy(findAttr(atts,"project"),xcp->pool); xcp->linkbase->textid = xcp->textid = xpool_copy(findAttr(atts,"textid"),xcp->pool); xcp->file = xpool_copy(findAttr(atts,"file"),xcp->pool); xcp->langs = xpool_copy(findAttr(atts,"langs"),xcp->pool); } else if (!strcmp(vbar, "c")) { const char *strtok = findAttr(atts, "type"); struct xcl_tok_tab *ttp = xcltok(strtok,strlen(strtok)); if (ttp && ttp->node_type == xcl_node_c) xcl_chunk(xcp, findAttr(atts, "xml:id"), ttp->subtype); else fprintf(stderr,"unknown xcl chunk token type '%s'\n",strtok); } else if (!strcmp(vbar, "psu")) psu_lang = findAttr(atts,"lang"); else if (!strcmp(vbar, "d")) { const char *strtok = findAttr(atts, "type"); struct xcl_tok_tab *ttp = xcltok(strtok,strlen(strtok)); if (ttp && ttp->node_type == xcl_node_d) { xcl_discontinuity(xcp, xpool_copy(findAttr(atts,"ref"),xcp->pool), ttp->subtype, NULL); } else fprintf(stderr,"unknown xcl discontinuity token type '%s'\n",strtok); } else if (!strcmp(vbar,"mds")) curr_meta = xcl_create_meta(xcp,(const char*)npool_copy((unsigned char *)get_xml_id(atts), xcp->pool)); else if (!strcmp(vbar,"m")) next_k = findAttr(atts,"k"); else if (!strcmp(vbar, "multi")) { in_multi = 1; } else if (!strcmp(vbar, "prop")) { if (curr_form) { props_add_prop(curr_form, uxpool_copy(findAttr(atts,"group"),xcp->pool), uxpool_copy(findAttr(atts,"name"),xcp->pool), uxpool_copy(findAttr(atts,"value"),xcp->pool), xpool_copy(findAttr(atts,"ref"),xcp->pool), xpool_copy(findAttr(atts,"xml:id"),xcp->pool), xpool_copy(findAttr(atts,"p"),xcp->pool), atoi(findAttr(atts,"ngram"))); } else { fprintf(stderr,"xff loader: invalid XML: found prop outside form\n"); return; } } } }
static void sH(void *userData, const char *name, const char **atts) { charData_discard(); if (!strcmp(name,"system")) { const char *det; const char *mev; char *endll; mev = findAttr(atts,"mev"); curr_system = new_system(); curr_system->n = (const char *)npool_copy((unsigned char *)findAttr(atts,"n"),context->cpool); curr_system->mev = new_count(); curr_system->mev->num = strtoll(mev,&endll,10); curr_system->mev->den = (int)strtol(endll+1,&endll,10); curr_system->meu = (char *)npool_copy((unsigned char *)endll, context->cpool); hash_add(context->systems, (const unsigned char *)curr_system->n,curr_system); if ((det = findAttr(atts,"det"))) hash_add(context->sysdets, npool_copy((unsigned char*)det,context->cpool), curr_system); } else if (!strcmp(name,"step")) { struct nsa_step *curr_step = new_step(); const char *overt = findAttr(atts,"overt"); const char *aev = findAttr(atts,"aev"); const char *sex = findAttr(atts,"sex"); char *slash; int overt_star; curr_step->ecf = (const char *)npool_copy((unsigned char *)findAttr(atts,"ecf"),context->cpool); curr_step->etr = (const char *)npool_copy((unsigned char *)findAttr(atts,"etr"),context->cpool); curr_step->atf = (const char *)npool_copy((unsigned char *)findAttr(atts,"atf"),context->cpool); curr_step->utf = (const char *)npool_copy((unsigned char *)findAttr(atts,"utf"),context->cpool); if (sex && *sex == 'a') /* horrible cheat! */ curr_step->sex = nsa_sex_asz_axis; curr_step->sys = curr_system; list_add(curr_system->steps,curr_step); if (aev && *aev) { curr_step->aev = new_count(); slash = strchr(aev,'/'); if (!slash) { fprintf(stderr,"nsa: system %s/step %s: bad AEV (should be n/1; actual='%s')\n",curr_system->n,curr_step->atf,aev); curr_step->aev->num = 0; curr_step->aev->den = 1; } else { curr_step->aev->num = strtoll(aev,NULL,10); curr_step->aev->den = (int)strtol(slash+1,NULL,10); } } curr_step->node = curr_system->steps->last; curr_step->sys = curr_system; if (!overt || !*overt || strcmp(overt,"no")) overt_star = 0; else overt_star = 1; /* sH_index_step(curr_step->ecf, curr_step); */ /* sH_index_step(curr_step->etr, curr_step); */ sH_index_step(curr_step->utf, curr_step, overt_star); if (curr_step->atf && strcmp(curr_step->utf,curr_step->atf)) sH_index_step(curr_step->atf, curr_step, overt_star); } else if (!strcmp(name,"ok-com-heads")) { curr_comhead_sys = (const char *)npool_copy((unsigned char *)findAttr(atts,"sys"),context->cpool); } else if (!strcmp(name,"igi")) last_u = (char *)npool_copy((unsigned char *)findAttr(atts,"u"),context->cpool); }
DrawCount PointArray::drawPoints(QGLShaderProgram& prog, const TransformState& transState, double quality, bool incrementalDraw) const { GLuint vao = getVAO("points"); glBindVertexArray(vao); GLuint vbo = getVBO("point_buffer"); glBindBuffer(GL_ARRAY_BUFFER, vbo); TransformState relativeTrans = transState.translate(offset()); relativeTrans.setUniforms(prog.programId()); //printActiveShaderAttributes(prog.programId()); std::vector<ShaderAttribute> activeAttrs = activeShaderAttributes(prog.programId()); // Figure out shader locations for each point field // TODO: attributeLocation() forces the OpenGL usage here to be // synchronous. Does this matter? (Alternative: bind them ourselves.) std::vector<const ShaderAttribute*> attributes; for (size_t i = 0; i < m_fields.size(); ++i) { const GeomField& field = m_fields[i]; if (field.spec.isArray()) { for (int j = 0; j < field.spec.count; ++j) { std::string name = tfm::format("%s[%d]", field.name, j); attributes.push_back(findAttr(name, activeAttrs)); } } else { attributes.push_back(findAttr(field.name, activeAttrs)); } } // Zero out active attributes in case they don't have associated fields GLfloat zeros[16] = {0}; for (size_t i = 0; i < activeAttrs.size(); ++i) { prog.setAttributeValue((int)i, zeros, activeAttrs[i].rows, activeAttrs[i].cols); } // Enable attributes which have associated fields for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i]) prog.enableAttributeArray(attributes[i]->location); } DrawCount drawCount; ClipBox clipBox(relativeTrans); // Draw points in each bucket, with total number drawn depending on how far // away the bucket is. Since the points are shuffled, this corresponds to // a stochastic simplification of the full point cloud. V3f relCamera = relativeTrans.cameraPos(); std::vector<const OctreeNode*> nodeStack; nodeStack.push_back(m_rootNode.get()); while (!nodeStack.empty()) { const OctreeNode* node = nodeStack.back(); nodeStack.pop_back(); if (clipBox.canCull(node->bbox)) continue; if (!node->isLeaf()) { for (int i = 0; i < 8; ++i) { OctreeNode* n = node->children[i]; if (n) nodeStack.push_back(n); } continue; } size_t idx = node->beginIndex; if (!incrementalDraw) node->nextBeginIndex = node->beginIndex; DrawCount nodeDrawCount = node->drawCount(relCamera, quality, incrementalDraw); drawCount += nodeDrawCount; idx = node->nextBeginIndex; if (nodeDrawCount.numVertices == 0) continue; if (m_fields.size() < 1) continue; long bufferSize = 0; for (size_t i = 0; i < m_fields.size(); ++i) { const GeomField &field = m_fields[i]; unsigned int arraySize = field.spec.arraySize(); unsigned int vecSize = field.spec.vectorSize(); // tfm::printfln("FIELD-NAME: %s", field.name); // tfm::printfln("AS: %i, VS: %i, FSS: %i, FSES: %i, GLBTFSS: %i", arraySize, vecSize, field.spec.size(), field.spec.elsize, sizeof(glBaseType(field.spec))); bufferSize += arraySize * vecSize * field.spec.elsize; //sizeof(glBaseType(field.spec)); } bufferSize = bufferSize * (GLsizei)nodeDrawCount.numVertices; // TODO: might be able to do something more efficient here, for example use glBufferSubData to avoid re-allocation of memory by glBufferData // INITIALIZE THE BUFFER TO FULL SIZE // tfm::printfln("INIT BUFFER: %i, BS: %i", vbo, bufferSize); glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)bufferSize, NULL, GL_STREAM_DRAW); /// ======================================================================== /// ======================================================================== GLintptr bufferOffset = 0; for (size_t i = 0, k = 0; i < m_fields.size(); k+=m_fields[i].spec.arraySize(), ++i) { const GeomField& field = m_fields[i]; int arraySize = field.spec.arraySize(); int vecSize = field.spec.vectorSize(); // TODO: should use a single data-array that isn't split into vertex / normal / color / etc. sections, but has interleaved data ? // OpenGL has a stride value in glVertexAttribPointer for exactly this purpose, which should be used for better efficiency // here we write only the current attribute data into this the buffer (e.g. all positions, then all colors) bufferSize = arraySize * vecSize * field.spec.elsize * (GLsizei)nodeDrawCount.numVertices; //sizeof(glBaseType(field.spec)) char* bufferData = field.data.get() + idx*field.spec.size(); glBufferSubData(GL_ARRAY_BUFFER, bufferOffset, bufferSize, bufferData); // tfm::printfln("UPDATE BUFFER: %i, BS: %i", vbo, bufferSize); for (int j = 0; j < arraySize; ++j) { const ShaderAttribute* attr = attributes[k+j]; if (!attr) continue; // we have to create an intermediate buffer offsets for glVertexAttribPointer, but we can still upload the whole data array earlier !? GLintptr intermediate_bufferOffset = bufferOffset + j*field.spec.elsize; if (attr->baseType == TypeSpec::Int || attr->baseType == TypeSpec::Uint) { glVertexAttribIPointer(attr->location, vecSize, glBaseType(field.spec), 0, (const GLvoid *)intermediate_bufferOffset); } else { glVertexAttribPointer(attr->location, vecSize, glBaseType(field.spec), field.spec.fixedPoint, 0, (const GLvoid *)intermediate_bufferOffset); } glEnableVertexAttribArray(attr->location); } bufferOffset += bufferSize; } glDrawArrays(GL_POINTS, 0, (GLsizei)nodeDrawCount.numVertices); node->nextBeginIndex += nodeDrawCount.numVertices; } //tfm::printf("Drew %d of total points %d, quality %f\n", totDraw, m_npoints, quality); // Disable all attribute arrays - leaving these enabled seems to screw with // the OpenGL fixed function pipeline in unusual ways. for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i]) prog.disableAttributeArray(attributes[i]->location); } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); return drawCount; }
// ---------------------------------- int XML::Node::findAttrInt(const char *name) { char *v = findAttr(name); if (!v) return 0; return atoi(v); }
__INLINE bool ElementRef::hasAttr (KeyId keyId, AttributeType type) { return (bool) findAttr(keyId, type); }
// ---------------------------------- int XML::Node::findAttrID(const char *name) { char *v = findAttr(name); if (!v) return 0; return strToID(v); }
void XMLCALL Xml::processStartTag(void* data, const char* tag, const char** attrs) { tags.push(findXmlTag(tag)); switch (tags.top()) { case Id::XmlTagDemo: pProgramList->SetFolder(filename.GetPath(wxPATH_GET_SEPARATOR) + wxString(findAttr(attrs, Id::XmlAttrFolder))); break; case Id::XmlTagProgram: { // Retreive the relevent XML attributes. wxString name = findAttr(attrs, Id::XmlAttrName); wxString vertex = findAttr(attrs, Id::XmlAttrVertex); wxString fragment = findAttr(attrs, Id::XmlAttrFragment); wxString blending = findAttr(attrs, Id::XmlAttrBlending); wxString reflection = findAttr(attrs, Id::XmlAttrReflection); wxString depth = findAttr(attrs, Id::XmlAttrDepth); wxString stressText = findAttr(attrs, Id::XmlAttrStress); // Set up defaults. if (vertex.empty()) vertex = name; if (fragment.empty()) fragment = name; if (blending.empty()) blending = "off"; if (reflection.empty()) reflection = "on"; if (depth.empty()) depth = "on"; Id stress; if (stressText.empty()) stress = Id::StressNone; else stress = stressText == "vertex" ? Id::StressVertex : Id::StressFragment; // Form full path strings. vertex = pProgramList->GetFolder() + "/" + vertex + ".vert"; fragment = pProgramList->GetFolder() + "/" + fragment + ".frag"; // Create the program object. pProgram = pProgramList->NewShader(name, vertex, fragment, blending == "on", reflection == "on", depth == "on", stress); break; } case Id::XmlTagUniform: { if (!pProgram) { wxGetApp().Errorf("XML error: <uniform> outside <shader>.\n"); break; } const char* name = findAttr(attrs, Id::XmlAttrName); const char* type = findAttr(attrs, Id::XmlAttrType); pUniform = pProgram->NewUniform(name, type); break; } case Id::XmlTagTangents: { if (!pProgram) { wxGetApp().Errorf("XML error: <tangents> outside <shader>.\n"); break; } pProgram->RequiresTangents(); break; } case Id::XmlTagBinormals: { if (!pProgram) { wxGetApp().Errorf("XML error: <binormals> outside <shader>.\n"); break; } pProgram->RequiresBinormals(); break; } case Id::XmlTagMotion: { if (!pUniform) { wxGetApp().Errorf("XML error: <linear> outside <uniform>.\n"); break; } if (pUniform->GetType() == 0) { wxGetApp().Errorf("XML error: <motion> specified in <uniform> with unknown 'type'.\n"); break; } const char* type = findAttr(attrs, Id::XmlAttrType); const char* length = findAttr(attrs, Id::XmlAttrLength); pMotion = length ? pUniform->NewMotion(type, length) : 0; pProgram->SetMotion(); break; } case Id::XmlTagSlider: { if (!pUniform) { wxGetApp().Errorf("XML error: <linear> outside <uniform>.\n"); break; } if (pUniform->GetType() == 0) { wxGetApp().Errorf("XML error: <slider> specified in <uniform> with unknown 'type'.\n"); break; } const char* type = findAttr(attrs, Id::XmlAttrType); pSlider = pUniform->NewSlider(type); break; } case Id::XmlTagSilhouette: { if (!pProgram) { wxGetApp().Errorf("XML error: <silhouette> outside <program>.\n"); break; } pProgram->SetSilhouette(); break; } case Id::XmlTagTextures: { const char* stage = findAttr(attrs, Id::XmlAttrStage); if (stage) pProgram->TextureStage(atoi(stage)); const char* mipmap = findAttr(attrs, Id::XmlAttrMipmap); if (mipmap) pProgram->Mipmap(atoi(mipmap)); break; } case Id::XmlTagModels: { const char* lod = findAttr(attrs, Id::XmlAttrLod); if (lod) pProgram->Lod(atoi(lod)); break; } } content.push(std::string()); }