summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/rltiles/tool
diff options
context:
space:
mode:
authorEnne Walker <ennewalker@users.sourceforge.net>2009-12-23 23:32:52 -0500
committerEnne Walker <ennewalker@users.sourceforge.net>2009-12-24 00:15:48 -0500
commitbcc249f77c1459b75b7a4f96b018a15569e675b3 (patch)
tree72ad82e9ff51f45396c95933e3583437ab5489fb /crawl-ref/source/rltiles/tool
parent5b9916a319a570598c8cd54e916eb10dab0eb916 (diff)
downloadcrawl-ref-bcc249f77c1459b75b7a4f96b018a15569e675b3.tar.gz
crawl-ref-bcc249f77c1459b75b7a4f96b018a15569e675b3.zip
Basic support for tile recolouring.
Added %variation, %repeat, %desat, %lum, %hue, %pal, %resetcol commands to rltiles. Also, multiple enum synonyms can now be specified. Documentation on all rltiles commands is forthcoming. Sorry. Added coloured variations for a number of floor and wall tiles, removing duplicate source art where it made sense. The variations probably need some adjusting to look less like fruit salad. COLOUR in a vault specification will now automatically try to pick coloured variations of basic floor and rock wall tiles by default. It will also pick coloured variations of any tiles specified by FTILE/RTILE/TILE. I'll leave it as an exercise for due to generalize this to features and monsters. tile_dngn_coloured (and corresponding functions for other tile sheets) can be used to look up coloured variations for a given tile index.
Diffstat (limited to 'crawl-ref/source/rltiles/tool')
-rw-r--r--crawl-ref/source/rltiles/tool/tile.cc43
-rw-r--r--crawl-ref/source/rltiles/tool/tile.h20
-rw-r--r--crawl-ref/source/rltiles/tool/tile_colour.cc220
-rw-r--r--crawl-ref/source/rltiles/tool/tile_colour.h49
-rw-r--r--crawl-ref/source/rltiles/tool/tile_list_processor.cc390
-rw-r--r--crawl-ref/source/rltiles/tool/tile_list_processor.h17
-rw-r--r--crawl-ref/source/rltiles/tool/tile_page.cc34
-rw-r--r--crawl-ref/source/rltiles/tool/tile_page.h5
8 files changed, 703 insertions, 75 deletions
diff --git a/crawl-ref/source/rltiles/tool/tile.cc b/crawl-ref/source/rltiles/tool/tile.cc
index 2febfd73b2..65d82c9b18 100644
--- a/crawl-ref/source/rltiles/tool/tile.cc
+++ b/crawl-ref/source/rltiles/tool/tile.cc
@@ -17,9 +17,12 @@ tile::tile(const tile &img, const char *enumnam, const char *parts) :
copy(img);
if (enumnam)
- m_enumname = enumnam;
+ m_enumname.push_back(enumnam);
if (parts)
m_parts_ctg = parts;
+
+ for (int i = 0; i < MAX_COLOUR; ++i)
+ m_variations[i] = -1;
}
tile::~tile()
@@ -39,27 +42,37 @@ bool tile::valid() const
return m_pixels && m_width && m_height;
}
-const std::string &tile::filename()
+const std::string &tile::filename() const
{
return m_filename;
}
-const std::string &tile::enumname()
+int tile::enumcount() const
+{
+ return m_enumname.size();
+}
+
+const std::string &tile::enumname(int idx) const
{
- return m_enumname;
+ return m_enumname[idx];
}
-const std::string &tile::parts_ctg()
+void tile::add_enumname(const std::string &name)
+{
+ m_enumname.push_back(name);
+}
+
+const std::string &tile::parts_ctg() const
{
return m_parts_ctg;
}
-int tile::width()
+int tile::width() const
{
return m_width;
}
-int tile::height()
+int tile::height() const
{
return m_height;
}
@@ -484,3 +497,19 @@ void tile::get_bounding_box(int &x0, int &y0, int &w, int &h)
w = x1 - x0 + 1;
h = y1 - y0 + 1;
}
+
+void tile::add_variation(int colour, int idx)
+{
+ assert(colour >= 0);
+ assert(colour < MAX_COLOUR);
+ m_variations[colour] = idx;
+}
+
+bool tile::get_variation(int colour, int &idx)
+{
+ if (m_variations[colour] == -1)
+ return (false);
+
+ idx = m_variations[colour];
+ return (true);
+}
diff --git a/crawl-ref/source/rltiles/tool/tile.h b/crawl-ref/source/rltiles/tool/tile.h
index b14e14d100..7381763ead 100644
--- a/crawl-ref/source/rltiles/tool/tile.h
+++ b/crawl-ref/source/rltiles/tool/tile.h
@@ -3,6 +3,7 @@
#include "tile_colour.h"
#include <string>
+#include <vector>
class tile
{
@@ -30,25 +31,32 @@ public:
void replace_colour(tile_colour &find, tile_colour &replace);
void fill(const tile_colour &col);
- const std::string &filename();
- const std::string &enumname();
- const std::string &parts_ctg();
- int width();
- int height();
+ const std::string &filename() const;
+ int enumcount() const;
+ const std::string &enumname(int idx) const;
+ void add_enumname(const std::string &name);
+ const std::string &parts_ctg() const;
+ int width() const;
+ int height() const;
bool shrink();
void set_shrink(bool new_shrink);
void get_bounding_box(int &x0, int &y0, int &w, int &h);
tile_colour &get_pixel(unsigned int x, unsigned int y);
+
+ void add_variation(int colour, int idx);
+ bool get_variation(int colour, int &idx);
protected:
int m_width;
int m_height;
std::string m_filename;
- std::string m_enumname;
+ std::vector<std::string> m_enumname;
std::string m_parts_ctg;
tile_colour *m_pixels;
bool m_shrink;
+
+ int m_variations[MAX_COLOUR];
};
#endif
diff --git a/crawl-ref/source/rltiles/tool/tile_colour.cc b/crawl-ref/source/rltiles/tool/tile_colour.cc
index f1969f37be..2f098b387b 100644
--- a/crawl-ref/source/rltiles/tool/tile_colour.cc
+++ b/crawl-ref/source/rltiles/tool/tile_colour.cc
@@ -28,6 +28,226 @@ const tile_colour &tile_colour::operator=(const tile_colour &rhs)
return (*this);
}
+unsigned char &tile_colour::operator[](int idx)
+{
+ assert(idx >= 0 && idx <= 4);
+ switch (idx)
+ {
+ default:
+ case 0: return r;
+ case 1: return g;
+ case 2: return b;
+ case 3: return a;
+ }
+}
+
+unsigned char tile_colour::operator[](int idx) const
+{
+ assert(idx >= 0 && idx <= 4);
+ switch (idx)
+ {
+ default:
+ case 0: return r;
+ case 1: return g;
+ case 2: return b;
+ case 3: return a;
+ }
+}
+
+int tile_colour::get_hue() const
+{
+ int max_rgb = get_max_rgb();
+ int min_rgb = get_min_rgb();
+
+ if (max_rgb == min_rgb)
+ return (0);
+
+ int diff = max_rgb - min_rgb;
+
+ if (max_rgb == r)
+ {
+ return ((60 * (g - b)) / diff + 360) % 360;
+ }
+ else if (max_rgb == g)
+ {
+ return (60 * (b - r)) / diff + 120;
+ }
+ else // if (max_rgb == b)
+ {
+ return (60 * (r - g)) / diff + 240;
+ }
+}
+
+int tile_colour::get_max_rgb() const
+{
+ int max_rgb = std::max(std::max(r, g), b);
+ return (max_rgb);
+}
+
+int tile_colour::get_min_rgb() const
+{
+ int min_rgb = std::min(std::min(r, g), b);
+ return (min_rgb);
+}
+
+void tile_colour::set_hue(int h)
+{
+ set_from_hue(h, get_min_rgb(), get_max_rgb());
+}
+
+void tile_colour::set_from_hue(int h, int min_rgb, int max_rgb)
+{
+ // http://en.wikipedia.org/wiki/HSL_and_HSV
+ // H is passed in
+ // S = diff / max or 0 if max == 0
+ // V = max / 255
+
+ int v = max_rgb;
+ int s = max_rgb - min_rgb;
+
+ float f = ((float)h / 60.0f) - (int)(h / 60);
+
+ // When calculating P, Q, T, also convert to 0..255 range.
+ int p = v - s;
+ int q = v - f * s;
+ int t = v - (1.0f - f) * s;
+
+ // Sanity bounds.
+ q = std::max(std::min(q, 255), 0);
+ t = std::max(std::min(t, 255), 0);
+
+ int h_idx = (h / 60) % 6;
+
+ switch (h_idx)
+ {
+ default:
+ case 0:
+ r = static_cast<unsigned char>(v);
+ g = static_cast<unsigned char>(t);
+ b = static_cast<unsigned char>(p);
+ break;
+ case 1:
+ r = static_cast<unsigned char>(q);
+ g = static_cast<unsigned char>(v);
+ b = static_cast<unsigned char>(p);
+ break;
+ case 2:
+ r = static_cast<unsigned char>(p);
+ g = static_cast<unsigned char>(v);
+ b = static_cast<unsigned char>(t);
+ break;
+ case 3:
+ r = static_cast<unsigned char>(p);
+ g = static_cast<unsigned char>(q);
+ b = static_cast<unsigned char>(v);
+ break;
+ case 4:
+ r = static_cast<unsigned char>(t);
+ g = static_cast<unsigned char>(p);
+ b = static_cast<unsigned char>(v);
+ break;
+ case 5:
+ r = static_cast<unsigned char>(v);
+ g = static_cast<unsigned char>(p);
+ b = static_cast<unsigned char>(q);
+ break;
+ }
+}
+
+void tile_colour::desaturate()
+{
+ set_from_hue(get_hue(), get_max_rgb(), get_max_rgb());
+}
+
+float tile_colour::get_lum() const
+{
+ return ((get_min_rgb() + get_max_rgb()) / (255 * 2.0f));
+}
+
+float tile_colour::get_sat() const
+{
+ int min_rgb = get_min_rgb();
+ int max_rgb = get_max_rgb();
+ int sum = min_rgb + max_rgb;
+
+ float sat;
+ if (sum == 0)
+ sat = 0;
+ else if (sum > 255)
+ sat = (max_rgb - min_rgb) / (float)(255*2 - min_rgb - max_rgb);
+ else
+ sat = (max_rgb - min_rgb) / (float)(min_rgb + max_rgb);
+
+ return (sat);
+}
+
+void tile_colour::set_from_hsl(int hue, float sat, float lum)
+{
+ float q;
+ if (lum < 0.5f)
+ q = lum * (1 + sat);
+ else
+ q = lum + sat - (lum * sat);
+
+ float p = 2 * lum - q;
+
+ for (int i = 0; i < 3; ++i)
+ {
+ int h = hue + (1 - i) * 120;
+ if (h < 0)
+ h += 360;
+ if (h >= 360)
+ h -= 360;
+
+ float val;
+
+ if (h < 60)
+ val = p + (q - p) * h / 60.0f;
+ else if (h < 180)
+ val = q;
+ else if (h < 240)
+ val = p + (q - p) * (4 - h / 60.0f);
+ else
+ val = p;
+
+ int final = val * 255;
+ final = std::max(0, std::min(255, final));
+ (*this)[i] = static_cast<unsigned char>(final);
+ }
+}
+
+void tile_colour::change_lum(int lum_percent)
+{
+ int min_rgb = get_min_rgb();
+ int max_rgb = get_max_rgb();
+ int hue = get_hue();
+
+ if (min_rgb == max_rgb)
+ {
+ int rgb_change = (lum_percent * 255) / 100;
+
+ min_rgb += rgb_change;
+ max_rgb += rgb_change;
+
+ min_rgb = std::max(0, std::min(255, min_rgb));
+ max_rgb = std::max(0, std::min(255, max_rgb));
+
+ set_from_hue(get_hue(), min_rgb, max_rgb);
+ return;
+ }
+
+ float lum_change = lum_percent / 100.0f;
+ float lum = get_lum() + lum_change;
+
+ if (lum > 1.0f)
+ lum = 1.0f;
+ if (lum < 0.0f)
+ lum = 0.0f;
+
+ float sat = get_sat();
+ set_from_hsl(hue, sat, lum);
+}
+
bool write_png(const char *filename, tile_colour *pixels,
unsigned int width, unsigned int height)
{
diff --git a/crawl-ref/source/rltiles/tool/tile_colour.h b/crawl-ref/source/rltiles/tool/tile_colour.h
index 4c77162b9f..f660c84829 100644
--- a/crawl-ref/source/rltiles/tool/tile_colour.h
+++ b/crawl-ref/source/rltiles/tool/tile_colour.h
@@ -1,6 +1,30 @@
#ifndef TILE_COLOUR_H
#define TILE_COLOUR_H
+enum COLORS
+{
+ BLACK,
+ BLUE,
+ GREEN,
+ CYAN,
+ RED,
+ MAGENTA,
+ BROWN,
+ LIGHTGRAY,
+ LIGHTGREY = LIGHTGRAY,
+ DARKGRAY,
+ DARKGREY = DARKGRAY,
+ LIGHTBLUE,
+ LIGHTGREEN,
+ LIGHTCYAN,
+ LIGHTRED,
+ LIGHTMAGENTA,
+ YELLOW,
+ WHITE,
+ MAX_TERM_COLOUR,
+ MAX_COLOUR = MAX_TERM_COLOUR
+};
+
class tile_colour
{
public:
@@ -12,6 +36,31 @@ public:
bool operator!=(const tile_colour &rhs) const;
const tile_colour &operator=(const tile_colour &rhs);
+ unsigned char &operator[](int idx);
+ unsigned char operator[](int idx) const;
+
+ // Get the HSV/HSL hue, from 0..360.
+ int get_hue() const;
+ // Set the hue, from 0..360.
+ void set_hue(int h);
+ // Change the saturation to 0.
+ void desaturate();
+ // Change the luminance by lum_percent %.
+ void change_lum(int lum_percent);
+
+ int get_max_rgb() const;
+ int get_min_rgb() const;
+
+ // Set the color from HSV. hue is 0..360. min_rgb and max_rgb are 0..255.
+ void set_from_hue(int hue, int min_rgb, int max_rgb);
+
+ // Set the color from HSL. hue is 0..360. sat and lum are 0..1.
+ void set_from_hsl(int hue, float sat, float lum);
+ // Get the HSL saturation, from 0..1.
+ float get_sat() const;
+ // Get the HSL luminance, from 0..1.
+ float get_lum() const;
+
unsigned char r;
unsigned char g;
unsigned char b;
diff --git a/crawl-ref/source/rltiles/tool/tile_list_processor.cc b/crawl-ref/source/rltiles/tool/tile_list_processor.cc
index 091d195fca..dfd8385296 100644
--- a/crawl-ref/source/rltiles/tool/tile_list_processor.cc
+++ b/crawl-ref/source/rltiles/tool/tile_list_processor.cc
@@ -17,7 +17,9 @@ tile_list_processor::tile_list_processor() :
m_composing(false),
m_shrink(true),
m_prefix("TILE"),
- m_start_value("0")
+ m_start_value("0"),
+ m_variation_idx(-1),
+ m_variation_col(-1)
{
}
@@ -150,6 +152,73 @@ static void eat_comments(char *&text)
}
}
+static const std::string colour_list[16] =
+{
+ "black", "blue", "green", "cyan", "red", "magenta", "brown",
+ "lightgrey", "darkgrey", "lightblue", "lightgreen", "lightcyan",
+ "lightred", "lightmagenta", "yellow", "white"
+};
+
+static int str_to_colour(std::string colour)
+{
+ if (colour.empty())
+ return (0);
+
+ for (unsigned int c = 0; c < colour.size(); c++)
+ colour[c] = std::tolower(colour[c]);
+
+ for (int i = 0; i < 16; ++i)
+ {
+ if (colour == colour_list[i])
+ return (i);
+ }
+
+ // Check for alternate spellings.
+ if (colour == "lightgray")
+ return (7);
+ else if (colour == "darkgray")
+ return (8);
+
+ return (0);
+}
+
+void tile_list_processor::recolour(tile &img)
+{
+ for (int y = 0; y < img.height(); ++y)
+ for (int x = 0; x < img.width(); ++x)
+ {
+ tile_colour &col = img.get_pixel(x, y);
+ tile_colour orig = col;
+ for (palette_list::iterator iter = m_palette.begin();
+ iter != m_palette.end(); ++iter)
+ {
+ if (orig == iter->first)
+ col = iter->second;
+ }
+
+ for (hue_list::iterator iter = m_hues.begin();
+ iter != m_hues.end(); ++iter)
+ {
+ if (orig.get_hue() == iter->first)
+ col.set_hue(iter->second);
+ }
+
+ for (desat_list::iterator iter = m_desat.begin();
+ iter != m_desat.end(); ++iter)
+ {
+ if (orig.get_hue() == *iter)
+ col.desaturate();
+ }
+
+ for (lum_list::iterator iter = m_lum.begin();
+ iter != m_lum.end(); ++iter)
+ {
+ if (orig.get_hue() == iter->first)
+ col.change_lum(iter->second);
+ }
+ }
+}
+
bool tile_list_processor::process_line(char *read_line, const char *list_file,
int line)
{
@@ -254,6 +323,8 @@ bool tile_list_processor::process_line(char *read_line, const char *list_file,
if (m_rim)
img.add_rim(tile_colour::black);
+ recolour(img);
+
if (!m_compose.compose(img))
{
fprintf(stderr, "Error (%s:%d): failed composing '%s'"
@@ -270,6 +341,8 @@ bool tile_list_processor::process_line(char *read_line, const char *list_file,
"'%s'.\n", list_file, line, m_args[1]);
return (false);
}
+
+ recolour(m_compose);
}
}
else if (strcmp(arg, "corpse") == 0)
@@ -409,6 +482,133 @@ bool tile_list_processor::process_line(char *read_line, const char *list_file,
if (m_args.size() > 2)
m_include = m_args[2];
}
+ else if (strcmp(arg, "pal") == 0)
+ {
+ // rgb (optional a) = rgb (optional a)
+ tile_colour cols[2] = { tile_colour::black, tile_colour::black };
+ int col_idx = 0;
+ int comp_idx = 0;
+
+ for (size_t i = 1; i < m_args.size(); ++i)
+ {
+ if (strcmp(m_args[i], "="))
+ {
+ if (comp_idx > 3)
+ {
+ fprintf(stderr, "Error (%s:%d): "
+ "Must be R G B (A) = R G B (A).\n",
+ list_file, line);
+ return (false);
+ }
+
+ int val = atoi(m_args[i]);
+ if (val < 0 || val > 255)
+ {
+ fprintf(stderr,
+ "Error (%s:%d): Arg %d must be 0-255.\n",
+ list_file, line, i);
+ }
+
+ cols[col_idx][comp_idx++] = static_cast<unsigned char>(val);
+ }
+ else if (col_idx > 0)
+ {
+ fprintf(stderr,
+ "Error (%s:%d): Too many '=' characters.\n",
+ list_file, line);
+ return (false);
+ }
+ else
+ {
+ col_idx++;
+ comp_idx = 0;
+ }
+ }
+
+ m_palette.push_back(palette_entry(cols[0], cols[1]));
+ }
+ else if (strcmp(arg, "hue") == 0)
+ {
+ CHECK_ARG(2);
+ m_hues.push_back(int_pair(atoi(m_args[1]), atoi(m_args[2])));
+ }
+ else if (strcmp(arg, "resetcol") == 0)
+ {
+ CHECK_NO_ARG(1);
+ m_palette.clear();
+ m_hues.clear();
+ m_desat.clear();
+ m_lum.clear();
+ }
+ else if (strcmp(arg, "desat") == 0)
+ {
+ CHECK_ARG(1);
+ CHECK_NO_ARG(2);
+
+ m_desat.push_back(atoi(m_args[1]));
+ }
+ else if (strcmp(arg, "lum") == 0)
+ {
+ CHECK_ARG(2);
+ CHECK_NO_ARG(3);
+
+ m_lum.push_back(int_pair(atoi(m_args[1]), atoi(m_args[2])));
+ }
+ else if (strcmp(arg, "variation") == 0)
+ {
+ CHECK_ARG(2);
+ CHECK_NO_ARG(3);
+
+ int idx = m_page.find(m_args[1]);
+ if (idx == -1)
+ {
+ fprintf(stderr, "Error (%s:%d): invalid tile name '%s'\n",
+ list_file, line, m_args[1]);
+ return (false);
+ }
+
+ int colour = str_to_colour(m_args[2]);
+ if (colour == 0)
+ {
+ fprintf(stderr, "Error (%s:%d): invalid colour '%s'\n",
+ list_file, line, m_args[2]);
+ return (false);
+ }
+
+ m_variation_idx = idx;
+ m_variation_col = colour;
+ }
+ else if (strcmp(arg, "repeat") == 0)
+ {
+ CHECK_ARG(1);
+
+ int idx = m_page.find(m_args[1]);
+ if (idx == -1)
+ {
+ fprintf(stderr, "Error (%s:%d): invalid tile name '%s'\n",
+ list_file, line, m_args[1]);
+ return (false);
+ }
+
+ int cnt = m_page.m_counts[idx];
+
+ for (int i = 0; i < cnt; ++i)
+ {
+ tile img;
+ img.copy(*m_page.m_tiles[idx + i]);
+ recolour(img);
+ add_image(img, (i == 0 && m_args[2]) ? m_args[2] : NULL);
+ }
+
+ if (m_args.size() > 2)
+ {
+ for (int i = 3; i < m_args.size(); ++i)
+ {
+ // Add enums for additional values.
+ m_page.add_synonym(m_args[2], m_args[i]);
+ }
+ }
+ }
else
{
fprintf(stderr, "Error (%s:%d): unknown command '%%%s'\n",
@@ -464,11 +664,19 @@ bool tile_list_processor::process_line(char *read_line, const char *list_file,
img.corpsify();
}
+ recolour(img);
+
if (m_rim && !m_corpsify)
img.add_rim(tile_colour::black);
// Push tile onto tile page.
add_image(img, m_args.size() > 1 ? m_args[1] : NULL);
+
+ for (int i = 2; i < m_args.size(); ++i)
+ {
+ // Add enums for additional values.
+ m_page.add_synonym(m_args[1], m_args[i]);
+ }
}
return (true);
@@ -489,6 +697,12 @@ void tile_list_processor::add_image(tile &img, const char *enumname)
if (m_categories.size() > 0)
m_ctg_counts[m_categories.size()-1]++;
+
+ if (m_variation_idx != -1)
+ {
+ m_page.add_variation(m_last_enum, m_variation_idx, m_variation_col);
+ m_variation_idx = -1;
+ }
}
bool tile_list_processor::write_data()
@@ -560,24 +774,47 @@ bool tile_list_processor::write_data()
for (unsigned int i = 0; i < m_page.m_tiles.size(); i++)
{
- const std::string &enumname = m_page.m_tiles[i]->enumname();
const std::string &parts_ctg = m_page.m_tiles[i]->parts_ctg();
- if (enumname.empty())
+ int enumcount = m_page.m_tiles[i]->enumcount();
+
+ std::string full_enum;
+ if (enumcount == 0)
{
fprintf(fp, " %s_%s_FILLER_%d%s,\n", m_prefix.c_str(),
ucname.c_str(), i, start_val.c_str());
}
else if (parts_ctg.empty())
{
+ const std::string &enumname = m_page.m_tiles[i]->enumname(0);
fprintf(fp, " %s_%s%s,\n", m_prefix.c_str(),
enumname.c_str(), start_val.c_str());
}
else
{
+ const std::string &enumname = m_page.m_tiles[i]->enumname(0);
fprintf(fp, " %s_%s_%s%s,\n", m_prefix.c_str(),
parts_ctg.c_str(), enumname.c_str(), start_val.c_str());
}
+ for (int c = 1; c < enumcount; ++c)
+ {
+ const std::string &basename = m_page.m_tiles[i]->enumname(0);
+ const std::string &enumname = m_page.m_tiles[i]->enumname(c);
+
+ if (parts_ctg.empty())
+ {
+ fprintf(fp, " %s_%s = %s_%s,\n",
+ m_prefix.c_str(), enumname.c_str(),
+ m_prefix.c_str(), basename.c_str());
+ }
+ else
+ {
+ fprintf(fp, " %s_%s_%s = %s_%s_%s,\n",
+ m_prefix.c_str(), parts_ctg.c_str(), enumname.c_str(),
+ m_prefix.c_str(), parts_ctg.c_str(), basename.c_str());
+ }
+ }
+
start_val = "";
if (!parts_ctg.empty())
@@ -597,13 +834,15 @@ bool tile_list_processor::write_data()
fprintf(fp, "int tile_%s_count(unsigned int idx);\n", lcname.c_str());
fprintf(fp, "const char *tile_%s_name(unsigned int idx);\n",
- lcname.c_str());
+ lcname.c_str());
fprintf(fp, "tile_info &tile_%s_info(unsigned int idx);\n",
- lcname.c_str());
+ lcname.c_str());
fprintf(fp, "bool tile_%s_index(const char *str, unsigned int &idx);\n",
- lcname.c_str());
+ lcname.c_str());
fprintf(fp, "bool tile_%s_equal(unsigned int tile, unsigned int idx);\n",
- lcname.c_str());
+ lcname.c_str());
+ fprintf(fp, "unsigned int tile_%s_coloured(unsigned int idx, int col);\n",
+ lcname.c_str());
if (m_categories.size() > 0)
{
@@ -663,11 +902,15 @@ bool tile_list_processor::write_data()
lcname.c_str(), max.c_str(), m_start_value.c_str());
for (unsigned int i = 0; i < m_page.m_tiles.size(); i++)
{
- const std::string &enumname = m_page.m_tiles[i]->enumname();
- if (enumname.empty())
+ if (m_page.m_tiles[i]->enumcount() == 0)
+ {
fprintf(fp, " \"%s_FILLER_%d\",\n", ucname.c_str(), i);
+ }
else
+ {
+ const std::string &enumname = m_page.m_tiles[i]->enumname(0);
fprintf(fp, " \"%s\",\n", enumname.c_str());
+ }
}
fprintf(fp, "};\n\n");
@@ -718,9 +961,9 @@ bool tile_list_processor::write_data()
fprintf(fp, "};\n\n");
}
- fprintf(fp, "\ntypedef std::pair<const char*, int> _tile_pair;\n\n");
+ fprintf(fp, "\ntypedef std::pair<const char*, unsigned int> _name_pair;\n\n");
- fprintf(fp, "_tile_pair %s_map_pairs[] =\n"
+ fprintf(fp, "_name_pair %s_name_pairs[] =\n"
"{\n", lcname.c_str());
typedef std::map<std::string, int> sort_map;
@@ -728,22 +971,22 @@ bool tile_list_processor::write_data()
for (unsigned int i = 0; i < m_page.m_tiles.size(); i++)
{
- const std::string &enumname = m_page.m_tiles[i]->enumname();
- // Filler can't be looked up.
- if (enumname.empty())
- continue;
+ for (int c = 0; c < m_page.m_tiles[i]->enumcount(); ++c)
+ {
+ const std::string &enumname = m_page.m_tiles[i]->enumname(c);
- std::string lcenum = enumname;
- for (unsigned int c = 0; c < enumname.size(); c++)
- lcenum[c] = std::tolower(enumname[c]);
+ std::string lcenum = enumname;
+ for (unsigned int c = 0; c < enumname.size(); c++)
+ lcenum[c] = std::tolower(enumname[c]);
- table.insert(sort_map::value_type(lcenum, i));
+ table.insert(sort_map::value_type(lcenum, i));
+ }
}
sort_map::iterator itor;
for (itor = table.begin(); itor != table.end(); itor++)
{
- fprintf(fp, " _tile_pair(\"%s\", %d + %s),\n",
+ fprintf(fp, " _name_pair(\"%s\", %d + %s),\n",
itor->first.c_str(), itor->second, m_start_value.c_str());
}
@@ -760,29 +1003,12 @@ bool tile_list_processor::write_data()
" for (unsigned int i = 0; i < lc.size(); i++)\n"
" lc[i] = tolower(lc[i]);\n"
"\n"
- " int num_pairs = sizeof(%s_map_pairs) / sizeof(%s_map_pairs[0]);\n"
- "\n"
- " int first = 0;\n"
- " int last = num_pairs - 1;\n"
- "\n"
- " do\n"
- " {\n"
- " int half = (last - first) / 2 + first;\n"
- " int cmp = strcmp(str, %s_map_pairs[half].first);\n"
- " if (cmp < 0)\n"
- " last = half - 1;\n"
- " else if (cmp > 0)\n"
- " first = half + 1;\n"
- " else\n"
- " {\n"
- " idx = %s_map_pairs[half].second;\n"
- " return true;\n"
- " }\n" "\n"
- " } while (first <= last);\n"
- "\n"
- " return false;\n"
- "}\n",
- lcname.c_str(), lcname.c_str(), lcname.c_str(), lcname.c_str(), lcname.c_str());
+ " int num_pairs = sizeof(%s_name_pairs) / sizeof(%s_name_pairs[0]);\n"
+ " bool result = binary_search<const char *, unsigned int>(\n"
+ " lc.c_str(), &%s_name_pairs[0], num_pairs, &strcmp, idx);\n"
+ " return (result);\n"
+ "}\n\n",
+ lcname.c_str(), lcname.c_str(), lcname.c_str(), lcname.c_str());
fprintf(fp,
"bool tile_%s_equal(unsigned int tile, unsigned int idx)\n"
@@ -792,6 +1018,43 @@ bool tile_list_processor::write_data()
"}\n\n",
lcname.c_str(), m_start_value.c_str(), max.c_str(), lcname.c_str());
+ fprintf(fp, "\ntypedef std::pair<tile_variation, unsigned int> _colour_pair;\n\n");
+
+ fprintf(fp,
+ "_colour_pair %s_colour_pairs[] =\n"
+ "{\n"
+ " _colour_pair(tile_variation(0, 0), 0),\n",
+ lcname.c_str());
+
+ for (unsigned int i = 0; i < m_page.m_tiles.size(); i++)
+ {
+ for (int c = 0; c < MAX_COLOUR; ++c)
+ {
+ int var;
+ if (!m_page.m_tiles[i]->get_variation(c, var))
+ continue;
+
+ fprintf(fp,
+ " _colour_pair(tile_variation(%d + %s, %d), %d + %s),\n",
+ i, m_start_value.c_str(), c, var, m_start_value.c_str());
+ }
+ }
+
+ fprintf(fp, "%s", "};\n\n");
+
+ fprintf(fp,
+ "unsigned int tile_%s_coloured(unsigned int idx, int col)\n"
+ "{\n"
+ " int num_pairs = sizeof(%s_colour_pairs) / sizeof(%s_colour_pairs[0]);\n"
+ " tile_variation key(idx, col);\n"
+ " unsigned int found;\n"
+ " bool result = binary_search<tile_variation, unsigned int>(\n"
+ " key, &%s_colour_pairs[0], num_pairs,\n"
+ " &tile_variation::cmp, found);\n"
+ " return (result ? found : idx);\n"
+ "}\n\n",
+ lcname.c_str(), lcname.c_str(), lcname.c_str(), lcname.c_str());
+
fclose(fp);
}
@@ -818,29 +1081,32 @@ bool tile_list_processor::write_data()
fprintf(fp, "<td><img src=\"%s\"/></td>",
m_page.m_tiles[i]->filename().c_str());
- std::string lcenum = m_page.m_tiles[i]->enumname();
- for (unsigned int c = 0; c < lcenum.size(); c++)
- lcenum[c] = std::tolower(lcenum[c]);
-
- fprintf(fp, "<td>%s</td>", lcenum.c_str());
-
- const std::string &parts_ctg = m_page.m_tiles[i]->parts_ctg();
- if (m_page.m_tiles[i]->enumname().empty())
+ if (m_page.m_tiles[i]->enumcount() == 0)
{
- fprintf(fp, "<td></td>");
- }
- else if (parts_ctg.empty())
- {
- fprintf(fp, "<td>%s_%s</td>",
- m_prefix.c_str(),
- m_page.m_tiles[i]->enumname().c_str());
+ fprintf(fp, "<td></td><td></td>");
}
else
{
- fprintf(fp, "<td>%s_%s_%s</td>",
- m_prefix.c_str(),
- parts_ctg.c_str(),
- m_page.m_tiles[i]->enumname().c_str());
+ std::string lcenum = m_page.m_tiles[i]->enumname(0);
+ for (unsigned int c = 0; c < lcenum.size(); c++)
+ lcenum[c] = std::tolower(lcenum[c]);
+
+ fprintf(fp, "<td>%s</td>", lcenum.c_str());
+
+ const std::string &parts_ctg = m_page.m_tiles[i]->parts_ctg();
+ if (parts_ctg.empty())
+ {
+ fprintf(fp, "<td>%s_%s</td>",
+ m_prefix.c_str(),
+ m_page.m_tiles[i]->enumname(0).c_str());
+ }
+ else
+ {
+ fprintf(fp, "<td>%s_%s_%s</td>",
+ m_prefix.c_str(),
+ parts_ctg.c_str(),
+ m_page.m_tiles[i]->enumname(0).c_str());
+ }
}
fprintf(fp, "<td>%s</td>", m_page.m_tiles[i]->filename().c_str());
diff --git a/crawl-ref/source/rltiles/tool/tile_list_processor.h b/crawl-ref/source/rltiles/tool/tile_list_processor.h
index 74b199b5ef..5e95d1815b 100644
--- a/crawl-ref/source/rltiles/tool/tile_list_processor.h
+++ b/crawl-ref/source/rltiles/tool/tile_list_processor.h
@@ -18,6 +18,7 @@ protected:
bool load_image(tile &img, const char *filename);
bool process_line(char *read_line, const char *list_file, int line);
void add_image(tile &img, const char *enumname);
+ void recolour(tile &img);
std::string m_name;
@@ -38,6 +39,22 @@ protected:
std::vector<std::string> m_categories;
std::vector<int> m_ctg_counts;
tile m_compose;
+ int m_variation_idx;
+ int m_variation_col;
+
+ typedef std::pair<tile_colour, tile_colour> palette_entry;
+ typedef std::vector<palette_entry> palette_list;
+ palette_list m_palette;
+
+ typedef std::pair<int, int> int_pair;
+ typedef std::vector<int_pair> hue_list;
+ hue_list m_hues;
+
+ typedef std::vector<int> desat_list;
+ desat_list m_desat;
+
+ typedef std::vector<int_pair> lum_list;
+ lum_list m_lum;
};
#endif
diff --git a/crawl-ref/source/rltiles/tool/tile_page.cc b/crawl-ref/source/rltiles/tool/tile_page.cc
index 67c77db3ea..4bd6c8a10f 100644
--- a/crawl-ref/source/rltiles/tool/tile_page.cc
+++ b/crawl-ref/source/rltiles/tool/tile_page.cc
@@ -88,6 +88,31 @@ bool tile_page::place_images()
return (true);
}
+int tile_page::find(const std::string &enumname) const
+{
+ for (size_t i = 0; i < m_tiles.size(); ++i)
+ {
+ for (int c = 0; c < m_tiles[i]->enumcount(); ++c)
+ {
+ if (m_tiles[i]->enumname(c) == enumname)
+ return (i);
+ }
+ }
+
+ return (-1);
+}
+
+bool tile_page::add_synonym(const std::string &enumname, const std::string &syn)
+{
+ int idx = find(enumname);
+ if (idx == -1)
+ return (false);
+
+ m_tiles[idx]->add_enumname(syn);
+
+ return (true);
+}
+
bool tile_page::write_image(const char *filename)
{
if (m_width * m_height <= 0)
@@ -123,3 +148,12 @@ bool tile_page::write_image(const char *filename)
delete[] pixels;
return success;
}
+
+void tile_page::add_variation(int var_idx, int base_idx, int colour)
+{
+ assert(var_idx < (2 << 15));
+ assert(base_idx < (2 << 15));
+
+ m_tiles[base_idx]->add_variation(colour, var_idx);
+}
+
diff --git a/crawl-ref/source/rltiles/tool/tile_page.h b/crawl-ref/source/rltiles/tool/tile_page.h
index 9f13651a1d..d9f6a47861 100644
--- a/crawl-ref/source/rltiles/tool/tile_page.h
+++ b/crawl-ref/source/rltiles/tool/tile_page.h
@@ -13,10 +13,15 @@ public:
bool place_images();
bool write_image(const char *filename);
+ int find(const std::string &enumname) const;
+ bool add_synonym(const std::string &enumname, const std::string &syn);
+ void add_variation(int var_idx, int base_idx, int colour);
+
std::vector<tile*> m_tiles;
std::vector<unsigned int> m_counts;
std::vector<int> m_texcoords;
std::vector<int> m_offsets;
+
protected:
int m_width;
int m_height;