482 lines
20 KiB
C++
482 lines
20 KiB
C++
#include "converter.hh"
|
|
#include <fstream>
|
|
#include <sys/stat.h>
|
|
#include <iostream>
|
|
|
|
using namespace tinyxml2;
|
|
|
|
Converter::Converter(std::string levelPath, std::string levelName, std::string compositionsPath){
|
|
xmlFile = levelPath + levelName + ".xml";
|
|
|
|
//Load Compositions
|
|
std::string stringCompositions = compositionsPath;
|
|
const char* charCompositions = stringCompositions.c_str();
|
|
compositions->LoadFile(charCompositions);
|
|
if (compositions->ErrorID()!=0){
|
|
printf("Could not open Compositions!\n");
|
|
exit(-1);
|
|
}
|
|
|
|
//Create a backup of the current Level png file, if no backup exists
|
|
std::string pngFile = levelPath + levelName + ".png";
|
|
std::string backupPNG = levelPath + levelName + "Backup.png";
|
|
struct stat buf;
|
|
if(stat(backupPNG.c_str(), &buf) != 0){
|
|
std::ifstream src(pngFile, std::ios::binary);
|
|
std::ofstream dst(backupPNG, std::ios::binary);
|
|
dst << src.rdbuf();
|
|
}
|
|
|
|
//Load the Level xml file
|
|
nextID.push_back(0);
|
|
nextID.push_back(1);
|
|
for (int i=0; i<256; i++){
|
|
for (int j=0; j<256; j++){
|
|
idUsed[i][j] = false;
|
|
}
|
|
}
|
|
idUsed[0][0] = true;
|
|
const char* charXmlFile = xmlFile.c_str();
|
|
doc->LoadFile(charXmlFile);
|
|
//check if the xml file did not already exist
|
|
if (doc->ErrorID()!=0){
|
|
std::string answer;
|
|
printf("Could not open xml, do you want to create a new xml? (y/n)\n");
|
|
std::cin >> answer;
|
|
while(answer.compare("y") != 0 && answer.compare("n") != 0){
|
|
printf("Answer with y or n\n");
|
|
std::cin >> answer;
|
|
}
|
|
if(answer.compare("n") == 0){
|
|
exit(-1);
|
|
}
|
|
printf("Creating new xml.\n");
|
|
//Create all global Lightingparameters with Dummy-Values
|
|
std::vector<XMLElement*> lightAttributes;
|
|
lightAttributes.push_back(doc->NewElement("xOffset"));
|
|
lightAttributes.push_back(doc->NewElement("yOffset"));
|
|
lightAttributes.push_back(doc->NewElement("zOffset"));
|
|
lightAttributes.push_back(doc->NewElement("rColour"));
|
|
lightAttributes.push_back(doc->NewElement("gColour"));
|
|
lightAttributes.push_back(doc->NewElement("bColour"));
|
|
lightAttributes.push_back(doc->NewElement("intensity"));
|
|
XMLElement* rColourAmbient = doc->NewElement("rColour");
|
|
XMLElement* gColourAmbient = doc->NewElement("gColour");
|
|
XMLElement* bColourAmbient = doc->NewElement("bColour");
|
|
XMLElement* rColourFogDay = doc->NewElement("rColour");
|
|
XMLElement* gColourFogDay = doc->NewElement("gColour");
|
|
XMLElement* bColourFogDay = doc->NewElement("bColour");
|
|
XMLElement* alphaFogDay = doc->NewElement("alpha");
|
|
XMLElement* rColourFogRise = doc->NewElement("rColour");
|
|
XMLElement* gColourFogRise = doc->NewElement("gColour");
|
|
XMLElement* bColourFogRise = doc->NewElement("bColour");
|
|
XMLElement* alphaFogRise = doc->NewElement("alpha");
|
|
XMLElement* rColourFogNight = doc->NewElement("rColour");
|
|
XMLElement* gColourFogNight = doc->NewElement("gColour");
|
|
XMLElement* bColourFogNight = doc->NewElement("bColour");
|
|
XMLElement* alphaFogNight = doc->NewElement("alpha");
|
|
|
|
lightAttributes[0]->SetText("-1.0");
|
|
lightAttributes[1]->SetText("1.5");
|
|
lightAttributes[2]->SetText("1.0");
|
|
lightAttributes[3]->SetText("1.0");
|
|
lightAttributes[4]->SetText("1.0");
|
|
lightAttributes[5]->SetText("0.9");
|
|
lightAttributes[6]->SetText("0.2");
|
|
rColourAmbient->SetText("1.0");
|
|
gColourAmbient->SetText("1.0");
|
|
bColourAmbient->SetText("1.0");
|
|
rColourFogDay->SetText("0.57");
|
|
gColourFogDay->SetText("0.80");
|
|
bColourFogDay->SetText("0.98");
|
|
alphaFogDay->SetText("1.0");
|
|
rColourFogRise->SetText("0.88");
|
|
gColourFogRise->SetText("0.38");
|
|
bColourFogRise->SetText("0.38");
|
|
alphaFogRise->SetText("1.0");
|
|
rColourFogNight->SetText("0.09");
|
|
gColourFogNight->SetText("0.1");
|
|
bColourFogNight->SetText("0.24");
|
|
alphaFogNight->SetText("1.0");
|
|
|
|
XMLElement* ambientLight = doc->NewElement("ambientLight");
|
|
XMLElement* fogColourDay = doc->NewElement("fogColourDay");
|
|
XMLElement* fogColourRise = doc->NewElement("fogColourRise");
|
|
XMLElement* fogColourNight = doc->NewElement("fogColourNight");
|
|
XMLElement* directionalLight = doc->NewElement("directionalLight");
|
|
|
|
ambientLight->InsertEndChild(rColourAmbient);
|
|
ambientLight->InsertEndChild(gColourAmbient);
|
|
ambientLight->InsertEndChild(bColourAmbient);
|
|
fogColourDay->InsertEndChild(rColourFogDay);
|
|
fogColourDay->InsertEndChild(gColourFogDay);
|
|
fogColourDay->InsertEndChild(bColourFogDay);
|
|
fogColourDay->InsertEndChild(alphaFogDay);
|
|
fogColourRise->InsertEndChild(rColourFogRise);
|
|
fogColourRise->InsertEndChild(gColourFogRise);
|
|
fogColourRise->InsertEndChild(bColourFogRise);
|
|
fogColourRise->InsertEndChild(alphaFogRise);
|
|
fogColourNight->InsertEndChild(rColourFogNight);
|
|
fogColourNight->InsertEndChild(gColourFogNight);
|
|
fogColourNight->InsertEndChild(bColourFogNight);
|
|
fogColourNight->InsertEndChild(alphaFogNight);
|
|
for(int i=0;i<7;i++){
|
|
directionalLight->InsertEndChild(lightAttributes[i]);
|
|
}
|
|
doc->InsertEndChild(ambientLight);
|
|
doc->InsertEndChild(fogColourDay);
|
|
doc->InsertEndChild(fogColourRise);
|
|
doc->InsertEndChild(fogColourNight);
|
|
doc->InsertEndChild(directionalLight);
|
|
|
|
//Create global terrain Element
|
|
XMLElement* terrain = doc->NewElement("terrain");
|
|
XMLElement* terrainHeightmap = doc->NewElement("heightmap");
|
|
XMLElement* terrainTexture = doc->NewElement("texture");
|
|
XMLElement* terrainAmbientFactor = doc->NewElement("ambientFactor");
|
|
XMLElement* terrainDiffuseFactor = doc->NewElement("diffuseFactor");
|
|
XMLElement* terrainSpecularFactor = doc->NewElement("specularFactor");
|
|
XMLElement* terrainShininess = doc->NewElement("shininess");
|
|
std::string heightmapPath = "heightmap" + levelName + ".png";
|
|
terrainHeightmap->SetText(heightmapPath.c_str());
|
|
terrainTexture->SetText("terrainTexture.png");
|
|
terrainAmbientFactor->SetText("0.1");
|
|
terrainDiffuseFactor->SetText("0.8");
|
|
terrainSpecularFactor->SetText("0.2");
|
|
terrainShininess->SetText("1.0");
|
|
terrain->InsertEndChild(terrainHeightmap);
|
|
terrain->InsertEndChild(terrainTexture);
|
|
terrain->InsertEndChild(terrainAmbientFactor);
|
|
terrain->InsertEndChild(terrainDiffuseFactor);
|
|
terrain->InsertEndChild(terrainSpecularFactor);
|
|
terrain->InsertEndChild(terrainShininess);
|
|
doc->InsertEndChild(terrain);
|
|
|
|
//Create global skydome Element
|
|
XMLElement* skydome = doc->NewElement("skydome");
|
|
XMLElement* skydomeModel = doc->NewElement("model");
|
|
XMLElement* skydomeTexture = doc->NewElement("texture");
|
|
XMLElement* skydomeTextureNight = doc->NewElement("nightTexture");
|
|
skydomeModel->SetText("skydome.obj");
|
|
skydomeTexture->SetText("skydome.png");
|
|
skydomeTextureNight->SetText("skydomeNight.png");
|
|
skydome->InsertEndChild(skydomeModel);
|
|
skydome->InsertEndChild(skydomeTexture);
|
|
skydome->InsertEndChild(skydomeTextureNight);
|
|
doc->InsertEndChild(skydome);
|
|
|
|
//Create global physics parameters
|
|
XMLElement* physics = doc->NewElement("physics");
|
|
XMLElement* playerFriction = doc->NewElement("friction");
|
|
XMLElement* playerStrength = doc->NewElement("strength");
|
|
playerFriction->SetText("0.9");
|
|
playerStrength->SetText("300.0");
|
|
physics->InsertEndChild(playerFriction);
|
|
physics->InsertEndChild(playerStrength);
|
|
doc->InsertEndChild(physics);
|
|
|
|
//Create positionConstraint Dummy
|
|
XMLElement* positionConstraint = doc->NewElement("positionConstraint");
|
|
XMLElement* positionConstraintObjectNum = doc->NewElement("objectNum");
|
|
XMLElement* positionConstraintXPos = doc->NewElement("xPosition");
|
|
XMLElement* positionConstraintYPos = doc->NewElement("yPosition");
|
|
XMLElement* positionConstraintZPos = doc->NewElement("zPosition");
|
|
XMLElement* positionConstraintStrength = doc->NewElement("strength");
|
|
positionConstraintObjectNum->SetText("0");
|
|
positionConstraintXPos->SetText("0.0");
|
|
positionConstraintYPos->SetText("0.0");
|
|
positionConstraintZPos->SetText("0.0");
|
|
positionConstraintStrength->SetText("100.0");
|
|
positionConstraint->InsertEndChild(positionConstraintObjectNum);
|
|
positionConstraint->InsertEndChild(positionConstraintXPos);
|
|
positionConstraint->InsertEndChild(positionConstraintYPos);
|
|
positionConstraint->InsertEndChild(positionConstraintZPos);
|
|
positionConstraint->InsertEndChild(positionConstraintStrength);
|
|
doc->InsertEndChild(positionConstraint);
|
|
}else{
|
|
//Create a backup of the current Level xml file
|
|
std::string backupXML = levelPath + levelName + "Backup.xml";
|
|
std::ifstream src(xmlFile, std::ios::binary);
|
|
std::ofstream dst(backupXML, std::ios::binary);
|
|
dst << src.rdbuf();
|
|
//Check what IDs are already in use
|
|
XMLElement* thisComposition = doc->FirstChildElement("composition");
|
|
for(; thisComposition; thisComposition=thisComposition->NextSiblingElement("composition")){
|
|
int idGreen = queryInt(thisComposition, "idGreen");
|
|
int idBlue = queryInt(thisComposition, "idBlue");
|
|
idUsed[idGreen][idBlue] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
Converter::Converter(){
|
|
}
|
|
|
|
Converter::~Converter(){
|
|
}
|
|
|
|
std::vector<int> Converter::newComposition(int type, float posX, float posZ){
|
|
int oldIDGreen, oldIDBlue;
|
|
bool alreadyExists = false;
|
|
XMLElement* thisComposition = doc->FirstChildElement("composition");
|
|
for(; thisComposition; thisComposition=thisComposition->NextSiblingElement("composition")){
|
|
float xPos = queryFloat(thisComposition, "xPos");
|
|
float zPos = queryFloat(thisComposition, "zPos");
|
|
int typeID = queryInt(thisComposition, "typeID");
|
|
if(xPos == posX && zPos == posZ && typeID == type){
|
|
if(alreadyExists){
|
|
std::cout << "At the position " << xPos << "," << zPos << " multiple compositions with the ID " << typeID << " exist in the xml." << std::endl;
|
|
exit(-1);
|
|
}
|
|
oldIDGreen = queryInt(thisComposition, "idGreen");
|
|
oldIDBlue = queryInt(thisComposition, "idBlue");
|
|
alreadyExists = true;
|
|
}
|
|
}
|
|
if (alreadyExists){
|
|
if (! idUsed[oldIDGreen][oldIDBlue]){
|
|
std::cout << "The composition with ID " << oldIDGreen << "," << oldIDBlue << " exists in the xml but the converter thinks it does not." << std::endl;
|
|
exit(-1);
|
|
}
|
|
std::vector<int> oldID;
|
|
oldID.push_back(oldIDGreen);
|
|
oldID.push_back(oldIDBlue);
|
|
return oldID;
|
|
}
|
|
|
|
bool full = false;
|
|
while(idUsed[nextID[0]][nextID[1]]){
|
|
nextID[1] += 1;
|
|
if (nextID[1] == 256){
|
|
nextID[1] = 0;
|
|
nextID[0] +=1;
|
|
if (nextID[0] == 256){
|
|
if(full){
|
|
printf("Can not have more than 65535 compositions.\n");
|
|
exit(-1);
|
|
}
|
|
nextID[0] = 0;
|
|
full = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
XMLElement* newComposition = doc->NewElement("composition");
|
|
XMLElement* typeID = doc->NewElement("typeID");
|
|
XMLElement* idBlue = doc->NewElement("idBlue");
|
|
XMLElement* idGreen = doc->NewElement("idGreen");
|
|
XMLElement* zPos = doc->NewElement("zPos");
|
|
XMLElement* yOffset = doc->NewElement("yOffset");
|
|
XMLElement* xPos = doc->NewElement("xPos");
|
|
XMLElement* manualPos = doc->NewElement("manualPos");
|
|
XMLElement* zRot = doc->NewElement("zRot");
|
|
XMLElement* yRot = doc->NewElement("yRot");
|
|
XMLElement* xRot = doc->NewElement("xRot");
|
|
XMLElement* scale = doc->NewElement("scale");
|
|
|
|
typeID->SetText(std::to_string(type).c_str());
|
|
idBlue->SetText(std::to_string(nextID[1]).c_str());
|
|
idGreen->SetText(std::to_string(nextID[0]).c_str());
|
|
zPos->SetText(std::to_string(posZ).c_str());
|
|
yOffset->SetText("0.0");
|
|
xPos->SetText(std::to_string(posX).c_str());
|
|
manualPos->SetText("false");
|
|
zRot->SetText("0.0");
|
|
yRot->SetText("0.0");
|
|
xRot->SetText("0.0");
|
|
scale->SetText("1.0");
|
|
|
|
newComposition->InsertFirstChild(typeID);
|
|
newComposition->InsertFirstChild(idBlue);
|
|
newComposition->InsertFirstChild(idGreen);
|
|
newComposition->InsertFirstChild(zPos);
|
|
newComposition->InsertFirstChild(yOffset);
|
|
newComposition->InsertFirstChild(xPos);
|
|
newComposition->InsertFirstChild(manualPos);
|
|
newComposition->InsertFirstChild(zRot);
|
|
newComposition->InsertFirstChild(yRot);
|
|
newComposition->InsertFirstChild(xRot);
|
|
newComposition->InsertFirstChild(scale);
|
|
|
|
//Create a Dummy-trigger
|
|
XMLElement* trigger = doc->NewElement("trigger");
|
|
newComposition->InsertEndChild(trigger);
|
|
XMLElement* name = doc->NewElement("name");
|
|
XMLElement* undo = doc->NewElement("undo");
|
|
XMLElement* xPosition = doc->NewElement("xPosition");
|
|
XMLElement* yPosition = doc->NewElement("yPosition");
|
|
XMLElement* zPosition = doc->NewElement("zPosition");
|
|
XMLElement* targetIdGreen = doc->NewElement("targetIdGreen");
|
|
XMLElement* targetIdBlue = doc->NewElement("targetIdBlue");
|
|
XMLElement* distance = doc->NewElement("distance");
|
|
XMLElement* isBiggerThan = doc->NewElement("isBiggerThan");
|
|
XMLElement* objectNum = doc->NewElement("objectNum");
|
|
XMLElement* luaScript = doc->NewElement("luaScript");
|
|
XMLElement* toChangeIdGreen = doc->NewElement("toChangeIdGreen");
|
|
XMLElement* toChangeIdBlue = doc->NewElement("toChangeIdBlue");
|
|
XMLElement* toChangeObjNum = doc->NewElement("toChangeObjNum");
|
|
|
|
name->SetText("-");
|
|
undo->SetText("false");
|
|
xPosition->SetText("0");
|
|
yPosition->SetText("0");
|
|
zPosition->SetText("0");
|
|
targetIdGreen->SetText("-");
|
|
targetIdBlue->SetText("-");
|
|
distance->SetText("1.0");
|
|
isBiggerThan->SetText("false");
|
|
objectNum->SetText("0");
|
|
luaScript->SetText("-");
|
|
toChangeIdGreen->SetText("0");
|
|
toChangeIdBlue->SetText("0");
|
|
toChangeObjNum->SetText("0");
|
|
|
|
trigger->InsertEndChild(name);
|
|
trigger->InsertEndChild(undo);
|
|
trigger->InsertEndChild(xPosition);
|
|
trigger->InsertEndChild(yPosition);
|
|
trigger->InsertEndChild(zPosition);
|
|
trigger->InsertEndChild(targetIdGreen);
|
|
trigger->InsertEndChild(targetIdBlue);
|
|
trigger->InsertEndChild(distance);
|
|
trigger->InsertEndChild(isBiggerThan);
|
|
trigger->InsertEndChild(objectNum);
|
|
trigger->InsertEndChild(luaScript);
|
|
trigger->InsertEndChild(toChangeIdGreen);
|
|
trigger->InsertEndChild(toChangeIdBlue);
|
|
trigger->InsertEndChild(toChangeObjNum);
|
|
|
|
idUsed[nextID[0]][nextID[1]] = true;
|
|
doc->InsertFirstChild(newComposition);
|
|
return nextID;
|
|
}
|
|
|
|
void Converter::updateComposition(int idG, int idB, float posX, float posZ){
|
|
XMLElement* thisComposition = doc->FirstChildElement("composition");
|
|
bool compositionExists = false;
|
|
for(; thisComposition; thisComposition=thisComposition->NextSiblingElement("composition")){
|
|
int idGreen = queryInt(thisComposition, "idGreen");
|
|
int idBlue = queryInt(thisComposition, "idBlue");
|
|
if(idGreen == idG && idBlue == idB){
|
|
if (compositionExists){
|
|
std::cout << "The ID " << idGreen << "," << idBlue << " is used for multiple compositions in the xml." << std::endl;
|
|
exit(-1);
|
|
}
|
|
bool manualPos = queryBool(thisComposition, "manualPos");
|
|
if(!manualPos){
|
|
thisComposition->FirstChildElement("xPos")->SetText(std::to_string(posX).c_str());
|
|
thisComposition->FirstChildElement("zPos")->SetText(std::to_string(posZ).c_str());
|
|
}
|
|
compositionExists = true;
|
|
}
|
|
}
|
|
if(!compositionExists){
|
|
std::cout << "A composition has the ID " << idG << "," << idB << " and the position " << posX << "," << posZ << " in the png, but does not exist in the xml." << std::endl;
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
void Converter::deleteComposition(int idG, int idB){
|
|
XMLElement* thisComposition = doc->FirstChildElement("composition");
|
|
for(; thisComposition; thisComposition=thisComposition->NextSiblingElement("composition")){
|
|
int idGreen = queryInt(thisComposition, "idGreen");
|
|
int idBlue = queryInt(thisComposition, "idBlue");
|
|
if(idGreen == idG && idBlue == idB){
|
|
doc->DeleteChild(thisComposition);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Converter::save(){
|
|
const char* charXmlFile = xmlFile.c_str();
|
|
doc->SaveFile(charXmlFile);
|
|
}
|
|
|
|
float Converter::queryFloat(XMLElement* element, const char* attribute){
|
|
XMLElement* attributeElement = element->FirstChildElement(attribute);
|
|
if (attributeElement == NULL){
|
|
std::cout << "XMLError: Attribute " << attribute << " does not exist." << std::endl;
|
|
exit(-1);
|
|
}
|
|
float ret;
|
|
errorCheck(attributeElement->QueryFloatText(&ret));
|
|
return ret;
|
|
}
|
|
|
|
float Converter::queryFloat(XMLDocument*& element, const char* attribute){
|
|
XMLElement* attributeElement = element->FirstChildElement(attribute);
|
|
if (attributeElement == NULL){
|
|
std::cout << "XMLError: Attribute " << attribute << " does not exist." << std::endl;
|
|
exit(-1);
|
|
}
|
|
float ret;
|
|
errorCheck(attributeElement->QueryFloatText(&ret));
|
|
return ret;
|
|
}
|
|
|
|
int Converter::queryInt(XMLElement* element, const char* attribute){
|
|
XMLElement* attributeElement = element->FirstChildElement(attribute);
|
|
if (attributeElement == NULL){
|
|
std::cout << "XMLError: Attribute " << attribute << " does not exist." << std::endl;
|
|
exit(-1);
|
|
}
|
|
int ret;
|
|
errorCheck(attributeElement->QueryIntText(&ret));
|
|
return ret;
|
|
}
|
|
|
|
int Converter::queryInt(XMLDocument*& element, const char* attribute){
|
|
XMLElement* attributeElement = element->FirstChildElement(attribute);
|
|
if (attributeElement == NULL){
|
|
std::cout << "XMLError: Attribute " << attribute << " does not exist." << std::endl;
|
|
exit(-1);
|
|
}
|
|
int ret;
|
|
errorCheck(attributeElement->QueryIntText(&ret));
|
|
return ret;
|
|
}
|
|
|
|
bool Converter::queryBool(XMLElement* element, const char* attribute){
|
|
XMLElement* attributeElement = element->FirstChildElement(attribute);
|
|
if (attributeElement == NULL){
|
|
std::cout << "XMLError: Attribute " << attribute << " does not exist." << std::endl;
|
|
exit(-1);
|
|
}
|
|
bool ret;
|
|
errorCheck(attributeElement->QueryBoolText(&ret));
|
|
return ret;
|
|
}
|
|
|
|
bool Converter::queryBool(XMLDocument*& element, const char* attribute){
|
|
XMLElement* attributeElement = element->FirstChildElement(attribute);
|
|
if (attributeElement == NULL){
|
|
std::cout << "XMLError: Attribute " << attribute << " does not exist." << std::endl;
|
|
exit(-1);
|
|
}
|
|
bool ret;
|
|
errorCheck(attributeElement->QueryBoolText(&ret));
|
|
return ret;
|
|
}
|
|
|
|
void Converter::errorCheck(XMLError error){
|
|
if (error) {
|
|
printf("XMLError: ");
|
|
if (error == XML_WRONG_ATTRIBUTE_TYPE) {
|
|
printf("Wrong attribute type.\n");
|
|
}
|
|
else if (error == XML_NO_ATTRIBUTE) {
|
|
printf("No attribute.\n");
|
|
}
|
|
else if (error == XML_CAN_NOT_CONVERT_TEXT) {
|
|
printf("Can not convert text.\n");
|
|
}
|
|
else if (error == XML_NO_TEXT_NODE) {
|
|
printf("No text.\n");
|
|
}
|
|
else {
|
|
printf("Unknown error.\n");
|
|
}
|
|
exit(-1);
|
|
}
|
|
}
|