aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt9
-rw-r--r--src/client/tile.cpp63
2 files changed, 56 insertions, 16 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index a01e72889..4a4e345a9 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -357,8 +357,13 @@ The mask is applied using binary AND.
#### `[colorize:<color>:<ratio>`
Colorize the textures with the given color.
`<color>` is specified as a `ColorString`.
-`<ratio>` is an int ranging from 0 to 255, and specifies how much of the
-color to apply. If ommitted, the alpha will be used.
+`<ratio>` is an int ranging from 0 to 255 or the word "`alpha`". If
+it is an int, then it specifies how far to interpolate between the
+colors where 0 is only the texture color and 255 is only `<color>`. If
+omitted, the alpha of `<color>` will be used as the ratio. If it is
+the word "`alpha`", then the alpha of the color will be multiplied with
+the alpha of the texture with the RGB of the color replacing the RGB of
+the texture.
Sounds
------
diff --git a/src/client/tile.cpp b/src/client/tile.cpp
index 7a9bc0159..f0c0b4e9e 100644
--- a/src/client/tile.cpp
+++ b/src/client/tile.cpp
@@ -558,6 +558,13 @@ static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst,
v2s32 src_pos, v2s32 dst_pos, v2u32 size, int ratio);
+// Apply a color to an image. Uses an int (0-255) to calculate the ratio.
+// If the ratio is 255 or -1 and keep_alpha is true, then it multiples the
+// color alpha with the destination alpha.
+// Otherwise, any pixels that are not fully transparent get the color alpha.
+static void apply_colorize(video::IImage *dst, v2s32 dst_pos, v2u32 size,
+ video::SColor color, int ratio, bool keep_alpha);
+
// Apply a mask to an image
static void apply_mask(video::IImage *mask, video::IImage *dst,
v2s32 mask_pos, v2s32 dst_pos, v2u32 size);
@@ -1639,27 +1646,17 @@ bool TextureSource::generateImagePart(std::string part_of_name,
video::SColor color;
int ratio = -1;
+ bool keep_alpha = false;
if (!parseColorString(color_str, color, false))
return false;
if (is_number(ratio_str))
ratio = mystoi(ratio_str, 0, 255);
+ else if (ratio_str == "alpha")
+ keep_alpha = true;
- 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_interpolate_overlay(img, baseimg, v2s32(0,0), v2s32(0,0), dim, ratio);
- img->drop();
+ apply_colorize(baseimg, v2s32(0, 0), baseimg->getDimension(), color, ratio, keep_alpha);
}
else if (str_starts_with(part_of_name, "[applyfiltersformesh"))
{
@@ -1784,6 +1781,44 @@ static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst
}
/*
+ Apply color to destination
+*/
+static void apply_colorize(video::IImage *dst, v2s32 dst_pos, v2u32 size,
+ video::SColor color, int ratio, bool keep_alpha)
+{
+ u32 alpha = color.getAlpha();
+ video::SColor dst_c;
+ if ((ratio == -1 && alpha == 255) || ratio == 255) { // full replacement of color
+ if (keep_alpha) { // replace the color with alpha = dest alpha * color alpha
+ dst_c = color;
+ for (s32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
+ for (s32 x = dst_pos.X; x < dst_pos.X + size.X; x++) {
+ u32 dst_alpha = dst->getPixel(x, y).getAlpha();
+ if (dst_alpha > 0) {
+ dst_c.setAlpha(dst_alpha * alpha / 255);
+ dst->setPixel(x, y, dst_c);
+ }
+ }
+ } else { // replace the color including the alpha
+ for (s32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
+ for (s32 x = dst_pos.X; x < dst_pos.X + size.X; x++)
+ if (dst->getPixel(x, y).getAlpha() > 0)
+ dst->setPixel(x, y, color);
+ }
+ } else { // interpolate between the color and destination
+ float interp = (ratio == -1 ? color.getAlpha() / 255.0f : ratio / 255.0f);
+ for (s32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
+ for (s32 x = dst_pos.X; x < dst_pos.X + size.X; x++) {
+ dst_c = dst->getPixel(x, y);
+ if (dst_c.getAlpha() > 0) {
+ dst_c = color.getInterpolated(dst_c, interp);
+ dst->setPixel(x, y, dst_c);
+ }
+ }
+ }
+}
+
+/*
Apply mask to destination
*/
static void apply_mask(video::IImage *mask, video::IImage *dst,