Compare commits
10 Commits
a241dc857d
...
a0a8c3fff9
Author | SHA1 | Date | |
---|---|---|---|
|
a0a8c3fff9 | ||
|
c02f8da854 | ||
|
dde573d436 | ||
|
662f01150f | ||
|
3cb21258b8 | ||
|
e6511e3306 | ||
|
579b23fccb | ||
|
f88a4710f0 | ||
|
fc711448d8 | ||
|
957e262560 |
4
Makefile
4
Makefile
@ -1,6 +1,6 @@
|
||||
EX=reflex2q3
|
||||
CC=g++
|
||||
CFLAGS=-std=c++11 -I"include" -I"lib/Catch/single_include" -I"lib/cxxopts/include" -I"/usr/include/eigen3"
|
||||
CFLAGS=-std=c++11 -static -static-libgcc -static-libstdc++ -I"/mingw64/include/eigen3" -I"include" -I"lib/Catch/single_include" -I"lib/cxxopts/include" -I"/usr/include/eigen3"
|
||||
TESTEX=runtests
|
||||
|
||||
all: main test
|
||||
@ -28,5 +28,5 @@ EntityConverter.o: src/EntityConverter.cpp
|
||||
$(CC) -c $^ $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm *.o *.log $(EX)
|
||||
rm *.o $(EX)
|
||||
|
||||
|
20
README.md
20
README.md
@ -1,37 +1,37 @@
|
||||
#reflex2q3
|
||||
# reflex2q3
|
||||
Converts Reflex maps (Version 8 and below) into id Tech map files. A pre-compiled [Windows executable](https://u.teknik.io/eOmo5.zip) is available.
|
||||
|
||||
####Build Requirements
|
||||
#### Build Requirements
|
||||
* [Eigen 3, C++ template library](http://eigen.tuxfamily.org/index.php?title=Main_Page)
|
||||
|
||||
####Building:
|
||||
#### Building:
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
make
|
||||
```
|
||||
|
||||
####Convert map geometry:
|
||||
#### Convert map geometry:
|
||||
```bash
|
||||
./reflex2q3 [input].map [output].map
|
||||
```
|
||||
|
||||
####Convert map geometry and entities:
|
||||
#### Convert map geometry and entities:
|
||||
```bash
|
||||
./reflex2q3 [input].map [output].map -e [entity file].ent
|
||||
./reflex2q3 [input].map [output].map -e [entity file].rem
|
||||
```
|
||||
|
||||
We've provided Quake 3 and Xonotic entity conversion files (r2q3.ent and r2xonotic.ent). To create entity files for other games built on the [id Tech 3](https://en.wikipedia.org/wiki/Id_Tech_3) engine or previous [id Tech](https://en.wikipedia.org/wiki/Id_Tech) engines, refer to our [Reflex entity documentation](https://git.teknik.io/scuti/reflex2q3/src/f2b0341da38b82ad4f0a0cf258b0f6e6d8335fda/docs/doc-entities.txt), our sample .ent files, and relevant documentation for your game.
|
||||
We've provided Quake 3 and Xonotic entity conversion files (r2q3.rem and r2xonotic.rem). To create entity files for other games built on the [id Tech 3](https://en.wikipedia.org/wiki/Id_Tech_3) engine or previous [id Tech](https://en.wikipedia.org/wiki/Id_Tech) engines, refer to our [Reflex entity documentation](https://git.teknik.io/scuti/reflex2q3/src/f2b0341da38b82ad4f0a0cf258b0f6e6d8335fda/docs/doc-entities.txt), our sample .rem files, and relevant documentation for your game.
|
||||
|
||||
####List all command line arguments:
|
||||
#### List all command line arguments:
|
||||
```bash
|
||||
./reflex2q3 --help
|
||||
```
|
||||
|
||||
####Compiler(s)
|
||||
#### Compiler(s)
|
||||
* mingw-w64, GCC 5.3.0
|
||||
* gcc version 7.1.1 20170528
|
||||
|
||||
####Tested With
|
||||
#### Tested With
|
||||
* netradiant-1.5.0-20120301
|
||||
|
||||
__________________
|
||||
|
@ -57,23 +57,23 @@ class EntityConverter
|
||||
* Method: Constructor
|
||||
* Description: Creates entity format mapping
|
||||
* CAUTION: Requires extractMapInfo method to be called after this
|
||||
* Requires: .ent filename for mapping entities from reflex format to xonotic format
|
||||
* THROWS: runtime_error on .ent format error
|
||||
* Requires: Reflex Entity Mapping filename
|
||||
* THROWS: runtime_error on Reflex Entity Mapping file format error
|
||||
* THROWS: std::ios::failure on IO failure
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
EntityConverter(const std::string &entityMapFile);
|
||||
EntityConverter (const std::string &entityMapFile);
|
||||
/* *--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
* Method: Constructor
|
||||
* Description: Creates entity format mapping and pre-scans for map info
|
||||
* Parameter: string entityMapFile, file maps source to target entity formats
|
||||
* Parameter: string reflexMapFile, for pre-scan
|
||||
* THROWS: runtime_error on .ent format error
|
||||
* THROWS: runtime_error on Reflex Entity Mapping file format error
|
||||
* THROWS: std::ios::failure on IO failure
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
EntityConverter(const std::string &entityMapFile, const std::string &reflexMapFile);
|
||||
EntityConverter (const std::string &entityMapFile, const std::string &reflexMapFile);
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -86,7 +86,7 @@ class EntityConverter
|
||||
* THROWS: runtime_error when called before map info has been extracted
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
std::vector<std::string> convert(const std::vector<std::string> &lines);
|
||||
std::vector<std::string> convert (const std::vector<std::string> &lines);
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -97,7 +97,7 @@ class EntityConverter
|
||||
* THROWS: runtime_error when encountering malformed entity
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
void extractMapInfo(std::queue<std::vector<std::string>> entities);
|
||||
void extractMapInfo (std::queue<std::vector<std::string>> entities);
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -108,7 +108,7 @@ class EntityConverter
|
||||
* THROWS: runtime_error when encountering malformed entity
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
void extractMapInfo(const std::vector<std::vector<std::string>> &entities);
|
||||
void extractMapInfo (const std::vector<std::vector<std::string>> &entities);
|
||||
|
||||
|
||||
|
||||
@ -124,14 +124,14 @@ class EntityConverter
|
||||
* Return: vector of strings, the converted entity
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
std::vector<std::string> convertPickup(const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertPlayerSpawn(const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertJumpPad(const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertTeleporter(const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertTarget(const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertRaceStart(const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertRaceFinish(const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertPointLight(const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertPickup (const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertPlayerSpawn (const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertJumpPad (const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertTeleporter (const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertTarget (const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertRaceStart (const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertRaceFinish (const std::vector<std::string> &lines) const;
|
||||
std::vector<std::string> convertPointLight (const std::vector<std::string> &lines) const;
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
@ -141,7 +141,7 @@ class EntityConverter
|
||||
* Parameter: string "line", entity keyword followed by the type
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
std::string getAttributeType(const std::string &line) const;
|
||||
std::string getAttributeType (const std::string &line) const;
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -151,7 +151,7 @@ class EntityConverter
|
||||
* Return: true if no error, false if error
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
void mapEntities(const std::string &mapFile);
|
||||
void mapEntities (const std::string &mapFile);
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -170,7 +170,7 @@ class EntityConverter
|
||||
* single entity
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
void extractFromEntity(const std::string &line, std::istream &is);
|
||||
void extractFromEntity (const std::string &line, std::istream &is);
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -182,7 +182,7 @@ class EntityConverter
|
||||
* Return: string, float value passed as string
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
std::string offset(const std::string &value, const float offset) const;
|
||||
std::string offset (const std::string &value, const float offset) const;
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -192,7 +192,7 @@ class EntityConverter
|
||||
* Return: string, the adjusted angle in degrees
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
std::string adjustAngleForHandedness(const std::string &angle) const;
|
||||
std::string adjustAngleForHandedness (const std::string &angle) const;
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -204,7 +204,7 @@ class EntityConverter
|
||||
* Parameter: float b, RETURN BY REFERENCE: converted blue value
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
void hexToRGB(const std::string &hex, float &r, float &g, float &b) const;
|
||||
void hexToRGB (const std::string &hex, float &r, float &g, float &b) const;
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -213,7 +213,7 @@ class EntityConverter
|
||||
* Parameter: string value, original brightness value
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
int adjustBrightness(const std::string &value) const;
|
||||
int adjustBrightness (const std::string &value) const;
|
||||
/*
|
||||
*--------------------------------------------------------------------------------------
|
||||
* Class: EntityConverter
|
||||
@ -221,7 +221,7 @@ class EntityConverter
|
||||
* Description: Combine a message and the entity responsible into an error message
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
std::string makeErrorMessage(const std::string message,
|
||||
std::string makeErrorMessage (const std::string message,
|
||||
const std::vector<std::string> entity) const;
|
||||
|
||||
|
||||
|
@ -25,12 +25,7 @@ void write(const std::vector<std::string> &,
|
||||
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
|
||||
EntityConverter &);
|
||||
|
||||
void parse_prefab(std::ifstream &,
|
||||
std::ofstream &,
|
||||
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
|
||||
std::vector<std::vector<std::string> > &);
|
||||
|
||||
bool convertmap(const char * const,
|
||||
bool convertmap(std::stringstream &,
|
||||
const char * const,
|
||||
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
|
||||
std::vector<std::vector<std::string> > &);
|
||||
@ -180,4 +175,19 @@ using namespace std;
|
||||
return output;
|
||||
}
|
||||
|
||||
template <class ISTR>
|
||||
void parse_prefab(ISTR &f,
|
||||
std::ofstream &out,
|
||||
void (*b) (std::stringstream &, const std::vector<TPlanePoints> &),
|
||||
std::vector<std::vector<std::string> > &entities) {
|
||||
using namespace std;
|
||||
string l;
|
||||
getline(f, l);
|
||||
if (l.find(KEYWORD_BRUSH) != string::npos) {
|
||||
write(parse_brush<ISTR>(f), out, b);
|
||||
} else if (l.find(KEYWORD_ENTITY) != string::npos) {
|
||||
entities.push_back(get_entity<ISTR>(f));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1 +1 @@
|
||||
Subproject commit 27640a5a968a0981eeab5f354aa52459641b2e91
|
||||
Subproject commit d2d8455b571b6c66c4b7003500a77f9a93ecdc28
|
@ -1 +1 @@
|
||||
Subproject commit c2c2262626b20c75d1bebbab5e35d3f9282d7f63
|
||||
Subproject commit d7b930846cdccfc8bcecc4d7150ddcbadffac360
|
@ -33,9 +33,11 @@
|
||||
|
||||
|
||||
|
||||
EntityConverter::EntityConverter(const std::string &entityMapFile) :
|
||||
OFFSET_PLAYER(32.0), OFFSET_PICKUP(2.0), BRIGHTNESS_ADJUST(50.0),
|
||||
OUTPUT_PRECISION(10)
|
||||
EntityConverter::EntityConverter (const std::string &entityMapFile)
|
||||
: OFFSET_PLAYER(32.0),
|
||||
OFFSET_PICKUP(2.0),
|
||||
BRIGHTNESS_ADJUST(50.0),
|
||||
OUTPUT_PRECISION(6)
|
||||
{
|
||||
//MUST RUN extractMapInfo method after this constructor
|
||||
haveMapInfo_ = false;
|
||||
@ -46,14 +48,14 @@ EntityConverter::EntityConverter(const std::string &entityMapFile) :
|
||||
ws_.tdm = true;
|
||||
ws_.duel = true;
|
||||
|
||||
mapEntities(entityMapFile);
|
||||
mapEntities (entityMapFile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
EntityConverter::EntityConverter(const std::string &entityMapFile,
|
||||
EntityConverter::EntityConverter (const std::string &entityMapFile,
|
||||
const std::string &reflexMapFile) : OFFSET_PLAYER(32.0),
|
||||
OFFSET_PICKUP(2.0), BRIGHTNESS_ADJUST(50.0), OUTPUT_PRECISION(10)
|
||||
OFFSET_PICKUP(2.0), BRIGHTNESS_ADJUST(50.0), OUTPUT_PRECISION(6)
|
||||
{
|
||||
haveMapInfo_ = false;
|
||||
// game modes default to enabled
|
||||
@ -63,21 +65,21 @@ EntityConverter::EntityConverter(const std::string &entityMapFile,
|
||||
ws_.tdm = true;
|
||||
ws_.duel = true;
|
||||
|
||||
mapEntities(entityMapFile);
|
||||
mapEntities (entityMapFile);
|
||||
|
||||
// Pre-scan for info needed by converter
|
||||
std::ifstream fin;
|
||||
fin.open(reflexMapFile);
|
||||
fin.open (reflexMapFile);
|
||||
|
||||
if ( fin.is_open() ) {
|
||||
if (fin.is_open()) {
|
||||
//Extract the source type of targets (teleporters or jump pads)
|
||||
std::string line;
|
||||
while (std::getline(fin, line)) {
|
||||
extractFromEntity(line, fin);
|
||||
extractFromEntity (line, fin);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::ios::failure( "Error: EntityConverter failed to open .map file " + reflexMapFile );
|
||||
throw std::ios::failure ("Error: EntityConverter failed to open .map file " + reflexMapFile);
|
||||
}
|
||||
|
||||
fin.close();
|
||||
@ -89,22 +91,22 @@ EntityConverter::EntityConverter(const std::string &entityMapFile,
|
||||
|
||||
|
||||
void
|
||||
EntityConverter::extractMapInfo(std::queue<std::vector<std::string>> entities)
|
||||
EntityConverter::extractMapInfo (std::queue<std::vector<std::string>> entities)
|
||||
{
|
||||
if( haveMapInfo_ ) {
|
||||
if (haveMapInfo_) {
|
||||
std::cerr << "Map info already extracted, doing nothing" << std::endl;
|
||||
}
|
||||
else {
|
||||
while ( ! entities.empty() ) {
|
||||
std::vector<std::string> entity( entities.front() );
|
||||
while ( ! entities.empty()) {
|
||||
std::vector<std::string> entity (entities.front());
|
||||
entities.pop();
|
||||
|
||||
std::stringstream ss;
|
||||
std::copy(entity.begin(), entity.end(),
|
||||
std::ostream_iterator<std::string>(ss, "\n"));
|
||||
std::copy (entity.begin(), entity.end(),
|
||||
std::ostream_iterator<std::string> (ss, "\n"));
|
||||
|
||||
std::string nextLine;
|
||||
if ( getline(ss, nextLine )) {
|
||||
if (getline(ss, nextLine)) {
|
||||
extractFromEntity(nextLine, ss);
|
||||
}
|
||||
}
|
||||
@ -117,23 +119,23 @@ EntityConverter::extractMapInfo(std::queue<std::vector<std::string>> entities)
|
||||
|
||||
|
||||
void
|
||||
EntityConverter::extractMapInfo(const std::vector<std::vector<std::string>> &entities)
|
||||
EntityConverter::extractMapInfo (const std::vector<std::vector<std::string>> &entities)
|
||||
{
|
||||
if( haveMapInfo_ ) {
|
||||
if (haveMapInfo_) {
|
||||
std::cerr << "Map info already extracted, doing nothing" << std::endl;
|
||||
}
|
||||
else {
|
||||
std::vector<std::vector<std::string>>::const_iterator it;
|
||||
for ( it=entities.begin(); it!=entities.end(); ++it ) {
|
||||
std::vector<std::string> entity( *it );
|
||||
for (it=entities.begin(); it!=entities.end(); ++it) {
|
||||
std::vector<std::string> entity (*it);
|
||||
|
||||
std::stringstream ss;
|
||||
std::copy(entity.begin(), entity.end(),
|
||||
std::ostream_iterator<std::string>(ss, "\n"));
|
||||
std::copy (entity.begin(), entity.end(),
|
||||
std::ostream_iterator<std::string> (ss, "\n"));
|
||||
|
||||
std::string nextLine;
|
||||
if ( getline(ss, nextLine )) {
|
||||
extractFromEntity(nextLine, ss);
|
||||
if (getline (ss, nextLine)) {
|
||||
extractFromEntity (nextLine, ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -144,29 +146,29 @@ EntityConverter::extractMapInfo(const std::vector<std::vector<std::string>> &ent
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convert(const std::vector<std::string> &lines)
|
||||
EntityConverter::convert (const std::vector<std::string> &lines)
|
||||
{
|
||||
if ( haveMapInfo_ )
|
||||
if (haveMapInfo_)
|
||||
{
|
||||
std::string attribute;
|
||||
std::string trash; //unused tokens
|
||||
|
||||
std::string type;
|
||||
if ( lines.size() < 1 ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: empty entity cannot be converted", lines ));
|
||||
if (lines.size() < 1) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage( "error: empty entity cannot be converted", lines));
|
||||
}
|
||||
// second token is the type
|
||||
std::istringstream iss(lines[0]);
|
||||
if ( ! (iss >> trash >> type)) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: type is required", lines ));
|
||||
makeErrorMessage ("error: type is required", lines));
|
||||
}
|
||||
|
||||
// If worldspawn, first reenable all gamemodes
|
||||
// then check worldspawn for disabled modes
|
||||
// then RETURN EMPTY VECTOR
|
||||
if ( type == "WorldSpawn" ) {
|
||||
if (type == "WorldSpawn") {
|
||||
ws_.cts = true;
|
||||
ws_.ctf = true;
|
||||
ws_.ffa = true;
|
||||
@ -174,53 +176,53 @@ EntityConverter::convert(const std::vector<std::string> &lines)
|
||||
ws_.duel = true;
|
||||
|
||||
// Each worldspawn can specify modes enabled/disabled
|
||||
for ( int i = 1; i < lines.size(); ++i ) {
|
||||
if ( lines[i].find("modeRace 0") != std::string::npos) {
|
||||
for (int i = 1; i < lines.size(); ++i) {
|
||||
if (lines[i].find("modeRace 0") != std::string::npos) {
|
||||
ws_.cts = false;
|
||||
}
|
||||
else if ( lines[i].find("modeCTF 0") != std::string::npos) {
|
||||
else if (lines[i].find("modeCTF 0") != std::string::npos) {
|
||||
ws_.ctf = false;
|
||||
}
|
||||
else if ( lines[i].find("modeFFA 0") != std::string::npos) {
|
||||
else if (lines[i].find("modeFFA 0") != std::string::npos) {
|
||||
ws_.ffa = false;
|
||||
}
|
||||
else if ( lines[i].find("modeTDM 0") != std::string::npos) {
|
||||
else if (lines[i].find("modeTDM 0") != std::string::npos) {
|
||||
ws_.tdm = false;
|
||||
}
|
||||
else if ( lines[i].find("mode1v1 0") != std::string::npos) {
|
||||
else if (lines[i].find("mode1v1 0") != std::string::npos) {
|
||||
ws_.duel = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if ( type == "Pickup" ) {
|
||||
return convertPickup(lines);
|
||||
else if (type == "Pickup") {
|
||||
return convertPickup (lines);
|
||||
}
|
||||
else if ( type == "PlayerSpawn" ) {
|
||||
return convertPlayerSpawn(lines);
|
||||
else if (type == "PlayerSpawn") {
|
||||
return convertPlayerSpawn (lines);
|
||||
}
|
||||
else if ( type == "JumpPad" ) {
|
||||
return convertJumpPad(lines);
|
||||
else if (type == "JumpPad") {
|
||||
return convertJumpPad (lines);
|
||||
}
|
||||
else if ( type == "Teleporter" ) {
|
||||
return convertTeleporter(lines);
|
||||
else if (type == "Teleporter") {
|
||||
return convertTeleporter (lines);
|
||||
}
|
||||
else if ( type == "Target" ) {
|
||||
return convertTarget(lines);
|
||||
else if (type == "Target") {
|
||||
return convertTarget (lines);
|
||||
}
|
||||
else if ( type == "RaceStart" ) {
|
||||
return convertRaceStart(lines);
|
||||
else if (type == "RaceStart") {
|
||||
return convertRaceStart (lines);
|
||||
}
|
||||
else if ( type == "RaceFinish" ) {
|
||||
return convertRaceFinish(lines);
|
||||
else if (type == "RaceFinish") {
|
||||
return convertRaceFinish (lines);
|
||||
}
|
||||
else if ( type == "PointLight" ) {
|
||||
return convertPointLight(lines);
|
||||
else if (type == "PointLight") {
|
||||
return convertPointLight (lines);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Map info must be extracted prior to conversion", lines ));
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Map info must be extracted prior to conversion", lines));
|
||||
}
|
||||
|
||||
// If unsupported entity, return empty vector
|
||||
@ -238,7 +240,7 @@ EntityConverter::convert(const std::vector<std::string> &lines)
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertPickup(const std::vector<std::string> &lines) const
|
||||
EntityConverter::convertPickup (const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
//can ignore angle of pickups in xonotic format
|
||||
@ -247,52 +249,52 @@ EntityConverter::convertPickup(const std::vector<std::string> &lines) const
|
||||
std::string trash;
|
||||
bool havePickupID = false;
|
||||
|
||||
if ( lines.size() < 2 ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Pickup entity requires minimum of two lines (type and ID)", lines ));
|
||||
if (lines.size() < 2) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Pickup entity requires minimum of two lines (type and ID)", lines));
|
||||
}
|
||||
|
||||
for (int i = 1; i < lines.size(); i++) {
|
||||
std::string type = getAttributeType(lines[i]);
|
||||
if ( type == "position" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
std::string type = getAttributeType (lines[i]);
|
||||
if ( type == "position") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// Vector3 position coord0 coord1 coord2
|
||||
if ( ! (iss >> trash >> trash >>
|
||||
coords[0] >> coords[1] >> coords[2])) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid Pickup position", lines ));
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid Pickup position", lines));
|
||||
}
|
||||
}
|
||||
else if ( type == "pickupType" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
else if (type == "pickupType") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// UInt8 pickupType ID
|
||||
if ( ! (iss >> trash >> trash >> pickupID) ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Format of Pickup ID line is invalid", lines ));
|
||||
if ( ! (iss >> trash >> trash >> pickupID)) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Format of Pickup ID line is invalid", lines));
|
||||
}
|
||||
havePickupID = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( havePickupID ) {
|
||||
auto pickupIter = entityMap_.find(pickupID);
|
||||
if ( pickupIter == entityMap_.end() ) {
|
||||
if (havePickupID) {
|
||||
auto pickupIter = entityMap_.find (pickupID);
|
||||
if ( pickupIter == entityMap_.end()) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Pickup ID is invalid", lines ));
|
||||
makeErrorMessage ("error: Pickup ID is invalid", lines));
|
||||
}
|
||||
std::stringstream pickupStream;
|
||||
pickupStream << "\"classname\" \"" << pickupIter->second << "\"" << std::endl;
|
||||
convertedLines.push_back ( pickupStream.str() );
|
||||
convertedLines.push_back (pickupStream.str());
|
||||
// coordinates reordered to x, z, y
|
||||
std::stringstream positionStream;
|
||||
positionStream << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
||||
offset(coords[1], OFFSET_PICKUP) << "\"" << std::endl;
|
||||
convertedLines.push_back ( positionStream.str() );
|
||||
offset (coords[1], OFFSET_PICKUP) << "\"" << std::endl;
|
||||
convertedLines.push_back (positionStream.str());
|
||||
return convertedLines;
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Pickup ID was not in the entity", lines ));
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Pickup ID was not in the entity", lines));
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,7 +311,7 @@ EntityConverter::convertPickup(const std::vector<std::string> &lines) const
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertPlayerSpawn(const std::vector<std::string> &lines) const
|
||||
EntityConverter::convertPlayerSpawn (const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
// Requires position coordinate
|
||||
@ -329,82 +331,78 @@ EntityConverter::convertPlayerSpawn(const std::vector<std::string> &lines) const
|
||||
|
||||
for (int i = 1; i < lines.size(); i++) {
|
||||
std::string type = getAttributeType(lines[i]);
|
||||
if ( type == "position" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
if (type == "position") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// Vector3 position coord0 coord1 coord2
|
||||
if ( ! (iss >> trash >> trash >>
|
||||
coords[0] >> coords[1] >> coords[2])) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid PlayerSpawn position", lines ));
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid PlayerSpawn position", lines));
|
||||
}
|
||||
}
|
||||
else if ( type == "angles" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
else if (type == "angles") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// UInt8 pickupType ID
|
||||
if ( ! (iss >> trash >> trash >> angle )) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid PlayerSpawn angle", lines ));
|
||||
if ( ! (iss >> trash >> trash >> angle)) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid PlayerSpawn angle", lines));
|
||||
}
|
||||
}
|
||||
// Bool8 modeX 0 indicates this spawn is not for game mode X
|
||||
else if ( type == "modeRace" ) {
|
||||
else if (type == "modeRace") {
|
||||
isModeRace = false;
|
||||
}
|
||||
else if ( type == "modeCTF" ) {
|
||||
else if (type == "modeCTF") {
|
||||
isModeCtf = false;
|
||||
}
|
||||
else if ( type == "modeTDM" ) {
|
||||
else if (type == "modeTDM") {
|
||||
isModeTdm = false;
|
||||
}
|
||||
else if ( type == "modeFFA" ) {
|
||||
else if (type == "modeFFA") {
|
||||
isModeFfa = false;
|
||||
}
|
||||
else if ( type == "mode1v1" ) {
|
||||
else if (type == "mode1v1") {
|
||||
isModeDuel = false;
|
||||
}
|
||||
else if ( type == "teamA" ) {
|
||||
else if (type == "teamA") {
|
||||
team = 2; // Bool8 teamA 0 indicates teamB only
|
||||
}
|
||||
else if ( type == "teamB" ) {
|
||||
else if (type == "teamB") {
|
||||
team = 1; // Bool8 teamB 0 indicates teamA only
|
||||
}
|
||||
}
|
||||
|
||||
if ( isModeCtf || isModeTdm || isModeFfa || isModeDuel ) {
|
||||
if (isModeCtf || isModeTdm || isModeFfa || isModeDuel) {
|
||||
std::stringstream ss;
|
||||
std::map<std::string, std::string>::const_iterator it;
|
||||
switch (team) {
|
||||
case 0:
|
||||
convertedLines.push_back ("\"classname\" \"info_player_deathmatch\"\n" );
|
||||
convertedLines.push_back ("\"classname\" \"info_player_deathmatch\"\n");
|
||||
break;
|
||||
case 1:
|
||||
it = entityMap_.find("team1");
|
||||
it = entityMap_.find ("team1");
|
||||
ss << "\"classname\" \"" << it->second << "\"" << std::endl;
|
||||
convertedLines.push_back (ss.str());
|
||||
break;
|
||||
case 2:
|
||||
it = entityMap_.find("team2");
|
||||
it = entityMap_.find ("team2");
|
||||
ss << "\"classname\" \"" << it->second << "\"" << std::endl;
|
||||
convertedLines.push_back (ss.str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
convertedLines.push_back ( "\"classname\" \"info_player_race\"\n" );
|
||||
// Reflex maps have only start and finish, point to start on spawn
|
||||
convertedLines.push_back ( "\"target\" \"cp1\"\n" );
|
||||
// Reflex maps are only cts, set spawn to cts-only type
|
||||
convertedLines.push_back ( "\"race_place\" \"-1\"\n" );
|
||||
convertedLines.push_back ("\"classname\" \"info_player_start\"\n");
|
||||
}
|
||||
|
||||
std::stringstream positionStream;
|
||||
// coordinates reordered to x, z, y
|
||||
positionStream << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
||||
offset(coords[1], OFFSET_PLAYER) << "\"" << std::endl;
|
||||
convertedLines.push_back ( positionStream.str() );
|
||||
offset (coords[1], OFFSET_PLAYER) << "\"" << std::endl;
|
||||
convertedLines.push_back (positionStream.str());
|
||||
std::stringstream angleStream;
|
||||
angleStream << "\"angle\" \"" << adjustAngleForHandedness(angle) << "\"" << std::endl;
|
||||
convertedLines.push_back (angleStream.str() );
|
||||
convertedLines.push_back (angleStream.str());
|
||||
return convertedLines;
|
||||
|
||||
}
|
||||
@ -412,61 +410,61 @@ EntityConverter::convertPlayerSpawn(const std::vector<std::string> &lines) const
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertJumpPad(const std::vector<std::string> &lines) const
|
||||
EntityConverter::convertJumpPad (const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
std::string targetName;
|
||||
std::string trash;
|
||||
|
||||
if ( lines.size() < 2 ) {
|
||||
if (lines.size() < 2) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: JumpPad entity requires minimum of two lines (type and target)", lines ));
|
||||
makeErrorMessage ("error: JumpPad entity requires minimum of two lines (type and target)", lines));
|
||||
}
|
||||
std::istringstream iss(lines[1]);
|
||||
std::istringstream iss (lines[1]);
|
||||
// String32 target targetName
|
||||
if ( ! (iss >> trash >> trash >> targetName) ) {
|
||||
if ( ! (iss >> trash >> trash >> targetName)) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid JumpPad target", lines ));
|
||||
makeErrorMessage ("error: Invalid JumpPad target", lines));
|
||||
}
|
||||
|
||||
convertedLines.push_back ( "\"classname\" \"trigger_push\"\n" );
|
||||
convertedLines.push_back ("\"classname\" \"trigger_push\"\n");
|
||||
std::stringstream oss;
|
||||
oss << "\"target\" \"" << targetName << "\"" << std::endl;
|
||||
convertedLines.push_back ( oss.str() );
|
||||
convertedLines.push_back (oss.str());
|
||||
return convertedLines;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertTeleporter(const std::vector<std::string> &lines) const
|
||||
EntityConverter::convertTeleporter (const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
std::string targetName;
|
||||
std::string trash;
|
||||
|
||||
if ( lines.size() < 2 ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Teleport entity requires minimum of two lines (type and target)", lines ));
|
||||
if (lines.size() < 2) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Teleport entity requires minimum of two lines (type and target)", lines));
|
||||
}
|
||||
std::istringstream iss(lines[1]);
|
||||
std::istringstream iss (lines[1]);
|
||||
// String32 target targetName
|
||||
if ( ! (iss >> trash >> trash >> targetName) ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid Teleport target", lines ));
|
||||
if ( ! (iss >> trash >> trash >> targetName)) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid Teleport target", lines));
|
||||
}
|
||||
|
||||
convertedLines.push_back ( "\"classname\" \"trigger_teleport\"\n" );
|
||||
convertedLines.push_back ("\"classname\" \"trigger_teleport\"\n");
|
||||
std::stringstream oss;
|
||||
oss << "\"target\" \"" << targetName << "\"" << std::endl;
|
||||
convertedLines.push_back ( oss.str() );
|
||||
convertedLines.push_back (oss.str());
|
||||
return convertedLines;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertTarget(const std::vector<std::string> &lines) const
|
||||
EntityConverter::convertTarget (const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
//position and name required, angles optional
|
||||
@ -477,80 +475,80 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
|
||||
bool haveName = false;
|
||||
|
||||
|
||||
if ( lines.size() < 3 ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Target entity requires minimum of two lines (type and name)", lines ));
|
||||
if (lines.size() < 3) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Target entity requires minimum of two lines (type and name)", lines));
|
||||
}
|
||||
|
||||
for (int i = 1; i < lines.size(); i++) {
|
||||
std::string type = getAttributeType(lines[i]);
|
||||
if ( type == "position" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
std::string type = getAttributeType (lines[i]);
|
||||
if (type == "position") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// Vector3 position coord0 coord1 coord2
|
||||
if ( ! (iss >> trash >> trash >>
|
||||
coords[0] >> coords[1] >> coords[2])) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid Target position", lines ));
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid Target position", lines));
|
||||
}
|
||||
}
|
||||
else if ( type == "name" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
else if (type == "name") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// UInt8 name uniqueName
|
||||
if ( ! (iss >> trash >> trash >> targetName) ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid Target \"target\"", lines ));
|
||||
if ( ! (iss >> trash >> trash >> targetName)) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid Target \"target\"", lines));
|
||||
}
|
||||
haveName = true;
|
||||
}
|
||||
else if ( type == "angles" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
else if (type == "angles") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// Vector3 angles angle notapplicable notapplicable
|
||||
if ( ! (iss >> trash >> trash >> angle) ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid Target angle", lines ));
|
||||
if ( ! (iss >> trash >> trash >> angle)) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid Target angle", lines));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( haveName) {
|
||||
auto targetIter = targetMap_.find(targetName);
|
||||
if ( targetIter == targetMap_.end() ) {
|
||||
std::cerr << makeErrorMessage("End-game camera Target is not a supported feature in id Tech games. Skipping", lines);
|
||||
if (haveName) {
|
||||
auto targetIter = targetMap_.find (targetName);
|
||||
if (targetIter == targetMap_.end()) {
|
||||
//std::cerr << makeErrorMessage ("End-game camera Target is not a supported feature in id Tech games. Skipping", lines);
|
||||
|
||||
std::vector<std::string> empty;
|
||||
return empty;
|
||||
}
|
||||
if ( targetIter->second == "Teleporter") {
|
||||
convertedLines.push_back ( "\"classname\" \"misc_teleporter_dest\"\n" );
|
||||
if (targetIter->second == "Teleporter") {
|
||||
convertedLines.push_back ("\"classname\" \"misc_teleporter_dest\"\n");
|
||||
// coordinates reordered to x, z, y
|
||||
// teleporter height is OFFSET
|
||||
std::stringstream oss;
|
||||
oss << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
||||
offset(coords[1], OFFSET_PLAYER) << "\"" << std::endl;
|
||||
convertedLines.push_back ( oss.str() );
|
||||
offset (coords[1], OFFSET_PLAYER) << "\"" << std::endl;
|
||||
convertedLines.push_back ( oss.str());
|
||||
}
|
||||
else if ( targetIter->second == "JumpPad") {
|
||||
convertedLines.push_back ( "\"classname\" \"target_position\"\n" );
|
||||
convertedLines.push_back ("\"classname\" \"target_position\"\n");
|
||||
// coordinates reordered to x, z, y
|
||||
std::stringstream oss;
|
||||
oss << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
||||
coords[1] << "\"" << std::endl;
|
||||
convertedLines.push_back ( oss.str() );
|
||||
convertedLines.push_back (oss.str());
|
||||
}
|
||||
std::stringstream targetStream;
|
||||
targetStream << "\"targetname\" \"" << targetName << "\"" << std::endl;
|
||||
convertedLines.push_back ( targetStream.str() );
|
||||
convertedLines.push_back (targetStream.str());
|
||||
|
||||
// write angle every time
|
||||
std::stringstream angleStream;
|
||||
angleStream << "\"angle\" \"" << adjustAngleForHandedness(angle) << "\"" << std::endl;
|
||||
convertedLines.push_back( angleStream.str() );
|
||||
angleStream << "\"angle\" \"" << adjustAngleForHandedness (angle) << "\"" << std::endl;
|
||||
convertedLines.push_back( angleStream.str());
|
||||
return convertedLines;
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: \"target\" was not found in this Target entity", lines ));
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: \"target\" was not found in this Target entity", lines));
|
||||
}
|
||||
|
||||
}
|
||||
@ -558,23 +556,12 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertRaceStart(const std::vector<std::string> &lines) const
|
||||
EntityConverter::convertRaceStart (const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
convertedLines.push_back ("\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
convertedLines.push_back ("\"targetname\" \"cp1\"\n");
|
||||
convertedLines.push_back ("\"cnt\" \"1\"\n");
|
||||
return convertedLines;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertRaceFinish(const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
convertedLines.push_back ("\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
convertedLines.push_back ("\"targetname\" \"finish\"\n");
|
||||
// While 0 is finish in Race, in CTS, checkpoints numbered from 0 to n
|
||||
convertedLines.push_back ("\"cnt\" \"0\"\n");
|
||||
return convertedLines;
|
||||
}
|
||||
@ -582,7 +569,20 @@ EntityConverter::convertRaceFinish(const std::vector<std::string> &lines) const
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertPointLight(const std::vector<std::string> &lines) const
|
||||
EntityConverter::convertRaceFinish (const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
convertedLines.push_back ("\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
convertedLines.push_back ("\"targetname\" \"finish\"\n");
|
||||
// While 0 is finish in Race, in CTS, checkpoints numbered from 0 to n
|
||||
convertedLines.push_back ("\"cnt\" \"1\"\n");
|
||||
return convertedLines;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
EntityConverter::convertPointLight (const std::vector<std::string> &lines) const
|
||||
{
|
||||
std::vector<std::string> convertedLines;
|
||||
//position and intensity required, color optional
|
||||
@ -596,36 +596,36 @@ EntityConverter::convertPointLight(const std::vector<std::string> &lines) const
|
||||
bool haveColor = false;
|
||||
|
||||
|
||||
if ( lines.size() < 2 ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: PointLight entity requires at least one line (type)", lines ));
|
||||
if (lines.size() < 2) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: PointLight entity requires at least one line (type)", lines));
|
||||
}
|
||||
|
||||
for (int i = 1; i < lines.size(); i++) {
|
||||
std::string type = getAttributeType(lines[i]);
|
||||
if ( type == "position" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
if (type == "position") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// Vector3 position coord0 coord1 coord2
|
||||
if ( ! (iss >> trash >> trash >>
|
||||
coords[0] >> coords[1] >> coords[2])) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid PointLight position", lines ));
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid PointLight position", lines));
|
||||
}
|
||||
}
|
||||
else if ( type == "intensity" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
else if (type == "intensity") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// Float intensity validFloat
|
||||
if ( ! (iss >> trash >> trash >> intensity) ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid PointLight intensity", lines ));
|
||||
if ( ! (iss >> trash >> trash >> intensity)) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid PointLight intensity", lines));
|
||||
}
|
||||
}
|
||||
else if ( type == "color" ) {
|
||||
std::istringstream iss(lines[i]);
|
||||
else if (type == "color") {
|
||||
std::istringstream iss (lines[i]);
|
||||
// ColourXRGB32 color eightDigitHexValue
|
||||
if ( ! (iss >> trash >> trash >> color) ) {
|
||||
throw std::runtime_error(
|
||||
makeErrorMessage( "error: Invalid PointLight color", lines ));
|
||||
if ( ! (iss >> trash >> trash >> color)) {
|
||||
throw std::runtime_error (
|
||||
makeErrorMessage ("error: Invalid PointLight color", lines));
|
||||
}
|
||||
haveColor = true;
|
||||
}
|
||||
@ -633,26 +633,26 @@ EntityConverter::convertPointLight(const std::vector<std::string> &lines) const
|
||||
}
|
||||
|
||||
|
||||
convertedLines.push_back ( "\"classname\" \"light\"\n" );
|
||||
convertedLines.push_back ("\"classname\" \"light\"\n");
|
||||
// coordinates reordered to x, z, y
|
||||
std::stringstream positionStream;
|
||||
positionStream << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
|
||||
coords[1] << "\"" << std::endl;
|
||||
convertedLines.push_back ( positionStream.str() );
|
||||
convertedLines.push_back (positionStream.str());
|
||||
// convert intensity
|
||||
std::stringstream intensityStream;
|
||||
intensityStream << "\"light\" \"" << adjustBrightness(intensity) << "\"\n";
|
||||
convertedLines.push_back ( intensityStream.str() );
|
||||
intensityStream << "\"light\" \"" << adjustBrightness (intensity) << "\"\n";
|
||||
convertedLines.push_back (intensityStream.str());
|
||||
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
// Convert 32bit hex RGBA value (ALPHA ALWAYS FULL) into RGB values
|
||||
hexToRGB(color, red, green, blue);
|
||||
hexToRGB (color, red, green, blue);
|
||||
|
||||
std::stringstream colorStream;
|
||||
colorStream << "\"_color\" \"" << red << " " << green << " " << blue << "\"" << std::endl;
|
||||
convertedLines.push_back (colorStream.str() );
|
||||
convertedLines.push_back (colorStream.str());
|
||||
|
||||
return convertedLines;
|
||||
}
|
||||
@ -661,12 +661,12 @@ EntityConverter::convertPointLight(const std::vector<std::string> &lines) const
|
||||
|
||||
|
||||
std::string
|
||||
EntityConverter::getAttributeType(const std::string &line) const
|
||||
EntityConverter::getAttributeType (const std::string &line) const
|
||||
{
|
||||
std::string type;
|
||||
std::string dataType;
|
||||
std::istringstream iss(line);
|
||||
if ( ! (iss >> dataType >> type )) {
|
||||
std::istringstream iss (line);
|
||||
if ( ! (iss >> dataType >> type)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
@ -676,27 +676,27 @@ EntityConverter::getAttributeType(const std::string &line) const
|
||||
|
||||
|
||||
void
|
||||
EntityConverter::mapEntities(const std::string &mapFile)
|
||||
EntityConverter::mapEntities (const std::string &mapFile)
|
||||
{
|
||||
std::ifstream fin;
|
||||
fin.open(mapFile);
|
||||
fin.open (mapFile);
|
||||
|
||||
if ( fin.is_open() ) {
|
||||
//Read .ent contents into pickup map
|
||||
if (fin.is_open()) {
|
||||
//Read Reflex Entity Mapping file contents into pickup map
|
||||
std::string line;
|
||||
while (std::getline(fin, line)) {
|
||||
std::istringstream iss(line);
|
||||
while (std::getline (fin, line)) {
|
||||
std::istringstream iss (line);
|
||||
// Reflex ID corresponds to xonotic pickup name
|
||||
std::string id;
|
||||
std::string pickup;
|
||||
if ( ! (iss >> id >> pickup)) {
|
||||
throw std::runtime_error( "format error in Pickup .pck file " + mapFile );
|
||||
throw std::runtime_error ("format error in Pickup .pck file " + mapFile);
|
||||
}
|
||||
entityMap_.insert ( std::pair<std::string, std::string>(id, pickup) );
|
||||
entityMap_.insert (std::pair<std::string, std::string> (id, pickup));
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::ios::failure( "Error: EntityConverter failed to open .ent file" );
|
||||
throw std::ios::failure ("Error: EntityConverter failed to open Reflex Entity Mapping file");
|
||||
}
|
||||
fin.close();
|
||||
|
||||
@ -710,8 +710,8 @@ EntityConverter::haveRequiredMappings()
|
||||
std::vector<std::string> required = { "team1",
|
||||
"team2" };
|
||||
for (std::string id : required) {
|
||||
auto pickupIter = entityMap_.find(id);
|
||||
if ( pickupIter == entityMap_.end() ) {
|
||||
auto pickupIter = entityMap_.find (id);
|
||||
if ( pickupIter == entityMap_.end()) {
|
||||
throw std::runtime_error ("error: Missing required entity mappings");
|
||||
return false;
|
||||
}
|
||||
@ -723,63 +723,63 @@ EntityConverter::haveRequiredMappings()
|
||||
|
||||
|
||||
void
|
||||
EntityConverter::extractFromEntity(const std::string &line, std::istream &is)
|
||||
EntityConverter::extractFromEntity (const std::string &line, std::istream &is)
|
||||
{
|
||||
std::string trash;
|
||||
std::string targetName;
|
||||
std::string nextLine;
|
||||
if ( line.find("type Teleporter") != std::string::npos) {
|
||||
std::getline(is, nextLine);
|
||||
std::istringstream iss(nextLine);
|
||||
if (line.find("type Teleporter") != std::string::npos) {
|
||||
std::getline (is, nextLine);
|
||||
std::istringstream iss (nextLine);
|
||||
if ( ! (iss >> trash >> trash >> targetName)) {
|
||||
throw std::runtime_error( "Format error in .map file" );
|
||||
throw std::runtime_error ("Format error in .map file");
|
||||
}
|
||||
targetMap_.insert ( std::pair<std::string, std::string>(targetName, "Teleporter") );
|
||||
targetMap_.insert (std::pair<std::string, std::string>(targetName, "Teleporter"));
|
||||
}
|
||||
else if ( line.find("type JumpPad") != std::string::npos) {
|
||||
std::getline(is, nextLine);
|
||||
std::istringstream iss(nextLine);
|
||||
else if (line.find ("type JumpPad") != std::string::npos) {
|
||||
std::getline (is, nextLine);
|
||||
std::istringstream iss (nextLine);
|
||||
if ( ! (iss >> trash >> trash >> targetName)) {
|
||||
throw std::runtime_error( "Format error in .map file" );
|
||||
throw std::runtime_error ( "Format error in .map file");
|
||||
}
|
||||
targetMap_.insert ( std::pair<std::string, std::string>(targetName, "JumpPad") );
|
||||
targetMap_.insert (std::pair<std::string, std::string> (targetName, "JumpPad"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
EntityConverter::offset(const std::string &value, const float amount) const
|
||||
EntityConverter::offset (const std::string &value, const float amount) const
|
||||
{
|
||||
std::istringstream iss(value);
|
||||
std::istringstream iss (value);
|
||||
float c;
|
||||
iss >> c;
|
||||
c += amount;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::fixed << std::setprecision(OUTPUT_PRECISION) << c;
|
||||
ss << std::fixed << std::fixed << std::setprecision (OUTPUT_PRECISION) << c;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
EntityConverter::adjustAngleForHandedness(const std::string &angle) const
|
||||
EntityConverter::adjustAngleForHandedness (const std::string &angle) const
|
||||
{
|
||||
std::istringstream iss(angle);
|
||||
std::istringstream iss (angle);
|
||||
float a;
|
||||
iss >> a;
|
||||
a = -a + 90.0;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::fixed << std::setprecision(OUTPUT_PRECISION) << a;
|
||||
ss << std::fixed << std::fixed << std::setprecision (OUTPUT_PRECISION) << a;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
EntityConverter::hexToRGB(const std::string &hex, float &r, float &g, float &b) const
|
||||
EntityConverter::hexToRGB (const std::string &hex, float &r, float &g, float &b) const
|
||||
{
|
||||
unsigned int value;
|
||||
std::stringstream ss;
|
||||
@ -797,10 +797,10 @@ EntityConverter::hexToRGB(const std::string &hex, float &r, float &g, float &b)
|
||||
|
||||
|
||||
int
|
||||
EntityConverter::adjustBrightness(const std::string &value) const
|
||||
EntityConverter::adjustBrightness (const std::string &value) const
|
||||
{
|
||||
float inputBright;
|
||||
std::stringstream ss(value);
|
||||
std::stringstream ss (value);
|
||||
ss >> inputBright;
|
||||
|
||||
return static_cast<int>(inputBright * BRIGHTNESS_ADJUST);
|
||||
@ -810,14 +810,14 @@ EntityConverter::adjustBrightness(const std::string &value) const
|
||||
|
||||
|
||||
std::string
|
||||
EntityConverter::makeErrorMessage(const std::string message,
|
||||
EntityConverter::makeErrorMessage (const std::string message,
|
||||
const std::vector<std::string> entity) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::endl << message << ":" << std::endl;
|
||||
|
||||
std::vector<std::string>::const_iterator it;
|
||||
for ( it=entity.begin(); it!=entity.end(); ++it ) {
|
||||
for (it=entity.begin(); it!=entity.end(); ++it) {
|
||||
ss << *it << std::endl;
|
||||
}
|
||||
|
||||
@ -841,7 +841,7 @@ EntityConverter::printMapping() const
|
||||
{
|
||||
std::cout << std::endl << "Reflex pickup ID mapped to Xonotic pickup names: " << std::endl;
|
||||
std::map<std::string, std::string>::const_iterator it;
|
||||
for ( it=entityMap_.begin(); it!=entityMap_.end(); ++it )
|
||||
for (it=entityMap_.begin(); it!=entityMap_.end(); ++it)
|
||||
std::cout << it->first << " => " << it->second << std::endl;
|
||||
}
|
||||
|
||||
@ -851,7 +851,7 @@ EntityConverter::printTargetSources() const
|
||||
{
|
||||
std::cout << std::endl << "Target and Sources: " << std::endl;
|
||||
std::map<std::string, std::string>::const_iterator it;
|
||||
for ( it=targetMap_.begin(); it!=targetMap_.end(); ++it )
|
||||
for (it=targetMap_.begin(); it!=targetMap_.end(); ++it)
|
||||
std::cout << it->first << " => " << it->second << std::endl;
|
||||
}
|
||||
|
||||
|
34
src/main.cpp
34
src/main.cpp
@ -16,6 +16,7 @@
|
||||
|
||||
#include "oopless-parser.hpp"
|
||||
#include "brushdef.hpp"
|
||||
#include <iterator>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -57,6 +58,22 @@ cxxopts::Options arguments(int ac, char ** av) {
|
||||
return o;
|
||||
}
|
||||
|
||||
stringstream loadmap(const char *filename) {
|
||||
ifstream fin;
|
||||
fin.open(filename);
|
||||
if (!fin.good()) {
|
||||
cout << "error: can not open input file." << endl;
|
||||
}
|
||||
vector<string> v;
|
||||
string line;
|
||||
stringstream output;
|
||||
while (getline(fin, line)) {
|
||||
v.push_back(line);
|
||||
}
|
||||
move(v.begin(), v.end(), ostream_iterator<string>(output, "\n"));
|
||||
return output;
|
||||
}
|
||||
|
||||
bool convert_worldspawn(const cxxopts::Options &o,
|
||||
vector<vector<string> > &q) {
|
||||
bool is_ok = false;
|
||||
@ -64,9 +81,11 @@ bool convert_worldspawn(const cxxopts::Options &o,
|
||||
if (o.count(ARG_BRUSHFORMAT)) {
|
||||
fn = &brushdef_gtk;
|
||||
}
|
||||
string inputfile = o[ARG_INPUT_SHORTALIAS].as<string>();
|
||||
stringstream mapdata = loadmap(inputfile.c_str());
|
||||
try {
|
||||
is_ok = convertmap(
|
||||
o[ARG_INPUT_SHORTALIAS].as<string>().c_str(), // in file
|
||||
mapdata, // in file
|
||||
o[ARG_OUTPUT_SHORTALIAS].as<string>().c_str(), // out file
|
||||
fn, // brush definition
|
||||
q); // queue of entities
|
||||
@ -126,11 +145,22 @@ void convert_entities(const cxxopts::Options &o, const vector<vector<string> > &
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try {
|
||||
cxxopts::Options p = arguments(argc, argv);
|
||||
|
||||
vector<vector<string> > entities;
|
||||
bool is_ok = convert_worldspawn(p, entities);
|
||||
// print_entities(entities);
|
||||
convert_entities(p, entities);
|
||||
}
|
||||
catch (cxxopts::option_not_exists_exception e) {
|
||||
cerr << e.what() << endl
|
||||
<< "./reflex2q3 -h for usage information" << endl;
|
||||
return -1;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
cerr << e.what() << endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -101,29 +101,10 @@ void write(const vector<string> &entity,
|
||||
fo << "}" << endl;
|
||||
}
|
||||
|
||||
void parse_prefab(ifstream &f,
|
||||
ofstream &out,
|
||||
void (*b) (stringstream &, const vector<TPlanePoints> &),
|
||||
vector<vector<string> > &entities) {
|
||||
string l;
|
||||
getline(f, l);
|
||||
if (l.find(KEYWORD_BRUSH) != string::npos) {
|
||||
write(parse_brush<ifstream>(f), out, b);
|
||||
} else if (l.find(KEYWORD_ENTITY) != string::npos) {
|
||||
entities.push_back(get_entity<ifstream>(f));
|
||||
}
|
||||
}
|
||||
|
||||
bool convertmap(const char * const infile,
|
||||
bool convertmap(stringstream &mapdata,
|
||||
const char * const outfile,
|
||||
void (*brushdef) (stringstream &, const vector<TPlanePoints> &),
|
||||
vector<vector<string> > &entities) {
|
||||
ifstream fin;
|
||||
fin.open(infile);
|
||||
if (!fin.good()){
|
||||
cerr << "error: failed to open input file" << endl;
|
||||
return false;
|
||||
}
|
||||
ofstream fout;
|
||||
fout.open(outfile);
|
||||
if (!fout.good()) {
|
||||
@ -133,18 +114,17 @@ bool convertmap(const char * const infile,
|
||||
fout << "{\n"
|
||||
<< "\"classname\" \"worldspawn\"" << endl;
|
||||
string line;
|
||||
while (getline(fin, line)) {
|
||||
while (getline(mapdata, line)) {
|
||||
if (line.find(KEYWORD_PREFAB) != string::npos ||
|
||||
line.find(KEYWORD_GLOBAL) != string::npos) {
|
||||
parse_prefab(fin, fout, brushdef, entities);
|
||||
parse_prefab<stringstream>(mapdata, fout, brushdef, entities);
|
||||
} else if (line.find(KEYWORD_ENTITY) != string::npos) {
|
||||
entities.push_back(get_entity<ifstream>(fin));
|
||||
entities.push_back(get_entity<stringstream>(mapdata));
|
||||
} else if (line.find(KEYWORD_BRUSH) != string::npos) {
|
||||
write(parse_brush<ifstream>(fin), fout, brushdef);
|
||||
write(parse_brush<stringstream>(mapdata), fout, brushdef);
|
||||
}
|
||||
}
|
||||
fout << "}" << endl;
|
||||
fin.close();
|
||||
fout.close();
|
||||
return true;
|
||||
}
|
||||
|
@ -5,12 +5,12 @@
|
||||
*
|
||||
* Description: Unit tests for EntityConverter class
|
||||
*
|
||||
* Version: 0.1
|
||||
* Version: 1.0
|
||||
* Created: 07/14/2017 20:36:31 PM
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: suhrke@teknik.io
|
||||
* Author: surkeh@protonmail.com
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
@ -21,75 +21,75 @@
|
||||
|
||||
#include "EntityConverter.hpp"
|
||||
|
||||
#define ENTITY_FILENAME "r2xonotic.ent"
|
||||
#define ENTITY_FILENAME "r2xonotic.rem"
|
||||
#define DELTA 0.00001
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: Unsupported entity types cause return of empty vector", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: Unsupported entity types cause return of empty vector", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type NotAType");
|
||||
entity.push_back (" type NotAType");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
std::vector<std::string> converted = ec.convert (entity);
|
||||
|
||||
REQUIRE( converted.size() == 0 );
|
||||
REQUIRE (converted.size() == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single Pickup entity can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single Pickup entity can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type Pickup");
|
||||
entity.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back(" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
entity.push_back(" UInt8 pickupType 2");
|
||||
entity.push_back (" type Pickup");
|
||||
entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
entity.push_back (" UInt8 pickupType 2");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
std::vector<std::string> converted = ec.convert (entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"weapon_grenadelauncher\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"weapon_grenadelauncher\"\n");
|
||||
|
||||
// The z (vertical) is offset by +2
|
||||
std::istringstream iss(converted[1]);
|
||||
std::istringstream iss (converted[1]);
|
||||
std::string attribute;
|
||||
std::string coords[2];
|
||||
float offsetCoord;
|
||||
iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
|
||||
|
||||
REQUIRE( attribute == "\"origin\"" );
|
||||
REQUIRE( coords[0] == "\"-216.00000" );
|
||||
REQUIRE( coords[1] == "-1488.000488" );
|
||||
REQUIRE( fabs(-130.00000 - offsetCoord) <= DELTA );
|
||||
REQUIRE (attribute == "\"origin\"");
|
||||
REQUIRE (coords[0] == "\"-216.00000");
|
||||
REQUIRE (coords[1] == "-1488.000488");
|
||||
REQUIRE (fabs(-130.00000 - offsetCoord) <= DELTA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single PlayerSpawn (race) entity can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single PlayerSpawn (race) entity can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
@ -97,56 +97,54 @@ TEST_CASE( "r2x: a single PlayerSpawn (race) entity can be converted", "[EntityC
|
||||
// Mock up WorldSpawn entity
|
||||
// (needed for mode info)
|
||||
std::vector<std::string> worldspawn;
|
||||
worldspawn.push_back(" type WorldSpawn");
|
||||
worldspawn.push_back(" Bool8 modeCTF 0");
|
||||
worldspawn.push_back(" Bool8 modeFFA 0");
|
||||
worldspawn.push_back(" Bool8 modeTDM 0");
|
||||
worldspawn.push_back(" Bool8 mode1v1 0");
|
||||
worldspawn.push_back (" type WorldSpawn");
|
||||
worldspawn.push_back (" Bool8 modeCTF 0");
|
||||
worldspawn.push_back (" Bool8 modeFFA 0");
|
||||
worldspawn.push_back (" Bool8 modeTDM 0");
|
||||
worldspawn.push_back (" Bool8 mode1v1 0");
|
||||
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type PlayerSpawn");
|
||||
entity.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back(" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
entity.push_back(" Bool8 teamA 0");
|
||||
entity.push_back(" Bool8 teamB 0");
|
||||
entity.push_back(" Bool8 modeCTF 0");
|
||||
entity.push_back(" Bool8 modeFFA 0");
|
||||
entity.push_back(" Bool8 modeTDM 0");
|
||||
entity.push_back(" Bool8 mode1v1 0");
|
||||
entity.push_back (" type PlayerSpawn");
|
||||
entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
entity.push_back (" Bool8 teamA 0");
|
||||
entity.push_back (" Bool8 teamB 0");
|
||||
entity.push_back (" Bool8 modeCTF 0");
|
||||
entity.push_back (" Bool8 modeFFA 0");
|
||||
entity.push_back (" Bool8 modeTDM 0");
|
||||
entity.push_back (" Bool8 mode1v1 0");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( worldspawn );
|
||||
q.push( entity );
|
||||
q.push (worldspawn);
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity (worldspawn conversion returns empty vector
|
||||
// BUT sets the supported game modes for entities in that worldspawn
|
||||
std::vector<std::string> unused = ec.convert(worldspawn);
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"info_player_race\"\n" );
|
||||
REQUIRE( converted[1] == "\"target\" \"cp1\"\n" );
|
||||
REQUIRE( converted[2] == "\"race_place\" \"-1\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"info_player_start\"\n");
|
||||
|
||||
// The z (vertical) is offset by +32
|
||||
std::istringstream iss(converted[3]);
|
||||
std::istringstream iss (converted[1]);
|
||||
std::string attribute;
|
||||
std::string coords[2];
|
||||
float offsetCoord;
|
||||
iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
|
||||
|
||||
REQUIRE( attribute == "\"origin\"" );
|
||||
REQUIRE( coords[0] == "\"-216.00000" );
|
||||
REQUIRE( coords[1] == "-1488.000488" );
|
||||
REQUIRE( fabs(-100.00000 - offsetCoord) <= DELTA );
|
||||
REQUIRE (attribute == "\"origin\"");
|
||||
REQUIRE (coords[0] == "\"-216.00000");
|
||||
REQUIRE (coords[1] == "-1488.000488");
|
||||
REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
|
||||
|
||||
SECTION( "Converted angles are valid (Different coordinate system handedness)" ) {
|
||||
std::istringstream angleLineStream(converted[4]);
|
||||
SECTION( "Converted angles are valid (Different coordinate system handedness)") {
|
||||
std::istringstream angleLineStream(converted[2]);
|
||||
std::string angleAttribute;
|
||||
std::string a;
|
||||
float angle;
|
||||
@ -156,210 +154,210 @@ TEST_CASE( "r2x: a single PlayerSpawn (race) entity can be converted", "[EntityC
|
||||
std::stringstream angleStream(a);
|
||||
angleStream >> angle;
|
||||
|
||||
REQUIRE( attribute == "\"angle\"" );
|
||||
REQUIRE( fabs( -90.0 - angle) <= DELTA );
|
||||
REQUIRE (attribute == "\"angle\"");
|
||||
REQUIRE (fabs (-90.0 - angle) <= DELTA);
|
||||
}
|
||||
|
||||
|
||||
SECTION( "Encountering a new worldspawn reenables all modes" ) {
|
||||
SECTION( "Encountering a new worldspawn reenables all modes") {
|
||||
std::vector<std::string> basicWorldspawn;
|
||||
basicWorldspawn.push_back(" type WorldSpawn");
|
||||
basicWorldspawn.push_back (" type WorldSpawn");
|
||||
|
||||
std::vector<std::string> e;
|
||||
e.push_back(" type PlayerSpawn");
|
||||
e.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
e.push_back(" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
e.push_back (" type PlayerSpawn");
|
||||
e.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
e.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
|
||||
std::vector<std::string> u = ec.convert(basicWorldspawn);
|
||||
std::vector<std::string> c = ec.convert(e);
|
||||
REQUIRE( c[0] == "\"classname\" \"info_player_deathmatch\"\n" );
|
||||
REQUIRE (c[0] == "\"classname\" \"info_player_deathmatch\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single PlayerSpawn (teamA) entity can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single PlayerSpawn (teamA) entity can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type PlayerSpawn");
|
||||
entity.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back(" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
entity.push_back(" Bool8 teamB 0");
|
||||
entity.push_back(" Bool8 modeRace 0");
|
||||
entity.push_back (" type PlayerSpawn");
|
||||
entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
entity.push_back (" Bool8 teamB 0");
|
||||
entity.push_back (" Bool8 modeRace 0");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"info_player_team1\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"info_player_team1\"\n");
|
||||
|
||||
// The z (vertical) is offset by +32
|
||||
std::istringstream iss(converted[1]);
|
||||
std::istringstream iss (converted[1]);
|
||||
std::string attribute;
|
||||
std::string coords[2];
|
||||
float offsetCoord;
|
||||
iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
|
||||
|
||||
REQUIRE( attribute == "\"origin\"" );
|
||||
REQUIRE( coords[0] == "\"-216.00000" );
|
||||
REQUIRE( coords[1] == "-1488.000488" );
|
||||
REQUIRE( fabs(-100.00000 - offsetCoord) <= DELTA );
|
||||
REQUIRE (attribute == "\"origin\"");
|
||||
REQUIRE (coords[0] == "\"-216.00000");
|
||||
REQUIRE (coords[1] == "-1488.000488");
|
||||
REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single PlayerSpawn (non-team) entity can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single PlayerSpawn (non-team) entity can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type PlayerSpawn");
|
||||
entity.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back(" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
entity.push_back (" type PlayerSpawn");
|
||||
entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"info_player_deathmatch\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"info_player_deathmatch\"\n");
|
||||
|
||||
// The z (vertical) is offset by +32
|
||||
std::istringstream iss(converted[1]);
|
||||
std::istringstream iss (converted[1]);
|
||||
std::string attribute;
|
||||
std::string coords[2];
|
||||
float offsetCoord;
|
||||
iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
|
||||
|
||||
REQUIRE( attribute == "\"origin\"" );
|
||||
REQUIRE( coords[0] == "\"-216.00000" );
|
||||
REQUIRE( coords[1] == "-1488.000488" );
|
||||
REQUIRE( fabs(-100.00000 - offsetCoord) <= DELTA );
|
||||
REQUIRE (attribute == "\"origin\"");
|
||||
REQUIRE (coords[0] == "\"-216.00000");
|
||||
REQUIRE (coords[1] == "-1488.000488");
|
||||
REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single RaceStart entity can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single RaceStart entity can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type RaceStart");
|
||||
entity.push_back (" type RaceStart");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"trigger_race_checkpoint\"\n" );
|
||||
REQUIRE( converted[1] == "\"targetname\" \"cp1\"\n" );
|
||||
REQUIRE( converted[2] == "\"cnt\" \"1\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
REQUIRE (converted[1] == "\"targetname\" \"cp1\"\n");
|
||||
REQUIRE (converted[2] == "\"cnt\" \"0\"\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single RaceFinish entity can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single RaceFinish entity can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type RaceFinish");
|
||||
entity.push_back (" type RaceFinish");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"trigger_race_checkpoint\"\n" );
|
||||
REQUIRE( converted[1] == "\"targetname\" \"finish\"\n" );
|
||||
REQUIRE( converted[2] == "\"cnt\" \"0\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"trigger_race_checkpoint\"\n");
|
||||
REQUIRE (converted[1] == "\"targetname\" \"finish\"\n");
|
||||
REQUIRE (converted[2] == "\"cnt\" \"1\"\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single Teleporter and related Target can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single Teleporter and related Target can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up Teleporter entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type Teleporter");
|
||||
entity.push_back(" String32 target tp1");
|
||||
entity.push_back (" type Teleporter");
|
||||
entity.push_back (" String32 target tp1");
|
||||
|
||||
// Mock up Target entity
|
||||
std::vector<std::string> entity2;
|
||||
entity2.push_back(" type Target");
|
||||
entity2.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity2.push_back(" String32 name tp1");
|
||||
entity2.push_back (" type Target");
|
||||
entity2.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity2.push_back (" String32 name tp1");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push( entity2 );
|
||||
q.push (entity);
|
||||
q.push (entity2);
|
||||
|
||||
// Match related entities (one pair)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert two entities
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
REQUIRE( converted[0] == "\"classname\" \"trigger_teleport\"\n" );
|
||||
REQUIRE( converted[1] == "\"target\" \"tp1\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"trigger_teleport\"\n");
|
||||
REQUIRE (converted[1] == "\"target\" \"tp1\"\n");
|
||||
|
||||
std::vector<std::string> converted2 = ec.convert(entity2);
|
||||
REQUIRE( converted2[0] == "\"classname\" \"misc_teleporter_dest\"\n" );
|
||||
REQUIRE( converted2[2] == "\"targetname\" \"tp1\"\n" );
|
||||
REQUIRE (converted2[0] == "\"classname\" \"misc_teleporter_dest\"\n");
|
||||
REQUIRE (converted2[2] == "\"targetname\" \"tp1\"\n");
|
||||
//
|
||||
// The z (vertical) is offset by +32
|
||||
std::istringstream iss(converted2[1]);
|
||||
std::istringstream iss (converted2[1]);
|
||||
std::string attribute;
|
||||
std::string coords[2];
|
||||
float offsetCoord;
|
||||
iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
|
||||
|
||||
// next REQUIRE fails without busy wait
|
||||
for( int i = 0; i < 10000000; i++ )
|
||||
for( int i = 0; i < 10000000; i++)
|
||||
int x = i;
|
||||
|
||||
REQUIRE( attribute == "\"origin\"" );
|
||||
REQUIRE( coords[0] == "\"-216.00000" );
|
||||
REQUIRE( coords[1] == "-1488.000488" );
|
||||
REQUIRE( fabs(-100.00000 - offsetCoord) <= DELTA );
|
||||
REQUIRE (attribute == "\"origin\"");
|
||||
REQUIRE (coords[0] == "\"-216.00000");
|
||||
REQUIRE (coords[1] == "-1488.000488");
|
||||
REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
|
||||
|
||||
SECTION( "When angle unspecified, defaults to 0.0 (converted to 90.0)" ) {
|
||||
SECTION( "When angle unspecified, defaults to 0.0 (converted to 90.0)") {
|
||||
std::istringstream angleStream(converted2[3]);
|
||||
std::string a;
|
||||
float angle;
|
||||
@ -367,79 +365,79 @@ TEST_CASE( "r2x: a single Teleporter and related Target can be converted", "[Ent
|
||||
a.erase(a.begin()); //removing preceding quote is necessary
|
||||
std::stringstream out(a);
|
||||
out >> angle;
|
||||
REQUIRE( fabs(90.0 - angle) <= DELTA );
|
||||
REQUIRE (fabs(90.0 - angle) <= DELTA);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single JumpPad and related Target can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single JumpPad and related Target can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up JumpPad entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type JumpPad");
|
||||
entity.push_back(" String32 target jp1");
|
||||
entity.push_back (" type JumpPad");
|
||||
entity.push_back (" String32 target jp1");
|
||||
|
||||
// Mock up Target entity
|
||||
std::vector<std::string> entity2;
|
||||
entity2.push_back(" type Target");
|
||||
entity2.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity2.push_back(" String32 name jp1");
|
||||
entity2.push_back (" type Target");
|
||||
entity2.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity2.push_back (" String32 name jp1");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push( entity2 );
|
||||
q.push (entity);
|
||||
q.push (entity2);
|
||||
|
||||
// Match related entities (one pair)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert two entities
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
REQUIRE( converted[0] == "\"classname\" \"trigger_push\"\n" );
|
||||
REQUIRE( converted[1] == "\"target\" \"jp1\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"trigger_push\"\n");
|
||||
REQUIRE (converted[1] == "\"target\" \"jp1\"\n");
|
||||
|
||||
std::vector<std::string> converted2 = ec.convert(entity2);
|
||||
REQUIRE( converted2[0] == "\"classname\" \"target_position\"\n" );
|
||||
REQUIRE( converted2[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n" );
|
||||
REQUIRE( converted2[2] == "\"targetname\" \"jp1\"\n" );
|
||||
REQUIRE (converted2[0] == "\"classname\" \"target_position\"\n");
|
||||
REQUIRE (converted2[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n");
|
||||
REQUIRE (converted2[2] == "\"targetname\" \"jp1\"\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "r2x: a single PointLight entity can be converted", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: a single PointLight entity can be converted", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type PointLight");
|
||||
entity.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back(" ColourXRGB32 color ffffc400");
|
||||
entity.push_back(" Float intensity 1.500000");
|
||||
entity.push_back(" Float nearAttenuation 32.000000");
|
||||
entity.push_back(" Float farAttenuation 160.000000");
|
||||
entity.push_back (" type PointLight");
|
||||
entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back (" ColourXRGB32 color ffffc400");
|
||||
entity.push_back (" Float intensity 1.500000");
|
||||
entity.push_back (" Float nearAttenuation 32.000000");
|
||||
entity.push_back (" Float farAttenuation 160.000000");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"light\"\n" );
|
||||
REQUIRE( converted[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n" );
|
||||
REQUIRE( converted[2] == "\"light\" \"75\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"light\"\n");
|
||||
REQUIRE (converted[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n");
|
||||
REQUIRE (converted[2] == "\"light\" \"75\"\n");
|
||||
|
||||
INFO( converted[3] );
|
||||
std::istringstream iss(converted[3]);
|
||||
INFO (converted[3]);
|
||||
std::istringstream iss (converted[3]);
|
||||
std::string attribute;
|
||||
std::string r;
|
||||
float red;
|
||||
@ -450,55 +448,55 @@ TEST_CASE( "r2x: a single PointLight entity can be converted", "[EntityConverter
|
||||
std::stringstream redStream(r);
|
||||
redStream >> red;
|
||||
|
||||
REQUIRE( attribute == "\"_color\"" );
|
||||
REQUIRE (attribute == "\"_color\"");
|
||||
|
||||
REQUIRE( fabs( 1.0 - red) <= DELTA );
|
||||
REQUIRE( fabs( 0.768627 - green) <= DELTA );
|
||||
REQUIRE( fabs( 0.0 - blue) <= DELTA );
|
||||
REQUIRE (fabs (1.0 - red) <= DELTA);
|
||||
REQUIRE (fabs (0.768627 - green) <= DELTA);
|
||||
REQUIRE (fabs (0.0 - blue) <= DELTA);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "r2x: PointLight defaults to white light of typical intensity", "[EntityConverter]" ) {
|
||||
TEST_CASE ("r2x: PointLight defaults to white light of typical intensity", "[EntityConverter]") {
|
||||
|
||||
// Instantiate object
|
||||
EntityConverter ec (ENTITY_FILENAME);
|
||||
|
||||
// Mock up entity
|
||||
std::vector<std::string> entity;
|
||||
entity.push_back(" type PointLight");
|
||||
entity.push_back(" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
entity.push_back (" type PointLight");
|
||||
entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
|
||||
|
||||
// Mock up entity queue
|
||||
std::queue<std::vector<std::string>> q;
|
||||
q.push( entity );
|
||||
q.push (entity);
|
||||
|
||||
// Match related entities (none)
|
||||
ec.extractMapInfo( q );
|
||||
ec.extractMapInfo (q);
|
||||
|
||||
// Convert a single entity
|
||||
std::vector<std::string> converted = ec.convert(entity);
|
||||
|
||||
REQUIRE( converted[0] == "\"classname\" \"light\"\n" );
|
||||
REQUIRE( converted[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n" );
|
||||
REQUIRE( converted[2] == "\"light\" \"50\"\n" );
|
||||
REQUIRE (converted[0] == "\"classname\" \"light\"\n");
|
||||
REQUIRE (converted[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n");
|
||||
REQUIRE (converted[2] == "\"light\" \"50\"\n");
|
||||
|
||||
INFO( converted[3] );
|
||||
std::istringstream iss(converted[3]);
|
||||
INFO (converted[3]);
|
||||
std::istringstream iss (converted[3]);
|
||||
std::string attribute;
|
||||
std::string r;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
iss >> attribute >> r >> green >> blue;
|
||||
r.erase(r.begin()); //removing preceding quote is necessary
|
||||
std::stringstream redStream(r);
|
||||
r.erase (r.begin()); //removing preceding quote is necessary
|
||||
std::stringstream redStream (r);
|
||||
redStream >> red;
|
||||
|
||||
REQUIRE( attribute == "\"_color\"" );
|
||||
REQUIRE (attribute == "\"_color\"");
|
||||
|
||||
REQUIRE( fabs( 0.0 - red) <= DELTA );
|
||||
REQUIRE( fabs( 0.0 - green) <= DELTA );
|
||||
REQUIRE( fabs( 0.0 - blue) <= DELTA );
|
||||
REQUIRE (fabs (0.0 - red) <= DELTA);
|
||||
REQUIRE (fabs (0.0 - green) <= DELTA);
|
||||
REQUIRE (fabs (0.0 - blue) <= DELTA);
|
||||
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: suhrke@teknik.io
|
||||
* Author: surkeh@protonmail.com
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user