reflex2q3/ReflexToQ3/includes/oopless-parser.cpp

166 lines
5.4 KiB
C++

#include "oopless-parser.hpp"
#include "brushdef.hpp"
#include <sstream>
#include <iostream>
#include <iterator>
using namespace std;
bool is_ebrush(const std::vector<std::string> &input) {
#define KEYWORD_ENTBRUSH1 "type Teleporter"
#define KEYWORD_ENTBRUSH2 "type JumpPad"
#define KEYWORD_ENTBRUSH3 "type RaceStart"
#define KEYWORD_ENTBRUSH4 "type RaceFinish"
for (const string &str : input) {
if (str.find(KEYWORD_ENTBRUSH1) != string::npos ||
str.find(KEYWORD_ENTBRUSH2) != string::npos ||
str.find(KEYWORD_ENTBRUSH3) != string::npos ||
str.find(KEYWORD_ENTBRUSH4) != string::npos) {
return true;
}
}
return false;
}
// place holding functions to test proper control flow.
bool write(const struct TBrush &geometry,
ofstream &fout,
void (*b) (stringstream &, const vector<TPlanePoints> &)) {
bool ok = true;
if (geometry.m_Vertices.size() < 1) {
cerr << "error: geometry has no vertices" << endl;
ok = false;
}
if (geometry.m_Faces.size() < 1) {
cerr << "error: geometry has no faces"<< endl;
ok = false;
}
if (ok) {
fout << GetBrushString(geometry, b);
}
return ok;
}
// currently for the specific case to specify trigger to brush entities
struct TBrush override_textures(struct TBrush x, const char *texture) {
struct TBrush output = x;
for (struct TFace &z : output.m_Faces) {
// prevent appending color infomation to texture file path
// may need re-ordering on when to append that.
z.hex = string();
z.m_Material = texture;
}
return output;
}
void write(const vector<string> &entity,
ofstream &fo,
void (*b) (stringstream &, const vector<TPlanePoints> &),
EntityConverter &e) {
/* Likely inefficient.
Current process for the entities:
1. It acquires the lines.
2. Searches through and splits the vector.
3. Recombines the brush vector.
(4. Sends the vector to parse the brush through again.)*/
bool brushent = false;
unsigned int i;
for (i = 0; i < entity.size(); ++i) {
if (entity[i].find(KEYWORD_BRUSH) != string::npos) {
brushent = true;
break;
}
}
vector<string> brush(entity.size() - i);
if (brushent) {
// entity.begin() + i = vector that begins with KEYWORD_BRUSH
// parsing functions will expect only the contents underneath the keyword.
move((entity.begin() + i), entity.end(), brush.begin());
}
vector<string> converted = e.convert(entity);
if (converted.empty()) {
return;
}
fo << "{" << endl;
for (const string &s : converted) {
fo << s;
}
if (brushent) {
stringstream ss;
string line;
copy(brush.begin(), brush.end(), ostream_iterator<string>(ss, "\n"));
getline(ss, line); // this both discards the brush keyboard and prevents a crash
write(override_textures(parse_brush<stringstream>(ss), "common/trigger"), fo, b);
}
fo << "}" << endl;
}
// entities will vary widely depending on their type and available flags.
// for now, acquire entity data, and handle their conversion in the write methods.
vector<string> get_entity(ifstream &f) {
vector<string> output;
string line;
unsigned int pos = f.tellg();
while (getline(f, line)) {
// stop when
// entity or a prefab keyword
// brush keyword and the entity is not of the type teleporter or jumppad.
if ((line.find(KEYWORD_ENTITY) != string::npos ||
line.find(KEYWORD_PREFAB) != string::npos) || (
line.find(KEYWORD_BRUSH) != string::npos && !is_ebrush(output))) {
f.seekg(pos);
return output;
} else {
output.push_back(line);
}
pos = f.tellg();
}
}
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(f));
}
}
bool convertmap(const char * const infile,
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()) {
cerr << "error: failed to open output file" << endl;
return false;
}
fout << "{\n"
<< "\"classname\" \"worldspawn\"" << endl;
string line;
while (getline(fin, line)) {
if (line.find(KEYWORD_PREFAB) != string::npos ||
line.find(KEYWORD_GLOBAL) != string::npos) {
parse_prefab(fin, fout, brushdef, entities);
} else if (line.find(KEYWORD_ENTITY) != string::npos) {
entities.push_back(get_entity(fin));
} else if (line.find(KEYWORD_BRUSH) != string::npos) {
write(parse_brush<ifstream>(fin), fout, brushdef);
}
}
fout << "}" << endl;
fin.close();
fout.close();
return true;
}