浏览代码

Add ^[mask texture modifier

sfan5 10 年之前
父节点
当前提交
b19dd922ec
共有 2 个文件被更改,包括 53 次插入0 次删除
  1. 4 0
      doc/lua_api.txt
  2. 49 0
      src/tile.cpp

+ 4 - 0
doc/lua_api.txt

@@ -258,6 +258,10 @@ Advanced texture modifiers:
     Crops the texture to a frame of a vertical animation.
     Example: default_torch_animated.png^[verticalframe:16:8
 
+  [mask:<file>
+    Apply a mask to the base image.
+    The mask is applied using binary AND.
+
 Sounds
 -------
 Only OGG Vorbis files are supported.

+ 49 - 0
src/tile.cpp

@@ -537,6 +537,10 @@ static void blit_with_alpha(video::IImage *src, video::IImage *dst,
 static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
 		v2s32 src_pos, v2s32 dst_pos, v2u32 size);
 
+// Apply a mask to an image
+static void apply_mask(video::IImage *mask, video::IImage *dst,
+		v2s32 mask_pos, v2s32 dst_pos, v2u32 size);
+
 // Draw or overlay a crack
 static void draw_crack(video::IImage *crack, video::IImage *dst,
 		bool use_overlay, s32 frame_count, s32 progression,
@@ -1557,6 +1561,31 @@ bool TextureSource::generateImagePart(std::string part_of_name,
 			baseimg->drop();
 			baseimg = img;
 		}
+		/*
+			[mask:filename
+			Applies a mask to an image
+		*/
+		else if(part_of_name.substr(0,6) == "[mask:")
+		{
+			if (baseimg == NULL) {
+				errorstream << "generateImage(): baseimg == NULL "
+						<< "for part_of_name=\"" << part_of_name
+						<< "\", cancelling." << std::endl;
+				return false;
+			}
+			Strfnd sf(part_of_name);
+			sf.next(":");
+			std::string filename = sf.next(":");
+
+			video::IImage *img = m_sourcecache.getOrLoad(filename, m_device);
+			if (img) {
+				apply_mask(img, baseimg, v2s32(0, 0), v2s32(0, 0),
+						img->getDimension());
+			} else {
+				errorstream << "generateImage(): Failed to load \""
+						<< filename << "\".";
+			}
+		}
 		else
 		{
 			errorstream<<"generateImagePart(): Invalid "
@@ -1615,6 +1644,26 @@ static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
 	}
 }
 
+/*
+	Apply mask to destination
+*/
+static void apply_mask(video::IImage *mask, video::IImage *dst,
+		v2s32 mask_pos, v2s32 dst_pos, v2u32 size)
+{
+	for(u32 y0 = 0; y0 < size.Y; y0++) {
+		for(u32 x0 = 0; x0 < size.X; x0++) {
+			s32 mask_x = x0 + mask_pos.X;
+			s32 mask_y = y0 + mask_pos.Y;
+			s32 dst_x = x0 + dst_pos.X;
+			s32 dst_y = y0 + dst_pos.Y;
+			video::SColor mask_c = mask->getPixel(mask_x, mask_y);
+			video::SColor dst_c = dst->getPixel(dst_x, dst_y);
+			dst_c.color &= mask_c.color;
+			dst->setPixel(dst_x, dst_y, dst_c);
+		}
+	}
+}
+
 static void draw_crack(video::IImage *crack, video::IImage *dst,
 		bool use_overlay, s32 frame_count, s32 progression,
 		video::IVideoDriver *driver)