Implemented TSX exporting for expanded tile hitboxes.

master
sigonasr2 11 months ago
parent 4defd6d5ea
commit d9107f3077
  1. 16
      TiledCollisionEditor/TSXParser.h
  2. 0
      TiledCollisionEditor/Tiles/Basic Tileset - Copy - Copy - Copy - Copy - Copy.tsx
  3. 282
      TiledCollisionEditor/Tiles/Basic Tileset.tsx
  4. 28
      TiledCollisionEditor/TilesetObject.cpp
  5. 1
      TiledCollisionEditor/TilesetObject.h
  6. 29
      TiledCollisionEditor/XMLTag.cpp
  7. 19
      TiledCollisionEditor/XMLTag.h
  8. 45
      TiledCollisionEditor/main.cpp

@ -53,12 +53,10 @@ class TSXParser{
inline Tileset&GetData(){ inline Tileset&GetData(){
return parsedTilesetInfo; return parsedTilesetInfo;
} }
private:
class NonObject{ std::vector<XMLTag>originalData;
public: std::vector<NonObject>nonObjects;
std::vector<XMLTag>tags; private:
};
enum NextObjectType{ enum NextObjectType{
OBJECT, OBJECT,
@ -67,8 +65,6 @@ class TSXParser{
}; };
Tileset parsedTilesetInfo; Tileset parsedTilesetInfo;
std::vector<XMLTag>originalData;
std::vector<NonObject>nonObjects;
int previousTagID; int previousTagID;
std::string currentObj; std::string currentObj;
NextObjectType nextObjType; NextObjectType nextObjType;
@ -137,6 +133,7 @@ class TSXParser{
if(newTag.data["name"]=="Name"){ if(newTag.data["name"]=="Name"){
std::string objectName=newTag.data["value"]; std::string objectName=newTag.data["value"];
currentObj=objectName; currentObj=objectName;
parsedTilesetInfo.objects[objectName].name=objectName;
parsedTilesetInfo.objects[objectName].AddTile(parsedTilesetInfo,previousTagID); parsedTilesetInfo.objects[objectName].AddTile(parsedTilesetInfo,previousTagID);
parsedTilesetInfo.objects[objectName].perspectiveObj=nextObjType==PERSPECTIVEOBJECT; parsedTilesetInfo.objects[objectName].perspectiveObj=nextObjType==PERSPECTIVEOBJECT;
} }
@ -170,6 +167,11 @@ class TSXParser{
findComma=!findComma; findComma=!findComma;
} }
if(pointCount<3)ERR("WARNING! Trying to parse a shape that has less than 4 sides!"); if(pointCount<3)ERR("WARNING! Trying to parse a shape that has less than 4 sides!");
for(vf2d&point:collisionQuad){ //Reposition the bounds so they are at the correct location.
point+=parsedTilesetInfo.objects[currentObj].bounds.pos;
}
parsedTilesetInfo.objects[currentObj].collisionTiles.push_back(collisionQuad); parsedTilesetInfo.objects[currentObj].collisionTiles.push_back(collisionQuad);
}else }else
if (newTag.tag=="tile"){ if (newTag.tag=="tile"){

File diff suppressed because it is too large Load Diff

@ -76,3 +76,31 @@ void TilesetObject::AddTile(const Tileset&tileset,int tileID){
this->upperLeftTileId=upperLeftTileId; this->upperLeftTileId=upperLeftTileId;
} }
} }
std::vector<std::pair<int,std::string>>TilesetObject::OutputTag(const Tileset&activeTileset)const{
std::vector<std::pair<int,std::string>>tileID_tileStr;
for(int y=bounds.pos.y;y<bounds.bottom().end.y;y+=activeTileset.tileheight){
for(int x=bounds.pos.x;x<bounds.right().end.x;x+=activeTileset.tilewidth){
std::string finalStr="";
int tileID=(y/activeTileset.tileheight)*activeTileset.columns+(x/activeTileset.tilewidth);
finalStr+=std::format("<tile id=\"{}\" type=\"{}\">",tileID,perspectiveObj?"PerspectiveObject":"Object")+"\n";
finalStr+="<properties>\n";
finalStr+=std::format("<property name=\"Name\" value=\"{}\"/>",name)+"\n";
finalStr+="</properties>\n";
if(tileID==upperLeftTileId){ //Only the upper left tile will store the collision.
finalStr+="<objectgroup draworder=\"index\" id=\"1\">\n";
for(int id=1;const Quadrilateral&quad:collisionTiles){
finalStr+=std::format("<object id=\"{}\" x=\"0\" y=\"0\">",id)+"\n";
finalStr+=std::format("<polygon points=\"{},{} {},{} {},{} {},{}\"/>",quad[0].x-bounds.pos.x,quad[0].y-bounds.pos.y,quad[1].x-bounds.pos.x,quad[1].y-bounds.pos.y,quad[2].x-bounds.pos.x,quad[2].y-bounds.pos.y,quad[3].x-bounds.pos.x,quad[3].y-bounds.pos.y)+"\n";
finalStr+="</object>\n";
id++;
}
finalStr+="</objectgroup>\n";
}
finalStr+="</tile>\n";
tileID_tileStr.push_back({tileID,finalStr});
}
}
return tileID_tileStr;
}

