generated from sigonasr2/CPlusPlusProjectTemplate
Add in missing parsing features for TSX reading so that we have all the information we need to recreate the file.
This commit is contained in:
parent
5255502945
commit
a70e604c62
116
TiledCollisionEditor/Error.h
Normal file
116
TiledCollisionEditor/Error.h
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#pragma region License
|
||||||
|
/*
|
||||||
|
License (OLC-3)
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce the above
|
||||||
|
copyright notice. This list of conditions and the following disclaimer must be
|
||||||
|
reproduced in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
Portions of this software are copyright © 2024 The FreeType
|
||||||
|
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
#pragma endregion
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <format>
|
||||||
|
#include <any>
|
||||||
|
#include <memory>
|
||||||
|
#include <source_location>
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
#ifndef __linux__
|
||||||
|
#define NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
|
||||||
|
// Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the
|
||||||
|
// allocations to be of _CLIENT_BLOCK type
|
||||||
|
#else
|
||||||
|
#define NEW new
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define NEW new
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define NEW new
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef ERR //Stupid Windows
|
||||||
|
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
//WARNING! err accepts a stream of data using << operators. If you want to concatenate strings via the + operator, you must wrap the entire operation in ()
|
||||||
|
#define ERR(err) { \
|
||||||
|
std::stringstream errStream; \
|
||||||
|
errStream<<err; \
|
||||||
|
Error::log(errStream,std::source_location::current());}
|
||||||
|
|
||||||
|
class Error{
|
||||||
|
public:
|
||||||
|
inline static void log(std::stringstream&str,std::source_location loc){
|
||||||
|
std::cout<<loc.file_name()<<"("<<loc.line()<<":"<<loc.column()<<") "<<loc.function_name()<<": "<<str.str()<<std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#define ERR(err) { \
|
||||||
|
std::stringstream errStream; \
|
||||||
|
errStream<<err; \
|
||||||
|
Error::log(errStream,std::source_location::current());}
|
||||||
|
|
||||||
|
class Error{
|
||||||
|
public:
|
||||||
|
inline static void log(std::stringstream&str,std::source_location loc){
|
||||||
|
std::cout<<loc.file_name()<<"("<<loc.line()<<":"<<loc.column()<<") "<<loc.function_name()<<": "<<str.str()<<std::endl;
|
||||||
|
#ifdef __DEBUG__
|
||||||
|
throw;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define _CrtDumpMemoryLeaks() ((int)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename type>
|
||||||
|
type DYNAMIC_CAST(auto variable){
|
||||||
|
type pointer=dynamic_cast<type>(variable);
|
||||||
|
if(pointer==nullptr)ERR("Could not dynamic cast to type "<<typeid(variable).name()<<"!");
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T,typename U>
|
||||||
|
std::shared_ptr<T>DYNAMIC_POINTER_CAST(const std::shared_ptr<U>&variable){
|
||||||
|
std::shared_ptr<T> newVariable=dynamic_pointer_cast<T>(variable);
|
||||||
|
if(!newVariable)ERR("Could not dynamic cast to pointer type "<<typeid(newVariable).name()<<"!");
|
||||||
|
return newVariable;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T,typename U>
|
||||||
|
std::shared_ptr<T>DYNAMIC_POINTER_CAST(const std::weak_ptr<U>&variable){
|
||||||
|
std::shared_ptr<T> newVariable=dynamic_pointer_cast<T>(variable.lock());
|
||||||
|
if(!newVariable)ERR("Could not dynamic cast to pointer type "<<typeid(newVariable).name()<<"!");
|
||||||
|
return newVariable;
|
||||||
|
}
|
@ -43,6 +43,7 @@ All rights reserved.
|
|||||||
|
|
||||||
#include "olcUTIL_Geometry2D.h"
|
#include "olcUTIL_Geometry2D.h"
|
||||||
#include "Tileset.h"
|
#include "Tileset.h"
|
||||||
|
#include "Error.h"
|
||||||
|
|
||||||
using namespace olc;
|
using namespace olc;
|
||||||
using namespace olc::utils;
|
using namespace olc::utils;
|
||||||
@ -53,8 +54,24 @@ class TSXParser{
|
|||||||
return parsedTilesetInfo;
|
return parsedTilesetInfo;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
class NonObject{
|
||||||
|
public:
|
||||||
|
std::vector<XMLTag>tags;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NextObjectType{
|
||||||
|
OBJECT,
|
||||||
|
PERSPECTIVEOBJECT,
|
||||||
|
NONOBJECT,
|
||||||
|
};
|
||||||
|
|
||||||
Tileset parsedTilesetInfo;
|
Tileset parsedTilesetInfo;
|
||||||
|
std::vector<XMLTag>originalData;
|
||||||
|
std::vector<NonObject>nonObjects;
|
||||||
int previousTagID;
|
int previousTagID;
|
||||||
|
std::string currentObj;
|
||||||
|
NextObjectType nextObjType;
|
||||||
inline void ParseTag(std::string tag){
|
inline void ParseTag(std::string tag){
|
||||||
XMLTag newTag;
|
XMLTag newTag;
|
||||||
//First character is a '<' so we discard it.
|
//First character is a '<' so we discard it.
|
||||||
@ -99,27 +116,77 @@ class TSXParser{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//objectgroup
|
||||||
|
//object
|
||||||
|
//polygon
|
||||||
if (newTag.tag=="tileset") {
|
if (newTag.tag=="tileset") {
|
||||||
|
parsedTilesetInfo.name=newTag.data["name"];
|
||||||
parsedTilesetInfo.tilecount=stoi(newTag.data["tilecount"]);
|
parsedTilesetInfo.tilecount=stoi(newTag.data["tilecount"]);
|
||||||
parsedTilesetInfo.tilewidth=stoi(newTag.data["tilewidth"]);
|
parsedTilesetInfo.tilewidth=stoi(newTag.data["tilewidth"]);
|
||||||
parsedTilesetInfo.tileheight=stoi(newTag.data["tileheight"]);
|
parsedTilesetInfo.tileheight=stoi(newTag.data["tileheight"]);
|
||||||
parsedTilesetInfo.columns=stoi(newTag.data["columns"]);
|
parsedTilesetInfo.columns=stoi(newTag.data["columns"]);
|
||||||
} else
|
}else
|
||||||
if (newTag.tag=="image") {
|
if (newTag.tag=="image") {
|
||||||
parsedTilesetInfo.ImageData=newTag;
|
parsedTilesetInfo.ImageData=newTag;
|
||||||
parsedTilesetInfo.filename=newTag.GetString("source");
|
parsedTilesetInfo.filename=newTag.GetString("source");
|
||||||
parsedTilesetInfo.imagewidth=newTag.GetInteger("width");
|
parsedTilesetInfo.imagewidth=newTag.GetInteger("width");
|
||||||
parsedTilesetInfo.imageheight=newTag.GetInteger("height");
|
parsedTilesetInfo.imageheight=newTag.GetInteger("height");
|
||||||
} else
|
}else
|
||||||
if (newTag.tag=="property"){
|
if (newTag.tag=="property"){
|
||||||
if(newTag.data["name"]=="Name"){
|
if(nextObjType!=NONOBJECT){
|
||||||
std::string objectName=newTag.data["value"];
|
if(newTag.data["name"]=="Name"){
|
||||||
parsedTilesetInfo.objects[objectName].AddTile(parsedTilesetInfo,previousTagID);
|
std::string objectName=newTag.data["value"];
|
||||||
|
currentObj=objectName;
|
||||||
|
parsedTilesetInfo.objects[objectName].AddTile(parsedTilesetInfo,previousTagID);
|
||||||
|
parsedTilesetInfo.objects[objectName].perspectiveObj=nextObjType==PERSPECTIVEOBJECT;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
nonObjects.back().tags.push_back(newTag);
|
||||||
}
|
}
|
||||||
} else
|
}else
|
||||||
|
if (newTag.tag=="object"){
|
||||||
|
if(newTag.GetInteger("x")!=0||newTag.GetInteger("y")!=0){
|
||||||
|
ERR(std::format("WARNING! The collision for {} was not properly made inside of this editor, but in Tiled!\n\nTHIS IS NOT ALLOWED!\n\nPlease delete the collision for {} to modify it here (Tileset ID: {}) \n\nCollision X:{} Collision Y:{}",currentObj,currentObj,previousTagID,newTag.GetInteger("x"),newTag.GetInteger("y")));
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
if (newTag.tag=="polygon"){
|
||||||
|
int pointCount=0;
|
||||||
|
size_t parseMarker=0;
|
||||||
|
bool findComma=true;
|
||||||
|
vf2d collision;
|
||||||
|
Quadrilateral collisionQuad;
|
||||||
|
const std::string points=newTag.GetString("points");
|
||||||
|
while(parseMarker<points.length()){
|
||||||
|
size_t currentMarker=parseMarker;
|
||||||
|
if(findComma){
|
||||||
|
collision.x=std::stof(points.substr(currentMarker,(parseMarker=points.find(',',currentMarker))-currentMarker));
|
||||||
|
}else{
|
||||||
|
collision.y=std::stof(points.substr(currentMarker,(parseMarker=points.find(' ',currentMarker))-currentMarker));
|
||||||
|
if(pointCount>3)ERR("WARNING! Trying to parse a shape that has more than 4 sides!");
|
||||||
|
collisionQuad[pointCount++]=collision;
|
||||||
|
}
|
||||||
|
if(parseMarker==std::string::npos)break;
|
||||||
|
parseMarker++; //Ignore the symbol
|
||||||
|
findComma=!findComma;
|
||||||
|
}
|
||||||
|
if(pointCount<3)ERR("WARNING! Trying to parse a shape that has less than 4 sides!");
|
||||||
|
parsedTilesetInfo.objects[currentObj].collisionTiles.push_back(collisionQuad);
|
||||||
|
}else
|
||||||
if (newTag.tag=="tile"){
|
if (newTag.tag=="tile"){
|
||||||
|
if(newTag.data["type"]=="Object"){
|
||||||
|
nextObjType=OBJECT;
|
||||||
|
}else
|
||||||
|
if(newTag.data["type"]=="PerspectiveObject"){
|
||||||
|
nextObjType=PERSPECTIVEOBJECT;
|
||||||
|
}else{
|
||||||
|
nextObjType=NONOBJECT;
|
||||||
|
nonObjects.push_back({});
|
||||||
|
nonObjects.back().tags.push_back(newTag);
|
||||||
|
}
|
||||||
previousTagID=newTag.GetInteger("id");
|
previousTagID=newTag.GetInteger("id");
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
originalData.push_back(newTag);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
|
@ -129,6 +129,10 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Error.h">
|
||||||
|
<SubType>
|
||||||
|
</SubType>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="olcPGEX_QuickGUI.h">
|
<ClInclude Include="olcPGEX_QuickGUI.h">
|
||||||
<SubType>
|
<SubType>
|
||||||
</SubType>
|
</SubType>
|
||||||
|
@ -48,6 +48,9 @@
|
|||||||
<ClInclude Include="olcPGEX_ViewPort.h">
|
<ClInclude Include="olcPGEX_ViewPort.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Error.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
|
@ -722,6 +722,12 @@
|
|||||||
<property name="Name" value="BlueHouse1"/>
|
<property name="Name" value="BlueHouse1"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
|
<tile id="257" type="TestClass">
|
||||||
|
<properties>
|
||||||
|
<property name="TestNumber" type="int" value="10"/>
|
||||||
|
<property name="TestProperty" value="Testing"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
<tile id="264" type="PerspectiveObject">
|
<tile id="264" type="PerspectiveObject">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="Name" value="BlueHouse1"/>
|
<property name="Name" value="BlueHouse1"/>
|
||||||
|
@ -43,6 +43,7 @@ All rights reserved.
|
|||||||
|
|
||||||
struct Tileset{
|
struct Tileset{
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
std::string name;
|
||||||
std::unordered_map<std::string,TilesetObject>objects;
|
std::unordered_map<std::string,TilesetObject>objects;
|
||||||
XMLTag ImageData;
|
XMLTag ImageData;
|
||||||
int tilecount=0;
|
int tilecount=0;
|
||||||
|
@ -44,7 +44,7 @@ public:
|
|||||||
|
|
||||||
ImageCheckBox*createNewButton=nullptr;
|
ImageCheckBox*createNewButton=nullptr;
|
||||||
ImageCheckBox*editButton=nullptr;
|
ImageCheckBox*editButton=nullptr;
|
||||||
|
TSXParser parsedMap{""};
|
||||||
public:
|
public:
|
||||||
bool OnUserCreate() override
|
bool OnUserCreate() override
|
||||||
{
|
{
|
||||||
@ -61,7 +61,8 @@ public:
|
|||||||
editButtonImg.Load("EditButton.png");
|
editButtonImg.Load("EditButton.png");
|
||||||
|
|
||||||
std::string tilesetFilename=TILESET_DIR+"Basic Tileset.tsx";
|
std::string tilesetFilename=TILESET_DIR+"Basic Tileset.tsx";
|
||||||
Tileset&tileset=tilesets[tilesetFilename]=TSXParser{tilesetFilename}.GetData();
|
parsedMap={tilesetFilename};
|
||||||
|
Tileset&tileset=tilesets[tilesetFilename]=parsedMap.GetData();
|
||||||
|
|
||||||
Renderable&tilesetImg=images[tilesetFilename];
|
Renderable&tilesetImg=images[tilesetFilename];
|
||||||
tilesetImg.Load(TILESET_DIR+tileset.filename);
|
tilesetImg.Load(TILESET_DIR+tileset.filename);
|
||||||
|
@ -6,6 +6,11 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property name="Name" value="Stop Sign"/>
|
<property name="Name" value="Stop Sign"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
<objectgroup draworder="index" id="2">
|
||||||
|
<object id="1" x="0" y="0">
|
||||||
|
<polygon points="-5,-55 20,-80 50,-59 25,27"/>
|
||||||
|
</object>
|
||||||
|
</objectgroup>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="4" type="Object">
|
<tile id="4" type="Object">
|
||||||
<properties>
|
<properties>
|
||||||
@ -16,6 +21,17 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property name="Name" value="BlueHouse1"/>
|
<property name="Name" value="BlueHouse1"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
<objectgroup draworder="index" id="2">
|
||||||
|
<object id="1" x="-33" y="31">
|
||||||
|
<polygon points="0,0 12,20 -25,35 -30,2"/>
|
||||||
|
</object>
|
||||||
|
<object id="2" x="-33" y="31">
|
||||||
|
<polygon points="0,0 29,-17 45,4 12,20"/>
|
||||||
|
</object>
|
||||||
|
<object id="3" x="-21" y="51">
|
||||||
|
<polygon points="0,0 33,-16 45,28 1,25"/>
|
||||||
|
</object>
|
||||||
|
</objectgroup>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="9" type="PerspectiveObject">
|
<tile id="9" type="PerspectiveObject">
|
||||||
<properties>
|
<properties>
|
||||||
@ -722,6 +738,12 @@
|
|||||||
<property name="Name" value="BlueHouse1"/>
|
<property name="Name" value="BlueHouse1"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
|
<tile id="257" type="TestClass">
|
||||||
|
<properties>
|
||||||
|
<property name="TestNumber" type="int" value="10"/>
|
||||||
|
<property name="TestProperty" value="Testing"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
<tile id="264" type="PerspectiveObject">
|
<tile id="264" type="PerspectiveObject">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="Name" value="BlueHouse1"/>
|
<property name="Name" value="BlueHouse1"/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user