void CopyXMLNode(csRef<iDocumentNode> source, csRef<iDocumentNode> target, int mode) { if (mode == 0) { target->RemoveNodes(); target->RemoveAttributes(); } // copy nodes csRef<iDocumentNodeIterator> nodeIter = source->GetNodes(); while (nodeIter->HasNext()) { csRef<iDocumentNode> child = nodeIter->Next(); csRef<iDocumentNode> targetChild = target->GetNode(child->GetValue()); if (targetChild==NULL || mode==3) // Mode 3 means don't merge tags but just insert multiples, so we create a new one here every time { targetChild = target->CreateNodeBefore(child->GetType()); if (targetChild == NULL) assert(!"failed to create XML node, you are probably using wrong XML parser (xmlread instead of xmltiny)"); targetChild->SetValue(child->GetValue()); } CopyXMLNode(child, targetChild, mode); } // copy attributes csRef <iDocumentAttributeIterator> attrIter = source->GetAttributes(); while (attrIter->HasNext()) { csRef<iDocumentAttribute> attr = attrIter->Next(); const char* attrName = attr->GetName(); if (mode==1 || !target->GetAttribute(attrName)) target->SetAttribute(attrName, attr->GetValue()); } }
csRef < iDocumentNode > MD32spr::CreateValueNode(csRef < iDocumentNode > &parent, const char *name, const char *value) { csRef < iDocumentNode > child = parent->CreateNodeBefore(CS_NODE_ELEMENT, 0); child->SetValue(name); csRef < iDocumentNode > text = child->CreateNodeBefore(CS_NODE_TEXT, 0); text->SetValue(value); return child; }
void MD32spr::WriteXMLMaterials(md3Model * model, csRef < iDocumentNode > &parent) { int i = 0, j = 0; for (i = 0; i < model->header->numMeshes; i++) for (j = 0; j < model->meshes[i].meshHeader->numSkins; j++) { csRef < iDocumentNode > child = parent->CreateNodeBefore(CS_NODE_ELEMENT, 0); child->SetValue("material"); char *name = new char[strlen(model->meshes[i].skins[j].name) + 1]; if(basename(model->meshes[i].skins[j].name, name) == 0) continue; child->SetAttribute("name", strcat(lowercase(name), ".mat")); char *tname = new char[strlen(model->meshes[i].skins[j].name) + 1]; if(basename(model->meshes[i].skins[j].name, tname) == 0) continue; CreateValueNode(child, "texture", lowercase(tname)); } }
void MD32spr::WriteGeneric(md3Model * model, csRef < iDocumentNode > &parent) { int i = 0, j = 0, k = 0; csRef < iDocumentNode > localParent; localParent = parent->CreateNodeBefore(CS_NODE_ELEMENT, 0); localParent->SetValue("textures"); if (model->header->numMeshes > 0) { WriteXMLTextures(model, localParent); localParent = parent->CreateNodeBefore(CS_NODE_ELEMENT, 0); localParent->SetValue("materials"); WriteXMLMaterials(model, localParent); for (i = 0; i < model->header->numMeshes; i++) { localParent = parent->CreateNodeBefore(CS_NODE_ELEMENT, 0); localParent->SetValue("meshfact"); localParent->SetAttribute("name", model->meshes[i].meshHeader->name); CreateValueNode(localParent, "plugin", "crystalspace.mesh.loader.factory.sprite.3d"); csRef < iDocumentNode > child = localParent->CreateNodeBefore(CS_NODE_ELEMENT, 0); child->SetValue("params"); for (j = 0; j < model->meshes[i].meshHeader->numSkins; j++) { char *matName = new char[strlen(model->meshes[i].skins[j].name) + 1]; if(basename(model->meshes[i].skins[j].name, matName) == 0) continue; CreateValueNode(child, "material", strcat(matName, ".mat")); } csRef < iDocumentNode > frame; for (j = 0; j < model->meshes[i].meshHeader->numMeshFrames; j++) { csString fNum; int numVertices = model->meshes[i].meshHeader->numVertices; frame = child->CreateNodeBefore(CS_NODE_ELEMENT, 0); frame->SetValue("frame"); fNum.Format ("f%d", j); frame->SetAttribute("name", fNum); for (k = 0; k < model->meshes[i].meshHeader->numVertices; k++) { float u, v, x, y, z; csRef < iDocumentNode > texel = frame->CreateNodeBefore(CS_NODE_ELEMENT, 0); texel->SetValue("v"); x = model->meshes[i].vertices[j * numVertices + k].vec[0]; y = model->meshes[i].vertices[j * numVertices + k].vec[1]; z = model->meshes[i].vertices[j * numVertices + k].vec[2]; u = model->meshes[i].texCoords[k].texCoord[0]; v = model->meshes[i].texCoords[k].texCoord[1]; texel->SetAttributeAsFloat("x", x / scaleFactor); texel->SetAttributeAsFloat("y", y / scaleFactor); texel->SetAttributeAsFloat("z", z / scaleFactor); texel->SetAttributeAsFloat("u", u); texel->SetAttributeAsFloat("v", v); } } if((stristr(model->fileName.GetData(), "head") || stristr(model->fileName.GetData(), "upper") || stristr(model->fileName.GetData(), "lower")) && player) { // Write all the actions. for(j = 0; j < model->numActions; j++) { if(model->numActions == 1) { csRef < iDocumentNode > action = child->CreateNodeBefore(CS_NODE_ELEMENT, 0); action->SetValue("action"); action->SetAttribute("name", "default"); for (k = 0; k < model->meshes[i].meshHeader->numMeshFrames; k++) { csString fNum; csRef < iDocumentNode > f = action->CreateNodeBefore(CS_NODE_ELEMENT, 0); fNum.Format ("f%d", k); f->SetValue("f"); f->SetAttribute("name", fNum); f->SetAttribute("delay", "1000"); /// 1000 is the default delay. } } else { csRef < iDocumentNode > action = child->CreateNodeBefore(CS_NODE_ELEMENT, 0); action->SetValue("action"); action->SetAttribute("name", model->animInfo[j].actionName); for(k = model->animInfo[j].startFrame; k < (model->animInfo[j].startFrame + model->animInfo[j].numFrames); k++) { csString fNum; csRef < iDocumentNode > f = action->CreateNodeBefore(CS_NODE_ELEMENT, 0); fNum.Format ("f%d", k); f->SetValue("f"); f->SetAttribute("name", fNum); float delay = (1.0f/(float)model->animInfo[j].fps) * 1000; f->SetAttributeAsFloat("delay", delay); } } } } else { csRef < iDocumentNode > action = child->CreateNodeBefore(CS_NODE_ELEMENT, 0); action->SetValue("action"); action->SetAttribute("name", "default"); for (j = 0; j < model->meshes[i].meshHeader->numMeshFrames; j++) { csString fNum; csRef < iDocumentNode > f = action->CreateNodeBefore(CS_NODE_ELEMENT, 0); fNum.Format ("f%d", j); f->SetValue("f"); f->SetAttribute("name", fNum); f->SetAttribute("delay", "1000"); /// 1000 is the default delay. } } for (j = 0; j < model->meshes[i].meshHeader->numTriangles; j++) { csRef < iDocumentNode > triangles = child->CreateNodeBefore(CS_NODE_ELEMENT, 0); triangles->SetValue("t"); triangles->SetAttributeAsInt("v1", model->meshes[i].triangles[j]. triangle[2]); triangles->SetAttributeAsInt("v2", model->meshes[i].triangles[j]. triangle[1]); triangles->SetAttributeAsInt("v3", model->meshes[i].triangles[j]. triangle[0]); } } for (i = 0; i < model->header->numMeshes; i++) { localParent = parent->CreateNodeBefore(CS_NODE_ELEMENT, 0); localParent->SetValue("meshobj"); char *name = new char[strlen(model->fileName.GetData()) + strlen(model->meshes[i].meshHeader->name) + 1]; basename(model->fileName.GetData(), name); localParent->SetAttribute("name", strcat(name, model->meshes[i].meshHeader->name)); CreateValueNode(localParent, "plugin", "crystalspace.mesh.loader.sprite.3d"); csRef < iDocumentNode > params = localParent->CreateNodeBefore(CS_NODE_ELEMENT, 0); params->SetValue("params"); CreateValueNode(params, "factory", model->meshes[i].meshHeader->name); CreateValueNode(params, "action", "default"); } } }
bool psNPCLoader::WriteTrigger(csRef<iDocumentNode> specificsNode, csString &trigger,int priorID, int questID) { // <trigger> // <phrase value=".."> // <phrase value=".."> // <attitude min="0" max="100"> // <response say=".. "/> // <trigger> // .. // </trigger> // </attitude> // </trigger> Result result; Result phrases; csString escArea; csString escTrigger; db->Escape(escArea, area); db->Escape(escTrigger, trigger); if(questID == -1) { result = db->Select("SELECT response_id, " " min_attitude_required, " " max_attitude_required " "FROM npc_triggers " "WHERE prior_response_required=\"%i\" and trigger=\"%s\" and area=\"%s\" and quest_id<1;", priorID, escTrigger.GetData(), escArea.GetData()); // all triggers that have the same response id will be grouped together // and written to the xml file as <phrase value=".."> phrases = db->Select("SELECT id, trigger " "FROM npc_triggers " "WHERE response_id=\"%i\" and area=\"%s\" and quest_id<1;", result[0].GetInt(0), escArea.GetData()); } else { result = db->Select("SELECT response_id, " " min_attitude_required, " " max_attitude_required " "FROM npc_triggers " "WHERE prior_response_required=\"%i\" and trigger=\"%s\" and quest_id=\"%i\";", priorID, escTrigger.GetData(), questID); // all triggers that have the same response id will be grouped together // and written to the xml file as <phrase value=".."> phrases = db->Select("SELECT id, trigger, area " "FROM npc_triggers " "WHERE response_id=\"%i\" and quest_id=\"%i\";", result[0].GetInt(0), questID); } csString temp; csRef<iDocumentNode> triggerNode; for(int i=0; i< (int)phrases.Count(); i++) { int triggerID = phrases[i].GetInt(0); bool duplicate=false; for(size_t j=0; j<triggers.GetSize(); j++) { if(triggerID==triggers[j]) duplicate=true; } // if the trigger hasn't already been added if(!duplicate) { triggers.Push(triggerID); if(!triggerNode) { triggerNode = specificsNode->CreateNodeBefore(CS_NODE_ELEMENT); triggerNode->SetValue("trigger"); csString area(phrases[0][2]); if(this->area.IsEmpty() && !area.IsEmpty()) triggerNode->SetAttribute("area", area); } csRef<iDocumentNode> phraseNode = triggerNode->CreateNodeBefore(CS_NODE_ELEMENT); phraseNode->SetValue("phrase"); phraseNode->SetAttribute("value", phrases[i][1]); } } if(triggerNode) { for(int i=0; i<(int)result.Count(); i++) { int responseID = result[i].GetInt(0); int minAttitude = result[i].GetInt(1); int maxAttitude = result[i].GetInt(2); csRef<iDocumentNode> attitudeNode = triggerNode->CreateNodeBefore(CS_NODE_ELEMENT); attitudeNode->SetValue("attitude"); attitudeNode->SetAttributeAsInt("min", minAttitude); attitudeNode->SetAttributeAsInt("max", maxAttitude); if(!WriteResponse(attitudeNode, responseID, questID)) return false; // check if this trigger contains other triggers Result childResult(db->Select("SELECT DISTINCT trigger " "FROM npc_triggers " "WHERE prior_response_required=%i;" ,responseID)); if(childResult.IsValid()) { for(int j=0; j<(int)childResult.Count(); j++) { csString res(childResult[j][0]); if(!WriteTrigger(attitudeNode, res, responseID, questID)) return false; } } } } return true; }
bool psNPCLoader::WriteResponse(csRef<iDocumentNode> attitudeNode, int id, int questID) { // <attitude max=".." min=".."> // <pronoun him=".." her=".." it=".." them=".."/> // <response say="..."/> // <response say="..."/> // <script> // ... // </script> // </attitude> Result result(db->Select("SELECT response1, response2, response3, response4, response5, " "pronoun_him, pronoun_her, pronoun_it, pronoun_them, script, quest_id " "FROM npc_responses " "WHERE id=\"%i\";", id)); // Sanity check for quest_id if(questID != -1) { for(unsigned int i = 0; i < result.Count(); i++) { if(result[i].GetInt(10) != questID) { CPrintf(CON_ERROR, "Sanity check failed: Response id %i does not have expected quest id %i\n", id, questID); return false; } } } csString him = result[0][5]; csString her = result[0][6]; csString it = result[0][7]; csString them = result[0][8]; if(!him.IsEmpty() || !her.IsEmpty() || !it.IsEmpty() || !them.IsEmpty()) { csRef<iDocumentNode> pronounNode = attitudeNode->CreateNodeBefore(CS_NODE_ELEMENT); pronounNode->SetValue("pronoun"); if(!him.IsEmpty()) pronounNode ->SetAttribute("him", him.GetData()); if(!her.IsEmpty()) pronounNode ->SetAttribute("her", her.GetData()); if(!it.IsEmpty()) pronounNode ->SetAttribute("it", it.GetData()); if(!them.IsEmpty()) pronounNode ->SetAttribute("them", them.GetData()); } for(int i=0; i<5; i++) { if(!csString(result[0][i]).IsEmpty()) { csRef<iDocumentNode> responseNode = attitudeNode->CreateNodeBefore(CS_NODE_ELEMENT); responseNode->SetValue("response"); responseNode->SetAttribute("say", result[0][i]); } } csString script = result[0][9]; if(!script.IsEmpty()) { csRef<iDocumentNode> scriptNode = attitudeNode->CreateNodeBefore(CS_NODE_ELEMENT); scriptNode->SetValue("script"); csRef<iDocumentNode> textNode = scriptNode->CreateNodeBefore(CS_NODE_TEXT); textNode->SetValue(script.GetData()); } return true; }