@ -52,4 +52,5 @@ public:
geom2d::rect<int>bounds; geom2d::rect<int>bounds;
std::vector<Quadrilateral>collisionTiles; std::vector<Quadrilateral>collisionTiles;
void AddTile(const Tileset&tileset,int tileID); void AddTile(const Tileset&tileset,int tileID);
std::vector<std::pair<int,std::string>>OutputTag(const Tileset&activeTileset)const;
}; };

@ -49,20 +49,20 @@ std::string XMLTag::str(){
return tag+"\n"; return tag+"\n";
} }
int XMLTag::GetInteger(std::string dataTag){ int XMLTag::GetInteger(std::string dataTag)const{
return std::stoi(data[dataTag]); return std::stoi(data.at(dataTag));
} }
float XMLTag::GetFloat(std::string dataTag){ float XMLTag::GetFloat(std::string dataTag)const{
return std::stof(data[dataTag]); return std::stof(data.at(dataTag));
} }
double XMLTag::GetDouble(std::string dataTag){ double XMLTag::GetDouble(std::string dataTag)const{
return std::stod(data[dataTag]); return std::stod(data.at(dataTag));
} }
bool XMLTag::GetBool(std::string dataTag){ bool XMLTag::GetBool(std::string dataTag)const{
if (data[dataTag]=="0"||data[dataTag]=="false") { if (data.at(dataTag)=="0"||data.at(dataTag)=="false") {
return false; return false;
} else { } else {
return true; return true;
@ -73,7 +73,7 @@ std::string XMLTag::GetString(std::string dataTag){
return data[dataTag]; return data[dataTag];
} }
std::string XMLTag::OutputTag(std::string ending){ std::string XMLTag::OutputTag(std::string ending)const{
std::string finalStr{"<"}; std::string finalStr{"<"};
finalStr+=tag+" "; finalStr+=tag+" ";
for(auto&[name,value]:data){ for(auto&[name,value]:data){
@ -82,3 +82,14 @@ std::string XMLTag::OutputTag(std::string ending){
finalStr+=ending; finalStr+=ending;
return finalStr; return finalStr;
} }
std::pair<int,std::string>NonObject::OutputTag()const{
std::string finalStr;
finalStr+=tags[0].OutputTag()+"\n";
finalStr+="<properties>\n";
for(int i=1;i<tags.size();i++){
finalStr+=tags[i].OutputTag()+"\n";
}
finalStr+="</properties>\n";
return {tags[0].GetInteger("id"),finalStr};
}

@ -38,6 +38,7 @@ All rights reserved.
#pragma once #pragma once
#include <string> #include <string>
#include <map> #include <map>
#include <vector>
struct XMLTag{ struct XMLTag{
std::string tag; std::string tag;
@ -45,10 +46,18 @@ struct XMLTag{
const std::string FormatTagData(std::map<std::string,std::string>tiles); const std::string FormatTagData(std::map<std::string,std::string>tiles);
friend std::ostream& operator << (std::ostream& os, XMLTag& rhs); friend std::ostream& operator << (std::ostream& os, XMLTag& rhs);
std::string str(); std::string str();
int GetInteger(std::string dataTag); int GetInteger(std::string dataTag)const;
float GetFloat(std::string dataTag); float GetFloat(std::string dataTag)const;
double GetDouble(std::string dataTag); double GetDouble(std::string dataTag)const;
bool GetBool(std::string dataTag); bool GetBool(std::string dataTag)const;
std::string GetString(std::string dataTag); std::string GetString(std::string dataTag);
std::string OutputTag(std::string ending=">"); std::string OutputTag(std::string ending=">")const;
};
class NonObject{
public:
std::vector<XMLTag>tags;
std::pair<int,std::string>OutputTag()const;
}; };

@ -3,6 +3,7 @@
#include "olcPGEX_TransformedView.h" #include "olcPGEX_TransformedView.h"
#include "olcUTIL_Camera2D.h" #include "olcUTIL_Camera2D.h"
#include "olcPGEX_QuickGUI.h" #include "olcPGEX_QuickGUI.h"
#include <variant>
using namespace olc; using namespace olc;
using namespace olc::utils; using namespace olc::utils;
@ -78,12 +79,50 @@ public:
} }
void SaveFile(){ void SaveFile(){
std::ofstream file{activeTileset}; std::stringstream file;
if(file.good()){ if(file.good()){
const std::vector<XMLTag>originalData=parsedMap.originalData;
const std::vector<NonObject>nonObjects=parsedMap.nonObjects;
auto xmlTag=std::find_if(originalData.begin(),originalData.end(),[](const XMLTag tag){return tag.tag=="?xml";});
file<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<std::endl;
const Tileset&activeSet=tilesets.at(activeTileset);
file<<std::format("<tileset name=\"{}\" tilewidth=\"{}\" tileheight=\"{}\" tilecount=\"{}\" columns=\"{}\">",
activeSet.name,activeSet.tilewidth,activeSet.tileheight,(activeSet.imagewidth/activeSet.tilewidth)*(activeSet.imageheight/activeSet.tileheight),activeSet.columns)<<std::endl;
auto transformationsTag=std::find_if(originalData.begin(),originalData.end(),[](const XMLTag tag){return tag.tag=="transformations";});
file<<(*transformationsTag).OutputTag("/>")<<std::endl;
file<<std::format("<image source=\"{}\" width=\"{}\" height=\"{}\"/>",
activeSet.filename,activeSet.imagewidth,activeSet.imageheight)<<std::endl;
std::vector<std::pair<int,std::string>>tiles;
for(auto&[name,obj]:activeSet.objects){
const std::vector<std::pair<int,std::string>>objTiles{obj.OutputTag(activeSet)};
tiles.insert(tiles.end(),objTiles.begin(),objTiles.end());
}
for(const NonObject&obj:nonObjects){
tiles.push_back(obj.OutputTag());
}
std::sort(tiles.begin(),tiles.end(),[](const std::pair<int,std::string>tileData1,const std::pair<int,std::string>tileData2){
return tileData1.first<tileData2.first;
});
for(auto&[tileID,str]:tiles){
file<<str<<std::endl;
}
file<<"</tileset>"<<std::endl;
}else{ }else{
std::cout<<"WARNING! File not available for saving! Failed to save!"<<std::endl; std::cout<<"WARNING! File not available for saving! Failed to save!"<<std::endl;
} }
std::ofstream saveFile{activeTileset};
saveFile<<file.str()<<std::endl;
saveFile.close();
} }
void Update(){ void Update(){
@ -186,6 +225,10 @@ public:
if(GetMouse(Mouse::RIGHT).bPressed&&!EditingQuad&&!dragTranslate){ if(GetMouse(Mouse::RIGHT).bPressed&&!EditingQuad&&!dragTranslate){
if(highlightedQuad!=nullptr){ if(highlightedQuad!=nullptr){
std::erase_if(tilesets[activeTileset].objects[selectedObj].collisionTiles,[&](Quadrilateral&q){return &q==highlightedQuad;}); std::erase_if(tilesets[activeTileset].objects[selectedObj].collisionTiles,[&](Quadrilateral&q){return &q==highlightedQuad;});
editingPoint=4;
dragging=false;
editingQuad=nullptr;
dragTranslate=false;
SaveFile(); SaveFile();
} }
} }

Loading…
Cancel
Save