// This adds a patch to the texture public void AddPatch(TexturePatch patch) { // Add it patches.Add(patch); if (patch.LumpName == Name) { hasPatchWithSameName = true; //mxd } }
//mxd private Bitmap TransformPatch(Bitmap bitmap, TexturePatch p, Bitmap patchbmp) { //mxd. Flip if (p.FlipX || p.FlipY) { RotateFlipType flip; if (p.FlipX && !p.FlipY) { flip = RotateFlipType.RotateNoneFlipX; } else if (!p.FlipX && p.FlipY) { flip = RotateFlipType.RotateNoneFlipY; } else { flip = RotateFlipType.RotateNoneFlipXY; } patchbmp.RotateFlip(flip); } //mxd. Then rotate. I do it this way because RotateFlip function rotates THEN flips, and GZDoom does it the other way around. if (p.Rotate != 0) { RotateFlipType rotate; switch (p.Rotate) { case 90: rotate = RotateFlipType.Rotate90FlipNone; break; case 180: rotate = RotateFlipType.Rotate180FlipNone; break; default: rotate = RotateFlipType.Rotate270FlipNone; break; } patchbmp.RotateFlip(rotate); } // Adjust patch alpha, apply tint or blend if (p.BlendStyle != TexturePathBlendStyle.NONE || p.RenderStyle != TexturePathRenderStyle.COPY) { BitmapData bmpdata = null; try { bmpdata = patchbmp.LockBits(new Rectangle(0, 0, patchbmp.Size.Width, patchbmp.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); } catch (Exception e) { General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image \"" + p.LumpName + "\" for alpha adjustment. " + e.GetType().Name + ": " + e.Message); } if (bmpdata != null) { PixelColor *pixels = (PixelColor *)(bmpdata.Scan0.ToPointer()); int numpixels = bmpdata.Width * bmpdata.Height; int patchalpha = (int)Math.Round(General.Clamp(p.Alpha, 0f, 1f) * 255); //convert alpha to [0-255] range //mxd. Blend/Tint support if (p.BlendStyle == TexturePathBlendStyle.BLEND) { for (PixelColor *cp = pixels + numpixels - 1; cp >= pixels; cp--) { cp->r = (byte)((cp->r * p.BlendColor.r) * PixelColor.BYTE_TO_FLOAT); cp->g = (byte)((cp->g * p.BlendColor.g) * PixelColor.BYTE_TO_FLOAT); cp->b = (byte)((cp->b * p.BlendColor.b) * PixelColor.BYTE_TO_FLOAT); } } else if (p.BlendStyle == TexturePathBlendStyle.TINT) { float tintammount = p.BlendColor.a * PixelColor.BYTE_TO_FLOAT; // -0.1f; if (tintammount > 0) { float br = p.BlendColor.r * PixelColor.BYTE_TO_FLOAT * tintammount; float bg = p.BlendColor.g * PixelColor.BYTE_TO_FLOAT * tintammount; float bb = p.BlendColor.b * PixelColor.BYTE_TO_FLOAT * tintammount; float invtintammount = 1.0f - tintammount; for (PixelColor *cp = pixels + numpixels - 1; cp >= pixels; cp--) { cp->r = (byte)(((cp->r * PixelColor.BYTE_TO_FLOAT) * invtintammount + br) * 255.0f); cp->g = (byte)(((cp->g * PixelColor.BYTE_TO_FLOAT) * invtintammount + bg) * 255.0f); cp->b = (byte)(((cp->b * PixelColor.BYTE_TO_FLOAT) * invtintammount + bb) * 255.0f); } } } //mxd. Apply RenderStyle if (p.RenderStyle == TexturePathRenderStyle.BLEND) { for (PixelColor *cp = pixels + numpixels - 1; cp >= pixels; cp--) { cp->a = (byte)((cp->a * patchalpha) * PixelColor.BYTE_TO_FLOAT); } } //mxd. We need a copy of underlying part of texture for these styles else if (p.RenderStyle != TexturePathRenderStyle.COPY) { // Copy portion of texture int lockWidth = (p.X + patchbmp.Size.Width > bitmap.Width) ? bitmap.Width - p.X : patchbmp.Size.Width; int lockHeight = (p.Y + patchbmp.Size.Height > bitmap.Height) ? bitmap.Height - p.Y : patchbmp.Size.Height; Bitmap source = new Bitmap(patchbmp.Size.Width, patchbmp.Size.Height); using (Graphics sg = Graphics.FromImage(source)) sg.DrawImageUnscaled(bitmap, new Rectangle(-p.X, -p.Y, lockWidth, lockHeight)); // Lock texture BitmapData texturebmpdata = null; try { texturebmpdata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); } catch (Exception e) { General.ErrorLogger.Add(ErrorType.Error, "Cannot lock texture \"" + this.Name + "\" to apply render style. " + e.GetType().Name + ": " + e.Message); } if (texturebmpdata != null) { PixelColor *texturepixels = (PixelColor *)(texturebmpdata.Scan0.ToPointer()); PixelColor *tcp = texturepixels + numpixels - 1; switch (p.RenderStyle) { case TexturePathRenderStyle.ADD: for (PixelColor *cp = pixels + numpixels - 1; cp >= pixels; cp--) { cp->r = (byte)Math.Min(255, cp->r + tcp->r); cp->g = (byte)Math.Min(255, cp->g + tcp->g); cp->b = (byte)Math.Min(255, cp->b + tcp->b); cp->a = (byte)((cp->a * patchalpha) * PixelColor.BYTE_TO_FLOAT); tcp--; } break; case TexturePathRenderStyle.SUBTRACT: for (PixelColor *cp = pixels + numpixels - 1; cp >= pixels; cp--) { cp->r = (byte)Math.Max(0, tcp->r - cp->r); cp->g = (byte)Math.Max(0, tcp->g - cp->g); cp->b = (byte)Math.Max(0, tcp->b - cp->b); cp->a = (byte)((cp->a * patchalpha) * PixelColor.BYTE_TO_FLOAT); tcp--; } break; case TexturePathRenderStyle.REVERSE_SUBTRACT: for (PixelColor *cp = pixels + numpixels - 1; cp >= pixels; cp--) { cp->r = (byte)Math.Max(0, cp->r - tcp->r); cp->g = (byte)Math.Max(0, cp->g - tcp->g); cp->b = (byte)Math.Max(0, cp->b - tcp->b); cp->a = (byte)((cp->a * patchalpha) * PixelColor.BYTE_TO_FLOAT); tcp--; } break; case TexturePathRenderStyle.MODULATE: for (PixelColor *cp = pixels + numpixels - 1; cp >= pixels; cp--) { cp->r = (byte)((cp->r * tcp->r) * PixelColor.BYTE_TO_FLOAT); cp->g = (byte)((cp->g * tcp->g) * PixelColor.BYTE_TO_FLOAT); cp->b = (byte)((cp->b * tcp->b) * PixelColor.BYTE_TO_FLOAT); tcp--; } break; } source.UnlockBits(texturebmpdata); } } patchbmp.UnlockBits(bmpdata); } } return(patchbmp); }
// This adds a patch to the texture public void AddPatch(TexturePatch patch) { // Add it patches.Add(patch); }