diff options
author | Enne Walker <ennewalker@users.sourceforge.net> | 2009-12-23 23:32:52 -0500 |
---|---|---|
committer | Enne Walker <ennewalker@users.sourceforge.net> | 2009-12-24 00:15:48 -0500 |
commit | bcc249f77c1459b75b7a4f96b018a15569e675b3 (patch) | |
tree | 72ad82e9ff51f45396c95933e3583437ab5489fb /crawl-ref/source/rltiles/tool/tile_list_processor.cc | |
parent | 5b9916a319a570598c8cd54e916eb10dab0eb916 (diff) | |
download | crawl-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/tile_list_processor.cc')
-rw-r--r-- | crawl-ref/source/rltiles/tool/tile_list_processor.cc | 390 |
1 files changed, 328 insertions, 62 deletions
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()); |