add colorise to tile.cpp

This commit is contained in:
darkrose 2014-11-15 21:52:58 +10:00
parent b2d2868214
commit c37eb2f1d2
3 changed files with 369 additions and 47 deletions

View File

@ -983,7 +983,7 @@ void ServerEnvironment::step(float dtime)
block->incNodeTicks(p0);
MapNode n = block->getNodeNoEx(p0);
if (!has_spawned && active_object_count_wider < 20 && content_mob_spawn(this,p,active_object_count_wider)) {
if (!has_spawned && active_object_count_wider < 10 && content_mob_spawn(this,p,active_object_count_wider)) {
has_spawned = true;
active_object_count_wider++;
}

View File

@ -46,4 +46,17 @@ static inline std::string hex_encode(const std::string &data)
return hex_encode(data.c_str(), data.size());
}
static inline bool hex_digit_decode(char hexdigit, unsigned char &value)
{
if(hexdigit >= '0' && hexdigit <= '9')
value = hexdigit - '0';
else if(hexdigit >= 'A' && hexdigit <= 'F')
value = hexdigit - 'A' + 10;
else if(hexdigit >= 'a' && hexdigit <= 'f')
value = hexdigit - 'a' + 10;
else
return false;
return true;
}
#endif

View File

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "utility.h"
#include "settings.h"
#include "mesh.h"
#include "hex.h"
#include <ICameraSceneNode.h>
#include "log.h"
#include "mapnode.h" // For texture atlas making
@ -96,21 +97,16 @@ u32 TextureSource::getTextureId(const std::string &name)
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
core::map<std::string, u32>::Node *n;
n = m_name_to_id.find(name);
if(n != NULL)
{
if (n != NULL)
return n->getValue();
}
}
/*
Get texture
*/
if(get_current_thread_id() == m_main_thread)
{
if (get_current_thread_id() == m_main_thread) {
return getTextureIdDirect(name);
}
else
{
}else{
infostream<<"getTextureId(): Queued: name=\""<<name<<"\""<<std::endl;
// We're gonna ask the result to be put into here
@ -122,8 +118,7 @@ u32 TextureSource::getTextureId(const std::string &name)
infostream<<"Waiting for texture from main thread, name=\""
<<name<<"\""<<std::endl;
try
{
try{
// Wait result for a second
GetResult<std::string, u32, u8, u8>
result = result_queue.pop_front(1000);
@ -132,9 +127,7 @@ u32 TextureSource::getTextureId(const std::string &name)
assert(result.key == name);
return result.item;
}
catch(ItemNotFoundException &e)
{
}catch(ItemNotFoundException &e) {
infostream<<"Waiting for texture timed out."<<std::endl;
return 0;
}
@ -147,6 +140,8 @@ u32 TextureSource::getTextureId(const std::string &name)
// Draw a progress bar on the image
void make_progressbar(float value, video::IImage *image);
static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
v2s32 src_pos, v2s32 dst_pos, v2u32 size);
/*
Generate image based on a string like "stone.png" or "[crack0".
@ -172,8 +167,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
//infostream<<"getTextureIdDirect(): name=\""<<name<<"\""<<std::endl;
// Empty name means texture 0
if(name == "")
{
if (name == "") {
infostream<<"getTextureIdDirect(): name is empty"<<std::endl;
return 0;
}
@ -181,10 +175,8 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
/*
Calling only allowed from main thread
*/
if(get_current_thread_id() != m_main_thread)
{
errorstream<<"TextureSource::getTextureIdDirect() "
"called not from main thread"<<std::endl;
if (get_current_thread_id() != m_main_thread) {
errorstream<<"TextureSource::getTextureIdDirect() called not from main thread"<<std::endl;
return 0;
}
@ -196,10 +188,8 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
core::map<std::string, u32>::Node *n;
n = m_name_to_id.find(name);
if(n != NULL)
{
infostream<<"getTextureIdDirect(): \""<<name
<<"\" found in cache"<<std::endl;
if (n != NULL) {
infostream<<"getTextureIdDirect(): \""<<name<<"\" found in cache"<<std::endl;
return n->getValue();
}
}
@ -222,10 +212,8 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
// Find last meta separator in name
s32 last_separator_position = -1;
for(s32 i=name.size()-1; i>=0; i--)
{
if(name[i] == separator)
{
for (s32 i=name.size()-1; i>=0; i--) {
if (name[i] == separator) {
last_separator_position = i;
break;
}
@ -235,8 +223,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
base image using a recursive call
*/
std::string base_image_name;
if(last_separator_position != -1)
{
if (last_separator_position != -1) {
// Construct base name
base_image_name = name.substr(0, last_separator_position);
/*infostream<<"getTextureIdDirect(): Calling itself recursively"
@ -258,22 +245,18 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
video::IImage *baseimg = NULL;
// If a base image was found, copy it to baseimg
if(base_image_id != 0)
{
if (base_image_id != 0) {
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
SourceAtlasPointer ap = m_atlaspointer_cache[base_image_id];
video::IImage *image = ap.atlas_img;
if(image == NULL)
{
if (image == NULL) {
infostream<<"getTextureIdDirect(): NULL image in "
<<"cache: \""<<base_image_name<<"\""
<<std::endl;
}
else
{
}else{
core::dimension2d<u32> dim = ap.intsize;
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
@ -282,9 +265,9 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
core::position2d<s32> pos_from = ap.intpos;
image->copyTo(
baseimg, // target
v2s32(0,0), // position in target
core::rect<s32>(pos_from, dim) // from
baseimg, // target
v2s32(0,0), // position in target
core::rect<s32>(pos_from, dim) // from
);
/*infostream<<"getTextureIdDirect(): Loaded \""
@ -302,22 +285,19 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
//infostream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
// Generate image according to part of name
if(generate_image(last_part_of_name, baseimg, m_device) == false)
{
if (generate_image(last_part_of_name, baseimg, m_device) == false) {
infostream<<"getTextureIdDirect(): "
"failed to generate \""<<last_part_of_name<<"\""
<<std::endl;
}
// If no resulting image, print a warning
if(baseimg == NULL)
{
if (baseimg == NULL) {
infostream<<"getTextureIdDirect(): baseimg is NULL (attempted to"
" create texture \""<<name<<"\""<<std::endl;
}
if(baseimg != NULL)
{
if (baseimg != NULL) {
// Create texture from resulting image
t = driver->addTexture(name.c_str(), baseimg);
}
@ -335,7 +315,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
ap.size = v2f(1,1);
ap.tiled = 0;
core::dimension2d<u32> baseimg_dim(0,0);
if(baseimg)
if (baseimg)
baseimg_dim = baseimg->getDimension();
SourceAtlasPointer nap(name, ap, baseimg, v2s32(0,0), baseimg_dim);
m_atlaspointer_cache.push_back(nap);
@ -631,6 +611,275 @@ void TextureSource::buildMainAtlas()
driver->writeImageToFile(atlas_img, atlaspath.c_str());*/
}
static bool parseHexColorString(const std::string &value, video::SColor &color)
{
unsigned char components[] = { 0x00, 0x00, 0x00, 0xff }; // R,G,B,A
if (value[0] != '#')
return false;
size_t len = value.size();
bool short_form;
if (len == 9 || len == 7) // #RRGGBBAA or #RRGGBB
short_form = false;
else if (len == 5 || len == 4) // #RGBA or #RGB
short_form = true;
else
return false;
bool success = true;
for (size_t pos = 1, cc = 0; pos < len; pos++, cc++) {
assert(cc < sizeof components / sizeof components[0]);
if (short_form) {
unsigned char d;
if (!hex_digit_decode(value[pos], d)) {
success = false;
break;
}
components[cc] = (d & 0xf) << 4 | (d & 0xf);
} else {
unsigned char d1, d2;
if (!hex_digit_decode(value[pos], d1) ||
!hex_digit_decode(value[pos+1], d2)) {
success = false;
break;
}
components[cc] = (d1 & 0xf) << 4 | (d2 & 0xf);
pos++; // skip the second digit -- it's already used
}
}
if (success) {
color.setRed(components[0]);
color.setGreen(components[1]);
color.setBlue(components[2]);
color.setAlpha(components[3]);
}
return success;
}
struct ColorContainer {
ColorContainer();
std::map<const std::string, u32> colors;
};
ColorContainer::ColorContainer()
{
colors["aliceblue"] = 0xf0f8ff;
colors["antiquewhite"] = 0xfaebd7;
colors["aqua"] = 0x00ffff;
colors["aquamarine"] = 0x7fffd4;
colors["azure"] = 0xf0ffff;
colors["beige"] = 0xf5f5dc;
colors["bisque"] = 0xffe4c4;
colors["black"] = 00000000;
colors["blanchedalmond"] = 0xffebcd;
colors["blue"] = 0x0000ff;
colors["blueviolet"] = 0x8a2be2;
colors["brown"] = 0xa52a2a;
colors["burlywood"] = 0xdeb887;
colors["cadetblue"] = 0x5f9ea0;
colors["chartreuse"] = 0x7fff00;
colors["chocolate"] = 0xd2691e;
colors["coral"] = 0xff7f50;
colors["cornflowerblue"] = 0x6495ed;
colors["cornsilk"] = 0xfff8dc;
colors["crimson"] = 0xdc143c;
colors["cyan"] = 0x00ffff;
colors["darkblue"] = 0x00008b;
colors["darkcyan"] = 0x008b8b;
colors["darkgoldenrod"] = 0xb8860b;
colors["darkgray"] = 0xa9a9a9;
colors["darkgreen"] = 0x006400;
colors["darkkhaki"] = 0xbdb76b;
colors["darkmagenta"] = 0x8b008b;
colors["darkolivegreen"] = 0x556b2f;
colors["darkorange"] = 0xff8c00;
colors["darkorchid"] = 0x9932cc;
colors["darkred"] = 0x8b0000;
colors["darksalmon"] = 0xe9967a;
colors["darkseagreen"] = 0x8fbc8f;
colors["darkslateblue"] = 0x483d8b;
colors["darkslategray"] = 0x2f4f4f;
colors["darkturquoise"] = 0x00ced1;
colors["darkviolet"] = 0x9400d3;
colors["deeppink"] = 0xff1493;
colors["deepskyblue"] = 0x00bfff;
colors["dimgray"] = 0x696969;
colors["dodgerblue"] = 0x1e90ff;
colors["firebrick"] = 0xb22222;
colors["floralwhite"] = 0xfffaf0;
colors["forestgreen"] = 0x228b22;
colors["fuchsia"] = 0xff00ff;
colors["gainsboro"] = 0xdcdcdc;
colors["ghostwhite"] = 0xf8f8ff;
colors["gold"] = 0xffd700;
colors["goldenrod"] = 0xdaa520;
colors["gray"] = 0x808080;
colors["green"] = 0x008000;
colors["greenyellow"] = 0xadff2f;
colors["honeydew"] = 0xf0fff0;
colors["hotpink"] = 0xff69b4;
colors["indianred "] = 0xcd5c5c;
colors["indigo "] = 0x4b0082;
colors["ivory"] = 0xfffff0;
colors["khaki"] = 0xf0e68c;
colors["lavender"] = 0xe6e6fa;
colors["lavenderblush"] = 0xfff0f5;
colors["lawngreen"] = 0x7cfc00;
colors["lemonchiffon"] = 0xfffacd;
colors["lightblue"] = 0xadd8e6;
colors["lightcoral"] = 0xf08080;
colors["lightcyan"] = 0xe0ffff;
colors["lightgoldenrodyellow"] = 0xfafad2;
colors["lightgray"] = 0xd3d3d3;
colors["lightgreen"] = 0x90ee90;
colors["lightpink"] = 0xffb6c1;
colors["lightsalmon"] = 0xffa07a;
colors["lightseagreen"] = 0x20b2aa;
colors["lightskyblue"] = 0x87cefa;
colors["lightslategray"] = 0x778899;
colors["lightsteelblue"] = 0xb0c4de;
colors["lightyellow"] = 0xffffe0;
colors["lime"] = 0x00ff00;
colors["limegreen"] = 0x32cd32;
colors["linen"] = 0xfaf0e6;
colors["magenta"] = 0xff00ff;
colors["maroon"] = 0x800000;
colors["mediumaquamarine"] = 0x66cdaa;
colors["mediumblue"] = 0x0000cd;
colors["mediumorchid"] = 0xba55d3;
colors["mediumpurple"] = 0x9370db;
colors["mediumseagreen"] = 0x3cb371;
colors["mediumslateblue"] = 0x7b68ee;
colors["mediumspringgreen"] = 0x00fa9a;
colors["mediumturquoise"] = 0x48d1cc;
colors["mediumvioletred"] = 0xc71585;
colors["midnightblue"] = 0x191970;
colors["mintcream"] = 0xf5fffa;
colors["mistyrose"] = 0xffe4e1;
colors["moccasin"] = 0xffe4b5;
colors["navajowhite"] = 0xffdead;
colors["navy"] = 0x000080;
colors["oldlace"] = 0xfdf5e6;
colors["olive"] = 0x808000;
colors["olivedrab"] = 0x6b8e23;
colors["orange"] = 0xffa500;
colors["orangered"] = 0xff4500;
colors["orchid"] = 0xda70d6;
colors["palegoldenrod"] = 0xeee8aa;
colors["palegreen"] = 0x98fb98;
colors["paleturquoise"] = 0xafeeee;
colors["palevioletred"] = 0xdb7093;
colors["papayawhip"] = 0xffefd5;
colors["peachpuff"] = 0xffdab9;
colors["peru"] = 0xcd853f;
colors["pink"] = 0xffc0cb;
colors["plum"] = 0xdda0dd;
colors["powderblue"] = 0xb0e0e6;
colors["purple"] = 0x800080;
colors["red"] = 0xff0000;
colors["rosybrown"] = 0xbc8f8f;
colors["royalblue"] = 0x4169e1;
colors["saddlebrown"] = 0x8b4513;
colors["salmon"] = 0xfa8072;
colors["sandybrown"] = 0xf4a460;
colors["seagreen"] = 0x2e8b57;
colors["seashell"] = 0xfff5ee;
colors["sienna"] = 0xa0522d;
colors["silver"] = 0xc0c0c0;
colors["skyblue"] = 0x87ceeb;
colors["slateblue"] = 0x6a5acd;
colors["slategray"] = 0x708090;
colors["snow"] = 0xfffafa;
colors["springgreen"] = 0x00ff7f;
colors["steelblue"] = 0x4682b4;
colors["tan"] = 0xd2b48c;
colors["teal"] = 0x008080;
colors["thistle"] = 0xd8bfd8;
colors["tomato"] = 0xff6347;
colors["turquoise"] = 0x40e0d0;
colors["violet"] = 0xee82ee;
colors["wheat"] = 0xf5deb3;
colors["white"] = 0xffffff;
colors["whitesmoke"] = 0xf5f5f5;
colors["yellow"] = 0xffff00;
colors["yellowgreen"] = 0x9acd32;
}
static const ColorContainer named_colors;
static bool parseNamedColorString(const std::string &value, video::SColor &color)
{
std::string color_name;
std::string alpha_string;
/* If the string has a # in it, assume this is the start of a specified
* alpha value (if it isn't the string is invalid and the error will be
* caught later on, either because the color name won't be found or the
* alpha value will fail conversion)
*/
size_t alpha_pos = value.find('#');
if (alpha_pos != std::string::npos) {
color_name = value.substr(0, alpha_pos);
alpha_string = value.substr(alpha_pos + 1);
} else {
color_name = value;
}
color_name = lowercase(value);
std::map<const std::string, unsigned>::const_iterator it;
it = named_colors.colors.find(color_name);
if (it == named_colors.colors.end())
return false;
u32 color_temp = it->second;
/* An empty string for alpha is ok (none of the color table entries
* have an alpha value either). Color strings without an alpha specified
* are interpreted as fully opaque
*
* For named colors the supplied alpha string (representing a hex value)
* must be exactly two digits. For example: colorname#08
*/
if (!alpha_string.empty()) {
if (alpha_string.length() != 2)
return false;
unsigned char d1, d2;
if (!hex_digit_decode(alpha_string.at(0), d1)
|| !hex_digit_decode(alpha_string.at(1), d2))
return false;
color_temp |= ((d1 & 0xf) << 4 | (d2 & 0xf)) << 24;
} else {
color_temp |= 0xff << 24; // Fully opaque
}
color = video::SColor(color_temp);
return true;
}
bool parseColorString(const std::string &value, video::SColor &color, bool quiet)
{
bool success;
if (value[0] == '#')
success = parseHexColorString(value, color);
else
success = parseNamedColorString(value, color);
if (!success && !quiet)
errorstream << "Invalid color: \"" << value << "\"" << std::endl;
return success;
}
video::IImage* generate_image_from_scratch(std::string name,
IrrlichtDevice *device)
{
@ -1379,6 +1628,42 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
image->drop();
}
}
/*
[colorize:color
Overlays image with given color
color = color as ColorString
*/
else if (part_of_name.substr(0,10) == "[colorize:") {
Strfnd sf(part_of_name);
sf.next(":");
std::string color_str = sf.next(":");
if (baseimg == NULL) {
errorstream << "generateImagePart(): baseimg != NULL "
<< "for part_of_name=\"" << part_of_name
<< "\", cancelling." << std::endl;
return false;
}
video::SColor color;
if (!parseColorString(color_str, color, false))
return false;
core::dimension2d<u32> dim = baseimg->getDimension();
video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim);
if (!img) {
errorstream << "generateImagePart(): Could not create image "
<< "for part_of_name=\"" << part_of_name
<< "\", cancelling." << std::endl;
return false;
}
img->fill(video::SColor(color));
// Overlay the colored image
blit_with_alpha_overlay(img, baseimg, v2s32(0,0), v2s32(0,0), dim);
img->drop();
}
else
{
infostream<<"generate_image(): Invalid "
@ -1569,3 +1854,27 @@ void imageTransform(u32 transform, video::IImage *src, video::IImage *dst)
}
}
/*
Draw an image on top of an another one, using the alpha channel of the
source image; only modify fully opaque pixels in destinaion
*/
static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
v2s32 src_pos, v2s32 dst_pos, v2u32 size)
{
for(u32 y0=0; y0<size.Y; y0++)
for(u32 x0=0; x0<size.X; x0++)
{
s32 src_x = src_pos.X + x0;
s32 src_y = src_pos.Y + y0;
s32 dst_x = dst_pos.X + x0;
s32 dst_y = dst_pos.Y + y0;
video::SColor src_c = src->getPixel(src_x, src_y);
video::SColor dst_c = dst->getPixel(dst_x, dst_y);
if(dst_c.getAlpha() == 255 && src_c.getAlpha() != 0)
{
dst_c = src_c.getInterpolated(dst_c, (float)src_c.getAlpha()/255.0f);
dst->setPixel(dst_x, dst_y, dst_c);
}
}
}