Add an include directive for colors files
A colors file can now specify other colors files, from which additional node color specifications will be read. This allows, for instance, using system-installed colors file for most colors, and only overriding some of its colors in a custom colors file. As a purpose of using a custom colors file may be to leave the colors for some nodes undefined, it is now also possible to undefine a previously defined node color (i.e. after reading another colors file which defines a color for the node).master
parent
224c6b1df7
commit
e6322f2911
17
README.rst
17
README.rst
|
@ -89,6 +89,23 @@ colors <file>:
|
|||
# Entry that is used with 'drawalpha':
|
||||
default:water-source 78 132 212 64 224
|
||||
|
||||
The colors file can include other colors files using:
|
||||
`@include filename`
|
||||
Any entries after the inclusion point override entries from the
|
||||
included file. Already defined colors can be 'undefined' by specifying
|
||||
'-' as color:
|
||||
|
||||
::
|
||||
|
||||
default:stone 71 68 67
|
||||
# default-colors.txt might override the color of default:stone
|
||||
@include default-colors.txt
|
||||
# color of default:dirt_with_grass from default-colors.txt is overridden:
|
||||
default:dirt_with_grass 82 117 54
|
||||
# Color of water is undefined here:
|
||||
default:water_source -
|
||||
default:water_flowing -
|
||||
|
||||
bgcolor:
|
||||
Background color of image, `--bgcolor #ffffff`
|
||||
|
||||
|
|
|
@ -325,9 +325,11 @@ void TileGenerator::setMaxY(int y)
|
|||
m_reqYMaxNode = y - 16 * m_reqYMax;
|
||||
}
|
||||
|
||||
void TileGenerator::parseColorsFile(const std::string &fileName)
|
||||
void TileGenerator::parseColorsFile(const std::string &fileName, int depth)
|
||||
{
|
||||
if (verboseReadColors >= 2)
|
||||
if (depth > 100)
|
||||
throw std::runtime_error(std::string("Excessive inclusion depth of colors files - suspected recursion (i.e. cycle); current file: '") + fileName + "'");
|
||||
if (depth == 0 && verboseReadColors >= 2)
|
||||
cout << "Checking for colors file: " << fileName << std::endl;
|
||||
ifstream in;
|
||||
in.open(fileName.c_str(), ifstream::in);
|
||||
|
@ -337,7 +339,7 @@ void TileGenerator::parseColorsFile(const std::string &fileName)
|
|||
}
|
||||
if (verboseReadColors >= 1)
|
||||
cout << "Reading colors file: " << fileName << std::endl;
|
||||
parseColorsStream(in, fileName.c_str());
|
||||
parseColorsStream(in, fileName.c_str(), depth);
|
||||
in.close();
|
||||
}
|
||||
|
||||
|
@ -374,7 +376,7 @@ void TileGenerator::generate(const std::string &input, const std::string &output
|
|||
printUnknown();
|
||||
}
|
||||
|
||||
void TileGenerator::parseColorsStream(std::istream &in, const std::string &filename)
|
||||
void TileGenerator::parseColorsStream(std::istream &in, const std::string &filename, int depth)
|
||||
{
|
||||
string line;
|
||||
int linenr = 0;
|
||||
|
@ -388,45 +390,79 @@ void TileGenerator::parseColorsStream(std::istream &in, const std::string &filen
|
|||
iline >> std::skipws;
|
||||
string name;
|
||||
ColorEntry color;
|
||||
iline >> name;
|
||||
iline >> name >> std::ws;
|
||||
if (name.length() == 0)
|
||||
continue;
|
||||
int r, g, b, a, t;
|
||||
iline >> r;
|
||||
iline >> g;
|
||||
iline >> b;
|
||||
if (iline.fail()) {
|
||||
std::cerr << filename << ":" << linenr << ": bad line in colors file (" << line << ")" << std::endl;
|
||||
continue;
|
||||
}
|
||||
a = 0xff;
|
||||
iline >> a;
|
||||
t = 0;
|
||||
iline >> t;
|
||||
color = ColorEntry(r,g,b,a,t);
|
||||
if ((m_drawAlpha && a == 0xff) || (!m_drawAlpha && a != 0xff)) {
|
||||
// If drawing alpha, and the colors file contains both
|
||||
// an opaque entry and a non-opaque entry for a name, prefer
|
||||
// the non-opaque entry
|
||||
// If not drawing alpha, and the colors file contains both
|
||||
// an opaque entry and a non-opaque entry for a name, prefer
|
||||
// the opaque entry
|
||||
// Otherwise, any later entry overrides any previous entry
|
||||
ColorMap::iterator it = m_colors.find(name);
|
||||
if (it != m_colors.end()) {
|
||||
if (m_drawAlpha && (a == 0xff && it->second.a != 0xff)) {
|
||||
// drawing alpha: don't use opaque color to override
|
||||
// non-opaque color
|
||||
continue;
|
||||
}
|
||||
if (!m_drawAlpha && (a != 0xff && it->second.a == 0xff)) {
|
||||
// not drawing alpha: don't use non-opaque color to
|
||||
// override opaque color
|
||||
continue;
|
||||
if (name == "@include") {
|
||||
string includeFile;
|
||||
getline(iline,includeFile);
|
||||
size_t lastChar = includeFile.find_last_not_of(" \t\r\n");
|
||||
if (lastChar != string::npos)
|
||||
includeFile.erase(lastChar + 1);
|
||||
if (includeFile == "") {
|
||||
std::cerr << filename << ":" << linenr << ": include filename missing in colors file (" << line << ")" << std::endl;
|
||||
continue;
|
||||
}
|
||||
#if ! (MSDOS || __OS2__ || __NT__ || _WIN32)
|
||||
// This same feature seems needlessly complicated on windows - so it is not supported
|
||||
if (includeFile[0] != '/') {
|
||||
string includePath = filename;
|
||||
size_t offset = includePath.find_last_of('/');
|
||||
if (offset != string::npos) {
|
||||
includePath.erase(offset);
|
||||
includeFile = includePath + '/' + includeFile;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
parseColorsFile(includeFile, depth + 1);
|
||||
}
|
||||
else if (iline.good() && iline.peek() == '-') {
|
||||
char c;
|
||||
iline >> c >> std::ws;
|
||||
if (iline.bad() || !iline.eof()) {
|
||||
std::cerr << filename << ":" << linenr << ": bad line in colors file (" << line << ")" << std::endl;
|
||||
continue;
|
||||
}
|
||||
m_colors.erase(name);
|
||||
}
|
||||
else {
|
||||
int r, g, b, a, t;
|
||||
iline >> r;
|
||||
iline >> g;
|
||||
iline >> b;
|
||||
if (iline.fail()) {
|
||||
std::cerr << filename << ":" << linenr << ": bad line in colors file (" << line << ")" << std::endl;
|
||||
continue;
|
||||
}
|
||||
a = 0xff;
|
||||
iline >> a;
|
||||
t = 0;
|
||||
iline >> t;
|
||||
color = ColorEntry(r,g,b,a,t);
|
||||
if ((m_drawAlpha && a == 0xff) || (!m_drawAlpha && a != 0xff)) {
|
||||
// If drawing alpha, and the colors file contains both
|
||||
// an opaque entry and a non-opaque entry for a name, prefer
|
||||
// the non-opaque entry
|
||||
// If not drawing alpha, and the colors file contains both
|
||||
// an opaque entry and a non-opaque entry for a name, prefer
|
||||
// the opaque entry
|
||||
// Otherwise, any later entry overrides any previous entry
|
||||
ColorMap::iterator it = m_colors.find(name);
|
||||
if (it != m_colors.end()) {
|
||||
if (m_drawAlpha && (a == 0xff && it->second.a != 0xff)) {
|
||||
// drawing alpha: don't use opaque color to override
|
||||
// non-opaque color
|
||||
continue;
|
||||
}
|
||||
if (!m_drawAlpha && (a != 0xff && it->second.a == 0xff)) {
|
||||
// not drawing alpha: don't use non-opaque color to
|
||||
// override opaque color
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_colors[name] = color;
|
||||
}
|
||||
m_colors[name] = color;
|
||||
}
|
||||
if (!in.eof()) {
|
||||
std::cerr << filename << ": error reading colors file after line " << linenr << std::endl;
|
||||
|
|
|
@ -105,12 +105,12 @@ public:
|
|||
void setTileOrigin(int x, int y);
|
||||
void setTileCenter(int x, int y);
|
||||
void enableProgressIndicator(void);
|
||||
void parseColorsFile(const std::string &fileName);
|
||||
void parseColorsFile(const std::string &fileName, int depth = 0);
|
||||
void setBackend(std::string backend);
|
||||
void generate(const std::string &input, const std::string &output);
|
||||
|
||||
private:
|
||||
void parseColorsStream(std::istream &in, const std::string &filename);
|
||||
void parseColorsStream(std::istream &in, const std::string &filename, int depth);
|
||||
std::string getWorldDatabaseBackend(const std::string &input);
|
||||
void openDb(const std::string &input);
|
||||
void loadBlocks();
|
||||
|
|
Loading…
Reference in New Issue